import * as React from 'react';
import { observer } from 'mobx-react';
import { MakeMobxView } from '../../../shared/components/MobxView';
import LoadingIndicator from '../../../shared/components/loadingIndicator/LoadingIndicator';
import { getServerConfig, ServerConfigHelpers } from '../../../config/config';
import { MSKTab, MSKTabs } from '../../../shared/components/MSKTabs/MSKTabs';
import { PatientViewPageStore } from '../clinicalInformation/PatientViewPageStore';
import SampleManager from '../SampleManager';
import { IColumnVisibilityDef } from '../../../shared/components/columnVisibilityControls/ColumnVisibilityControls';
import { action, computed, makeObservable, observable } from 'mobx';
import autobind from 'autobind-decorator';
import PatientViewMutationsDataStore from './PatientViewMutationsDataStore';
import { ClinicalDataBySampleId, Mutation } from 'cbioportal-ts-api-client';
import MutationOncoprint from './oncoprint/MutationOncoprint';
import LabeledCheckbox from '../../../shared/components/labeledCheckbox/LabeledCheckbox';
import PatientViewMutationTable from './PatientViewMutationTable';
import { GeneFilterOption } from './GeneFilterMenu';
import { isFusion } from '../../../shared/lib/MutationUtils';
import PatientViewUrlWrapper from '../PatientViewUrlWrapper';
import WindowStore from '../../../shared/components/window/WindowStore';
import VAFChartWrapper from 'pages/patientView/timeline/VAFChartWrapper';
import TimelineWrapper from 'pages/patientView/timeline/TimelineWrapper';
import VAFChartWrapperStore from '../timeline/VAFChartWrapperStore';
import { ExtendedMutationTableColumnType } from 'shared/components/mutationTable/MutationTable';
import _ from 'lodash';
import { extractColumnNames } from 'shared/components/mutationMapper/MutationMapperUtils';
import SampleNotProfiledAlert from 'shared/components/SampleNotProfiledAlert';
export interface IPatientViewMutationsTabProps {
patientViewPageStore: PatientViewPageStore;
urlWrapper: PatientViewUrlWrapper;
mutationTableColumnVisibility?: { [columnId: string]: boolean };
samples?: ClinicalDataBySampleId[];
onMutationTableColumnVisibilityToggled: (
columnId: string,
columnVisibility?: IColumnVisibilityDef[]
) => void;
sampleManager: SampleManager | null;
sampleIds: string[];
mergeOncoKbIcons?: boolean;
onOncoKbIconToggle?: (mergeIcons: boolean) => void;
}
enum PlotTab {
LINE_CHART = 'lineChart',
HEATMAP = 'heatmap',
TIMELINE = 'timeline',
}
export const LOCAL_STORAGE_PLOT_TAB_KEY =
'patient_view_mutations_tab__vaf_plot_choice';
@observer
export default class PatientViewMutationsTab extends React.Component<
IPatientViewMutationsTabProps,
{}
> {
constructor(props: IPatientViewMutationsTabProps) {
super(props);
makeObservable(this);
}
get showTimeline() {
return (
this.props.urlWrapper.query.genomicEvolutionSettings
.showTimeline === 'true'
);
}
set showTimeline(o: boolean) {
this.props.urlWrapper.updateURL({
genomicEvolutionSettings: Object.assign(
{},
this.props.urlWrapper.query.genomicEvolutionSettings,
{
showTimeline: o.toString(),
}
),
});
}
@action.bound
private toggleTimeline() {
this.showTimeline = !this.showTimeline;
}
private vafChartWrapperStore = new VAFChartWrapperStore({
isOnlySequentialModeAvailable: () => {
const isOnlySequentialOrderingAvailable = this.props.sampleManager?.isOnlySequentialOrderingAvailable(
this.props.patientViewPageStore.clinicalEvents.result
);
return isOnlySequentialOrderingAvailable == undefined
? false
: isOnlySequentialOrderingAvailable;
},
});
private dataStore = new PatientViewMutationsDataStore(
() => this.mergedMutations,
this.props.urlWrapper
);
private vafLineChartSvg: SVGElement | null = null;
get vafLineChartLogScale() {
return (
this.props.urlWrapper.query.genomicEvolutionSettings
.logScaleChart === 'true'
);
}
set vafLineChartLogScale(o: boolean) {
this.props.urlWrapper.updateURL(currentParams => {
currentParams.genomicEvolutionSettings.logScaleChart = o.toString();
return currentParams;
});
}
get vafLineChartZeroToOneYAxis() {
const urlValue = this.props.urlWrapper.query.genomicEvolutionSettings
.yAxisDataRangeInChart;
return !urlValue || urlValue === 'true'; // default true
}
set vafLineChartZeroToOneYAxis(o: boolean) {
this.props.urlWrapper.updateURL(currentParams => {
currentParams.genomicEvolutionSettings.yAxisDataRangeInChart = o.toString();
return currentParams;
});
}
// TODO: replace this with URL stuff
@observable private _plotTab =
localStorage.getItem(LOCAL_STORAGE_PLOT_TAB_KEY) || PlotTab.LINE_CHART;
@computed get plotTab() {
return this._plotTab;
}
@action.bound
private setPlotTab(id: PlotTab) {
this._plotTab = id;
localStorage.setItem(LOCAL_STORAGE_PLOT_TAB_KEY, id);
}
@autobind
private vafLineChartSvgRef(elt: SVGElement | null) {
this.vafLineChartSvg = elt;
}
@computed get mergedMutations() {
// remove fusions
return this.props.patientViewPageStore.mergedMutationDataIncludingUncalledFilteredByGene.filter(
mutationArray => {
return !isFusion(mutationArray[0]);
}
);
}
readonly vafLineChart = MakeMobxView({
await: () => [
this.props.patientViewPageStore.coverageInformation,
this.props.patientViewPageStore.samples,
this.props.patientViewPageStore.mutationMolecularProfileId,
],
renderPending: () =>