import * as React from 'react';
import { CancerStudy } from 'cbioportal-ts-api-client';
import * as styles_any from './styles.module.scss';
import classNames from 'classnames';
import FontAwesome from 'react-fontawesome';
import LabeledCheckbox from '../../labeledCheckbox/LabeledCheckbox';
import { observer, Observer } from 'mobx-react';
import { computed, makeObservable } from 'mobx';
import _ from 'lodash';
import { getPubMedUrl } from '../../../api/urls';
import { QueryStoreComponent } from '../QueryStore';
import { DefaultTooltip } from 'cbioportal-frontend-commons';
import { FilteredCancerTreeView } from '../StudyListLogic';
import {
CancerTreeNode,
CancerTypeWithVisibility,
} from '../CancerStudyTreeData';
import { StudyLink } from '../../StudyLink/StudyLink';
import StudyTagsTooltip, {
IconType,
} from '../../studyTagsTooltip/StudyTagsTooltip';
import { formatStudyReferenceGenome } from 'shared/lib/referenceGenomeUtils';
import { getServerConfig } from 'config/config';
const styles = {
...styles_any,
Level: (level: number) => (styles_any as any)[`Level${level}`],
};
export interface IStudyListProps {
showSelectedStudiesOnly?: boolean;
}
@observer
export default class StudyList extends QueryStoreComponent<
IStudyListProps,
{}
> {
private _view: FilteredCancerTreeView;
get view() {
return (
this._view ||
(this.props.showSelectedStudiesOnly
? this.logic.selectedStudiesView
: this.logic.mainView)
);
}
get logic() {
return this.store.studyListLogic;
}
get rootCancerType() {
return this.store.treeData.rootCancerType;
}
componentDidMount() {
// when rendering selected studies view,
// cache the view object so studies do not disappear immediately when deselected.
if (this.props.showSelectedStudiesOnly) this._view = this.view;
}
render() {
let studyList = this.renderCancerType(this.rootCancerType);
if (this.props.showSelectedStudiesOnly) {
return (
{
this.view.onCheck(
this.store.treeData.rootCancerType,
false
);
this.store.showSelectedStudiesOnly = false;
}}
>
Deselect all
{studyList}
);
}
return studyList;
}
renderCancerType = (
cancerType: CancerTypeWithVisibility,
arrayIndex: number = 0
): JSX.Element | null => {
let currentLevel = this.logic.getDepth(cancerType);
let childCancerTypes = this.view.getChildCancerTypes(cancerType);
let childStudies = this.view.getChildCancerStudies(cancerType);
let childStudyIds = this.logic.cancerTypeListView
.getDescendantCancerStudies(cancerType)
.map(study => study.studyId);
let heading: JSX.Element | undefined;
let indentArrow: JSX.Element | undefined;
if (cancerType != this.rootCancerType) {
let liClassName = classNames(
styles.CancerType,
styles.Level(currentLevel)
// this.logic.isHighlighted(cancerType) && styles.highlighted
);
if (currentLevel === 3)
indentArrow = (
);
heading = (
{indentArrow}
{cancerType.name}
{!this.store.forDownloadTab && (
{_.intersection(
childStudyIds,
this.store.selectableSelectedStudyIds
).length
? 'Deselect All'
: 'Select All'}
)}
);
}
let ulClassName = classNames(
styles.StudyList,
styles.Level(currentLevel)
);
return (
{heading}
{childStudies.map(this.renderCancerStudy)}
{childCancerTypes.map(this.renderCancerType)}
);
};
renderCancerStudy = (study: CancerStudy, arrayIndex: number) => {
let liClassName = classNames(
styles.Study
// this.logic.isHighlighted(study) && styles.highlighted
);
const isOverlap = study.studyId in this.store.getOverlappingStudiesMap;
const overlapWarning = isOverlap ? (
This study has overlapping data with another selected
study.
}
>
) : null;
const isMixedReferenceGenome =
_.includes(this.store.selectableSelectedStudyIds, study.studyId) &&
this.store.isMixedReferenceGenome;
const mixedReferenceGenomeWarning = isMixedReferenceGenome ? (
You are combining studies with molecular data based on
both GRCh37/hg19 and GRCh38/hg38. This is not fully
supported yet. Please double check your findings
}
>
{' '}
{formatStudyReferenceGenome(study.referenceGenome)}
) : null;
return (
{() => {
const classes = classNames({
[styles.StudyName]: true,
overlappingStudy:
isOverlap || isMixedReferenceGenome,
[styles.DeletedStudy]: this.store.isDeletedVirtualStudy(
study.studyId
),
[`studyItem_${study.studyId}`]: true,
[styles.UnauthorizedStudy]:
getServerConfig()
.skin_home_page_show_unauthorized_studies &&
study.readPermission === false,
});
return (
{study.name}
{overlapWarning}
{mixedReferenceGenomeWarning}
);
}}
{() => {
return (
{!this.store.isDeletedVirtualStudy(
study.studyId
) && this.renderSamples(study)}
{this.renderStudyLinks(study)}
);
}}
);
};
// renderStudyName = (study:CancerStudy, afterName?:any) =>
// {
// return (
//
//
// {study.name} {afterName || null}
//
//
// );
// }
renderSamples = (study: CancerStudy) => {
return (
{`${study.allSampleCount} samples`}
);
};
renderStudyLinks = (study: CancerStudy) => {
if (this.store.isDeletedVirtualStudy(study.studyId)) {
return (
Restore study
}
children={
this.store.restoreVirtualStudy(study.studyId)
}
style={{
lineHeight: '80%',
}}
data-test="virtualStudyRestore"
>
Restore
}
/>
);
} else {
const links: {
icon: string;
onClick?: string | (() => void);
tooltip?: string;
}[] = [
{
icon: 'info-circle',
tooltip: '',
},
];
if (this.store.isVirtualStudy(study.studyId)) {
links.push({
icon: 'trash',
tooltip: 'Delete this virtual study.',
onClick: () => this.store.deleteVirtualStudy(study.studyId),
});
} else {
links.push({
icon: 'book',
onClick: study.pmid && getPubMedUrl(study.pmid),
tooltip: study.pmid && 'PubMed',
});
}
return (
{links.map((link, i) => {
let content = (
);
if (link.onClick) {
let anchorProps: any = {
key: i,
};
if (typeof link.onClick === 'string') {
anchorProps.href = link.onClick;
anchorProps.target = '_blank';
} else {
anchorProps.onClick = link.onClick;
}
content = {content} ;
}
if (link.tooltip) {
let overlay = (
);
content = (
);
}
if (link.icon === 'info-circle') {
content = (
'
)
: study.description
}
studyId={study.studyId}
isVirtualStudy={this.store.isVirtualStudy(
study.studyId
)}
mouseEnterDelay={0}
placement="top"
iconType={IconType.INFO_ICON}
>
{content}
);
}
return content;
})}
{study.studyId && (
View clinical and genomic data of this study
}
>
)}
{getServerConfig()
.skin_home_page_show_unauthorized_studies &&
study.studyId &&
study.readPermission === false && (
'
)
: study.description
}
studyId={study.studyId}
isVirtualStudy={this.store.isVirtualStudy(
study.studyId
)}
mouseEnterDelay={0}
placement="top"
iconType={IconType.LOCK_ICON}
>
)}
);
}
};
}
export interface ICancerTreeCheckboxProps {
view: FilteredCancerTreeView;
node: CancerTreeNode;
}
@observer
export class CancerTreeCheckbox extends QueryStoreComponent<
ICancerTreeCheckboxProps,
{}
> {
constructor(props: any) {
super(props);
makeObservable(this);
}
@computed.struct get checkboxProps() {
return this.props.view.getCheckboxProps(this.props.node);
}
render() {
return (
{
this.props.view.onCheck(
this.props.node,
(event.target as HTMLInputElement).checked
);
}}
>
{this.props.children}
);
}
}