Skip to content

Commit

Permalink
added patient similarity tab and basic patient table
Browse files Browse the repository at this point in the history
  • Loading branch information
MaDoeb committed Oct 2, 2024
1 parent 0b3ef12 commit 0ab3558
Show file tree
Hide file tree
Showing 6 changed files with 498 additions and 20 deletions.
29 changes: 27 additions & 2 deletions src/pages/patientView/PatientViewPage.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -317,12 +317,37 @@ export class PatientViewPageInner extends React.Component<

@computed
public get shouldShowMtbTab(): boolean {
return true;
return (
this.pageStore.mutationData.isComplete &&
this.pageStore.discreteCNAData.isComplete &&
(this.pageStore.oncoKbData.isComplete ||
this.pageStore.oncoKbData.isError) &&
(this.pageStore.mtbs.isComplete || this.pageStore.mtbs.isError) &&
(this.pageStore.cnaOncoKbData.isComplete ||
this.pageStore.cnaOncoKbData.isError)
);
}

@computed
public get shouldShowFollowUpTab(): boolean {
return true;
return (
this.pageStore.mutationData.isComplete &&
this.pageStore.followUps.isComplete &&
this.pageStore.discreteCNAData.isComplete &&
(this.pageStore.oncoKbData.isComplete ||
this.pageStore.oncoKbData.isError) &&
(this.pageStore.mtbs.isComplete || this.pageStore.mtbs.isError) &&
(this.pageStore.cnaOncoKbData.isComplete ||
this.pageStore.cnaOncoKbData.isError)
);
}

@computed
public get shouldShowPatientSimilarity(): boolean {
return (
//this.pageStore.similarPatientsPage.isComplete
true
);
}

@autobind
Expand Down
35 changes: 18 additions & 17 deletions src/pages/patientView/PatientViewPageTabs.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,8 @@ import SampleManager from 'pages/patientView/SampleManager';
import PatientViewPage from 'pages/patientView/PatientViewPage';
import PatientViewUrlWrapper from 'pages/patientView/PatientViewUrlWrapper';
import { ClinicalTrialMatchTable } from './clinicalTrialMatch/ClinicalTrialMatchTable';
//import { PatientSimilarityTable } from './patientSimilarity/patientSimilarityTable'
import PatientSimilarityTable from './patientSimilarity/patientSimilarityTable';
import MtbTable from './therapyRecommendation/MtbTable';
import { CompactVAFPlot } from 'pages/patientView/genomicOverview/CompactVAFPlot';
import {
Expand Down Expand Up @@ -55,6 +57,7 @@ export enum PatientViewPageTabs {
Mtb = 'mtb',
FollowUp = 'followUp',
ClinicalTrialsGov = 'clinicaltrialsGov',
PatientSimilarity = 'patientSimilarity',
}

export const PatientViewResourceTabPrefix = 'openResource_';
Expand Down Expand Up @@ -651,14 +654,6 @@ export function tabs(
);

pageComponent.shouldShowMtbTab &&
pageComponent.patientViewPageStore.mutationData.isComplete &&
pageComponent.patientViewPageStore.discreteCNAData.isComplete &&
(pageComponent.patientViewPageStore.oncoKbData.isComplete ||
pageComponent.patientViewPageStore.oncoKbData.isError) &&
(pageComponent.patientViewPageStore.mtbs.isComplete ||
pageComponent.patientViewPageStore.mtbs.isError) &&
(pageComponent.patientViewPageStore.cnaOncoKbData.isComplete ||
pageComponent.patientViewPageStore.cnaOncoKbData.isError) &&
tabs.push(
<MSKTab
key={42}
Expand Down Expand Up @@ -727,15 +722,6 @@ export function tabs(
);

pageComponent.shouldShowFollowUpTab &&
pageComponent.patientViewPageStore.mutationData.isComplete &&
pageComponent.patientViewPageStore.followUps.isComplete &&
pageComponent.patientViewPageStore.discreteCNAData.isComplete &&
(pageComponent.patientViewPageStore.oncoKbData.isComplete ||
pageComponent.patientViewPageStore.oncoKbData.isError) &&
(pageComponent.patientViewPageStore.mtbs.isComplete ||
pageComponent.patientViewPageStore.mtbs.isError) &&
(pageComponent.patientViewPageStore.cnaOncoKbData.isComplete ||
pageComponent.patientViewPageStore.cnaOncoKbData.isError) &&
tabs.push(
<MSKTab
key={44}
Expand Down Expand Up @@ -876,6 +862,21 @@ export function tabs(
</MSKTab>
);

pageComponent.shouldShowPatientSimilarity &&
tabs.push(
<MSKTab
key={70}
id={PatientViewPageTabs.PatientSimilarity}
linkText="Patient similarity"
unmountOnHide={false}
>
<h1>HELLO WORLD</h1>
<PatientSimilarityTable
store={pageComponent.patientViewPageStore}
/>
</MSKTab>
);

pageComponent.resourceTabs.component &&
/* @ts-ignore */
tabs.push(...pageComponent.resourceTabs.component);
Expand Down
36 changes: 36 additions & 0 deletions src/pages/patientView/clinicalInformation/PatientViewPageStore.ts
Original file line number Diff line number Diff line change
Expand Up @@ -250,6 +250,7 @@ import {
import { RecruitingStatus } from 'shared/enums/ClinicalTrialsGovRecruitingStatus';
import { ageAsNumber } from '../clinicalTrialMatch/utils/AgeSexConverter';
import { City } from '../clinicalTrialMatch/ClinicalTrialMatchSelectUtil';
import { SimilarPatient } from 'shared/api/SimilarPatientsAPI';

type PageMode = 'patient' | 'sample';
type ResourceId = string;
Expand Down Expand Up @@ -3498,4 +3499,39 @@ export class PatientViewPageStore {
default: {},
onError: () => {},
});

////fetchTest()
//readonly getPatients = remoteData({
// invoke: async () => {
// var result: Patient[] = []
// (await fetchPatients()).map((x) => {
// result.push(x.uniquePatientKey)
// });
// return result
// },
// default: []
//});
//
//
//readonly similarPatientsPage = remoteData<SimilarPatient[]>({
// await: () => [this.getPatientIds],
// invoke: async () => {
// var result: SimilarPatient[] = [];
//
//
// console.group('### TEST ###');
// console.log(this.getPatientIds.result)
// console.groupEnd();
//
// for (const patientId of this.getPatientIds.result) {
// //fetchClinicalDataForPatient
// result.push({
// id: patientId
// })
// }
//
//
// return result
// }
//})
}
213 changes: 213 additions & 0 deletions src/pages/patientView/patientSimilarity/patientSimilarityTable.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,213 @@
import * as React from 'react';
import { observable } from 'mobx';
import { PatientViewPageStore } from '../clinicalInformation/PatientViewPageStore';
import { observer } from 'mobx-react';
import { Link } from 'react-router-dom';
import { Collapse } from 'react-bootstrap';
import LazyMobXTable from '../../../shared/components/lazyMobXTable/LazyMobXTable';
import LoadingIndicator from 'shared/components/loadingIndicator/LoadingIndicator';
import { DefaultTooltip } from 'cbioportal-frontend-commons';
import { Button } from 'react-bootstrap';
import { IClinicalTrial } from 'cbioportal-utils';
import {
SimilarPatient,
fetchPatientsPage,
} from 'shared/api/SimilarPatientsAPI';
import { getServerConfig } from 'config/config';

import { remoteData } from 'cbioportal-frontend-commons';
import { sleep } from 'shared/lib/TimeUtils';

enum ColumnKey {
//patient_id: string;
//study_id: string;
//age: number;
//gender: string;
//name: string;
//cancertype: string;
STUDY = 'study',
NAME = 'name',
AGE = 'age',
GENDER = 'gender',
CANCERTYPE = 'cancertype',
}

interface PatientSimilarityProps {
store: PatientViewPageStore;
}

class SimilarPatientEntry {
private id;
constructor(id: string) {
this.id = id;
}
get_id(): string {
return this.id;
}
}

class SimilarPatientTableComponent extends LazyMobXTable<SimilarPatient> {}

//@observer
//export class PatientSimilarityTable extends React.Component<
// PatientSimilarityProps,
// {}
//> {
// private readonly ENTRIES_PER_PAGE = 10;
// private _columns = [
// {
// name: ColumnKey.PATIENTID,
// render: (patient: SimilarPatient) => (
// <div>
// {patient.id}
// </div>
// ),
// width: 250,
// resizable: true,
// },
// ];
//
// @observable
// patients: SimilarPatientEntry[] = [];
//
// constructor(props: PatientSimilarityProps) {
// super(props);
// this.state = {
//
// };
// }
//
// private current_page = 0;
//
// render() {
// return (
// <div>
// <div style={{ padding: '3px' }}>
// <Button
// type="button"
// className={'btn btn-default'}
// >
// TEST
// </Button>
// </div>
// <div>
// <SimilarPatientTableComponent
// showCopyDownload={false}
// data={this.props.store.similarPatientsPage.result} //
// columns={this._columns}
// initialItemsPerPage={this.ENTRIES_PER_PAGE}
// />
// </div>
// </div>
// );
// }
//}

const PatientSimilarityTable = (props: PatientSimilarityProps) => {
const [currentPage, setCurrentPage] = React.useState(0);
const [perPage, setPerPage] = React.useState(1);
const [totalPages, setTotalPages] = React.useState(2);
const [patients, setPatients] = React.useState<SimilarPatient[]>([]);

const _columns = [
{
name: ColumnKey.STUDY,
render: (patient: SimilarPatient) => <div>{patient.study_id}</div>,
width: 250,
resizable: true,
},
{
name: ColumnKey.NAME,
render: (patient: SimilarPatient) => <div>{patient.name}</div>,
width: 250,
resizable: true,
},
{
name: ColumnKey.AGE,
render: (patient: SimilarPatient) => <div>{patient.age}</div>,
width: 250,
resizable: true,
},
{
name: ColumnKey.GENDER,
render: (patient: SimilarPatient) => <div>{patient.gender}</div>,
width: 250,
resizable: true,
},
{
name: ColumnKey.CANCERTYPE,
render: (patient: SimilarPatient) => (
<div>{patient.cancertype}</div>
),
width: 250,
resizable: true,
},
];

React.useEffect(() => {
function sleep(ms: number) {
return new Promise(resolve => setTimeout(resolve, ms));
}

// fetch data
(async function() {
try {
const { patients, totalPages } = await fetchPatientsPage(
currentPage,
perPage
);
await sleep(50); // sometimes the re-render would not be triggered when fetch was too fast... any ideas why this happens?

//console.group('### TEST RELOAD PATIENTS ###');
//console.log(patients)
//console.groupEnd();

setPatients(patients);
setTotalPages(totalPages);
} catch (error) {
console.error('Error fetching data:', error);
}
})();
}, [currentPage, perPage]);

const handlePrevPage = () => {
if (currentPage > 0) {
setCurrentPage(currentPage - 1);
}
};

const handleNextPage = () => {
if (currentPage < totalPages) {
setCurrentPage(currentPage + 1);
}
};

return (
<div>
{/* Display table */}
<div>{currentPage}</div>
<div>{JSON.stringify(patients)}</div>
<SimilarPatientTableComponent
showCopyDownload={false}
data={patients} //
columns={_columns}
initialItemsPerPage={perPage}
showFilter={false}
showPagination={false}
/>

{/* Pagination controls */}
<button onClick={handlePrevPage} disabled={currentPage === 0}>
Previous Page
</button>
<button
onClick={handleNextPage}
disabled={currentPage === totalPages - 1}
>
Next Page
</button>
</div>
);
};

export default PatientSimilarityTable;
Loading

0 comments on commit 0ab3558

Please sign in to comment.