From f5ba1e651a6119679d131c4033b93fff9f087982 Mon Sep 17 00:00:00 2001 From: Ngoc Nguyen Date: Mon, 30 Sep 2019 12:45:06 +0200 Subject: [PATCH] Added Gene panel column to tables in Patient View --- src/pages/patientView/PatientViewPage.tsx | 1 + .../CopyNumberTableWrapper.tsx | 11 +++ .../mutation/PatientViewMutationTable.tsx | 13 +++- .../mutationTable/MutationTable.tsx | 4 +- .../column/PanelColumnFormatter.spec.tsx | 49 ++++++++++++++ .../column/PanelColumnFormatter.tsx | 67 +++++++++++++++++++ 6 files changed, 143 insertions(+), 2 deletions(-) create mode 100644 src/shared/components/mutationTable/column/PanelColumnFormatter.spec.tsx create mode 100644 src/shared/components/mutationTable/column/PanelColumnFormatter.tsx diff --git a/src/pages/patientView/PatientViewPage.tsx b/src/pages/patientView/PatientViewPage.tsx index ac5fe279361..21d606533fe 100644 --- a/src/pages/patientView/PatientViewPage.tsx +++ b/src/pages/patientView/PatientViewPage.tsx @@ -547,6 +547,7 @@ export default class PatientViewPage extends React.Component ) diff --git a/src/pages/patientView/copyNumberAlterations/CopyNumberTableWrapper.tsx b/src/pages/patientView/copyNumberAlterations/CopyNumberTableWrapper.tsx index 3ca23d6f17c..f679fc4e223 100644 --- a/src/pages/patientView/copyNumberAlterations/CopyNumberTableWrapper.tsx +++ b/src/pages/patientView/copyNumberAlterations/CopyNumberTableWrapper.tsx @@ -21,6 +21,7 @@ import CopyNumberCountCache from "../clinicalInformation/CopyNumberCountCache"; import {ICivicGeneDataWrapper, ICivicVariantDataWrapper} from "shared/model/Civic.ts"; import HeaderIconMenu from '../mutation/HeaderIconMenu'; import GeneFilterMenu, { GeneFilterOption } from '../mutation/GeneFilterMenu'; +import PanelColumnFormatter from "shared/components/mutationTable/column/PanelColumnFormatter"; class CNATableComponent extends LazyMobXTable { @@ -55,6 +56,7 @@ type ICopyNumberTableWrapperProps = { showGeneFilterMenu?:boolean; currentGeneFilter:GeneFilterOption; onFilterGenes?:(option:GeneFilterOption)=>void; + sampleToMutationGenePanelId?: {[sampleId:string]:string}; }; @observer @@ -112,6 +114,15 @@ export default class CopyNumberTableWrapper extends React.Component PanelColumnFormatter.renderFunction(d, this.props.sampleToMutationGenePanelId), + download: (d:DiscreteCopyNumberData[]) => PanelColumnFormatter.download(d, this.props.sampleToMutationGenePanelId), + sortBy: (d:DiscreteCopyNumberData[]) => PanelColumnFormatter.getGenePanelIds(d, this.props.sampleToMutationGenePanelId), + visible: false, + order: 35 + }); columns.push({ name: "CNA", diff --git a/src/pages/patientView/mutation/PatientViewMutationTable.tsx b/src/pages/patientView/mutation/PatientViewMutationTable.tsx index 556438d57f8..350a264b490 100644 --- a/src/pages/patientView/mutation/PatientViewMutationTable.tsx +++ b/src/pages/patientView/mutation/PatientViewMutationTable.tsx @@ -9,6 +9,7 @@ import {Mutation} from "shared/api/generated/CBioPortalAPI"; import AlleleCountColumnFormatter from "shared/components/mutationTable/column/AlleleCountColumnFormatter"; import AlleleFreqColumnFormatter from "./column/AlleleFreqColumnFormatter"; import TumorColumnFormatter from "./column/TumorColumnFormatter"; +import PanelColumnFormatter from "shared/components/mutationTable/column/PanelColumnFormatter"; import {isUncalled} from "shared/lib/MutationUtils"; import TumorAlleleFreqColumnFormatter from "shared/components/mutationTable/column/TumorAlleleFreqColumnFormatter"; import ExonColumnFormatter from "shared/components/mutationTable/column/ExonColumnFormatter"; @@ -66,7 +67,8 @@ export default class PatientViewMutationTable extends MutationTableTumorColumnFormatter.getSortValue(d, this.props.sampleManager), download: (d:Mutation[])=>TumorColumnFormatter.getSample(d), }; + + this._columns[MutationTableColumnType.GENE_PANEL] = { + name: "Gene panel", + render: (d:Mutation[]) => PanelColumnFormatter.renderFunction(d, this.props.sampleToMutationGenePanelId), + download: (d:Mutation[]) => PanelColumnFormatter.download(d, this.props.sampleToMutationGenePanelId), + visible: false, + sortBy: (d:Mutation[]) => PanelColumnFormatter.getGenePanelIds(d, this.props.sampleToMutationGenePanelId) + } // customization for allele count columns @@ -136,6 +146,7 @@ export default class PatientViewMutationTable extends MutationTable&{order?:number, shouldExclude?:()=>boolean}; diff --git a/src/shared/components/mutationTable/column/PanelColumnFormatter.spec.tsx b/src/shared/components/mutationTable/column/PanelColumnFormatter.spec.tsx new file mode 100644 index 00000000000..dc1ae81daf1 --- /dev/null +++ b/src/shared/components/mutationTable/column/PanelColumnFormatter.spec.tsx @@ -0,0 +1,49 @@ +import PanelColumnFormatter from "./PanelColumnFormatter"; +import { shallow } from "enzyme"; +import { assert } from 'chai'; + +const mockData = [ + { + alteration: 1, + entrezGeneId: 1, + gene: { + entrezGeneId: 1, + hugoGeneSymbol: 'test', + geneticEntityId: 1, + type: 'test' + }, + molecularProfileId: 'test', + patientId: 'test', + sampleId: 'sampleId', + studyId: 'test', + uniquePatientKey: 'test', + uniqueSampleKey: 'test', + } +]; + +const mockSampleToMutationGenePanelId = { 'sampleId': 'genePanelId' }; + +describe("PanelColumnFormatter", () => { + it('renders spinner icon if sampleToMutationGenePanelId object is empty', () => { + const PanelColumn = shallow(PanelColumnFormatter.renderFunction(mockData, {})); + assert.isTrue(PanelColumn.find('i.fa-spinner').exists()); + }); + + it('renders gene panel information', () => { + const PanelColumn = shallow(PanelColumnFormatter.renderFunction( + mockData, + mockSampleToMutationGenePanelId + )); + assert.isTrue(PanelColumn.text().includes('genePanelId')); + }); + + it('returns a list of gene panel ids on download', () => { + const genePanelIds = PanelColumnFormatter.download(mockData, mockSampleToMutationGenePanelId); + assert.deepEqual(genePanelIds, ['genePanelId']) + }); + + it('returns a list of gene panel ids on getGenePanelIds', () => { + const genePanelIds = PanelColumnFormatter.getGenePanelIds(mockData, mockSampleToMutationGenePanelId); + assert.deepEqual(genePanelIds, ['genePanelId']) + }) +}) diff --git a/src/shared/components/mutationTable/column/PanelColumnFormatter.tsx b/src/shared/components/mutationTable/column/PanelColumnFormatter.tsx new file mode 100644 index 00000000000..009a710c556 --- /dev/null +++ b/src/shared/components/mutationTable/column/PanelColumnFormatter.tsx @@ -0,0 +1,67 @@ +import * as React from 'react'; +import { + Mutation, + DiscreteCopyNumberData +} from 'shared/api/generated/CBioPortalAPI'; + +interface PanelColumnFormatterProps { + data: Mutation[] | DiscreteCopyNumberData[]; + sampleToMutationGenePanelId: {[sampleId:string]: string} | undefined; +} + +class PanelColumn extends React.Component { + constructor(props: PanelColumnFormatterProps) { + super(props); + } + + render() { + const { data, sampleToMutationGenePanelId } = this.props; + + if (!sampleToMutationGenePanelId) return; + + if (sampleToMutationGenePanelId && !Object.keys(sampleToMutationGenePanelId).length) { + return ; + } + + const genePanelIds: string[] = getGenePanelIds( + data, + sampleToMutationGenePanelId + ); + + return ( +
+
    + {genePanelIds.join(', ')} +
+
+ ); + } +} + +const getGenePanelIds = ( + data: any[], + sampleToMutationGenePanelId: {[sampleId:string]: string} | undefined +) => { + if (sampleToMutationGenePanelId) { + const sampleIds = data.map((datum) => datum.sampleId); + return sampleIds.map((id) => sampleToMutationGenePanelId[id]); + } + return []; +}; + +export default { + renderFunction: ( + data: Mutation[] | DiscreteCopyNumberData[], + sampleToMutationGenePanelId: {[sampleId:string]: string} | undefined + ) => ( + + ), + download: ( + data: Mutation[] | DiscreteCopyNumberData[], + sampleToMutationGenePanelId: {[sampleId:string]: string} | undefined + ) => getGenePanelIds(data, sampleToMutationGenePanelId), + getGenePanelIds +};