diff --git a/src/main/webapp/app/components/PageContainer.tsx b/src/main/webapp/app/components/PageContainer.tsx index 43ee9db7b..6b52726b4 100644 --- a/src/main/webapp/app/components/PageContainer.tsx +++ b/src/main/webapp/app/components/PageContainer.tsx @@ -24,7 +24,7 @@ const PageContainer: React.FunctionComponent<{ windowStore: WindowStore; }> = props => { const genePagePath = parseGenePagePath(props.routing.location.pathname); - const inGenePage = genePagePath.hugoSymbol !== undefined; + const inGenePage = genePagePath.geneticType !== undefined; return (
= props => { @@ -22,20 +23,20 @@ const Category: React.FunctionComponent = props => { style.fontFamily = 'Gotham Bold'; } return ( -
+
{props.title}
- {isNa ? 'NA' : props.content} + {props.content}
); }; const InfoTile: React.FunctionComponent = props => { - return ( -
+ return props.categories.length > 0 ? ( +
{props.title}
{props.categories.map(category => ( @@ -43,6 +44,8 @@ const InfoTile: React.FunctionComponent = props => { ))}
+ ) : ( + <> ); }; diff --git a/src/main/webapp/app/components/infoTile/LoETile.tsx b/src/main/webapp/app/components/infoTile/LoETile.tsx index db196b3a6..f38cb77d2 100644 --- a/src/main/webapp/app/components/infoTile/LoETile.tsx +++ b/src/main/webapp/app/components/infoTile/LoETile.tsx @@ -12,75 +12,88 @@ type LoETile = { highestDiagnosticImplicationLevel?: string | undefined; highestPrognosticImplicationLevel?: string | undefined; highestFdaLevel?: string | undefined; + className?: string; }; const LoETile: React.FunctionComponent = props => { const categories: Category[] = []; - categories.push({ - title: 'Therapeutic', - content: (props.highestSensitiveLevel || props.highestResistanceLevel) && ( -
- {props.highestSensitiveLevel && ( + if (props.highestSensitiveLevel || props.highestResistanceLevel) { + categories.push({ + title: 'Therapeutic', + content: ( +
+ {props.highestSensitiveLevel && ( + + )} + {props.highestResistanceLevel && ( + + )} +
+ ), + }); + } + if (props.highestDiagnosticImplicationLevel) { + categories.push({ + title: 'Diagnostic', + content: ( +
- )} - {props.highestResistanceLevel && ( +
+ ), + }); + } + if (props.highestPrognosticImplicationLevel) { + categories.push({ + title: 'Prognostic', + content: ( +
- )} -
- ), - }); - categories.push({ - title: 'Diagnostic', - content: props.highestDiagnosticImplicationLevel && ( -
- -
- ), - }); - categories.push({ - title: 'Prognostic', - content: props.highestPrognosticImplicationLevel && ( -
- -
- ), - }); - categories.push({ - title: 'FDA', - content: props.highestFdaLevel && ( -
- -
- ), - }); +
+ ), + }); + } + if (props.highestFdaLevel) { + categories.push({ + title: 'FDA', + content: ( +
+ +
+ ), + }); + } return ( - + ); }; diff --git a/src/main/webapp/app/config/constants.tsx b/src/main/webapp/app/config/constants.tsx index ce2cd15fa..317282c16 100644 --- a/src/main/webapp/app/config/constants.tsx +++ b/src/main/webapp/app/config/constants.tsx @@ -180,6 +180,7 @@ export enum LEVEL_TYPES { } export enum ANNOTATION_PAGE_TAB_KEYS { + BIOLOGICAL = 'Biological', TX = 'Tx', DX = 'Dx', PX = 'Px', @@ -207,6 +208,7 @@ export const ACTIONABLE_GENES_LEVEL_TITLE: { [key in LEVEL_TYPES]: string } = { export const ANNOTATION_PAGE_TAB_NAMES: { [key in ANNOTATION_PAGE_TAB_KEYS]: string; } = { + [ANNOTATION_PAGE_TAB_KEYS.BIOLOGICAL]: 'Annotated Alterations', [ANNOTATION_PAGE_TAB_KEYS.TX]: 'Therapeutic', [ANNOTATION_PAGE_TAB_KEYS.DX]: 'Diagnostic', [ANNOTATION_PAGE_TAB_KEYS.PX]: 'Prognostic', diff --git a/src/main/webapp/app/pages/annotationPage/AlterationTableTabs.tsx b/src/main/webapp/app/pages/annotationPage/AlterationTableTabs.tsx index 1326cf8e3..72d7c5ab0 100644 --- a/src/main/webapp/app/pages/annotationPage/AlterationTableTabs.tsx +++ b/src/main/webapp/app/pages/annotationPage/AlterationTableTabs.tsx @@ -52,6 +52,7 @@ export interface IEvidenceTableTabProps { hugoSymbol: string; alteration?: IAlteration; cancerType?: string; + biological: BiologicalVariant[]; tx: TherapeuticImplication[]; dx: TherapeuticImplication[]; px: TherapeuticImplication[]; @@ -74,7 +75,7 @@ export default class AlterationTableTabs extends React.Component< > { @observable selectedTab: ANNOTATION_PAGE_TAB_KEYS; @observable defaultSelectedTab: ANNOTATION_PAGE_TAB_KEYS = - ANNOTATION_PAGE_TAB_KEYS.TX; + ANNOTATION_PAGE_TAB_KEYS.BIOLOGICAL; constructor(props: any) { super(props); @@ -85,7 +86,26 @@ export default class AlterationTableTabs extends React.Component< } getTabDescription(key: ANNOTATION_PAGE_TAB_KEYS) { - if (key === ANNOTATION_PAGE_TAB_KEYS.TX) { + if (key === ANNOTATION_PAGE_TAB_KEYS.BIOLOGICAL) { + let content: JSX.Element; + if (this.props.alteration) { + content = ( + + A list of the oncogenic and mutation effects of {ONCOKB_TM} curated + alterations that related to {this.props.hugoSymbol}{' '} + {this.props.alteration.name}. + + ); + } else { + content = ( + + A list of the oncogenic and mutation effects of{' '} + all {ONCOKB_TM} curated {this.props.hugoSymbol} alterations. + + ); + } + return content; + } else if (key === ANNOTATION_PAGE_TAB_KEYS.TX) { return ( A list of the cancer type-specific {this.props.hugoSymbol} alterations @@ -167,6 +187,14 @@ export default class AlterationTableTabs extends React.Component< @computed get tabs() { const tabs: { title: string; key: ANNOTATION_PAGE_TAB_KEYS }[] = []; + if (this.props.biological.length > 0) { + tabs.push({ + key: ANNOTATION_PAGE_TAB_KEYS.BIOLOGICAL, + title: `${ + ANNOTATION_PAGE_TAB_NAMES[ANNOTATION_PAGE_TAB_KEYS.BIOLOGICAL] + }`, + }); + } if (this.props.tx.length > 0) { tabs.push({ key: ANNOTATION_PAGE_TAB_KEYS.TX, @@ -321,6 +349,69 @@ export default class AlterationTableTabs extends React.Component< return therapeuticTableColumns; } + @computed + get biologicalTableColumns(): SearchColumn[] { + return [ + { + ...getDefaultColumnDefinition(TABLE_COLUMN_KEY.ALTERATION), + accessor: 'variant', + onFilter: (data: BiologicalVariant, keyword) => + filterByKeyword(data.variant.name, keyword), + Cell: (props: { original: BiologicalVariant }) => { + return ( + <> + + + ); + }, + }, + { + ...getDefaultColumnDefinition(TABLE_COLUMN_KEY.ONCOGENICITY), + onFilter: (data: BiologicalVariant, keyword) => + filterByKeyword(data.oncogenic, keyword), + }, + { + ...getDefaultColumnDefinition(TABLE_COLUMN_KEY.MUTATION_EFFECT), + onFilter: (data: BiologicalVariant, keyword) => + filterByKeyword(data.mutationEffect, keyword), + }, + { + ...getDefaultColumnDefinition(TABLE_COLUMN_KEY.DESCRIPTION), + accessor(d) { + return { + abstracts: d.mutationEffectAbstracts, + pmids: d.mutationEffectPmids, + } as Citations; + }, + Cell(props: { original: BiologicalVariant }) { + return ( +
+ {props.original.mutationEffectDescription ? ( + + } + /> + ) : undefined} +
+ ); + }, + }, + ]; + } + @computed get dxpxTableColumns(): SearchColumn[] { return [ @@ -405,6 +496,14 @@ export default class AlterationTableTabs extends React.Component< @action getTable(key: ANNOTATION_PAGE_TAB_KEYS) { switch (key) { + case ANNOTATION_PAGE_TAB_KEYS.BIOLOGICAL: + return ( + + ); case ANNOTATION_PAGE_TAB_KEYS.TX: return ( = props => { const content = []; + if (props.gene.entrezGeneId > 0) { + content.push([ + 'NCBI Gene', + + {props.gene.entrezGeneId} + , + ]); + } if (props.grch37ensemblGene || props.grch38ensemblGene) { content.push([ 'Ensembl Gene', diff --git a/src/main/webapp/app/pages/genePage/GeneInfo.tsx b/src/main/webapp/app/pages/genePage/GeneInfo.tsx index d1d71de54..5792aa3c7 100644 --- a/src/main/webapp/app/pages/genePage/GeneInfo.tsx +++ b/src/main/webapp/app/pages/genePage/GeneInfo.tsx @@ -134,6 +134,18 @@ const GeneInfo: React.FunctionComponent = props => { const gene = props.gene; const info: GeneInfoItem[] = []; + // gene type + if (gene.oncogene || gene.tsg) { + info.push({ + key: 'geneType', + element: ( +
+
{getGeneTypeSentence(gene.oncogene, gene.tsg)}
+
+ ), + }); + } + // highest LoE if ( props.highestResistanceLevel || @@ -161,6 +173,17 @@ const GeneInfo: React.FunctionComponent = props => { }); } + if (gene.geneAliases.length > 0) { + info.push({ + key: 'aliases', + element: ( +
+ +
+ ), + }); + } + return ( <> {info.map(record => ( diff --git a/src/main/webapp/app/pages/genePage/GenePage.module.scss b/src/main/webapp/app/pages/genePage/GenePage.module.scss index 957915039..c9b2e1b5b 100644 --- a/src/main/webapp/app/pages/genePage/GenePage.module.scss +++ b/src/main/webapp/app/pages/genePage/GenePage.module.scss @@ -28,3 +28,8 @@ padding-left: 0; padding-right: 0; } + +.infoTile { + margin-top: 1rem; + flex-grow: 1; +} diff --git a/src/main/webapp/app/pages/genePage/GenePage.tsx b/src/main/webapp/app/pages/genePage/GenePage.tsx index 9e877c68d..f3bb5760e 100644 --- a/src/main/webapp/app/pages/genePage/GenePage.tsx +++ b/src/main/webapp/app/pages/genePage/GenePage.tsx @@ -1,4 +1,4 @@ -import React, { FunctionComponent } from 'react'; +import React from 'react'; import { inject, observer } from 'mobx-react'; import { AnnotationStore, @@ -14,7 +14,7 @@ import { } from 'mobx'; import { Else, If, Then } from 'react-if'; import { Redirect, RouteComponentProps } from 'react-router'; -import { Button, Col, Container, Row } from 'react-bootstrap'; +import { Col, Row } from 'react-bootstrap'; import { getCancerTypeNameFromOncoTreeType, getCancerTypesName, @@ -28,21 +28,15 @@ import BarChart from 'app/components/barChart/BarChart'; import { DefaultTooltip } from 'cbioportal-frontend-commons'; import { ANNOTATION_PAGE_TAB_KEYS, - ANNOTATION_PAGE_TAB_NAMES, DEFAULT_GENE, LEVEL_CLASSIFICATION, LEVEL_TYPES, ONCOGENIC_MUTATIONS, - ONCOKB_NEWS_GROUP_SUBSCRIPTION_LINK, PAGE_ROUTE, REFERENCE_GENOME, } from 'app/config/constants'; import { ClinicalVariant } from 'app/shared/api/generated/OncoKbPrivateAPI'; -import { - AlterationPageLink, - getGenePageLink, - parseGenePagePath, -} from 'app/shared/utils/UrlUtils'; +import { AlterationPageLink, getGenePageLink } from 'app/shared/utils/UrlUtils'; import AppStore from 'app/store/AppStore'; import { MskimpactLink } from 'app/components/MskimpactLink'; import WindowStore from 'app/store/WindowStore'; @@ -59,7 +53,7 @@ import { GenePageSearchQueries, } from 'app/shared/route/types'; import AlterationTableTabs from 'app/pages/annotationPage/AlterationTableTabs'; -import { getGeneTypeSentence } from './GeneInfo'; +import GeneInfo from './GeneInfo'; import GeneAdditionalInfoTable from 'app/pages/genePage/GeneAdditionalInfoTable'; import OncokbLollipopPlot from './OncokbLollipopPlot'; import { getUniqueFdaImplications } from 'app/pages/annotationPage/Utils'; @@ -67,21 +61,8 @@ import ShowHideText from 'app/shared/texts/ShowHideText'; import { AnnotationType } from 'app/pages/annotationPage/AnnotationPage'; import SummaryWithRefs from 'app/oncokb-frontend-commons/src/components/SummaryWithRefs'; import { findLast } from 'app/shared/utils/LodashUtils'; -import { Helmet } from 'react-helmet-async'; -import { NcbiLink } from 'app/shared/links/NcbiLink'; -import GeneAliasesDescription from 'app/shared/texts/GeneAliasesDescription'; -import { COLOR_GREY } from 'app/config/theme'; -import LoETile from 'app/components/infoTile/LoETile'; -import GeneticTypeTabs, { - GENETIC_TYPE, -} from 'app/components/geneticTypeTabs/GeneticTypeTabs'; -import InfoTile from 'app/components/infoTile/InfoTile'; -import AnnotatedAlterations from 'app/pages/annotationPage/AnnotatedAlterations'; -import { - LinkedInLink, - TwitterLink, - UserGoogleGroupLink, -} from 'app/shared/links/SocialMediaLinks'; +import { Helmet, HelmetProvider } from 'react-helmet-async'; +import windowStore from 'app/store/WindowStore'; interface MatchParams { hugoSymbol: string; @@ -93,40 +74,11 @@ interface GenePageProps extends RouteComponentProps { routing: RouterStore; } -const NoContent: FunctionComponent<{ - geneticType: GENETIC_TYPE; -}> = props => { - return ( -
-

- There are no known {props.geneticType} mutations associated with this - gene. -

-

Data will be updated as new findings emerge.

-

-

Don't miss out on the latest data releases and new features.
-
- Follow us on and , or subscribe to our - low-volume email list! -
-

- -
- ); -}; - @inject('appStore', 'windowStore', 'routing') @observer export default class GenePage extends React.Component { @observable hugoSymbolQuery: string; @observable showGeneBackground: boolean; - @observable showAdditionalGeneInfo = false; - @observable selectedGeneticType: GENETIC_TYPE; @observable selectedTab: ANNOTATION_PAGE_TAB_KEYS; @observable defaultSelectedTab: ANNOTATION_PAGE_TAB_KEYS; @@ -342,34 +294,15 @@ export default class GenePage extends React.Component { ); } - @computed - get hasClinicalImplications() { - return ( - this.filteredTxAlterations.length > 0 || - this.filteredDxAlterations.length > 0 || - this.filteredPxAlterations.length > 0 - ); - } - - @computed - get hasContent() { - return ( - this.hasClinicalImplications || - this.store.filteredBiologicalAlterations.length > 0 - ); - } - constructor(props: any) { super(props); - // eslint-disable-next-line no-console - console.log(`gene page constructer}`); - const genePagePath = parseGenePagePath(window.location.pathname); - if (genePagePath.geneticType) { - this.selectedGeneticType = genePagePath.geneticType; - } this.hugoSymbolQuery = props.match.params ? props.match.params.hugoSymbol : undefined; + this.store = new AnnotationStore({ + type: AnnotationType.GENE, + hugoSymbolQuery: this.hugoSymbolQuery, + }); const queryStringsHash = QueryString.parse( window.location.hash ) as GenePageHashQueries; @@ -414,23 +347,6 @@ export default class GenePage extends React.Component { } }, true - ), - reaction( - () => [this.selectedGeneticType], - ([newGeneticType]) => { - this.props.routing.history.push( - getGenePageLink({ - hugoSymbol: this.hugoSymbolQuery, - geneticType: newGeneticType, - }) - ); - this.store = new AnnotationStore({ - type: AnnotationType.GENE, - germline: newGeneticType === 'germline', - hugoSymbolQuery: this.hugoSymbolQuery, - }); - }, - true ) ); } @@ -450,12 +366,6 @@ export default class GenePage extends React.Component { this.showGeneBackground = !this.showGeneBackground; } - @autobind - @action - toggleAdditionalGeneInfo() { - this.showAdditionalGeneInfo = !this.showAdditionalGeneInfo; - } - @autobind @action onChangeTab( @@ -503,11 +413,6 @@ export default class GenePage extends React.Component { } } - @computed - get isGermline() { - return this.selectedGeneticType === 'germline'; - } - @computed get defaultShowGeneBackground() { if (this.store.biologicalAlterations.isComplete) { @@ -549,315 +454,179 @@ export default class GenePage extends React.Component { ) : ( - - - -
- - {this.store.hugoSymbol} - - {this.store.gene.result.geneAliases.length > - 0 && ( - - )} - - - -
-
- {getGeneTypeSentence( - this.store.gene.result.oncogene, - this.store.gene.result.tsg - )} -
-
- - | - -
- {this.showAdditionalGeneInfo && ( - - - - item.referenceGenome === - REFERENCE_GENOME.GRCh37 - )} - grch38ensemblGene={findLast( - this.store.ensemblGenes.result, - item => - item.referenceGenome === - REFERENCE_GENOME.GRCh38 - )} - /> - - - )} +

+ {this.store.hugoSymbol} + + + +

+ + +
+ {this.store.geneSummary.result && ( -
+
- -
- )} - {this.showGeneBackground && ( -
-
)} - - - - - (this.selectedGeneticType = status) - } - routing={this.props.routing} - hugoSymbol={this.store.hugoSymbol} - geneticType={this.selectedGeneticType} - /> - - - - {!this.hasContent && ( - + } + onClick={this.toggleGeneBackground} /> )} - {this.hasContent && ( - <> -
- {this.isGermline && ( - - )} - - { - return { - title: - pathogenicity.pathogenicity, - content: pathogenicity.counts.toString(), - }; - } - ) - : this.store.uniqOncogenicity.map( - oncogenicity => { - return { - title: - oncogenicity.oncogenicity, - content: oncogenicity.counts.toString(), - }; - } - ) - } - /> -
- 0 && - this.store.mutationMapperDataPortal.result - .length > 0 && - !this.isGermline - } - > - - -
- Annotated Mutations in -
- - - {this.store.barChartData.length > 0 ? ( - -
- Cancer Types with{' '} - {this.store.hugoSymbol} Mutations - ( -
- Currently, the mutation - frequency does not take into - account copy number changes, - chromosomal translocations or - cancer types with fewer than 50 - samples in -
- )} - > - -
-
- - this.store.mutationMapperStore && - this.store.mutationMapperStore - .result - ? onFilterOptionSelect( - selectedCancerTypes, - false, - this.store.mutationMapperStore - .result.dataStore, - DataFilterType.CANCER_TYPE, - CANCER_TYPE_FILTER_ID - ) - : undefined - } - /> - - ) : null} -
-
- {this.hasClinicalImplications && ( - <> -

- Clinical Implications -

- - - )} - {this.store.filteredBiologicalAlterations - .length > 0 && ( - <> -

- Annotated{' '} - {this.isGermline - ? 'Variants' - : 'Alterations'} -

- - - )} - +
+ + + + item.referenceGenome === REFERENCE_GENOME.GRCh37 + )} + grch38ensemblGene={findLast( + this.store.ensemblGenes.result, + item => + item.referenceGenome === REFERENCE_GENOME.GRCh38 )} + /> + + + 0 && + this.store.mutationMapperDataPortal.result.length > 0 + } + > + + +
+ Annotated Mutations in +
+ + {this.store.barChartData.length > 0 ? ( + +
+ Cancer Types with {this.store.hugoSymbol}{' '} + Mutations + ( +
+ Currently, the mutation frequency does not + take into account copy number changes, + chromosomal translocations or cancer types + with fewer than 50 samples in{' '} + +
+ )} + > + +
+
+ + this.store.mutationMapperStore && + this.store.mutationMapperStore.result + ? onFilterOptionSelect( + selectedCancerTypes, + false, + this.store.mutationMapperStore.result + .dataStore, + DataFilterType.CANCER_TYPE, + CANCER_TYPE_FILTER_ID + ) + : undefined + } + /> + + ) : null}
- +
+ + + + + { + appStore: AppStore; + windowStore: WindowStore; + routing: RouterStore; +} + +const NoContent: FunctionComponent<{ + geneticType: GENETIC_TYPE; +}> = props => { + return ( +
+

+ There are no known {props.geneticType} mutations associated with this + gene. +

+

Data will be updated as new findings emerge.

+

+

Don't miss out on the latest data releases and new features.
+
+ Follow us on and , or subscribe to our + low-volume email list! +
+

+ +
+ ); +}; + +@inject('appStore', 'windowStore', 'routing') +@observer +export default class SomaticGermlineGenePage extends React.Component< + GenePageProps, + any +> { + @observable hugoSymbolQuery: string; + @observable showGeneBackground: boolean; + @observable showAdditionalGeneInfo = false; + @observable showPrevalenceData = false; + @observable selectedGeneticType: GENETIC_TYPE; + @observable selectedTab: ANNOTATION_PAGE_TAB_KEYS; + @observable defaultSelectedTab: ANNOTATION_PAGE_TAB_KEYS; + + private store: AnnotationStore; + readonly reactions: IReactionDisposer[] = []; + + getAlterationsByLevelType( + alterations: ClinicalVariant[], + levelType: LEVEL_TYPES + ) { + return alterations.filter(alt => { + return LEVEL_CLASSIFICATION[alt.level] === levelType; + }); + } + + @computed + get filteredTxAlterations() { + if (this.store.filteredClinicalAlterations.length === 0) { + return []; + } + return this.getAlterationsByLevelType( + this.store.filteredClinicalAlterations, + LEVEL_TYPES.TX + ); + } + + getClinicalImplications( + clinicalVariants: ClinicalVariant[] + ): TherapeuticImplication[] { + return clinicalVariants.reduce((acc, variant) => { + const cancerTypeNames = variant.cancerTypes.map(cancerType => + getCancerTypeNameFromOncoTreeType(cancerType) + ); + const excludedCancerTypeNames = variant.excludedCancerTypes.map( + cancerType => getCancerTypeNameFromOncoTreeType(cancerType) + ); + const alterationView = variant.variant.consequence ? ( + + ) : ( + {variant.variant.name} + ); + const cancerTypesName = getCancerTypesName( + cancerTypeNames, + excludedCancerTypeNames + ); + const cancerTypesView = ( + <> + + {cancerTypeNames.map(cancerType => + variant.variant.consequence ? ( + + {cancerType} + + ) : ( + {cancerType} + ) + )} + + {excludedCancerTypeNames.length > 0 ? ( + (excluding {excludedCancerTypeNames.join(', ')}) + ) : ( + <> + )} + + ); + if (variant.drug.length > 0) { + variant.drug.forEach(drug => { + acc.push({ + level: variant.level, + alterations: variant.variant.name, + alterationsView: alterationView, + drugs: drug, + cancerTypes: cancerTypesName, + drugDescription: variant.drugDescription, + cancerTypesView, + citations: { + abstracts: variant.drugAbstracts, + pmids: variant.drugPmids, + }, + }); + }); + } else { + acc.push({ + level: variant.level, + alterations: variant.variant.name, + alterationsView: alterationView, + drugs: '', + cancerTypes: cancerTypesName, + drugDescription: variant.drugDescription, + cancerTypesView, + citations: { + abstracts: variant.drugAbstracts, + pmids: variant.drugPmids, + }, + }); + } + return acc; + }, [] as TherapeuticImplication[]); + } + + getFdaImplication(clinicalVariants: ClinicalVariant[]): FdaImplication[] { + const fdaImplications: FdaImplication[] = []; + clinicalVariants.forEach(clinicalVariant => { + let variants: ClinicalVariant[] = [clinicalVariant]; + // we want to link all oncogenic mutations with Oncogenic Mutations clinical variant + if (clinicalVariant.variant.name === ONCOGENIC_MUTATIONS) { + variants = this.store.oncogenicBiologicalVariants.map( + biologicalVariant => ({ + ...clinicalVariant, + variant: biologicalVariant.variant, + }) + ); + } + variants.forEach(variant => { + const ctNames = variant.cancerTypes.map(ct => + getCancerTypeNameFromOncoTreeType(ct) + ); + const excludedCtNames = variant.excludedCancerTypes.map(ct => + getCancerTypeNameFromOncoTreeType(ct) + ); + fdaImplications.push({ + level: variant.fdaLevel, + alteration: variant.variant, + alterationView: ( + + {variant.variant.name} + + ), + cancerType: getCancerTypesName(ctNames, excludedCtNames), + cancerTypeView: ( + <> + + {ctNames.map(cancerType => ( + + {cancerType} + + ))} + + {excludedCtNames.length > 0 ? ( + (excluding {excludedCtNames.join(', ')}) + ) : ( + <> + )} + + ), + }); + }); + }); + return getUniqueFdaImplications(fdaImplications); + } + + @computed + get filteredDxAlterations() { + if (this.store.filteredClinicalAlterations.length === 0) { + return []; + } + return this.getAlterationsByLevelType( + this.store.filteredClinicalAlterations, + LEVEL_TYPES.DX + ); + } + + @computed + get filteredPxAlterations() { + if (this.store.filteredClinicalAlterations.length === 0) { + return []; + } + return this.getAlterationsByLevelType( + this.store.filteredClinicalAlterations, + LEVEL_TYPES.PX + ); + } + + @computed + get hasClinicalImplications() { + return ( + this.filteredTxAlterations.length > 0 || + this.filteredDxAlterations.length > 0 || + this.filteredPxAlterations.length > 0 + ); + } + + @computed + get hasContent() { + return ( + this.hasClinicalImplications || + this.store.filteredBiologicalAlterations.length > 0 + ); + } + + constructor(props: any) { + super(props); + // eslint-disable-next-line no-console + console.log(`gene page constructer}`); + const genePagePath = parseGenePagePath(window.location.pathname); + if (genePagePath.geneticType) { + this.selectedGeneticType = genePagePath.geneticType; + } + this.hugoSymbolQuery = props.match.params + ? props.match.params.hugoSymbol + : undefined; + const queryStringsHash = QueryString.parse( + window.location.hash + ) as GenePageHashQueries; + if (queryStringsHash.tab) { + this.selectedTab = queryStringsHash.tab; + } + + this.props.appStore.toFdaRecognizedContent = false; + this.reactions.push( + reaction( + () => this.defaultShowGeneBackground, + defaultShowGeneBackground => { + if ( + this.showGeneBackground === undefined && + defaultShowGeneBackground !== undefined + ) { + this.showGeneBackground = defaultShowGeneBackground; + } + } + ), + reaction( + () => [props.routing.location.search], + ([search]) => { + const queryStrings = QueryString.parse( + search + ) as GenePageSearchQueries; + if (queryStrings.refGenome) { + this.store.referenceGenomeQuery = queryStrings.refGenome; + } + }, + { fireImmediately: true } + ), + reaction( + () => [props.routing.location.hash], + ([hash]) => { + const queryStrings = QueryString.parse(hash) as GenePageHashQueries; + if (queryStrings.tab) { + this.defaultSelectedTab = queryStrings.tab; + if (queryStrings.tab === ANNOTATION_PAGE_TAB_KEYS.FDA) { + this.props.appStore.inFdaRecognizedContent = true; + } + } + }, + true + ), + reaction( + () => [this.selectedGeneticType], + ([newGeneticType]) => { + this.props.routing.history.push( + getGenePageLink({ + hugoSymbol: this.hugoSymbolQuery, + geneticType: newGeneticType, + }) + ); + this.store = new AnnotationStore({ + type: AnnotationType.GENE, + germline: newGeneticType === 'germline', + hugoSymbolQuery: this.hugoSymbolQuery, + }); + }, + true + ) + ); + } + + componentDidUpdate(prevProps: any) { + if ( + this.props.match.params.hugoSymbol !== prevProps.match.params.hugoSymbol + ) { + this.hugoSymbolQuery = this.props.match.params.hugoSymbol; + this.store.hugoSymbolQuery = this.hugoSymbolQuery; + } + } + + @autobind + @action + toggleGeneBackground() { + this.showGeneBackground = !this.showGeneBackground; + } + + @autobind + @action + toggleAdditionalGeneInfo() { + this.showAdditionalGeneInfo = !this.showAdditionalGeneInfo; + } + + @autobind + @action + onChangeTab( + selectedTab: ANNOTATION_PAGE_TAB_KEYS, + newTabKey: ANNOTATION_PAGE_TAB_KEYS + ) { + if (newTabKey === ANNOTATION_PAGE_TAB_KEYS.FDA) { + this.props.appStore.inFdaRecognizedContent = true; + } + if ( + selectedTab === ANNOTATION_PAGE_TAB_KEYS.FDA && + newTabKey !== ANNOTATION_PAGE_TAB_KEYS.FDA + ) { + this.props.appStore.showFdaModal = true; + } else { + const newHash: GenePageHashQueries = { tab: newTabKey }; + window.location.hash = QueryString.stringify(newHash); + } + } + + @computed + get pageShouldBeRendered() { + return ( + this.store.geneNumber.isComplete && + this.store.gene.isComplete && + this.store.clinicalAlterations.isComplete && + this.store.biologicalAlterations.isComplete + ); + } + + @computed + get genePanelClass() { + if (this.store.barChartData.length > 0) { + return { + xl: 8, + lg: 8, + xs: 12, + }; + } else { + return { + xl: 12, + lg: 12, + xs: 12, + }; + } + } + + @computed + get isGermline() { + return this.selectedGeneticType === 'germline'; + } + + @computed + get defaultShowGeneBackground() { + if (this.store.biologicalAlterations.isComplete) { + return this.store.biologicalAlterations.result.length === 0; + } else { + return undefined; + } + } + + componentWillUnmount(): void { + for (const reactionItem of this.reactions) { + reactionItem(); + } + this.store.destroy(); + } + + render() { + return ( + <> + + {getPageTitle(`${this.store.hugoSymbol}`)} + + + + + + + + {this.store.gene.isError || + this.store.gene.result === DEFAULT_GENE ? ( + + ) : ( + + + + + +
+ + {this.store.hugoSymbol} + + {this.store.gene.result.geneAliases.length > + 0 && ( + + )} + + + +
+
+ {getGeneTypeSentence( + this.store.gene.result.oncogene, + this.store.gene.result.tsg + )} +
+
+ + | + +
+ {this.showAdditionalGeneInfo && ( + + + + item.referenceGenome === + REFERENCE_GENOME.GRCh37 + )} + grch38ensemblGene={findLast( + this.store.ensemblGenes.result, + item => + item.referenceGenome === + REFERENCE_GENOME.GRCh38 + )} + /> + + + )} + {this.store.geneSummary.result && ( +
+ + +
+ )} + {this.showGeneBackground && ( +
+ +
+ )} + +
+
+ + (this.selectedGeneticType = status) + } + routing={this.props.routing} + hugoSymbol={this.store.hugoSymbol} + geneticType={this.selectedGeneticType} + /> + + + + {!this.hasContent && ( + + )} + {this.hasContent && ( + <> +
+ {this.isGermline && ( + + )} + + { + return { + title: + pathogenicity.pathogenicity, + content: pathogenicity.counts.toString(), + }; + } + ) + : this.store.uniqOncogenicity.map( + oncogenicity => { + return { + title: + oncogenicity.oncogenicity, + content: oncogenicity.counts.toString(), + }; + } + ) + } + /> +
+ 0 && + this.store.mutationMapperDataPortal.result + .length > 0 && + !this.isGermline + } + > +
+ } + title={'Show prevalence data'} + onClick={() => + (this.showPrevalenceData = !this + .showPrevalenceData) + } + /> + {this.showPrevalenceData && ( + + +
+ Annotated Mutations in{' '} + +
+ + + {this.store.barChartData.length > 0 ? ( + +
+ Cancer Types with{' '} + {this.store.hugoSymbol} Mutations + ( +
+ Currently, the mutation + frequency does not take into + account copy number changes, + chromosomal translocations + or cancer types with fewer + than 50 samples in{' '} + +
+ )} + > + +
+
+ + this.store + .mutationMapperStore && + this.store.mutationMapperStore + .result + ? onFilterOptionSelect( + selectedCancerTypes, + false, + this.store + .mutationMapperStore + .result.dataStore, + DataFilterType.CANCER_TYPE, + CANCER_TYPE_FILTER_ID + ) + : undefined + } + /> + + ) : null} +
+ )} +
+
+ {this.hasClinicalImplications && ( + <> +

+ Clinical Implications +

+ + + )} + {this.store.filteredBiologicalAlterations + .length > 0 && ( + <> +

+ Annotated{' '} + {this.isGermline + ? 'Variants' + : 'Alterations'} +

+ + + )} + + )} + +
+
+
+ + + +
+ )} +
+ + + +
+
+ + + +
+ + ); + } +} diff --git a/src/main/webapp/app/routes/routes.tsx b/src/main/webapp/app/routes/routes.tsx index e80d6cfc8..79c1aaf91 100644 --- a/src/main/webapp/app/routes/routes.tsx +++ b/src/main/webapp/app/routes/routes.tsx @@ -9,7 +9,7 @@ import AuthenticationStore from 'app/store/AuthenticationStore'; import CancerGenesPage from 'app/pages/CancerGenesPage'; import ActionableGenesPage from 'app/pages/actionableGenesPage/ActionableGenesPage'; import { RouterStore } from 'mobx-react-router'; -import GenePage from 'app/pages/genePage/GenePage'; +import SomaticGermlineGenePage from 'app/pages/genePage/SomaticGermlineGenePage'; import AlterationPage from 'app/pages/alterationPage/AlterationPage'; import { AccountPage } from 'app/pages/AccountPage'; import ActivateAccount from 'app/components/account/ActivateAccount'; @@ -36,6 +36,7 @@ import OncologyTherapiesPage from 'app/pages/oncologyTherapiesPage/oncologyThera import { NewsPageNavTab } from 'app/pages/newsPage/NewsPageNavTab'; import CompanionDiagnosticDevicePage from 'app/pages/companionDiagnosticDevicesPage/companionDiagnosticDevicePage'; import OncokbRoute from 'app/shared/route/OncokbRoute'; +import GenePage from 'app/pages/genePage/GenePage'; const getOldLevelsRedirectRoute = (hash: string) => { const queryStrings = QueryString.parse(hash) as { @@ -175,14 +176,14 @@ const AppRouts = (props: { isUserAuthenticated={props.authenticationStore.isUserAuthenticated} appStore={props.appStore} path={PAGE_ROUTE.SOMATIC_GENE} - component={GenePage} + component={SomaticGermlineGenePage} />