Skip to content

Commit

Permalink
Merge pull request #8 from CBIIT/CRDCDH-95
Browse files Browse the repository at this point in the history
CRDCDH-95 Add apollo client and integrated with mock api server
  • Loading branch information
jonkiky authored Jun 23, 2023
2 parents be5fa77 + a0abe64 commit 538e05e
Show file tree
Hide file tree
Showing 12 changed files with 572 additions and 207 deletions.
400 changes: 321 additions & 79 deletions package-lock.json

Large diffs are not rendered by default.

6 changes: 4 additions & 2 deletions package.json
Original file line number Diff line number Diff line change
@@ -1,8 +1,9 @@
{
"name": "keeptrack",
"name": "CRDC DataHub",
"version": "0.1.0",
"private": true,
"dependencies": {
"@apollo/client": "^3.7.15",
"@emotion/react": "^11.11.0",
"@emotion/styled": "^11.11.0",
"@jalik/form-parser": "^2.0.12",
Expand All @@ -17,6 +18,7 @@
"@types/node": "^16.18.31",
"@types/react": "^18.2.6",
"@types/react-dom": "^18.2.4",
"graphql": "^16.6.0",
"lodash": "^4.17.21",
"nprogress": "^0.2.0",
"react": "^18.2.0",
Expand All @@ -35,7 +37,7 @@
"test": "react-scripts test",
"eject": "react-scripts eject",
"lint": "eslint .",
"lint:fix": "eslint --fix"
"lint:fix": "lint -- --fix"
},
"eslintConfig": {
"extends": [
Expand Down
59 changes: 59 additions & 0 deletions src/client.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,59 @@
/* eslint-disable */
import {
ApolloClient, InMemoryCache, ApolloLink, HttpLink, DefaultOptions
} from '@apollo/client';
import env from './env';

const defaultOptions:DefaultOptions = {
query: {
fetchPolicy: 'no-cache',
},
};

const BACKEND = env.REACT_APP_BACKEND_API;
const MOCK = 'https://7a242248-52f7-476a-a60f-d64a2db3dd5b.mock.pstmn.io/graphql';
const AUTH_SERVICE = `${env.REACT_APP_AUTH_SERVICE_API}graphql`;
const USER_SERVICE = `${env.REACT_APP_USER_SERVICE_API}graphql`;

const backendService = new HttpLink({
uri: BACKEND,
});

const authService = new HttpLink({
uri: AUTH_SERVICE,
});

const userService = new HttpLink({
uri: USER_SERVICE,
});


const mockService = new HttpLink({
uri: MOCK,
headers: {
'x-mock-match-request-body': 'true',
},
});

const client = new ApolloClient({
cache: new InMemoryCache(),
defaultOptions,
link: ApolloLink.split(
(operation) => operation.getContext().clientName === 'mockService',
mockService,
ApolloLink.split(
(operation) => operation.getContext().clientName === 'authService',
// the string "authService" can be anything you want,
authService, // <= apollo will send to this if clientName is "authService"
ApolloLink.split( // This is 2nd level of ApolloLink.
(operation) => operation.getContext().clientName === 'userService',
// the string "userService" can be anything you want,
userService, // <= apollo will send to this if clientName is "userService"
backendService, // <= otherwise will send to this
), // <= otherwise will send to this
),
),
});


export default client;
12 changes: 5 additions & 7 deletions src/components/Contexts/FormContext.test.tsx
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import React, { FC } from 'react';
import { Status as FormStatus, FormProvider, useFormContext } from "./FormContext";
import { render, waitFor } from '@testing-library/react';
import { Status as FormStatus, FormProvider, useFormContext } from "./FormContext";
import '@testing-library/jest-dom';

type Props = {
Expand All @@ -22,13 +22,11 @@ const TestChild: FC = () => {
);
};

const TestParent: FC<Props> = ({ appId } : Props) => {
return (
<FormProvider id={appId}>
<TestChild />
</FormProvider>
const TestParent: FC<Props> = ({ appId } : Props) => (
<FormProvider id={appId}>
<TestChild />
</FormProvider>
);
}

describe("FormContext tests", () => {
it("should return an error for empty IDs", async () => {
Expand Down
146 changes: 40 additions & 106 deletions src/components/Contexts/FormContext.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,8 @@ import React, {
useMemo,
useState,
} from "react";
import { useLazyQuery, useMutation } from '@apollo/client';
import { GET_APP, SAVE_APP, SUBMIT_APP } from './graphql';

export type ContextState = {
status: Status;
Expand All @@ -14,14 +16,12 @@ export type ContextState = {
error?: string;
};

/* eslint-disable */
export enum Status {
LOADING = "LOADING", // Loading initial data
LOADED = "LOADED", // Successfully loaded data
ERROR = "ERROR", // Error loading data
SAVING = "SAVING", // Saving data to the API
LOADED = "LOADED", // Successfully loaded data
ERROR = "ERROR", // Error loading data
SAVING = "SAVING", // Saving data to the API
}
/* eslint-enable */

const initialState: ContextState = { status: Status.LOADING, data: null };

Expand Down Expand Up @@ -70,9 +70,25 @@ export const FormProvider: FC<ProviderProps> = (props) => {
const { children, id } = props;
const [state, setState] = useState<ContextState>(initialState);

const [getAPP, { data, error }] = useLazyQuery(GET_APP, {
variables: { id },
context: { clientName: 'mockService' },
fetchPolicy: 'no-cache'
});

const [saveApp] = useMutation(SAVE_APP, {
context: { clientName: 'mockService' },
fetchPolicy: 'no-cache'
});

const [submitApp] = useMutation(SUBMIT_APP, {
variables: { id },
context: { clientName: 'mockService' },
fetchPolicy: 'no-cache'
});

// Here we update the state and send the data to the API
// otherwise we can just update the local state (i.e. within form sections)
/* eslint-disable */
const setData = async (data: Application) => new Promise<boolean>((resolve) => {
console.log("[UPDATING DATA]");
console.log("prior state", state);
Expand All @@ -88,119 +104,37 @@ export const FormProvider: FC<ProviderProps> = (props) => {
resolve(true);
}, 1500);
});
/* eslint-enable */

useEffect(() => {
/* eslint-disable */
// TODO: fetch form data from API
setTimeout(() => {
// TODO: validate API response
if (isNaN(parseInt(id.toString()))) {
if (Number.isNaN(parseInt(id.toString(), 10))) {
setState({
status: Status.ERROR,
data: null,
error: "Invalid form ID",
});
return;
}
if (id.toString() === "1234") {
setState({
status: Status.ERROR,
data: null,
error: "You do not have permission to view this form",
});
return;
}
// Call the lazy query when the component mounts or when dependencies change
getAPP();
}, [getAPP, id]);

useEffect(() => {
// Update the state when the lazy query response changes
if (data) {
setState({
status: Status.LOADED,
data: {
id: parseInt(id.toString()),
sections: [
{
name: "A",
status: "Completed",
},
{
name: "B",
status: "In Progress",
},
],
pi: {
firstName: "John " + Math.random().toString(36).substring(7), // randomize to test form updates
lastName: "Doe",
position: "Professor",
email: "john.doe@nih.gov",
institution: "University of California, San Diego",
eRAAccount: "#9-338480777",
address: "9500 Gilman Dr, La Jolla, CA 92093",
},
primaryContact: {
firstName: "Benjamin",
lastName: "Franklin",
email: "ben.franklin@nih.gov",
phone: "13015256364",
position: "ABC",
institution: "University of Pennsylvania",
},
additionalContacts: [
{
role: "Administrative Contact",
firstName: "Fred",
lastName: "Graph",
email: "fred.graph@nih.gov",
phone: "3015555555",
institution: "University of California, San Diego",
},
{
role: "Financial Contact",
firstName: "Jane",
lastName: "Eyre",
email: "jane.eyre@nih.gov",
phone: "",
institution: "University of California, San Diego",
},
],
program: {
title: "Example Pg",
abbreviation: "EPG",
description: "", // non-custom programs do not have descriptions
},
study: {
title: "Example Study 1",
abbreviation: "ES1",
description: "", // non-custom studies do not have descriptions
repositories: [
{
name: "Example Repository",
studyID: "1234",
}
]
},
publications: [
{
title: "ABC Pub 123",
pubmedID: "123456",
DOI: "10.123/abc123",
},
],
funding: {
agencies: [
{
name: "National Cancer Institute",
grantNumbers: [
"R01CA123456",
],
}
],
nciProgramOfficer: 'Fred Franklin',
nciGPA: 'Person ABC',
}
},
data: data?.getApplication
});
}, 500);
/* eslint-enable */
}, [id]);
}

if (error) {
setState({
status: Status.ERROR,
data: null,
error: "GraphQL Errors",
});
}
}, [data, error]);

const value = useMemo(() => ({ ...state, setData }), [state]);

Expand Down
Loading

0 comments on commit 538e05e

Please # to comment.