Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

IDS-957 display information retrieved from backend #21

Merged
merged 5 commits into from
Dec 16, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion .github/workflows/frontend-gh-pages-build.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ name: Deploy frontend to Pages
on:
# Runs on pushes targeting the default branch
push:
branches: ["main"]
branches: ["main", "IDS-957-display-information-retrieved-from-backend"]

# Allows you to run this workflow manually from the Actions tab
workflow_dispatch:
Expand Down
14 changes: 13 additions & 1 deletion web/src/App.vue
Original file line number Diff line number Diff line change
@@ -1,7 +1,10 @@
<script setup lang="ts">
import { RouterView } from 'vue-router'
import { formState } from './store';
import { formState, requestInfo } from './store';
import { client } from './client';
import { loadRequestInfo } from './client/requestInfo';
import { onErrorCaptured } from 'vue';
import router from './router';

window.addEventListener('beforeunload', (event) => {
// If the user has started the form but hasn't finished it, give a warning before
Expand All @@ -12,6 +15,7 @@ window.addEventListener('beforeunload', (event) => {
}
});

// Set up API client.
client.setConfig({
baseUrl: import.meta.env.VITE_API_BASE_URL
});
Expand All @@ -20,6 +24,14 @@ client.interceptors.request.use((request, _) => {
request.headers.set('x-api-key', import.meta.env.VITE_API_KEY);
return request;
});

// Load initial request information - project and drive.
loadRequestInfo().then((hasLoadedRequestInfo: boolean) => {
if (!hasLoadedRequestInfo) {
// If loading the request info wasn't successful, redirect to error page.
router.replace("/service-error");
}
});
</script>

<template>
Expand Down
62 changes: 62 additions & 0 deletions web/src/client/requestInfo.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,62 @@
/**
* Functions for loading information about the archive request.
*/
import { requestInfo } from "@/store";
import { getDriveInfoApiV1ResdriveinfoGet } from "./sdk.gen";
import type { ProjectWithDriveMember, ResearchDriveService } from "./types.gen";

/**
* Retrieves project information based on project code in URL.
* @returns Project information from server.
* @throws Exception if server did not return data or received an error status code.
*/
async function getProject(): Promise<ProjectWithDriveMember> {
const params = new URLSearchParams(window.location.search);
const driveId = params.get("drive");
if (driveId === null) {
throw new Error("No drive name found in parameter.");
}
const response = await getDriveInfoApiV1ResdriveinfoGet({
query: {
drive_id: driveId
}
});
if (response.error || !response.response.ok || response.data === undefined) {
throw response.error;
}
return response.data;
}

/**
* Retrieves drive information from server.
* @returns Drive information from server.
* @throws Exception if server did not return data.
*/
async function getDrive(): Promise<ResearchDriveService> {
const project = await getProject();
if (!project) {
throw new Error("Project is not loaded.");
}
return project.research_drives[0];
}

/**
* Retrieves archive information from server and stores it in the requestInfo store.
* @returns True if request was loaded successfully, false if not.
*/
export async function loadRequestInfo(): Promise<boolean> {
// Pre-populate archive request info.
try {
requestInfo.isLoading = true;
requestInfo.project = await getProject();
requestInfo.drive = await getDrive();
requestInfo.isLoading = false;
return true;
} catch (e) {
requestInfo.isLoading = false;
requestInfo.error = e;
console.error("Could not retrieve request information. Bad invite link?");
console.error(e);
return false;
}
}
66 changes: 60 additions & 6 deletions web/src/client/types.gen.ts
Original file line number Diff line number Diff line change
Expand Up @@ -77,6 +77,32 @@ export type InputServices = {
research_drive: Array<ResearchDriveService>;
};

/**
* SQL model for storing simple file manifests
*/
export type Manifest = {
id: number;
manifest: string;
};

/**
* Public model for project members.
*/
export type MemberPublic = {
role: Role;
person: Person;
};

/**
* Data class for a Person model in database.
*/
export type Person = {
id?: (number | null);
email: (string | null);
full_name: string;
username: string;
};

/**
* Project model for data stored in database
*/
Expand All @@ -97,19 +123,49 @@ export type ProjectChanges = {
description?: (string | null);
};

/**
* Public model for project with drive and member information.
*/
export type ProjectWithDriveMember = {
title: string;
description: string;
division: string;
start_date: string;
end_date: string;
id: number;
codes: Array<Code>;
research_drives: Array<ResearchDriveServicePublic>;
members: Array<MemberPublic>;
};

/**
* 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;
};

/**
Expand Down Expand Up @@ -144,9 +200,7 @@ export type GetDriveInfoApiV1ResdriveinfoGetData = {
};
};

export type GetDriveInfoApiV1ResdriveinfoGetResponse = ({
[key: string]: (string);
});
export type GetDriveInfoApiV1ResdriveinfoGetResponse = (ProjectWithDriveMember);

export type GetDriveInfoApiV1ResdriveinfoGetError = (HTTPValidationError);

Expand Down
62 changes: 0 additions & 62 deletions web/src/fixtures.ts

This file was deleted.

11 changes: 11 additions & 0 deletions web/src/main.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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')
43 changes: 43 additions & 0 deletions web/src/models/helpers.ts
Original file line number Diff line number Diff line change
@@ -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(", ");
}
Loading
Loading