Skip to content

Commit

Permalink
Dynamically show CMO or DMP Patient ID as title for Patient Samples view
Browse files Browse the repository at this point in the history
  • Loading branch information
qu8n authored and ao508 committed Jul 23, 2024
1 parent d57b742 commit 8efc9ac
Show file tree
Hide file tree
Showing 14 changed files with 284 additions and 188 deletions.
13 changes: 8 additions & 5 deletions frontend/src/components/RecordsList.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ import { Button, Container, Modal } from "react-bootstrap";
import { Dispatch, SetStateAction, useCallback, useMemo, useRef } from "react";
import { useNavigate } from "react-router-dom";
import { DownloadModal } from "./DownloadModal";
import { buildTsvString } from "../utils/buildTsvString";
import { buildTsvString } from "../utils/stringBuilders";
import { AgGridReact } from "ag-grid-react";
import { useState } from "react";
import styles from "./records.module.scss";
Expand All @@ -26,6 +26,8 @@ import {
import { PatientIdsTriplet } from "../pages/patients/PatientsPage";
import { ErrorMessage, LoadingSpinner, Toolbar } from "../shared/tableElements";
import { AgGridReact as AgGridReactType } from "ag-grid-react/lib/agGridReact";
import { BreadCrumb } from "../shared/components/BreadCrumb";
import { PageHeader } from "../shared/components/PageHeader";

interface IRecordsListProps {
colDefs: ColDef[];
Expand All @@ -50,7 +52,7 @@ interface IRecordsListProps {
showDownloadModal: boolean;
setShowDownloadModal: Dispatch<SetStateAction<boolean>>;
handleDownload: () => void;
samplesQueryParam: string | undefined;
samplesQueryParam: string | undefined | any; // TODO
prepareSamplesDataForAgGrid?: (samples: Sample[]) => any[];
samplesColDefs: ColDef[];
samplesParentWhereVariables: SampleWhere;
Expand Down Expand Up @@ -189,6 +191,9 @@ export default function RecordsList({

return (
<Container fluid>
<BreadCrumb currPageTitle={dataName} />
<PageHeader title={dataName} />

{showDownloadModal && (
<DownloadModal
loader={async () => {
Expand Down Expand Up @@ -261,9 +266,7 @@ export default function RecordsList({
<AutoSizer>
{({ height, width }) => (
<Modal show={true} dialogClassName="modal-90w" onHide={handleClose}>
<Modal.Header closeButton>
<Modal.Title>{`Viewing ${samplesQueryParam}`}</Modal.Title>
</Modal.Header>
<Modal.Header closeButton />
<Modal.Body>
<div className={styles.popupHeight}>
<SamplesList
Expand Down
43 changes: 36 additions & 7 deletions frontend/src/components/SamplesList.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -5,16 +5,17 @@ import {
useFindSamplesByInputValueQuery,
} from "../generated/graphql";
import AutoSizer from "react-virtualized-auto-sizer";
import { Button, Col } from "react-bootstrap";
import { Dispatch, SetStateAction, useEffect, useRef } from "react";
import { Button, Col, Container } from "react-bootstrap";
import { Dispatch, SetStateAction, useEffect, useMemo, useRef } from "react";
import { DownloadModal } from "./DownloadModal";
import { UpdateModal } from "./UpdateModal";
import { AlertModal } from "./AlertModal";
import { buildTsvString } from "../utils/buildTsvString";
import { buildTsvString } from "../utils/stringBuilders";
import {
SampleChange,
SampleMetadataExtended,
defaultColDef,
getSamplePopupParamId,
handleSearch,
isValidCostCenter,
} from "../shared/helpers";
Expand All @@ -29,6 +30,9 @@ import { ErrorMessage, LoadingSpinner, Toolbar } from "../shared/tableElements";
import styles from "./records.module.scss";
import { getUserEmail } from "../utils/getUserEmail";
import { openLoginPopup } from "../utils/openLoginPopup";
import { PageHeader } from "../shared/components/PageHeader";
import { BreadCrumb } from "../shared/components/BreadCrumb";
import { useParams } from "react-router-dom";

const POLLING_INTERVAL = 2000;
const max_rows = 500;
Expand Down Expand Up @@ -105,6 +109,7 @@ export default function SamplesList({
const [rowCount, setRowCount] = useState(0);

const gridRef = useRef<AgGridReactType>(null);
const params = useParams();

useEffect(() => {
gridRef.current?.api?.showLoadingOverlay();
Expand All @@ -123,12 +128,23 @@ export default function SamplesList({
setRowCount(data?.samplesConnection.edges.length || 0);
}, [data]);

const samples = data?.samplesConnection?.edges.map((e) => e.node) as Sample[];

const popupPageHeader = useMemo(() => {
if (parentWhereVariables && samples && params) {
return getSamplePopupParamId(
parentWhereVariables,
samples,
Object.values(params)?.[0]!
);
}
return undefined;
}, [parentWhereVariables, params, samples]);

if (loading) return <LoadingSpinner />;

if (error) return <ErrorMessage error={error} />;

const samples = data!.samplesConnection.edges.map((e) => e.node) as Sample[];

async function onCellValueChanged(params: CellValueChangedEvent) {
if (!editMode) return;

Expand Down Expand Up @@ -243,6 +259,13 @@ export default function SamplesList({

return (
<>
<Container fluid>
{!parentWhereVariables && <BreadCrumb currPageTitle="samples" />}
<PageHeader
title={[popupPageHeader, "samples"].filter(Boolean).join(" ")}
/>
</Container>

{showDownloadModal && (
<DownloadModal
loader={() => {
Expand All @@ -253,7 +276,9 @@ export default function SamplesList({
onComplete={() => {
setShowDownloadModal(false);
}}
exportFileName={exportFileName || "samples.tsv"}
exportFileName={[popupPageHeader, "samples.tsv"]
.filter(Boolean)
.join("_")}
/>
)}

Expand Down Expand Up @@ -323,7 +348,11 @@ export default function SamplesList({
<AutoSizer>
{({ width }) => (
<div
className={`ag-theme-alpine ${styles.tableHeight}`}
className={`ag-theme-alpine ${
parentWhereVariables
? styles.popupTableHeight
: styles.tableHeight
}`}
style={{ width: width }}
>
<AgGridReact<SampleMetadataExtended>
Expand Down
4 changes: 4 additions & 0 deletions frontend/src/components/records.module.scss
Original file line number Diff line number Diff line change
Expand Up @@ -17,3 +17,7 @@
.popupHeight {
height: calc(100vh - 180px);
}

.popupTableHeight {
height: calc(100vh - 270px);
}
18 changes: 17 additions & 1 deletion frontend/src/generated/graphql.ts
Original file line number Diff line number Diff line change
Expand Up @@ -12431,7 +12431,17 @@ export type FindSamplesByInputValueQuery = {
__typename?: "SamplePatientsHasSampleConnection";
edges: Array<{
__typename?: "SamplePatientsHasSampleRelationship";
node: { __typename?: "Patient"; smilePatientId: string };
node: {
__typename?: "Patient";
smilePatientId: string;
cmoPatientId?: string | null;
dmpPatientId?: string | null;
patientAliasesIsAlias: Array<{
__typename?: "PatientAlias";
namespace: string;
value: string;
}>;
};
}>;
};
cohortsHasCohortSampleConnection: {
Expand Down Expand Up @@ -12988,6 +12998,12 @@ export const FindSamplesByInputValueDocument = gql`
edges {
node {
smilePatientId
cmoPatientId
dmpPatientId
patientAliasesIsAlias {
namespace
value
}
}
}
}
Expand Down
105 changes: 50 additions & 55 deletions frontend/src/pages/cohorts/CohortsPage.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,6 @@ import {
} from "../../shared/helpers";
import RecordsList from "../../components/RecordsList";
import { useParams } from "react-router-dom";
import { PageHeader } from "../../shared/components/PageHeader";

function cohortFilterWhereVariables(parsedSearchVals: string[]): CohortWhere[] {
if (parsedSearchVals.length > 1) {
Expand Down Expand Up @@ -147,61 +146,57 @@ export default function CohortsPage({
const defaultSort = [{ initialCohortDeliveryDate: SortDirection.Desc }];

return (
<>
<PageHeader dataName={dataName} />

<RecordsList
colDefs={CohortsListColumns}
dataName={dataName}
enableInfiniteScroll={false}
lazyRecordsQuery={useCohortsListLazyQuery}
lazyRecordsQueryAddlVariables={
{
hasCohortCompleteCohortCompletesOptions2: {
sort: [{ date: SortDirection.Desc }],
},
} as CohortCompleteOptions
}
prepareDataForAgGrid={prepareCohortDataForAgGrid}
queryFilterWhereVariables={cohortFilterWhereVariables}
defaultSort={defaultSort}
userSearchVal={userSearchVal}
setUserSearchVal={setUserSearchVal}
parsedSearchVals={parsedSearchVals}
setParsedSearchVals={setParsedSearchVals}
handleSearch={() => handleSearch(userSearchVal, setParsedSearchVals)}
showDownloadModal={showDownloadModal}
setShowDownloadModal={setShowDownloadModal}
handleDownload={() => setShowDownloadModal(true)}
samplesColDefs={CohortSampleDetailsColumns}
samplesQueryParam={
sampleQueryParamValue &&
`${sampleQueryParamHeaderName} ${sampleQueryParamValue}`
}
prepareSamplesDataForAgGrid={prepareSampleCohortDataForAgGrid}
samplesParentWhereVariables={
{
cohortsHasCohortSampleConnection_SOME: {
node: {
[sampleQueryParamFieldName]: sampleQueryParamValue,
},
<RecordsList
colDefs={CohortsListColumns}
dataName={dataName}
enableInfiniteScroll={false}
lazyRecordsQuery={useCohortsListLazyQuery}
lazyRecordsQueryAddlVariables={
{
hasCohortCompleteCohortCompletesOptions2: {
sort: [{ date: SortDirection.Desc }],
},
} as CohortCompleteOptions
}
prepareDataForAgGrid={prepareCohortDataForAgGrid}
queryFilterWhereVariables={cohortFilterWhereVariables}
defaultSort={defaultSort}
userSearchVal={userSearchVal}
setUserSearchVal={setUserSearchVal}
parsedSearchVals={parsedSearchVals}
setParsedSearchVals={setParsedSearchVals}
handleSearch={() => handleSearch(userSearchVal, setParsedSearchVals)}
showDownloadModal={showDownloadModal}
setShowDownloadModal={setShowDownloadModal}
handleDownload={() => setShowDownloadModal(true)}
samplesColDefs={CohortSampleDetailsColumns}
samplesQueryParam={
sampleQueryParamValue &&
`${sampleQueryParamHeaderName} ${sampleQueryParamValue}`
}
prepareSamplesDataForAgGrid={prepareSampleCohortDataForAgGrid}
samplesParentWhereVariables={
{
cohortsHasCohortSampleConnection_SOME: {
node: {
[sampleQueryParamFieldName]: sampleQueryParamValue,
},
} as SampleWhere
}
samplesRefetchWhereVariables={(samplesParsedSearchVals) => {
return {
cohortsHasCohortSampleConnection_SOME: {
node: {
[sampleQueryParamFieldName]: sampleQueryParamValue,
},
},
} as SampleWhere
}
samplesRefetchWhereVariables={(samplesParsedSearchVals) => {
return {
cohortsHasCohortSampleConnection_SOME: {
node: {
[sampleQueryParamFieldName]: sampleQueryParamValue,
},
OR: cohortSampleFilterWhereVariables(samplesParsedSearchVals),
} as SampleWhere;
}}
sampleKeyForUpdate={sampleKeyForUpdate}
userEmail={userEmail}
setUserEmail={setUserEmail}
/>
</>
},
OR: cohortSampleFilterWhereVariables(samplesParsedSearchVals),
} as SampleWhere;
}}
sampleKeyForUpdate={sampleKeyForUpdate}
userEmail={userEmail}
setUserEmail={setUserEmail}
/>
);
}
9 changes: 5 additions & 4 deletions frontend/src/pages/patients/PatientsPage.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,6 @@ import {
import { Dispatch, SetStateAction, useEffect, useMemo, useState } from "react";
import RecordsList from "../../components/RecordsList";
import { useParams } from "react-router-dom";
import { PageHeader } from "../../shared/components/PageHeader";
import { Col, Form } from "react-bootstrap";
import { AlertModal } from "../../components/AlertModal";
import { Tooltip } from "@material-ui/core";
Expand Down Expand Up @@ -241,12 +240,11 @@ export default function PatientsPage({

const dataName = "patients";
const sampleQueryParamFieldName = "smilePatientId";
const sampleQueryParamHeaderName = "Patient";
const sampleQueryParamValue = params[sampleQueryParamFieldName];

return (
<>
<PageHeader dataName={dataName} />

<RecordsList
colDefs={ActivePatientsListColumns}
dataName={dataName}
Expand All @@ -269,7 +267,10 @@ export default function PatientsPage({
setShowDownloadModal(true);
}}
samplesColDefs={SampleMetadataDetailsColumns}
samplesQueryParam={sampleQueryParamValue && "Patient"}
samplesQueryParam={
sampleQueryParamValue &&
`${sampleQueryParamHeaderName} ${sampleQueryParamValue}`
}
samplesParentWhereVariables={
{
OR: [
Expand Down
Loading

0 comments on commit 8efc9ac

Please sign in to comment.