import * as React from 'react'; import * as _ from 'lodash'; import { observer } from 'mobx-react'; import { action, computed, makeObservable, observable } from 'mobx'; import { default as Track, TrackProps } from './Track'; import { Collapse } from 'react-collapse'; import { TrackItemSpec } from './TrackItem'; import { MutationMapperStore } from '../../model/MutationMapperStore'; import { Mutation, UniprotTopology, UniprotTopologyTypeToTitle, UniprotTopologyTrackToColor, } from 'cbioportal-utils'; import { DefaultTooltip, EllipsisTextTooltip, } from 'cbioportal-frontend-commons'; type UniprotTopologyTrackProps = TrackProps & { store: MutationMapperStore; subTrackMargin?: number; collapsed?: boolean; }; function topologyRectangleBlockSpec( color: string, title: string, uniprotData: UniprotTopology ) { return { color: color, startCodon: uniprotData.startPosition, endCodon: uniprotData.endPosition, tooltip: (
{title}
Start: {uniprotData.startPosition}

End: {uniprotData.endPosition}

Length: {uniprotData.endPosition - uniprotData.startPosition}

Description: {uniprotData.description}
), }; } export const UniprotTopologyTrackDescriptionTooltip: React.FunctionComponent<{ displayList: string[]; uniprotId?: string; }> = props => { const dataSourceDiv = props.uniprotId ? (
Data Source:{' '} UniProt
) : (
Data Source:{' '} UniProt
); return (

Information of the subcellular location of the mature protein.

{props.displayList.length > 0 && (

Domains and corresponding color codes are as follows:

)} {dataSourceDiv}
); }; @observer export default class UniprotTopologyTrack extends React.Component< UniprotTopologyTrackProps, {} > { constructor(props: any) { super(props); makeObservable(this); } public static defaultProps = { subTrackMargin: 25, }; @observable private expanded = !this.props.collapsed; @computed get subTrackMargin() { return ( this.props.subTrackMargin || UniprotTopologyTrack.defaultProps.subTrackMargin ); } @computed get subTrackTitleWidth() { return this.props.xOffset ? this.props.xOffset - this.subTrackMargin : 0; } @computed get uniprotTopologySpecs(): TrackItemSpec[] { const uniprotData = this.props.store.uniprotTopologyData.result; if (uniprotData && !_.isEmpty(uniprotData)) { return _.reduce( uniprotData, this.uniprotDataToTrackItemSpecsReducer, [] ); } else { return []; } } @computed get expander(): JSX.Element | null { const className = this.hasSubTracks ? this.mainTrackHidden ? 'fa fa-caret-down' : 'fa fa-caret-right' : null; if (className) { return ( ); } return null; } @computed get mainTrackTitle() { return ( {this.expander} } destroyTooltipOnHide={true} > Topology ); } @computed get uniprotTopologyTypes(): string[] { const uniprotData = this.props.store.uniprotTopologyData.result; const uniprotDataByType = _.uniq(_.map(uniprotData, data => data.type)); return uniprotDataByType || []; } @computed get uniprotTopologySubSpecs(): { title: string; specs: TrackItemSpec[]; }[] { const uniprotData = this.props.store.uniprotTopologyData.result; const uniprotDataByType = _.groupBy(uniprotData, data => data.type); return _.keys(uniprotDataByType) .map(type => ({ title: UniprotTopologyTypeToTitle[type], specs: _.reduce( uniprotDataByType[type], this.uniprotDataToTrackItemSpecsReducer, [] ), })) .filter(s => !_.isEmpty(s.specs)); } private uniprotDataToTrackItemSpecsReducer = ( acc: TrackItemSpec[], uniprotData: UniprotTopology ): TrackItemSpec[] => { const trackColor = UniprotTopologyTrackToColor[uniprotData.type]; const trackTitle = UniprotTopologyTypeToTitle[uniprotData.type]; if (trackTitle && trackColor) { acc.push( topologyRectangleBlockSpec(trackColor, trackTitle, uniprotData) ); } return acc; }; @computed get mainTrackHidden() { return this.expanded && this.hasSubTracks; } @computed get hasSubTracks() { return this.uniprotTopologySubSpecs.length > 0; } @computed get subTracks() { return this.hasSubTracks ? this.uniprotTopologySubSpecs.map((item, index) => ( } width={this.props.width} proteinLength={this.props.proteinLength} trackItems={item.specs} idClassPrefix={`uniprot-topology-${index}-`} isSubTrack={true} /> )) : null; } public render() { return ( {this.subTracks} ); } @action.bound private handleToggleExpand() { this.expanded = !this.expanded; } }