Skip to content

Commit

Permalink
Add initial Patient details modal
Browse files Browse the repository at this point in the history
  • Loading branch information
lbeckman314 committed Jun 14, 2024
1 parent 7e41bdc commit 3e84dca
Show file tree
Hide file tree
Showing 3 changed files with 160 additions and 5 deletions.
10 changes: 5 additions & 5 deletions packages/sampleCommons/config/aced/explorer.json
Original file line number Diff line number Diff line change
Expand Up @@ -27,10 +27,10 @@
"table": {
"enabled": true,
"detailsConfig": {
"panel": "default",
"panel": "patientDetails",
"mode" : "click",
"idField": "submitter_id",
"title": "Details"
"idField": "id",
"title": "Patient Details"
},
"fields": [
"id",
Expand Down Expand Up @@ -86,10 +86,10 @@
"detailsConfig": {
"panel": "fileDetails",
"mode": "click",
"idField": "file_name",
"idField": "id",
"title": "File Details"
},
"fields": ["project_id", "file_name", "object_id", "subject"],
"fields": ["id", "project_id", "file_name", "object_id", "subject"],
"columns": {
"id": {
"title": "id",
Expand Down
153 changes: 153 additions & 0 deletions packages/sampleCommons/src/lib/CohortBuilder/PatientDetailsPanel.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,153 @@
import {
Anchor,
Group,
LoadingOverlay,
Stack,
Table,
Text,
CopyButton,
ActionIcon,
Tooltip,
Button,
} from '@mantine/core';
import { useGeneralGQLQuery, GEN3_FENCE_API } from '@gen3/core';
import {
ErrorCard,
type TableDetailsPanelProps,
ExplorerTableDetailsPanelFactory,
} from '@gen3/frontend';
import {
MdContentCopy as IconCopy,
MdCheck as IconCheck,
} from 'react-icons/md';

// a definition of the query response
interface QueryResponse {
data?: Record<string, Array<any>>;
}

/**
* Checks if the given object is a QueryResponse.
*
* @param {any} obj - The object to be checked.
* @returns {boolean} Returns true if the object is a QueryResponse, false otherwise.
*/
const isQueryResponse = (obj: any): obj is QueryResponse => {
// Considering that the data property can be optional
return (
typeof obj === 'object' &&
(obj.data === undefined || typeof obj.data === 'object')
);
};

const extractData = (
data: QueryResponse,
index: string,
): Record<string, any> => {
if (data === undefined || data === null) return {};
if (data.data === undefined || data.data === null) return {};

return Array.isArray(data.data[index]) && data.data[index].length > 0
? data.data[index][0]
: {};
};

export const PatientDetailsPanel = ({
id,
index,
tableConfig,
onClose,
}: TableDetailsPanelProps) => {
//const [queryGuppy, { data, isLoading, isError }] = useLazyGeneralGQLQuery();
const idField = tableConfig.detailsConfig?.idField;
const { data, isLoading, isError } = useGeneralGQLQuery({
query: `query ($filter: JSON) {
${index} (filter: $filter, accessibility: all) {
${tableConfig.fields}
}
}`,
variables: {
filter: {
AND: [
{
IN: {
[idField ?? 0]: [id],
},
},
],
},
},
});

if (!idField || idField === null) {
return (
<ErrorCard message={'idField not configure in Tables Details Config'} />
);
}

if (isError) {
return <ErrorCard message={'Error occurred while fetching data'} />;
}

const queryData = isQueryResponse(data) ? extractData(data, index) : {};

const rows = Object.entries(queryData).map(([field, value]) => (
<tr key={field}>
<td>
<Text weight="bold">{field}</Text>
</td>
<td>
{field === 'object_id' ? (
<Anchor
href={`${GEN3_FENCE_API}/user/data/download/${
value ? (value as string) : ''
}?redirect=true`}
target="_blank"
>
{value ? (value as string) : ''}
</Anchor>
) : (
<Text>{value ? (value as string) : ''}</Text>
)}
</td>
</tr>
));
return (
<Stack>
<LoadingOverlay visible={isLoading} />
<Text color="primary.4">Results for {id}</Text>
<Table withBorder withColumnBorders>
<thead>
<tr>
<th>Field</th>
<th>Value</th>
</tr>
</thead>
<tbody>{rows}</tbody>
</Table>
<Group position="right">
<CopyButton value={JSON.stringify(queryData)} timeout={2000}>
{({ copied, copy }) => (
<Tooltip
label={copied ? 'Copied' : 'Copy'}
withArrow
position="right"
>
<ActionIcon color={copied ? 'accent.4' : 'gray'} onClick={copy}>
{copied ? <IconCheck size="1rem" /> : <IconCopy size="1rem" />}
</ActionIcon>
</Tooltip>
)}
</CopyButton>
<Button onClick={() => onClose && onClose(id)}>Close</Button>
</Group>
</Stack>
);
};

export const registerCustomExplorerPatientDetailsPanels = () => {
ExplorerTableDetailsPanelFactory().registerRendererCatalog({
// NOTE: The catalog name must be tableDetails
tableDetails: { patientDetails: PatientDetailsPanel }, // TODO: add simpler registration function that ensures the catalog name is tableDetails
});
};
2 changes: 2 additions & 0 deletions packages/sampleCommons/src/pages/Explorer.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -5,9 +5,11 @@ import {

import { registerCohortTableCustomCellRenderers } from '@/lib/CohortBuilder/CustomCellRenderers';
import { registerCustomExplorerDetailsPanels } from '@/lib/CohortBuilder/FileDetailsPanel';
import { registerCustomExplorerPatientDetailsPanels } from '@/lib/CohortBuilder/PatientDetailsPanel';

registerCohortTableCustomCellRenderers();
registerCustomExplorerDetailsPanels();
registerCustomExplorerPatientDetailsPanels();

export default ExplorerPage;

Expand Down

0 comments on commit 3e84dca

Please sign in to comment.