Skip to content

Commit 71475a1

Browse files
onursumeralisman
andauthored
Render the comparison page tabs without waiting for data (#5191)
* do not wait for data before loading the comparison page tabs * grey out certain tabs instead of hiding them * apply same changes to the results view comparison tab as well * workaround to rerender Clinical tab on overlap strategy change * workaround to rerender survival tab on overlap strategy change * increase timeout for infoIcon hover action * Adding pending loader for MSKTabs * add missing pending props for the comparison tabs * fix failing unit tests due to the new loader icon * fix failing custom tabs test for comparison page --------- Co-authored-by: alisman <lisman.aaron@gmail.com>
1 parent 129dae5 commit 71475a1

7 files changed

Lines changed: 308 additions & 284 deletions

File tree

end-to-end-test/remote/specs/core/customTabs.spec.js

Lines changed: 10 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -352,12 +352,17 @@ const runTests = async (pageName, url, tabLocation) => {
352352

353353
await browser.pause(2000);
354354

355-
await (await getElement('div=Second render')).waitForDisplayed();
355+
// 'Second Render' doesn't exist anymore for comparison page due to the newer way we load tabs
356+
if (tabLocation !== 'COMPARISON_PAGE') {
357+
await (
358+
await getElement('div=Second render')
359+
).waitForDisplayed();
356360

357-
assert(
358-
await (await getElement('div=Second render')).isDisplayed(),
359-
'changing query causes custom tab to remount'
360-
);
361+
assert(
362+
await (await getElement('div=Second render')).isDisplayed(),
363+
'changing query causes custom tab to remount'
364+
);
365+
}
361366
});
362367
});
363368
};

end-to-end-test/remote/specs/core/groupComparison.screenshot.spec.js

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -510,7 +510,11 @@ describe('group comparison page screenshot tests', () => {
510510
).waitForDisplayed({
511511
timeout: 20000,
512512
});
513-
await jsApiHover(await getElementByTestHandle('infoIcon'));
513+
await jsApiHover(
514+
await getElementByTestHandle('infoIcon', {
515+
timeout: 20000,
516+
})
517+
);
514518

515519
await (
516520
await getElementByTestHandle('patientMultipleMutationsMessage')

src/pages/groupComparison/ClinicalData.tsx

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -151,7 +151,10 @@ export default class ClinicalData extends React.Component<
151151

152152
readonly tabUI = MakeMobxView({
153153
await: () => {
154-
const ret: any[] = [this.props.store.activeGroups];
154+
const ret: any[] = [
155+
this.props.store.activeGroups,
156+
this.props.store._activeGroupsNotOverlapRemoved,
157+
];
155158
if (
156159
this.props.store.activeGroups.isComplete &&
157160
this.props.store.activeGroups.result.length < 2

src/pages/groupComparison/GroupComparisonPage.tsx

Lines changed: 163 additions & 156 deletions
Large diffs are not rendered by default.

src/pages/resultsView/comparison/ComparisonTab.tsx

Lines changed: 113 additions & 115 deletions
Original file line numberDiff line numberDiff line change
@@ -24,7 +24,6 @@ import {
2424
import Survival from '../../groupComparison/Survival';
2525
import AlterationFilterWarning from '../../../shared/components/banners/AlterationFilterWarning';
2626
import OqlStatusBanner from '../../../shared/components/banners/OqlStatusBanner';
27-
import _ from 'lodash';
2827
import groupComparisonStyles from '../../../pages/groupComparison/styles.module.scss';
2928
import GroupSelector from '../../groupComparison/groupSelector/GroupSelector';
3029
import CaseFilterWarning from '../../../shared/components/banners/CaseFilterWarning';
@@ -35,10 +34,7 @@ import AlterationEnrichmentTypeSelector from 'shared/lib/comparison/AlterationEn
3534
import styles from 'pages/resultsView/comparison/styles.module.scss';
3635
import { getServerConfig } from 'config/config';
3736
import { AlterationFilterMenuSection } from 'pages/groupComparison/GroupComparisonUtils';
38-
import {
39-
getSortedGenericAssayAllTabSpecs,
40-
getSortedGenericAssayTabSpecs,
41-
} from 'shared/lib/GenericAssayUtils/GenericAssayCommonUtils';
37+
import { getSortedGenericAssayAllTabSpecs } from 'shared/lib/GenericAssayUtils/GenericAssayCommonUtils';
4238

4339
export interface IComparisonTabProps {
4440
urlWrapper: ResultsViewURLWrapper;
@@ -131,18 +127,7 @@ export default class ComparisonTab extends React.Component<
131127
}
132128

133129
readonly tabs = MakeMobxView({
134-
await: () => [
135-
this.store._activeGroupsNotOverlapRemoved,
136-
this.store.activeGroups,
137-
this.store.mutationEnrichmentProfiles,
138-
this.store.structuralVariantEnrichmentProfiles,
139-
this.store.copyNumberEnrichmentProfiles,
140-
this.store.mRNAEnrichmentProfiles,
141-
this.store.proteinEnrichmentProfiles,
142-
this.store.methylationEnrichmentProfiles,
143-
this.store.survivalClinicalDataExists,
144-
this.store.genericAssayEnrichmentProfilesGroupedByGenericAssayType,
145-
],
130+
await: () => [],
146131
render: () => {
147132
return (
148133
<MSKTabs
@@ -154,119 +139,132 @@ export default class ComparisonTab extends React.Component<
154139
<MSKTab id={GroupComparisonTab.OVERLAP} linkText="Overlap">
155140
<Overlap store={this.store} />
156141
</MSKTab>
157-
{this.store.showSurvivalTab && (
158-
<MSKTab
159-
id={GroupComparisonTab.SURVIVAL}
160-
linkText="Survival"
161-
anchorClassName={
162-
this.store.survivalTabUnavailable
163-
? 'greyedOut'
164-
: ''
165-
}
166-
>
167-
<Survival store={this.store} />
168-
</MSKTab>
169-
)}
142+
<MSKTab
143+
id={GroupComparisonTab.SURVIVAL}
144+
linkText="Survival"
145+
anchorClassName={
146+
!this.store.showSurvivalTab ||
147+
this.store.survivalTabUnavailable
148+
? 'hidden'
149+
: ''
150+
}
151+
pending={
152+
this.store.survivalClinicalDataExists.isPending
153+
}
154+
>
155+
<Survival
156+
store={this.store}
157+
key={`gc-survival-${this.store.overlapStrategy}`}
158+
/>
159+
</MSKTab>
170160
<MSKTab
171161
id={GroupComparisonTab.CLINICAL}
162+
pending={this.store.activeGroups.isPending}
172163
linkText="Clinical"
173164
anchorClassName={
174165
this.store.clinicalTabUnavailable ? 'greyedOut' : ''
175166
}
176167
>
177-
<ClinicalData store={this.store} />
168+
<ClinicalData
169+
store={this.store}
170+
key={`gc-clinical-data-${this.store.overlapStrategy}`}
171+
/>
178172
</MSKTab>
179-
{this.store.showAlterationsTab && (
180-
<MSKTab
181-
id={ResultsViewComparisonSubTab.ALTERATIONS}
182-
linkText={this.alterationEnrichmentTabName}
183-
anchorClassName={
184-
this.store.alterationsTabUnavailable
185-
? 'greyedOut'
186-
: ''
187-
}
188-
>
189-
{(this.store.activeGroups.isComplete &&
190-
this.store.activeGroups.result!.length > 1 &&
191-
getServerConfig().skin_show_settings_menu && (
192-
<AlterationFilterMenuSection
193-
store={this.store}
194-
updateSelectedEnrichmentEventTypes={
195-
this.store
196-
.updateSelectedEnrichmentEventTypes
197-
}
198-
/>
199-
)) || (
200-
<AlterationEnrichmentTypeSelector
201-
classNames={
202-
styles.inlineAlterationTypeSelectorMenu
203-
}
173+
<MSKTab
174+
id={ResultsViewComparisonSubTab.ALTERATIONS}
175+
pending={this.store.activeGroups.isPending}
176+
linkText={this.alterationEnrichmentTabName}
177+
anchorClassName={
178+
!this.store.showAlterationsTab ||
179+
this.store.alterationsTabUnavailable
180+
? 'hidden'
181+
: ''
182+
}
183+
>
184+
{(this.store.activeGroups.isComplete &&
185+
this.store.activeGroups.result!.length > 1 &&
186+
getServerConfig().skin_show_settings_menu && (
187+
<AlterationFilterMenuSection
204188
store={this.store}
205189
updateSelectedEnrichmentEventTypes={
206190
this.store
207191
.updateSelectedEnrichmentEventTypes
208192
}
209-
showMutations={
210-
this.store.hasMutationEnrichmentData
211-
}
212-
showCnas={this.store.hasCnaEnrichmentData}
213-
showStructuralVariants={
214-
this.store.hasStructuralVariantData
215-
}
216193
/>
217-
)}
218-
<AlterationEnrichments
219-
store={this.store}
220-
resultsViewStore={this.props.store}
221-
/>
222-
</MSKTab>
223-
)}
224-
{this.store.showMRNATab && (
225-
<MSKTab
226-
id={GroupComparisonTab.MRNA}
227-
linkText="mRNA"
228-
anchorClassName={
229-
this.store.mRNATabUnavailable ? 'greyedOut' : ''
230-
}
231-
>
232-
<MRNAEnrichments
233-
store={this.store}
234-
resultsViewMode={true}
235-
/>
236-
</MSKTab>
237-
)}
238-
{this.store.showProteinTab && (
239-
<MSKTab
240-
id={GroupComparisonTab.PROTEIN}
241-
linkText="Protein"
242-
anchorClassName={
243-
this.store.proteinTabUnavailable
244-
? 'greyedOut'
245-
: ''
246-
}
247-
>
248-
<ProteinEnrichments
249-
store={this.store}
250-
resultsViewMode={true}
251-
/>
252-
</MSKTab>
253-
)}
254-
{this.store.showMethylationTab && (
255-
<MSKTab
256-
id={GroupComparisonTab.DNAMETHYLATION}
257-
linkText="DNA Methylation"
258-
anchorClassName={
259-
this.store.methylationTabUnavailable
260-
? 'greyedOut'
261-
: ''
262-
}
263-
>
264-
<MethylationEnrichments
194+
)) || (
195+
<AlterationEnrichmentTypeSelector
196+
classNames={
197+
styles.inlineAlterationTypeSelectorMenu
198+
}
265199
store={this.store}
266-
resultsViewMode={true}
200+
updateSelectedEnrichmentEventTypes={
201+
this.store
202+
.updateSelectedEnrichmentEventTypes
203+
}
204+
showMutations={
205+
this.store.hasMutationEnrichmentData
206+
}
207+
showCnas={this.store.hasCnaEnrichmentData}
208+
showStructuralVariants={
209+
this.store.hasStructuralVariantData
210+
}
267211
/>
268-
</MSKTab>
269-
)}
212+
)}
213+
<AlterationEnrichments
214+
store={this.store}
215+
resultsViewStore={this.props.store}
216+
/>
217+
</MSKTab>
218+
<MSKTab
219+
id={GroupComparisonTab.MRNA}
220+
pending={this.store.mRNAEnrichmentProfiles.isPending}
221+
linkText="mRNA"
222+
anchorClassName={
223+
!this.store.showMRNATab ||
224+
this.store.mRNATabUnavailable
225+
? 'hidden'
226+
: ''
227+
}
228+
>
229+
<MRNAEnrichments
230+
store={this.store}
231+
resultsViewMode={true}
232+
/>
233+
</MSKTab>
234+
<MSKTab
235+
id={GroupComparisonTab.PROTEIN}
236+
pending={this.store.proteinEnrichmentProfiles.isPending}
237+
linkText="Protein"
238+
anchorClassName={
239+
!this.store.showProteinTab ||
240+
this.store.proteinTabUnavailable
241+
? 'hidden'
242+
: ''
243+
}
244+
>
245+
<ProteinEnrichments
246+
store={this.store}
247+
resultsViewMode={true}
248+
/>
249+
</MSKTab>
250+
<MSKTab
251+
id={GroupComparisonTab.DNAMETHYLATION}
252+
pending={
253+
this.store.methylationEnrichmentProfiles.isPending
254+
}
255+
linkText="DNA Methylation"
256+
anchorClassName={
257+
!this.store.showMethylationTab ||
258+
this.store.methylationTabUnavailable
259+
? 'hidden'
260+
: ''
261+
}
262+
>
263+
<MethylationEnrichments
264+
store={this.store}
265+
resultsViewMode={true}
266+
/>
267+
</MSKTab>
270268
{(this.store.showGenericAssayCategoricalTab ||
271269
this.store.showGenericAssayBinaryTab ||
272270
this.store.showGenericAssayTab) &&
@@ -287,7 +285,7 @@ export default class ComparisonTab extends React.Component<
287285
this.store
288286
.genericAssayBinaryTabUnavailable &&
289287
this.store.genericAssayTabUnavailable
290-
? 'greyedOut'
288+
? 'hidden'
291289
: ''
292290
}
293291
>

src/shared/components/MSKTabs/MSKTabs.spec.tsx

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -45,7 +45,8 @@ describe('MSKTabs', () => {
4545

4646
it('creates two tab buttons and toggles them properly', done => {
4747
setTimeout(() => {
48-
assert.equal(tabs.update().find('li').length, 2);
48+
// the number of actual tabs are 2, but we have an additional 'li' element for the loader icon
49+
assert.equal(tabs.update().find('li').length, 3);
4950
assert.isTrue(
5051
tabs
5152
.find('li')

src/shared/components/MSKTabs/MSKTabs.tsx

Lines changed: 11 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,16 +1,12 @@
11
import * as React from 'react';
22
import _ from 'lodash';
33
import classnames from 'classnames';
4-
import { ThreeBounce } from 'better-react-spinkit';
5-
import ReactResizeDetector from 'react-resize-detector';
64
import './styles.scss';
75
import autobind from 'autobind-decorator';
8-
import Spinner from 'react-spinkit';
96
import LoadingIndicator from '../loadingIndicator/LoadingIndicator';
107
import {
118
action,
129
autorun,
13-
computed,
1410
IReactionDisposer,
1511
makeObservable,
1612
observable,
@@ -268,7 +264,6 @@ export class MSKTabs extends React.Component<IMSKTabsProps> {
268264
)}
269265
>
270266
{this.navTabs(children, targetTabId)}
271-
272267
<DeferredRender
273268
className="tab-content"
274269
loadingState={
@@ -326,13 +321,24 @@ export class MSKTabs extends React.Component<IMSKTabsProps> {
326321

327322
const navButtonStyle: string = this.props.tabButtonStyle || 'tabs';
328323

324+
const isPending = React.Children.toArray(this.props.children).some(
325+
(c: any) => c.props.pending
326+
);
327+
329328
return (
330329
<ul
331330
ref={this.navTabsRefHandler.bind(this)}
332331
className={classnames('nav', `nav-${navButtonStyle}`)}
333332
>
334333
{prev}
335334
{pages[this.currentPage - 1]}
335+
<li>
336+
<LoadingIndicator
337+
isLoading={isPending}
338+
style={{ position: 'absolute', top: 10, minWidth: 50 }}
339+
small={true}
340+
/>
341+
</li>
336342
{next}
337343
</ul>
338344
);

0 commit comments

Comments
 (0)