Skip to content

Commit

Permalink
updated screenshots + fixed null checks
Browse files Browse the repository at this point in the history
  • Loading branch information
Rajat-Sirohi committed Jun 10, 2021
1 parent 5bb2513 commit b72ac9a
Show file tree
Hide file tree
Showing 45 changed files with 663 additions and 41 deletions.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,7 @@ export default class TableCellStatusIndicator extends React.Component<
break;
case TableCellStatus.NA:
alt = this.props.naAlt || 'Data not available.';
text = '';
text = 'n/a';
break;
}
return (
Expand Down
73 changes: 73 additions & 0 deletions src/pages/resultsView/ResultsViewPageStore.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3442,6 +3442,10 @@ export class ResultsViewPageStore {
this.uniqueSampleKeyToTumorType.result!,
this.generateGenomeNexusHgvsgUrl,
this.clinicalDataGroupedBySampleMap,
this.mutationsTabClinicalAttributes,
this.mutationsTabClinicalData,
this.clinicalAttributeIdToAvailableSampleCount,
this.sampleCount,
this.genomeNexusClient,
this.genomeNexusInternalClient,
() => this.urlWrapper.query.mutations_transcript_id
Expand Down Expand Up @@ -3586,6 +3590,70 @@ export class ResultsViewPageStore {
{}
);

readonly mutationsTabClinicalAttributes = remoteData<
ExtendedClinicalAttribute[]
>({
await: () => [this.studyIds],
invoke: async () => {
const clinicalAttributes = await client.fetchClinicalAttributesUsingPOST(
{
studyIds: this.studyIds.result,
}
);
const excludeList = [
'CANCER_TYPE',
'CANCER_TYPE_DETAILED',
'MUTATION_COUNT',
];

return clinicalAttributes.filter(
x => !excludeList.includes(x.clinicalAttributeId)
);
},
});

readonly mutationsTabClinicalData = remoteData<ClinicalData[]>(
{
await: () => [
this.studies,
this.patients,
this.samples,
this.mutationsTabClinicalAttributes,
],
invoke: () => {
let patientAttributeIds = this.mutationsTabClinicalAttributes
.result!.filter(attribute => attribute.patientAttribute)
.map(attribute => attribute.clinicalAttributeId);
let sampleAttributeIds = this.mutationsTabClinicalAttributes
.result!.filter(attribute => !attribute.patientAttribute)
.map(attribute => attribute.clinicalAttributeId);

let patientData = Promise.resolve(new Array<ClinicalData>());
let sampleData = Promise.resolve(new Array<ClinicalData>());
if (patientAttributeIds.length > 0) {
patientData = this.getClinicalData(
REQUEST_ARG_ENUM.CLINICAL_DATA_TYPE_PATIENT,
this.studies.result!,
this.patients.result,
patientAttributeIds
);
}
if (sampleAttributeIds.length > 0) {
sampleData = this.getClinicalData(
REQUEST_ARG_ENUM.CLINICAL_DATA_TYPE_SAMPLE,
this.studies.result!,
this.samples.result,
sampleAttributeIds
);
}
return Promise.all([patientData, sampleData]).then(both =>
both[0].concat(both[1])
);
},
},
[]
);

private getClinicalData(
clinicalDataType: 'SAMPLE' | 'PATIENT',
studies: any[],
Expand Down Expand Up @@ -3647,6 +3715,11 @@ export class ResultsViewPageStore {
[]
);

readonly sampleCount = remoteData<number>({
await: () => [this.samples],
invoke: () => Promise.resolve(this.samples.result!.length),
});

readonly samples = remoteData(
{
await: () => [this.studyToDataQueryFilter],
Expand Down
276 changes: 276 additions & 0 deletions src/pages/resultsView/mutation/AddColumns.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,276 @@
import * as React from 'react';
import * as _ from 'lodash';
import { Checkbox } from 'react-bootstrap';
import { observer } from 'mobx-react';
import { action, computed, makeObservable, observable } from 'mobx';
import { remoteData, getTextWidth } from 'cbioportal-frontend-commons';
import { IColumnVisibilityDef } from 'shared/components/columnVisibilityControls/ColumnVisibilityControls';
import { MSKTab, MSKTabs } from 'shared/components/MSKTabs/MSKTabs';
import CustomDropdown from 'shared/components/oncoprint/controls/CustomDropdown';
import AddChartByType from '../../studyView/addChartButton/addChartByType/AddChartByType';
import { ChartDataCountSet } from '../../studyView/StudyViewUtils';

export interface IAddColumnsProps {
className?: string;
columnVisibility?: IColumnVisibilityDef[];
onColumnEnabled?: (columnId: string) => void;
onColumnDisabled?: (columnId: string) => void;
onColumnToggled?: (
columnId: string,
columnVisibility?: IColumnVisibilityDef[]
) => void;
clinicalAttributeIdToAvailableSampleCount?: { [id: string]: number };
sampleCount?: number;
}

enum Tab {
MUTATIONS = 'Mutations',
CLINICAL = 'Clinical',
}

// Copied these constants from oncoprint/AddTracks.tsx
// since importing them results in errors during testing
// due to a separate import in that file.
const MIN_DROPDOWN_WIDTH = 400;
const CONTAINER_PADDING_WIDTH = 20;
const TAB_PADDING_WIDTH = 14;
const COUNT_PADDING_WIDTH = 17;
@observer
export default class AddColumns extends React.Component<IAddColumnsProps, {}> {
@observable tabId: Tab = Tab.MUTATIONS;

constructor(props: IAddColumnsProps) {
super(props);
makeObservable(this);
}

@action.bound
private updateTabId(newId: Tab) {
this.tabId = newId;
}

@computed get clinicalAttributeIdsToNames() {
const clinicalAttributes = this.props.columnVisibility!.filter(
col => col.clinicalAttributeId !== undefined
);

let map: { [id: string]: string } = {};
for (let attribute of clinicalAttributes) {
map[attribute.clinicalAttributeId!] = attribute.name;
}

return map;
}

@action.bound
private addAll(ids: string[]) {
if (this.props.onColumnEnabled && ids) {
for (let id of ids) {
this.props.onColumnEnabled(id);
}
}
}

@action.bound
private clearAll(ids: string[]) {
if (this.props.onColumnDisabled && ids) {
for (let id of ids) {
this.props.onColumnDisabled(id);
}
}
}

@action.bound
private toggle(id: string) {
if (this.props.onColumnToggled && id) {
this.props.onColumnToggled(id, this.props.columnVisibility);
}
}

readonly emptyPromise = remoteData({
invoke: () =>
new Promise<ChartDataCountSet>(() => {
return;
}),
});

readonly clinicalAttributeIdToAvailableFrequencyPromise = remoteData({
invoke: () =>
Promise.resolve(
_.mapValues(
this.props.clinicalAttributeIdToAvailableSampleCount,
count => (100 * count) / this.props.sampleCount!
)
),
});

@computed get mutationsOptions() {
return this.props.columnVisibility
?.filter(col => col.clinicalAttributeId === undefined)
.map(col => ({
label: col.name,
key: col.id,
selected: col.visible,
}));
}

@computed get mutationsTabContent() {
return (
<div>
{this.mutationsOptions && (
<AddChartByType
options={this.mutationsOptions}
freqPromise={this.emptyPromise}
onAddAll={this.addAll}
onClearAll={this.clearAll}
onToggleOption={this.toggle}
optionsGivenInSortedOrder={true}
width={this.dropdownWidth}
excludeFrequency={true}
/>
)}
</div>
);
}

@computed get clinicalOptions() {
return this.props.columnVisibility
?.filter(col => col.clinicalAttributeId !== undefined)
.map(col => ({
label: col.name,
key: col.clinicalAttributeId!,
selected: col.visible,
}));
}

@computed get clinicalTabContent() {
return (
<div>
{this.props.columnVisibility && this.clinicalOptions && (
<AddChartByType
options={this.clinicalOptions}
freqPromise={
this.clinicalAttributeIdToAvailableFrequencyPromise
}
onAddAll={clinicalAttributeIds =>
this.addAll(
clinicalAttributeIds.map(
id => this.clinicalAttributeIdsToNames![id]
)
)
}
onClearAll={clinicalAttributeIds =>
this.clearAll(
clinicalAttributeIds.map(
id => this.clinicalAttributeIdsToNames![id]
)
)
}
onToggleOption={clinicalAttributeId =>
this.toggle(
this.clinicalAttributeIdsToNames![
clinicalAttributeId
]
)
}
optionsGivenInSortedOrder={false}
width={this.dropdownWidth}
/>
)}
</div>
);
}

@computed get mutationsTabText() {
return (
<div>
{Tab.MUTATIONS}
<span style={{ paddingLeft: 5 }}>
<span className="oncoprintDropdownCount">
{this.mutationsOptions?.length}
</span>
</span>
</div>
);
}

@computed get clinicalTabText() {
return (
<div>
{Tab.CLINICAL}
<span style={{ paddingLeft: 5 }}>
<span className="oncoprintDropdownCount">
{this.clinicalOptions?.length}
</span>
</span>
</div>
);
}

private getTextPixel(text: string | undefined, fontSize: string) {
// This is a very specified function to calculate the text length in Add Tracks dropdown
const FRONT_FAMILY = 'Helvetica Neue';
return Math.floor(
getTextWidth(text ? text : '', FRONT_FAMILY, fontSize)
);
}

@computed get dropdownWidth() {
let width = 2 * CONTAINER_PADDING_WIDTH;
const HEADER_FONT_SIZE = '14px';
const COUNT_FONT_SIZE = '11px';

const textWidth =
this.getTextPixel(Tab.CLINICAL, HEADER_FONT_SIZE) +
TAB_PADDING_WIDTH;
const countTextWidth =
this.getTextPixel(
this.clinicalOptions?.length.toString(),
COUNT_FONT_SIZE
) + COUNT_PADDING_WIDTH;
width += textWidth + countTextWidth;

return Math.max(width, MIN_DROPDOWN_WIDTH);
}

render() {
return (
<CustomDropdown
bsStyle="default"
title="Columns"
id="addColumnsDropdown"
className={this.props.className}
styles={{ minWidth: MIN_DROPDOWN_WIDTH, width: 'auto' }}
>
<div
style={{
display: 'flex',
flexDirection: 'column',
}}
>
<MSKTabs
activeTabId={this.tabId}
onTabClick={this.updateTabId}
unmountOnHide={false}
className="mainTabs mutationsTabAddColumnsDropdown"
>
<MSKTab
key={0}
id={Tab.MUTATIONS}
linkText={this.mutationsTabText}
>
{this.mutationsTabContent}
</MSKTab>
<MSKTab
key={1}
id={Tab.CLINICAL}
linkText={this.clinicalTabText}
>
{this.clinicalTabContent}
</MSKTab>
</MSKTabs>
</div>
</CustomDropdown>
);
}
}
Loading

0 comments on commit b72ac9a

Please sign in to comment.