import * as React from 'react'; import styles from './styles/styles.module.scss'; import { ObservableMap, toJS, computed, observable, makeObservable, } from 'mobx'; import { expr } from 'mobx-utils'; import { observer, Observer } from 'mobx-react'; import { Gistic } from 'cbioportal-ts-api-client'; import EnhancedReactTable from '../enhancedReactTable/EnhancedReactTable'; import { IColumnFormatterData } from '../enhancedReactTable/IColumnFormatter'; import { Td } from 'reactable'; import classNames from 'classnames'; import { IColumnDefMap } from '../enhancedReactTable/IEnhancedReactTableProps'; import { toPrecision } from '../../lib/FormatUtils'; import { getGeneSymbols, sortByCytoband } from '../../lib/GisticUtils'; const DEFAULT_NUM_GENES_SHOWN = 5; class GisticTable extends EnhancedReactTable {} export interface GisticGeneSelectorProps { initialSelection: string[]; data: Gistic[]; onSelect: (map_geneSymbol_selected: ObservableMap) => void; } @observer export default class GisticGeneSelector extends React.Component< GisticGeneSelectorProps, {} > { constructor(props: GisticGeneSelectorProps) { super(props); this.map_geneSymbol_selected.replace( props.initialSelection.map(geneSymbol => [geneSymbol, true]) ); } map_geneSymbol_selected = observable.map(); private columns: IColumnDefMap = { amp: { priority: 1, columnDataFunction: ({ rowData: gistic, }: IColumnFormatterData) => gistic && (gistic.amp ? 'Amp' : 'Del'), name: 'Amp Del', sortable: true, filterable: true, header: (
Amp Del
), formatter: ({ name, rowData: gistic, columnData: value, }: IColumnFormatterData) => ( {!!gistic && (
)} ), }, chromosome: { priority: 2, dataField: 'chromosome', name: 'Chr', sortable: true, filterable: true, }, cytoband: { priority: 3, dataField: 'cytoband', name: 'Cytoband', sortable: sortByCytoband, filterable: true, }, '#': { priority: 4, columnDataFunction: ({ rowData: gistic, }: IColumnFormatterData) => getGeneSymbols(gistic).length, name: '#', sortable: true, filterable: true, }, genes: { priority: 5, // this columnDataFunction allows quick searching by gene symbol columnDataFunction: ({ rowData: gistic, }: IColumnFormatterData) => getGeneSymbols(gistic).join(' '), name: 'Genes', sortable: (genes1: string, genes2: string) => { // sort by length, then alphabetically return ( genes1.length - genes2.length || +(genes1 > genes2) - +(genes1 < genes2) ); }, filterable: true, formatter: ({ name, rowData: gistic, columnData: value, }: IColumnFormatterData) => ( ), }, qValue: { priority: 6, dataField: 'qValue', name: 'Q-Value', sortable: true, filterable: true, formatter: ({ name, rowData: gistic, columnData: value, }: IColumnFormatterData) => ( {toPrecision(value, 2, 0.1)} ), }, }; render() { return (
{'Click on a gene to '} {'select'} {' it.'}
); } } @observer class GisticGeneToggles extends React.Component< { gistic?: Gistic; map_geneSymbol_selected: ObservableMap; }, {} > { @observable showAll = false; constructor(props: { gistic?: Gistic; map_geneSymbol_selected: ObservableMap; }) { super(props); makeObservable(this); } renderGeneToggles(genes: string[]) { return genes.map(gene => ( {() => { let selected = !!this.props.map_geneSymbol_selected.get( gene ); return ( this.props.map_geneSymbol_selected.set( gene, !selected ) } > {gene} ); }} )); } render() { let allGenes = getGeneSymbols(this.props.gistic); let someGenes = allGenes.slice(0, DEFAULT_NUM_GENES_SHOWN); let moreGenes = allGenes.slice(DEFAULT_NUM_GENES_SHOWN); return (
{this.renderGeneToggles(someGenes)} {!!moreGenes.length && ( (this.showAll = !this.showAll)} > {this.showAll ? 'less' : `+${moreGenes.length} more`} )}
{this.showAll && this.renderGeneToggles(moreGenes)}
); } }