import * as React from 'react'; import _ from 'lodash'; import styles from './styles.module.scss'; import { observer } from 'mobx-react'; import { computed, observable, action, makeObservable } from 'mobx'; import { CancerStudy, Sample } from 'cbioportal-ts-api-client'; import classnames from 'classnames'; import { DefaultTooltip, remoteData } from 'cbioportal-frontend-commons'; import sessionServiceClient from 'shared/api//sessionServiceInstance'; import { If, Then, Else } from 'react-if'; import { buildCBioPortalPageUrl, getStudySummaryUrl } from 'shared/api/urls'; import { ChartMeta } from 'pages/studyView/StudyViewUtils'; import { getVirtualStudyDescription, getCurrentDate, StudyViewFilterWithSampleIdentifierFilters, StudyWithSamples, } from 'pages/studyView/StudyViewUtils'; import autobind from 'autobind-decorator'; import { serializeEvent } from '../../../shared/lib/tracking'; const Clipboard = require('clipboard'); export interface IVirtualStudyProps { studyWithSamples: StudyWithSamples[]; selectedSamples: Sample[]; filter: StudyViewFilterWithSampleIdentifierFilters; attributesMetaSet: { [id: string]: ChartMeta }; molecularProfileNameSet: { [key: string]: string }; caseListNameSet: { [key: string]: string }; name?: string; description?: string; user?: string; } @observer export class StudySummaryRecord extends React.Component { @observable private showDescription = false; constructor(props: CancerStudy) { super(props); makeObservable(this); } render() { return (
(this.showDescription = !this .showDescription) } /> {this.props.name}
' )}`, }} />
); } } @observer export default class VirtualStudy extends React.Component< IVirtualStudyProps, {} > { @observable.ref private name: string; @observable.ref private description: string; @observable private saving = false; @observable private sharing = false; @observable private copied = false; constructor(props: IVirtualStudyProps) { super(props); makeObservable(this); this.name = props.name || ''; this.description = props.description || getVirtualStudyDescription( this.props.description, this.props.studyWithSamples, this.props.filter, this.attributeNamesSet, this.props.molecularProfileNameSet, this.props.caseListNameSet, this.props.user ); } @computed get namePlaceHolder() { return `Selected sample${ this.props.selectedSamples.length > 1 ? 's' : '' } (${getCurrentDate()})`; } @computed get buttonsDisabled() { return _.isEmpty(this.namePlaceHolder) && _.isEmpty(this.name); } readonly virtualStudy = remoteData( { invoke: async () => { if (this.saving || this.sharing) { let selectedSampleSet = _.groupBy( this.props.selectedSamples, (sample: Sample) => sample.studyId ); let studies = _.reduce( selectedSampleSet, ( acc: { id: string; samples: string[] }[], samples, studyId ) => { acc.push({ id: studyId, samples: samples.map(sample => sample.sampleId), }); return acc; }, [] ); let { sampleIdentifiersSet, ...studyViewFilter } = this.props.filter; let parameters = { name: this.name || this.namePlaceHolder, description: this.description, studyViewFilter: studyViewFilter, origin: this.props.studyWithSamples.map( study => study.studyId ), studies: studies, }; return await sessionServiceClient.saveVirtualStudy( parameters, this.saving ); } return undefined; }, }, undefined ); @computed get virtualStudyUrl() { // TODO: update path name once fully refactored return buildCBioPortalPageUrl({ pathname: 'study', query: { id: this.virtualStudy.result ? this.virtualStudy.result.id : '', }, }); } @autobind private copyLinkRef(el: HTMLAnchorElement | null) { if (el) { new Clipboard(el, { text: () => this.virtualStudyUrl, }); } } @action.bound onCopyClick() { this.copied = true; } @action.bound private onTooltipVisibleChange(visible: boolean) { this.copied = !visible; } @computed get showSaveButton() { //default value of userEmailAddress is anonymousUser. see my-index.ejs return !( _.isUndefined(this.props.user) || _.isEmpty(this.props.user) || _.isEqual(this.props.user.toLowerCase(), 'anonymoususer') ); } @computed get attributeNamesSet() { return _.reduce( this.props.attributesMetaSet, (acc: { [id: string]: string }, next, key) => { acc[key] = next.displayName; return acc; }, {} ); } render() { return (