import _ from 'lodash'; import * as React from 'react'; import ReactDOM from 'react-dom'; import { TypeOfCancer as CancerType } from 'cbioportal-ts-api-client'; import { FlexCol, FlexRow } from '../flexbox/FlexBox'; import styles from './styles/styles.module.scss'; import classNames from 'classnames'; import StudyList from './studyList/StudyList'; import { observer, Observer } from 'mobx-react'; import { action, computed, IReactionDisposer, reaction, makeObservable, } from 'mobx'; import { expr } from 'mobx-utils'; import memoize from 'memoize-weak-decorator'; import { If, Then, Else } from 'react-if'; import { QueryStore } from './QueryStore'; import SectionHeader from '../sectionHeader/SectionHeader'; import { Modal } from 'react-bootstrap'; import { getServerConfig } from 'config/config'; import { ServerConfigHelpers } from '../../../config/config'; import { PAN_CAN_SIGNATURE } from './StudyListLogic'; import QuickSelectButtons from './QuickSelectButtons'; import { StudySelectorStats } from 'shared/components/query/StudySelectorStats'; import WindowStore from 'shared/components/window/WindowStore'; import { StudySearch } from 'shared/components/query/StudySearch'; const MIN_LIST_HEIGHT = 200; export interface ICancerStudySelectorProps { style?: React.CSSProperties; queryStore: QueryStore; forkedMode: boolean; aboveStudyListBlurb?: JSX.Element; } @observer export default class CancerStudySelector extends React.Component< ICancerStudySelectorProps, {} > { @computed get studiesDataComplete(): boolean { return ( this.store.cancerTypes.isComplete && this.store.cancerStudies.isComplete && this.store.userVirtualStudies.isComplete ); } private handlers = { onSummaryClick: () => { this.store.openSummary(); }, onCheckAllFiltered: () => { this.logic.mainView.toggleAllFiltered(); }, onClearFilter: () => { this.store.setSearchText(''); }, }; public store: QueryStore; constructor(props: ICancerStudySelectorProps) { super(props); makeObservable(this); this.store = this.props.queryStore; } get logic() { return this.store.studyListLogic; } @memoize getCancerTypeListClickHandler(node: CancerType) { return (event: React.MouseEvent) => this.store.selectCancerType(node as CancerType, event.ctrlKey); } CancerTypeList = observer(() => { let cancerTypes = this.logic.cancerTypeListView.getChildCancerTypes( this.store.treeData.rootCancerType ); return ( ); }); CancerTypeListItem = observer( ({ cancerType }: { cancerType: CancerType }) => { let numStudies = expr( () => this.logic.cancerTypeListView.getDescendantCancerStudies( cancerType ).length ); let selected = _.includes( this.store.selectedCancerTypeIds, cancerType.cancerTypeId ); let highlighted = this.logic.isHighlighted(cancerType); let liClassName = classNames({ [styles.selectable]: true, [styles.selected]: selected, [styles.matchingNodeText]: !!this.store.searchText && highlighted, [styles.nonMatchingNodeText]: !!this.store.searchText && !highlighted, [styles.containsSelectedStudies]: expr(() => this.logic.cancerTypeContainsSelectedStudies(cancerType) ), }); return (
  • {cancerType.name} {numStudies}
  • ); } ); @action.bound selectTCGAPanAtlas() { this.logic.mainView.selectAllMatchingStudies(PAN_CAN_SIGNATURE); } @action.bound selectMatchingStudies(matches: string[]) { if (matches) { // if there is only one item and it has wildcard markers (*) then pass single string // otherwise pass array of exactly matching studyIds if (matches.length === 1 && /^\*.*\*$/.test(matches[0])) { // match wildcard of one this.logic.mainView.selectAllMatchingStudies( matches[0].replace(/\*/g, '') ); } else { this.logic.mainView.selectAllMatchingStudies(matches); } } } private windowSizeDisposer: IReactionDisposer; componentDidMount(): void { let resizeTimeout: any; this.windowSizeDisposer = reaction( () => { return WindowStore.size; }, () => { if (this.props.forkedMode) { clearTimeout(resizeTimeout); resizeTimeout = setTimeout(() => this.setListHeight(), 200); } }, { fireImmediately: true } ); } componentWillUnmount(): void { this.windowSizeDisposer(); } setListHeight() { const $el = $(ReactDOM.findDOMNode(this) as HTMLDivElement); var h = WindowStore.size.height - $el.offset()!.top; h = h < MIN_LIST_HEIGHT ? MIN_LIST_HEIGHT : h; // impose limit $el.css('height', h - 75); } render() { const { shownStudies, shownAndSelectedStudies, } = this.logic.mainView.getSelectionReport(); const quickSetButtons = this.logic.mainView.quickSelectButtons( getServerConfig().skin_quick_select_buttons ); return ( Select Studies for Visualization & Analysis: {this.store.selectableStudiesSet.isComplete && (
    )} {() => { let searchTextOptions = ServerConfigHelpers.skin_example_study_queries( getServerConfig()!.skin_example_study_queries || '' ); if ( this.store.searchText && searchTextOptions.indexOf( this.store.searchText ) < 0 ) searchTextOptions = [ this.store.searchText, ].concat(searchTextOptions as string[]); let searchTimeout: number | null = null; return (
    {this.store.queryParser && ( (this.store.searchClauses = query) } /> )}
    ); }}
    0}>
    0}>

    There are no studies matching your filter.

    {this.props.aboveStudyListBlurb}
    (this.store.showSelectedStudiesOnly = false)} > Selected Studies
    ); } }