Skip to content

Commit

Permalink
Oncoprint track selection: allow bulk submission of Oncoprint tracks (#…
Browse files Browse the repository at this point in the history
…4780)

* add submit button in tracks menu to add toggled tracks

* move buttom to bottom of menu and add functionality to other tabs

* change button name to update tracks

* fix bug with tracks having value Mixed

* fix tests and update tracks button now closes tracks menu

---------

Co-authored-by: Bryan Lai <[email protected]>
  • Loading branch information
gblaih and Bryan Lai authored Dec 8, 2023
1 parent 100f4b9 commit 744cee9
Show file tree
Hide file tree
Showing 5 changed files with 107 additions and 29 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -35,15 +35,14 @@ describe('oncoprint colors', () => {
getElementByTestHandle('add-chart-option-mutation-spectrum')
.$('label')
.click();
getElementByTestHandle('update-tracks').waitForDisplayed();
getElementByTestHandle('update-tracks').click();
waitForOncoprint(ONCOPRINT_TIMEOUT);

// check that mutation spectrum is added to the oncoprint
let legendText = getTextInOncoprintLegend();
assert(legendText.indexOf('Mutation spectrum') > -1);

$tracksDropdown.waitForDisplayed();
$tracksDropdown.click();

var trackOptionsElts = getNthOncoprintTrackOptionsElements(5);
// open menu
$(trackOptionsElts.button_selector).click();
Expand Down
95 changes: 80 additions & 15 deletions src/pages/resultsView/oncoprint/TracksMenu.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -65,11 +65,18 @@ export default class TracksMenu extends React.Component<IAddTrackProps, {}> {
string
>({}, { deep: true });

private tracksDropdown: CustomDropdown;

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

@autobind
private tracksDropdownRef(dropdown: CustomDropdown) {
this.tracksDropdown = dropdown;
}

@action.bound
private updateTabId(newId: Tab) {
this.tabId = newId;
Expand Down Expand Up @@ -288,6 +295,9 @@ export default class TracksMenu extends React.Component<IAddTrackProps, {}> {
clinicalAttributeIds.map(id => new ClinicalTrackConfig(id))
)
);
this.props.handlers.onChangeToggledClinicalTracks!(
this.getSelectedClinicalAttributes()
);
}

@action.bound
Expand All @@ -299,30 +309,64 @@ export default class TracksMenu extends React.Component<IAddTrackProps, {}> {
'stableId'
)
);
this.props.handlers.onChangeToggledClinicalTracks!(
this.getSelectedClinicalAttributes()
);
}

@action.bound
private submit() {
this.props.handlers.onChangeSelectedClinicalTracks!(
this.props.state.toggledClinicalTracks!
);
this.tracksDropdown.hide();
}

@action.bound
private toggleClinicalTrack(clinicalAttributeId: string) {
const toggled = toggleIncluded(
new ClinicalTrackConfig(clinicalAttributeId),
this.getSelectedClinicalAttributes(),
track => track.stableId === clinicalAttributeId
this.props.handlers.onChangeToggledClinicalTracks!(
toggleIncluded(
new ClinicalTrackConfig(clinicalAttributeId),
this.props.state.toggledClinicalTracks!,
track => track.stableId === clinicalAttributeId
)
);
}

@computed get showSubmit() {
return (
_.xorBy(
this.getSelectedClinicalAttributes(),
this.props.state.toggledClinicalTracks!,
'stableId'
).length !== 0
);
this.props.handlers.onChangeSelectedClinicalTracks!(toggled);
}

readonly addClinicalTracksMenu = MakeMobxView({
await: () => [this.trackOptionsByType],
render: () => (
<AddChartByType
options={this.trackOptionsByType.result!.clinical}
freqPromise={this.clinicalAttributeIdToAvailableFrequency}
onAddAll={this.addAll}
onClearAll={this.clear}
onToggleOption={this.toggleClinicalTrack}
optionsGivenInSortedOrder={true}
width={this.dropdownWidth}
/>
<>
<AddChartByType
options={this.trackOptionsByType.result!.clinical}
freqPromise={this.clinicalAttributeIdToAvailableFrequency}
onAddAll={this.addAll}
onClearAll={this.clear}
onToggleOption={this.toggleClinicalTrack}
optionsGivenInSortedOrder={true}
width={this.dropdownWidth}
/>
{this.showSubmit && (
<button
className="btn btn-primary btn-sm"
data-test="update-tracks"
style={{ marginTop: '10px', marginBottom: '0px' }}
onClick={this.submit}
>
{'Update tracks'}
</button>
)}
</>
),
renderPending: () => <LoadingIndicator isLoading={true} small={true} />,
showLastRenderWhenPending: true,
Expand All @@ -349,6 +393,16 @@ export default class TracksMenu extends React.Component<IAddTrackProps, {}> {
frequencyHeaderTooltip="% samples in group"
width={this.dropdownWidth}
/>
{this.showSubmit && (
<button
className="btn btn-primary btn-sm"
data-test="update-tracks"
style={{ marginTop: '10px', marginBottom: '0px' }}
onClick={this.submit}
>
{'Update tracks'}
</button>
)}
</>
),
renderPending: () => <LoadingIndicator isLoading={true} small={true} />,
Expand Down Expand Up @@ -376,6 +430,16 @@ export default class TracksMenu extends React.Component<IAddTrackProps, {}> {
frequencyHeaderTooltip="% samples in group"
width={this.dropdownWidth}
/>
{this.showSubmit && (
<button
className="btn btn-primary btn-sm"
data-test="update-tracks"
style={{ marginTop: '10px', marginBottom: '0px' }}
onClick={this.submit}
>
{'Update tracks'}
</button>
)}
</>
),
renderPending: () => <LoadingIndicator isLoading={true} small={true} />,
Expand All @@ -392,7 +456,7 @@ export default class TracksMenu extends React.Component<IAddTrackProps, {}> {
selected:
option.key in
_.keyBy(
this.getSelectedClinicalAttributes().map(
this.props.state.toggledClinicalTracks!.map(
a => a.stableId
)
),
Expand Down Expand Up @@ -677,6 +741,7 @@ export default class TracksMenu extends React.Component<IAddTrackProps, {}> {
id="addTracksDropdown"
className="oncoprintAddTracksDropdown"
styles={{ minWidth: MIN_DROPDOWN_WIDTH, width: 'auto' }}
ref={this.tracksDropdownRef}
>
<div
style={{
Expand Down
30 changes: 20 additions & 10 deletions src/shared/components/oncoprint/ResultsViewOncoprint.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -165,11 +165,7 @@ export function getClinicalTrackColor(
let valueIndex = _.indexOf(track.countsCategoryLabels, value);
return track.countsCategoryFills[valueIndex];
} else if (track.datatype === 'string' && track.category_to_color) {
if (
(track.label === 'Sample Type' ||
track.label === 'Sample type id') &&
value === 'Mixed'
) {
if (value === 'Mixed') {
return track.category_to_color[value] || [48, 97, 194, 1];
}
return track.category_to_color[value];
Expand Down Expand Up @@ -306,6 +302,8 @@ export default class ResultsViewOncoprint extends React.Component<

@observable renderingComplete = false;

@observable toggledClinicalTracks: ClinicalTrackConfig[];

private heatmapGeneInputValueUpdater: IReactionDisposer;

private molecularProfileIdToTrackGroupIndex: {
Expand Down Expand Up @@ -508,6 +506,13 @@ export default class ResultsViewOncoprint extends React.Component<
get selectedClinicalAttributeSpecInits(): ClinicalTrackConfigMap {
return self.selectedClinicalTrackConfig;
},
get toggledClinicalTracks(): ClinicalTrackConfig[] {
if (!self.toggledClinicalTracks) {
return _.values(self.selectedClinicalTrackConfig);
} else {
return self.toggledClinicalTracks;
}
},
get selectedColumnType() {
return self.oncoprintAnalysisCaseType;
},
Expand Down Expand Up @@ -859,6 +864,11 @@ export default class ResultsViewOncoprint extends React.Component<
});
},
onChangeSelectedClinicalTracks: this.setSessionClinicalTracks,
onChangeToggledClinicalTracks: (
clinicalTracks: ClinicalTrackConfig[]
) => {
this.toggledClinicalTracks = clinicalTracks;
},
onChangeHeatmapGeneInputValue: action((s: string) => {
this.heatmapGeneInputValue = s;
this.heatmapGeneInputValueUpdater(); // stop updating heatmap input if user has typed
Expand Down Expand Up @@ -1313,6 +1323,10 @@ export default class ResultsViewOncoprint extends React.Component<
...session.userSettings,
clinicallist: _.values(json),
};
this.controlsHandlers.onChangeToggledClinicalTracks &&
this.controlsHandlers.onChangeToggledClinicalTracks(
_.values(json)
);
}
}

Expand Down Expand Up @@ -1892,11 +1906,7 @@ export default class ResultsViewOncoprint extends React.Component<
_.indexOf(MUTATION_SPECTRUM_CATEGORIES, value)
];
} else if (this.selectedClinicalTrack.datatype === 'string') {
if (
(this.selectedClinicalTrack.label === 'Sample Type' ||
this.selectedClinicalTrack.label === 'Sample type id') &&
value === 'Mixed'
) {
if (value === 'Mixed') {
return [48, 97, 194, 1];
} else {
return hexToRGBA(
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -48,7 +48,7 @@ export default class CustomDropdown extends React.Component<
@observable private open: boolean = false;

private toggle: () => void;
private hide: () => void;
public hide: () => void;

constructor(props: ButtonProps) {
super(props);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -74,6 +74,9 @@ export interface IOncoprintControlsHandlers
onChangeSelectedClinicalTracks?: (
trackConfigs: ClinicalTrackConfig[]
) => void;
onChangeToggledClinicalTracks?: (
trackConfigs: ClinicalTrackConfig[]
) => void;
onClickAddGenesToHeatmap?: () => void;
onSelectGenericAssayProfile?: (molecularProfileId: string) => void;
onClickAddGenericAssays?: (info: GenericAssayTrackInfo[]) => void;
Expand Down Expand Up @@ -110,6 +113,7 @@ export interface IOncoprintControlsState
[clinicalAttributeId: string]: number;
}>;
selectedClinicalAttributeSpecInits?: ClinicalTrackConfigMap;
toggledClinicalTracks?: ClinicalTrackConfig[];
heatmapProfilesPromise?: MobxPromise<MolecularProfile[]>;
genericAssayEntitiesGroupedByGenericAssayTypePromise?: MobxPromise<{
[genericAssayType: string]: GenericAssayMeta[];
Expand Down

0 comments on commit 744cee9

Please sign in to comment.