;
+ research_drives: Array;
+ members: Array;
+};
+
/**
* Object describing a research drive service.
*/
export type ResearchDriveService = {
+ name: string;
allocated_gb: number;
+ free_gb: number;
+ used_gb: number;
+ percentage_used: number;
date: string;
first_day: string;
- free_gb: number;
- id: (number | null);
last_day: (string | null);
+ id?: (number | null);
+};
+
+/**
+ * Public model for Research Drive Service.
+ */
+export type ResearchDriveServicePublic = {
name: string;
- percentage_used: number;
+ allocated_gb: number;
+ free_gb: number;
used_gb: number;
+ percentage_used: number;
+ date: string;
+ first_day: string;
+ last_day: (string | null);
+ manifest: Manifest;
};
/**
@@ -144,9 +200,7 @@ export type GetDriveInfoApiV1ResdriveinfoGetData = {
};
};
-export type GetDriveInfoApiV1ResdriveinfoGetResponse = ({
- [key: string]: (string);
-});
+export type GetDriveInfoApiV1ResdriveinfoGetResponse = (ProjectWithDriveMember);
export type GetDriveInfoApiV1ResdriveinfoGetError = (HTTPValidationError);
diff --git a/web/src/fixtures.ts b/web/src/fixtures.ts
deleted file mode 100644
index 5447a12..0000000
--- a/web/src/fixtures.ts
+++ /dev/null
@@ -1,62 +0,0 @@
-/**
- * Fixtures containing a sample project and drive. TODO replace with an API client.
- */
-import type { ResearchDriveService, Project, Member, Role } from "./project";
-
-export function getDrive(): ResearchDriveService {
- return {
- name: "reslig202200001-Tītoki-metabolomics",
- allocated_gb: 25600.0,
- used_gb: 1596.0
- };
-}
-
-export function getProject(): Project {
- return {
- title: "Tītoki metabolomics",
- description: "Stress in plants could be defined as any change in growth condition(s) that disrupts metabolic homeostasis and requires an adjustment of metabolic pathways in a process that is usually referred to as acclimation. Metabolomics could contribute significantly to the study of stress biology in plants and other organisms by identifying different compounds, such as by-products of stress metabolism, stress signal transduction molecules or molecules that are part of the acclimation response of plants.",
- division: "Liggins Institute",
- members: [
- {
- person: {
- full_name: "Samina Nicholas",
- email: "s.nicholas@test.auckland.ac.nz",
- username: "snic021"
- },
- roles: [{
- name: "Project Owner"
- }]
- },
- {
- person: {
- full_name: "Zach Luther",
- email: "z.luther@test.auckland.ac.nz",
- username: "zlut014"
- },
- roles: [{
- name: "Project Team Member"
- }]
- },
- {
- person: {
- full_name: "Jarrod Hossam",
- email: "j.hossam@test.auckland.ac.nz",
- username: "jhos225"
- },
- roles: [{
- name: "Project Team Member"
- }]
- },
- {
- person: {
- full_name: "Melisa Edric",
- email: "m.edric@test.auckland.ac.nz",
- username: "medr894"
- },
- roles: [{
- name: "Project Team Member"
- }]
- }
- ]
- };
-}
diff --git a/web/src/main.ts b/web/src/main.ts
index 5a5dbdb..71d3cc3 100644
--- a/web/src/main.ts
+++ b/web/src/main.ts
@@ -8,4 +8,15 @@ const app = createApp(App)
app.use(router)
+// Global error handler
+app.config.errorHandler = (err, instance, info) => {
+
+ // Handle the error globally
+ console.error("Global error:", err);
+ console.log("Vue instance:", instance);
+ console.log("Error info:", info);
+
+ router.replace("/service-error");
+};
+
app.mount('#app')
diff --git a/web/src/models/helpers.ts b/web/src/models/helpers.ts
new file mode 100644
index 0000000..5f4c189
--- /dev/null
+++ b/web/src/models/helpers.ts
@@ -0,0 +1,43 @@
+/**
+ * Additional methods for Members.
+ */
+
+import type { MemberPublic } from "@/client";
+
+
+/**
+ * Given a list of members, filter for project owners.
+ * @param members List of members to search through
+ * @returns Members who are project owners.
+ */
+export function getProjectOwners(members: MemberPublic[]): MemberPublic[] {
+ return members.filter(member =>
+ member.role.name === "Project Owner"
+ );
+}
+
+/**
+ * Given a list of project members, filter for ordinary members.
+ * @param members List of members to search through
+ * @returns Members who are not project owners.
+ */
+export function getProjectMembers(members: MemberPublic[]): MemberPublic[] {
+ return members.filter(member =>
+ member.role.name !== "Project Owner"
+ );
+}
+
+/**
+ * Given a list of members, return a string of their names.
+ * @param members Members to return names for.
+ * @returns A string representing all member names.
+ */
+export function membersToString(members: MemberPublic[]): string {
+
+ return members.filter((_, idx, arr) =>
+ // Filter for unique members
+ arr.findIndex(member => member.person.email) === idx
+ ).map(member =>
+ member.person.full_name
+ ).join(", ");
+}
\ No newline at end of file
diff --git a/web/src/project.ts b/web/src/project.ts
deleted file mode 100644
index dcf351d..0000000
--- a/web/src/project.ts
+++ /dev/null
@@ -1,80 +0,0 @@
-/**
- * Type definitions for project information. TODO - generate based on output types in Python.
- */
-export interface Person {
- email: string | null;
- full_name: string;
- username: string;
-}
-
-export interface Role {
- name: string
-}
-
-export interface Member {
- person: Person;
- roles: Role[]
-}
-
-export interface Project {
- title: string
- description: string
- division: string
- members: Member[]
-}
-
-export interface ResearchDriveService {
- allocated_gb: number
- name: string
- used_gb: number
-}
-
-/**
- * Makes and returns an empty Project.
- * @returns An empty Project.
- */
-export function makeProject(): Project {
- return {
- title: "",
- description: "",
- division: "",
- members: []
- }
-}
-
-/**
- * Given a list of members, filter for project owners.
- * @param members List of members to search through
- * @returns Members who are project owners.
- */
-export function getProjectOwners(members: Member[]): Member[] {
- return members.filter(member =>
- member.roles.some(
- (role: Role) => role.name === "Project Owner"
- )
- );
-}
-
-/**
- * Given a list of project members, filter for ordinary members.
- * @param members List of members to search through
- * @returns Members who are not project owners.
- */
-export function getProjectMembers(members: Member[]): Member[] {
- return members.filter(member =>
- !member.roles.some(
- (role: Role) => role.name === "Project Owner"
- )
- );
-}
-
-/**
- * Given a list of members, return a string of their names.
- * @param members Members to return names for.
- * @returns A string representing all member names.
- */
-export function membersToString(members: Member[]): string {
- return members.map(member =>
- member.person.full_name
- ).join(", ");
-}
\ No newline at end of file
diff --git a/web/src/store.ts b/web/src/store.ts
index ddc1885..3212004 100644
--- a/web/src/store.ts
+++ b/web/src/store.ts
@@ -1,18 +1,15 @@
import { reactive } from 'vue';
-import { makeProject, type Project } from './project';
-import { getDrive } from "./fixtures"
-import { type DataClassification, type InputDriveOffboardSubmission } from './client';
+import { type DataClassification, type InputDriveOffboardSubmission, type ProjectChanges, type ProjectWithDriveMember, type ResearchDriveService } from './client';
interface FormStateStore {
hasStartedForm: boolean;
hasFinishedForm: boolean;
isCorrectDrive: boolean | null;
areProjectDetailsCorrect: boolean | null;
- project: Project;
+ projectChanges: ProjectChanges;
dataClassification: DataClassification | null;
retentionPeriod: number | null;
isRetentionPeriodCustom: boolean | null;
- getSubmission: () => InputDriveOffboardSubmission | null;
}
export const formState: FormStateStore = reactive({
@@ -20,24 +17,41 @@ export const formState: FormStateStore = reactive({
hasFinishedForm: false,
isCorrectDrive: null,
areProjectDetailsCorrect: null,
- project: makeProject(),
+ projectChanges: {},
dataClassification: null,
isRetentionPeriodCustom: null,
- retentionPeriod: null,
- getSubmission: function () {
- if (!this.dataClassification || !this.retentionPeriod) {
- return null;
- } else {
- return {
- dataClassification: this.dataClassification,
- retentionPeriodYears: this.retentionPeriod,
- isCompleted: true,
- driveName: getDrive().name,
- projectChanges: {
- title: this.project.title,
- description: this.project.description
- }
- }
- }
+ retentionPeriod: null
+});
+
+interface ArchiveRequestInfoStore {
+ isLoading: boolean,
+ error: any,
+ project: ProjectWithDriveMember,
+ drive: ResearchDriveService
+}
+
+export const requestInfo: ArchiveRequestInfoStore = reactive({
+ isLoading: false,
+ error: undefined,
+ project: {
+ title: "",
+ description: "",
+ division: "",
+ start_date: "",
+ end_date: "",
+ id: 0,
+ research_drives: [],
+ members: [],
+ codes: []
+ },
+ drive: {
+ allocated_gb: 0,
+ date: "",
+ first_day: "",
+ last_day: "",
+ free_gb: 0,
+ name: "",
+ percentage_used: 0,
+ used_gb: 0
}
-});
\ No newline at end of file
+})
\ No newline at end of file
diff --git a/web/src/views/CheckDetailsView.vue b/web/src/views/CheckDetailsView.vue
index c162529..53a645b 100644
--- a/web/src/views/CheckDetailsView.vue
+++ b/web/src/views/CheckDetailsView.vue
@@ -1,7 +1,6 @@
@@ -53,12 +50,12 @@ function tryContinue() {
{{ titleError }}
-
+
{{ descriptionError }}
-
+