import { ICivicGeneIndex, ICivicVariantIndex, IHotspotIndex, IMyCancerGenomeData, IOncoKbData, getRemoteDataGroupStatus, MobxCache, Mutation, RemoteData, Pathogenicity, } from 'cbioportal-utils'; import { MyVariantInfo, VariantAnnotation } from 'genome-nexus-ts-api-client'; import { CancerGene } from 'oncokb-ts-api-client'; import _ from 'lodash'; import { action, computed, makeObservable } from 'mobx'; import { observer } from 'mobx-react'; import * as React from 'react'; import { Column } from 'react-table'; import Annotation, { getAnnotationData } from '../column/Annotation'; import ClinvarInterpretation from '../column/ClinvarInterpretation'; import Dbsnp from '../column/Dbsnp'; import Gnomad from '../column/Gnomad'; import Hgvsc from '../column/Hgvsc'; import Hgvsg from '../column/Hgvsg'; import Signal, { getSignalData } from '../column/Signal'; import { getHgvscColumnData, getHgvsgColumnData } from '../column/HgvsHelper'; import { getMyVariantInfoData } from '../column/MyVariantInfoHelper'; import { MutationFilterValue } from '../../filter/MutationFilter'; import { DataFilterType } from '../../model/DataFilter'; import { findNonTextInputFilters, TEXT_INPUT_FILTER_ID, } from '../../util/FilterUtils'; import DataTable, { DataTableColumn, DataTableProps, } from '../dataTable/DataTable'; import { MutationColumn } from './MutationColumnHelper'; import './defaultMutationTable.scss'; import { getClinvarData } from '../clinvar/ClinvarHelper'; export type DefaultMutationTableProps = { hotspotData?: RemoteData; oncoKbData?: RemoteData; myCancerGenomeData?: IMyCancerGenomeData; oncoKbCancerGenes?: RemoteData; usingPublicOncoKbInstance: boolean; indexedMyVariantInfoAnnotations?: RemoteData< { [genomicLocation: string]: MyVariantInfo } | undefined >; indexedVariantAnnotations?: RemoteData< { [genomicLocation: string]: VariantAnnotation } | undefined >; selectedTranscriptId?: string; enableCivic?: boolean; civicGenes?: RemoteData; civicVariants?: RemoteData; pubMedCache?: MobxCache; columns: Column>[]; appendColumns?: boolean; } & DataTableProps>; @observer class DefaultMutationTableComponent extends DataTable> {} @observer export default class DefaultMutationTable extends React.Component< DefaultMutationTableProps, {} > { constructor(props: any) { super(props); makeObservable(this); } public static defaultProps = { initialSort: [{ column: MutationColumn.ANNOTATION }], appendColumns: true, }; @computed get annotationColumnData() { return [ this.props.oncoKbCancerGenes, this.props.hotspotData, this.props.oncoKbData, this.props.civicVariants, ]; } @computed get annotationColumnDataStatus() { return getRemoteDataGroupStatus( ..._.compact(this.annotationColumnData) ); } @computed get indexedVariantAnnotationDataStatus() { return this.props.indexedVariantAnnotations ? this.props.indexedVariantAnnotations.status : 'complete'; } @computed get myVariantInfoAnnotationsDataStatus() { return this.props.indexedMyVariantInfoAnnotations ? this.props.indexedMyVariantInfoAnnotations.status : 'complete'; } @computed get annotationColumnAccessor() { return this.annotationColumnDataStatus === 'pending' ? () => undefined : (mutation: Mutation) => getAnnotationData( mutation, this.props.oncoKbCancerGenes, this.props.hotspotData, this.props.myCancerGenomeData, this.props.oncoKbData, this.props.usingPublicOncoKbInstance, this.props.civicGenes, this.props.civicVariants ); } @computed get myVariantInfoAccessor() { return this.myVariantInfoAnnotationsDataStatus === 'pending' ? () => undefined : (mutation: Mutation) => getMyVariantInfoData( mutation, this.props.indexedMyVariantInfoAnnotations ); } @computed get hgvsgAccessor() { return this.indexedVariantAnnotationDataStatus === 'pending' ? () => undefined : (mutation: Mutation) => getHgvsgColumnData(mutation); } @computed get hgvscAccessor() { return this.indexedVariantAnnotationDataStatus === 'pending' ? () => undefined : (mutation: Mutation) => getHgvscColumnData( mutation, this.props.indexedVariantAnnotations, this.props.selectedTranscriptId ); } @computed get signalAccessor() { return this.indexedVariantAnnotationDataStatus === 'pending' ? () => undefined : (mutation: Mutation) => getSignalData( mutation, this.props.indexedVariantAnnotations, Pathogenicity.GERMLINE )[0]; } @computed get clinvarAccessor() { return this.indexedVariantAnnotationDataStatus === 'pending' ? () => undefined : (mutation: Mutation) => getClinvarData( mutation, this.props.indexedVariantAnnotations ); } @computed get initialSortRemoteData() { return this.props.initialSortRemoteData || this.annotationColumnData; } protected getDefaultColumnAccessor(columnKey: MutationColumn) { switch (columnKey) { case MutationColumn.ANNOTATION: return this.annotationColumnAccessor; case MutationColumn.HGVSG: return this.hgvsgAccessor; case MutationColumn.HGVSC: return this.hgvscAccessor; case MutationColumn.GNOMAD: return this.myVariantInfoAccessor; case MutationColumn.CLINVAR: return this.clinvarAccessor; case MutationColumn.DBSNP: return this.myVariantInfoAccessor; case MutationColumn.SIGNAL: return this.signalAccessor; default: return undefined; } } protected getDefaultColumnCellRender(columnKey: MutationColumn) { switch (columnKey) { case MutationColumn.ANNOTATION: return (column: any) => ( ); case MutationColumn.HGVSG: return (column: any) => ; case MutationColumn.HGVSC: return (column: any) => ( ); case MutationColumn.GNOMAD: return (column: any) => ( ); case MutationColumn.CLINVAR: return (column: any) => ( ); case MutationColumn.DBSNP: return (column: any) => ( ); case MutationColumn.SIGNAL: return (column: any) => ( ); default: return undefined; } } @computed get columns() { return this.props.columns.map(c => { // we need to clone the column definition first, // directly modifying the props.columns breaks certain column functionality const column = { ...c }; if (!column.accessor) { const defaultAccessor = this.getDefaultColumnAccessor( column.id as MutationColumn ); if (defaultAccessor) { column.accessor = defaultAccessor; } } if (!column.Cell) { const defaultCellRender = this.getDefaultColumnCellRender( column.id as MutationColumn ); if (defaultCellRender) { column.Cell = defaultCellRender; } } return column; }); } public render() { return ( ); } @action.bound protected onSearch( searchText: string, visibleSearchableColumns: DataTableColumn[] ) { if (this.props.dataStore) { // all other filters except current text input filter const otherFilters = findNonTextInputFilters( this.props.dataStore.dataFilters ); let dataFilterValues: MutationFilterValue[] = []; if (searchText.length > 0) { dataFilterValues = visibleSearchableColumns.map( c => ({ [c.id!]: searchText } as MutationFilterValue) ); const textInputFilter = { id: TEXT_INPUT_FILTER_ID, type: DataFilterType.MUTATION, values: dataFilterValues, }; // replace current text input filter with the new one this.props.dataStore.setDataFilters([ ...otherFilters, textInputFilter, ]); } else { // if no text input remove text input filter (set data filters to all other filters except input) this.props.dataStore.setDataFilters(otherFilters); } } } }