- {organizationName !== '' ? (
- <>
- {/* //TODO */}
-
-
-
- >
- ) : (
- <>
-
- Create New
-
- >
- )}
+
+ {getOrganizations().length > 0 &&
+ getOrganizations().map((org: Organization) => (
+
+ {org.name}
+
+
+
+
+ ))}
+
+ Create New
+
MyFiles
diff --git a/src/providers/OrganizationProvider.tsx b/src/providers/OrganizationProvider.tsx
new file mode 100644
index 0000000..1f363c0
--- /dev/null
+++ b/src/providers/OrganizationProvider.tsx
@@ -0,0 +1,82 @@
+/* eslint-disable react-refresh/only-export-components */
+import React, { ReactNode, useEffect } from 'react';
+import Organization from '../utils/Organization';
+import APIService from '../utils/ApiService';
+
+const OrganizationContext = React.createContext({
+ getOrganizations: (): Organization[] => {
+ return [];
+ },
+ updateOrganizations: () => {},
+});
+
+/**
+ * A hook to get the organizations from the OrganizationProvider
+ * @returns A function that returns an array of organizations
+ */
+export function useGetOrganizations() {
+ const context = React.useContext(OrganizationContext);
+ if (!context) {
+ throw new Error(
+ 'useGetOrganizations must be used within a OrganizationProvider'
+ );
+ }
+ return context.getOrganizations;
+}
+
+/**
+ * A hook to update the organizations in the OrganizationProvider
+ * @returns A function that updates the organizations in the OrganizationProvider
+ */
+export function useUpdateOrganizations() {
+ const context = React.useContext(OrganizationContext);
+ if (!context) {
+ throw new Error(
+ 'useUpdateOrganizations must be used within a OrganizationProvider'
+ );
+ }
+ return context.updateOrganizations;
+}
+
+interface Props {
+ children: ReactNode;
+}
+
+/**
+ * A provider that provides the organizations to the application
+ */
+export function OrganizationProvider({ children }: Props) {
+ const [organizations, setOrganizations] = React.useState(
+ []
+ );
+
+ useEffect(() => {
+ updateOrganizations();
+ }, []);
+
+ const getOrganizations = () => {
+ return organizations;
+ };
+
+ const updateOrganizations = () => {
+ APIService.getOrganizationNames().then((response) => {
+ if (!response) {
+ setOrganizations([]);
+ return;
+ }
+ response = response.filter((org) => org.id > 0);
+ setOrganizations(response);
+ });
+ };
+
+ return (
+
+ {children}
+
+ );
+}
diff --git a/src/utils/ApiService.test.ts b/src/utils/ApiService.test.ts
index bcd300f..ea05c8d 100644
--- a/src/utils/ApiService.test.ts
+++ b/src/utils/ApiService.test.ts
@@ -6,6 +6,7 @@ import {
beforeAll,
afterAll,
expectTypeOf,
+ assert,
} from 'vitest';
import 'src/utils/sessionStoragePolifill.js';
@@ -30,10 +31,11 @@ function generateRandomString(length: number): string {
describe('APIService', () => {
const salt = generateRandomString(10);
const alternative = generateRandomString(10);
+ let saltOrganisationID: number | undefined = undefined;
beforeAll(async () => {
await APIService.register(salt, salt);
- await APIService.createOrganization(salt);
+ saltOrganisationID = await APIService.createOrganization(salt);
});
afterAll(async () => {
@@ -72,17 +74,39 @@ describe('APIService', () => {
expect(token).toBe(null);
});
- test('should get organization successfully', async () => {
+ test('should get organizations successfully', async () => {
await APIService.login(salt, salt);
const organizationId = await APIService.getOrganizations();
expectTypeOf(organizationId).not.toBeBoolean();
expect(organizationId).toBeDefined();
+ if (!organizationId || organizationId.length === 0) {
+ assert(false);
+ }
+
+ expect(typeof organizationId[0]).toBe('number');
+ expect(organizationId[0]).toBeGreaterThan(0);
+ });
+ test('should get organizations successfully', async () => {
+ await APIService.login(salt, salt);
+ const organizations = await APIService.getOrganizationNames();
+ assert(organizations);
+ assert(typeof organizations != 'boolean');
+ expect(organizations[0].id > 0).true;
+ expect(typeof organizations[0].name).toBe('string');
+ });
+ test('should get organization successfully', async () => {
+ await APIService.login(salt, salt);
+ assert(saltOrganisationID);
+ const organizationName =
+ await APIService.getNameForOrganization(saltOrganisationID);
+ expectTypeOf(organizationName).not.toBeBoolean();
+ expect(organizationName).toBeDefined();
// eslint-disable-next-line @typescript-eslint/ban-ts-comment
// @ts-ignore
- expect(typeof organizationId[0]).toBe('number');
+ expect(typeof organizationName[0]).toBe('string');
// eslint-disable-next-line @typescript-eslint/ban-ts-comment
// @ts-ignore
- expect(organizationId[0]).toBeGreaterThan(10);
+ expect(organizationName[0].length).toBeGreaterThan(0);
});
test('should create organization successfully', async () => {
await APIService.login(salt, salt);
diff --git a/src/utils/ApiService.ts b/src/utils/ApiService.ts
index d91736d..d638b01 100644
--- a/src/utils/ApiService.ts
+++ b/src/utils/ApiService.ts
@@ -1,4 +1,5 @@
import axios from 'axios';
+import Organization from './Organization';
/**
* This class is used to make requests to the backend API.
@@ -11,26 +12,6 @@ class APIService {
* @param schema The username to login
* @returns A promise that resolves to true if the login was successful, false otherwise.
*/
- static async createTables(schema: string): Promise {
- try {
- const url = `${this.host}/dev/createTables/${schema}`;
- const resp = await axios.post(url);
- return resp.status === 200;
- } catch (err) {
- return false;
- }
- }
-
- static async dropTables(schema: string): Promise {
- try {
- const url = `${this.host}/dev/dropTables/${schema}`;
- const resp = await axios.post(url);
- return resp.status === 200;
- } catch (err) {
- return false;
- }
- }
-
static async login(username: string, password: string): Promise {
const url = `${this.host}/login`;
const resp = await axios.post(url, {
@@ -106,7 +87,7 @@ class APIService {
}
}
- static async getOrganizations(): Promise {
+ static async getOrganizations(): Promise {
try {
const url = `${this.host}/getOrganisations`;
const resp = await axios.get(url, {
@@ -117,7 +98,45 @@ class APIService {
if (resp.status == 200) {
return resp.data.organisation_ids as number[];
}
- if (resp.status == 204) return false;
+ if (resp.status == 204) return undefined;
+ } catch (err) {
+ return undefined;
+ }
+ }
+
+ static async getOrganizationNames(): Promise {
+ try {
+ const url = `${this.host}/getOrganisationNames`;
+ const resp = await axios.get<{
+ organisations: Organization[];
+ }>(url, {
+ headers: {
+ Authorization: this.getUserToken(),
+ },
+ });
+ if (resp.status == 200) {
+ return resp.data.organisations;
+ }
+ if (resp.status == 404) return undefined;
+ } catch (err) {
+ return undefined;
+ }
+ }
+
+ static async getNameForOrganization(
+ id: number
+ ): Promise {
+ try {
+ const url = `${this.host}/getOrganisationName/${id}`;
+ const resp = await axios.get(url, {
+ headers: {
+ Authorization: this.getUserToken(),
+ },
+ });
+ if (resp.status == 200) {
+ return resp.data.organisation_name as string;
+ }
+ if (resp.status == 404) return undefined;
} catch (err) {
return undefined;
}
@@ -130,7 +149,7 @@ class APIService {
*/
static async createOrganization(
orgName: string
- ): Promise {
+ ): Promise {
try {
const url = `${this.host}/createOrganisation`;
const resp = await axios.post(
@@ -149,10 +168,10 @@ class APIService {
'organisation',
JSON.stringify({
name: orgName,
- id: resp.data.organisation_id,
+ id: resp.data.organisation_id as number,
})
);
- return resp.data.organisation_id;
+ return resp.data.organisation_id as number;
}
} catch (err) {
return undefined;
@@ -180,7 +199,6 @@ class APIService {
Authorization: this.getUserToken(),
},
});
- console.log(resp);
if (resp.status === 201) {
return 'File uploaded successfully';
}
diff --git a/src/utils/Organization.ts b/src/utils/Organization.ts
new file mode 100644
index 0000000..9fe1400
--- /dev/null
+++ b/src/utils/Organization.ts
@@ -0,0 +1,14 @@
+/**
+ * Organization class to store organization data
+ */
+class Organization {
+ readonly name: string;
+ readonly id: number;
+
+ constructor(name: string, id: number) {
+ this.name = name;
+ this.id = id;
+ }
+}
+
+export default Organization;
diff --git a/templates/Provider/$$name$$Provider.tsx b/templates/Provider/$$name$$Provider.tsx
index e69de29..9871a16 100644
--- a/templates/Provider/$$name$$Provider.tsx
+++ b/templates/Provider/$$name$$Provider.tsx
@@ -0,0 +1,33 @@
+import React, { ReactNode } from 'react';
+
+const $$name$$Context = React.createContext({
+ test: () => {},
+});
+
+export function useTest() {
+ const context = React.useContext($$name$$Context);
+ if (!context) {
+ throw new Error('useTest must be used within a $$name$$Provider');
+ }
+ return context.test;
+}
+
+interface Props {
+ children: ReactNode;
+}
+
+export function $$name$$Provider({ children }: Props) {
+ const test = () => {
+ console.log('test');
+ };
+
+ return (
+ <$$name$$Context.Provider
+ value={{
+ test: test,
+ }}
+ >
+ {children}
+ $$name$$Context.Provider>
+ );
+}
diff --git a/tsconfig.json b/tsconfig.json
index ca6bde6..cbe4e08 100644
--- a/tsconfig.json
+++ b/tsconfig.json
@@ -1,6 +1,6 @@
{
"compilerOptions": {
- "target": "es2020",
+ "target": "ES2020",
"useDefineForClassFields": true,
"lib": ["ES2020", "DOM", "DOM.Iterable"],
"module": "esnext",
@@ -22,5 +22,5 @@
"noFallthroughCasesInSwitch": true
},
"include": ["src"],
- "references": [{ "path": "./tsconfig.node.json" }],
+ "references": [{ "path": "./tsconfig.node.json" }]
}