diff --git a/client/public/images/dgidb-404-logo.png b/client/public/images/dgidb-404-logo.png new file mode 100644 index 00000000..8a437ee3 Binary files /dev/null and b/client/public/images/dgidb-404-logo.png differ diff --git a/client/src/components/Drug/DrugRecord/DrugRecord.tsx b/client/src/components/Drug/DrugRecord/DrugRecord.tsx index 50861c9b..5111102c 100644 --- a/client/src/components/Drug/DrugRecord/DrugRecord.tsx +++ b/client/src/components/Drug/DrugRecord/DrugRecord.tsx @@ -17,11 +17,12 @@ import TableCell from '@mui/material/TableCell'; import Table from '@mui/material/Table'; // components -import { LinearProgress, Link } from '@mui/material'; +import { Alert, LinearProgress, Link } from '@mui/material'; import InteractionTable from 'components/Shared/InteractionTable/InteractionTable'; import { useGetDrugInteractions } from 'hooks/queries/useGetDrugInteractions'; import { generateXrefLink } from 'utils/generateXrefLink'; import { ResultTypes } from 'types/types'; +import { NotFoundError } from 'components/Shared/NotFoundError/NotFoundError'; export const DrugRecord: React.FC = () => { const drugId = useParams().drug as string; @@ -43,6 +44,8 @@ export const DrugRecord: React.FC = () => { setInteractionResults(interactionData); }, [fetchedInteractionData]); + const drugExists = drugData !== null; + const noData = ( No data available. @@ -206,7 +209,7 @@ export const DrugRecord: React.FC = () => { }, ]; - return ( + return drugExists ? ( {drugData?.name} @@ -267,5 +270,12 @@ export const DrugRecord: React.FC = () => { + ) : ( + + + We could not find any results for this drug. + + + ); }; diff --git a/client/src/components/Gene/GeneRecord/GeneRecord.tsx b/client/src/components/Gene/GeneRecord/GeneRecord.tsx index d4650361..0f14bd0d 100644 --- a/client/src/components/Gene/GeneRecord/GeneRecord.tsx +++ b/client/src/components/Gene/GeneRecord/GeneRecord.tsx @@ -15,12 +15,13 @@ import Table from '@mui/material/Table'; import TableRow from '@mui/material/TableRow'; import TableCell from '@mui/material/TableCell'; -import { LinearProgress, Link } from '@mui/material'; +import { Alert, LinearProgress, Link } from '@mui/material'; import { useGetGeneInteractions } from 'hooks/queries/useGetGeneInteractions'; import InteractionTable from 'components/Shared/InteractionTable/InteractionTable'; import { dropRedundantCites } from 'utils/dropRedundantCites'; import { generateXrefLink } from 'utils/generateXrefLink'; import { ResultTypes } from 'types/types'; +import { NotFoundError } from 'components/Shared/NotFoundError/NotFoundError'; export const GeneRecord: React.FC = () => { const geneId: any = useParams().gene; @@ -30,6 +31,8 @@ export const GeneRecord: React.FC = () => { useGetGeneRecord(geneId); const geneData = fetchedGeneData?.gene; + const geneExists = geneData !== null; + // get interaction data const { data: fetchedInteractionData, isLoading: interactionDataIsLoading } = useGetGeneInteractions(geneId); @@ -204,7 +207,7 @@ export const GeneRecord: React.FC = () => { }, ]; - return ( + return geneExists ? ( {geneData?.name} @@ -265,6 +268,13 @@ export const GeneRecord: React.FC = () => { + ) : ( + + + We could not find any results for this gene. + + + ); }; diff --git a/client/src/components/Interaction/InteractionRecord/InteractionRecord.tsx b/client/src/components/Interaction/InteractionRecord/InteractionRecord.tsx index 21196af6..8e2c0a00 100644 --- a/client/src/components/Interaction/InteractionRecord/InteractionRecord.tsx +++ b/client/src/components/Interaction/InteractionRecord/InteractionRecord.tsx @@ -16,10 +16,16 @@ import AccordionDetails from '@mui/material/AccordionDetails'; import ExpandMoreIcon from '@mui/icons-material/ExpandMore'; import ArrowRightIcon from '@mui/icons-material/ArrowRight'; import { truncateDecimals } from 'utils/format'; +import { Alert } from '@mui/material'; +import { NotFoundError } from 'components/Shared/NotFoundError/NotFoundError'; export const InteractionRecord: React.FC = () => { const interactionId = useParams().id; const { data } = useGetInteractionRecord(interactionId!); + const interactionData = data?.interaction; + + const interactionExists = interactionData !== null; + const noData = ( No data available. @@ -38,10 +44,10 @@ export const InteractionRecord: React.FC = () => { - {data?.interaction?.drug?.name} [ - {data?.interaction?.drug?.conceptId}] + {interactionData?.drug?.name} [ + {interactionData?.drug?.conceptId}] @@ -50,10 +56,10 @@ export const InteractionRecord: React.FC = () => { - {data?.interaction?.gene?.name} [ - {data?.interaction?.gene?.conceptId}] + {interactionData?.gene?.name} [ + {interactionData?.gene?.conceptId}] @@ -62,12 +68,12 @@ export const InteractionRecord: React.FC = () => { Interaction Score: - {truncateDecimals(data?.interaction?.interactionScore, 2)} + {truncateDecimals(interactionData?.interactionScore, 2)} - {data?.interaction?.interactionTypes - ? data?.interaction?.interactionTypes?.map((attribute: any) => { + {interactionData?.interactionTypes + ? interactionData?.interactionTypes?.map((attribute: any) => { return ( { - {data?.interaction?.publications.length - ? data?.interaction?.publications?.map( + {interactionData?.publications.length + ? interactionData?.publications?.map( (pmid: any, index: number) => { return ( @@ -123,8 +129,8 @@ export const InteractionRecord: React.FC = () => {
- {data?.interaction?.sources.length - ? data?.interaction?.sources?.map( + {interactionData?.sources.length + ? interactionData?.sources?.map( (source: any, index: number) => { return ( @@ -143,97 +149,102 @@ export const InteractionRecord: React.FC = () => { }, ]; - return ( - data && ( - - - - - {data?.interaction?.drug?.name} - {' '} - {' '} - - {data?.interaction?.gene?.name} - - + return interactionExists ? ( + + + + + {interactionData?.drug?.name} + {' '} + {' '} + + {interactionData?.gene?.name} + - - - {sectionsMap.map((section) => { - return ( - - } - > -

- {section.name} -

-
- - {section.sectionContent} - -
- ); - })} -
- - - } - > -

- Interaction Attributes -

-
- -
- - {data?.interaction?.interactionAttributes.length - ? data?.interaction?.interactionAttributes?.map( - (attribute: any) => { - return ( - - - {attribute.name}: - - - {attribute.value} - - - ); - } - ) - : noData} - -
- - -
+ + + + {sectionsMap.map((section) => { + return ( + + } + > +

+ {section.name} +

+
+ + {section.sectionContent} + +
+ ); + })} +
+ + + } + > +

+ Interaction Attributes +

+
+ + + + {interactionData?.interactionAttributes.length + ? interactionData?.interactionAttributes?.map( + (attribute: any) => { + return ( + + + {attribute.name}: + + + {attribute.value} + + + ); + } + ) + : noData} + +
+
+
- ) + + ) : ( + + + We could not find any results for this interaction. + + + ); }; diff --git a/client/src/components/Layout/MainLayout.scss b/client/src/components/Layout/MainLayout.scss index cc05fcde..754399e2 100644 --- a/client/src/components/Layout/MainLayout.scss +++ b/client/src/components/Layout/MainLayout.scss @@ -18,6 +18,7 @@ body { background-color: var(--background-light); color: var(--text-content); min-height: 100vh; + position: relative; .content-container { background-color: var(--background-light); @@ -25,10 +26,13 @@ body { flex-direction: column; align-items: stretch; padding: 20px; + padding-bottom: 75px; + min-height: 100%; } .content { background-color: var(--background); + min-height: 75vh; } } @@ -117,6 +121,8 @@ footer { font-size: 20px; font-family: 'Work Sans'; font-weight: 300; + position: absolute; + bottom: 0; } .ant-tabs { diff --git a/client/src/components/Shared/NotFoundError/NotFoundError.scss b/client/src/components/Shared/NotFoundError/NotFoundError.scss new file mode 100644 index 00000000..ced501cd --- /dev/null +++ b/client/src/components/Shared/NotFoundError/NotFoundError.scss @@ -0,0 +1,7 @@ +.not-found-404 { + object-fit: contain; + height: 50%; + width: 50%; + margin: auto; + margin-top: 50px; +} diff --git a/client/src/components/Shared/NotFoundError/NotFoundError.tsx b/client/src/components/Shared/NotFoundError/NotFoundError.tsx new file mode 100644 index 00000000..3b53952a --- /dev/null +++ b/client/src/components/Shared/NotFoundError/NotFoundError.tsx @@ -0,0 +1,14 @@ +import { Box } from '@mui/material'; +import './NotFoundError.scss'; + +export const NotFoundError: React.FC = () => { + return ( + + 404 error + + ); +}; diff --git a/client/src/components/Shared/ReleaseInformation/ReleaseInformation.scss b/client/src/components/Shared/ReleaseInformation/ReleaseInformation.scss index cb4174c8..c31e736f 100644 --- a/client/src/components/Shared/ReleaseInformation/ReleaseInformation.scss +++ b/client/src/components/Shared/ReleaseInformation/ReleaseInformation.scss @@ -5,4 +5,4 @@ color: white; text-decoration: underline; } -} \ No newline at end of file +} diff --git a/client/src/pages/Playground/Playground.scss b/client/src/pages/API/API.scss similarity index 54% rename from client/src/pages/Playground/Playground.scss rename to client/src/pages/API/API.scss index 199750ef..62e78171 100644 --- a/client/src/pages/Playground/Playground.scss +++ b/client/src/pages/API/API.scss @@ -1,3 +1,24 @@ +.api-page-header { + font-size: 36px; + margin-bottom: 15px; +} + +.api-info-container { + padding: 20px; + p { + margin-bottom: 15px; + code { + color: #c7254e; + } + } +} + +.playground-page-header { + padding-left: 20px; + font-size: 36px; + margin-bottom: 15px; +} + .playground-page-container { background-color: var(--background); display: flex; diff --git a/client/src/pages/Playground/Playground.tsx b/client/src/pages/API/API.tsx similarity index 81% rename from client/src/pages/Playground/Playground.tsx rename to client/src/pages/API/API.tsx index 5024497a..c1256292 100644 --- a/client/src/pages/Playground/Playground.tsx +++ b/client/src/pages/API/API.tsx @@ -1,6 +1,6 @@ // hooks/dependencies import { useState } from 'react'; -import './Playground.scss'; +import './API.scss'; import { API_URL } from 'config'; // graphiql @@ -185,7 +185,7 @@ const query6 = ` const fetcher = createGraphiQLFetcher({ url: API_URL ?? '' }); -export const Playground = () => { +export const API = () => { const [isCopied, setIsCopied] = useState(false); const onCopyText = () => { @@ -339,37 +339,55 @@ export const Playground = () => { ]; return ( -
-
- {sectionsMap.map((section) => { - return ( - - } - > -
- {section.header} -
-
- - {section.sectionContent} - -
- ); - })} +
+
+
API Documentation
+

+ The DGIdb API can be used to query for drug-gene interactions in your + own applications. +

+

+ To query the API, make GraphQL queries to:{' '} + https://dgidb.org/api/graphql +

+

+ For examples and to experiment with API requests in your browser, + refer to the Playground below. +

-
- +
Playground
+
+
+ {sectionsMap.map((section) => { + return ( + + } + > +
+ {section.header} +
+
+ + {section.sectionContent} + +
+ ); + })} +
+
+ +
); diff --git a/client/src/pages/API/index.ts b/client/src/pages/API/index.ts new file mode 100644 index 00000000..6e432e7c --- /dev/null +++ b/client/src/pages/API/index.ts @@ -0,0 +1 @@ +export * from './API'; diff --git a/client/src/pages/Playground/index.ts b/client/src/pages/Playground/index.ts deleted file mode 100644 index 469667af..00000000 --- a/client/src/pages/Playground/index.ts +++ /dev/null @@ -1 +0,0 @@ -export * from './Playground'; diff --git a/client/src/routes/public.tsx b/client/src/routes/public.tsx index be874b60..4cb6c843 100644 --- a/client/src/routes/public.tsx +++ b/client/src/routes/public.tsx @@ -11,7 +11,7 @@ import { DrugRecord } from 'components/Drug/DrugRecord'; import { MainLayout } from 'components/Layout'; import { About } from 'pages/About'; import { Downloads } from 'pages/Downloads'; -import { Playground } from 'pages/Playground'; +import { API } from 'pages/API'; import { InteractionRecord } from 'components/Interaction/InteractionRecord'; const App = () => { @@ -91,7 +91,7 @@ export const Routes = () => { { path: '/browse/sources', element: }, { path: '/about', element: }, { path: '/downloads', element: }, - { path: '/api', element: }, + { path: '/api', element: }, { path: '/', element: }, { path: '*', element: }, ],