/** * Copyright (c) 2018-2024 mol* contributors, licensed under MIT, See LICENSE file for more info. * * @author Aliaksei Chareshneu */ import { Button, ExpandGroup, IconButton, TextInput } from 'molstar/lib/mol-plugin-ui/controls/common'; import { sleep } from 'molstar/lib/mol-util/sleep'; import { actionSelectSegment, actionToggleAllFilteredSegments, actionToggleSegment } from './common'; import { WaitingButton } from './extensions/volumes-and-segmentations/ui'; import { createSegmentKey, parseSegmentKey } from './extensions/volumes-and-segmentations/volseg-api/utils'; import * as Icons from 'molstar/lib/mol-plugin-ui/controls/icons'; import { useBehavior } from 'molstar/lib/mol-plugin-ui/hooks/use-behavior'; import { VolsegEntryData } from './extensions/volumes-and-segmentations/entry-root'; import Markdown from 'react-markdown'; import { capitalize } from 'molstar/lib/mol-util/string'; import { useState } from 'react'; import { DescriptionData, DetailsText, ExternalReference } from './extensions/volumes-and-segmentations/volseg-api/data'; export function DescriptionTextUI({ descriptionText: d }: { descriptionText: DetailsText }) { if (d.format === 'markdown') { return <>

Description: {d.text} ; } else if (d.format === 'text') { return <>

Description:

{d.text}

; } } // Renders all external references export function ExternalReferencesUI({ externalReferences: e }: { externalReferences: ExternalReference[] }) { return <> {e.map(ref => { return

{ref.url ? {ref.resource}:{ref.accession} : {ref.resource}:{ref.accession}}
{capitalize(ref.label ? ref.label : '')}
{ref.description}

; } )} ; } export function EntryDescriptionUI({ entryDescriptionData: e }: { entryDescriptionData: DescriptionData }) { return
{e.name ?? ''} {e.details && } {e.external_references && }
; } export const MetadataTextFilter = ({ setFilteredDescriptions, descriptions, model }: { setFilteredDescriptions: any, descriptions: DescriptionData[], model: VolsegEntryData }) => { const [text, setText] = useState(''); function filterDescriptions(keyword: string) { return model.metadata!.value!.filterDescriptions(descriptions, keyword); } return ( { setText(newText); const filteredDescriptions = filterDescriptions(newText); setFilteredDescriptions(filteredDescriptions); }} /> ); }; export function DescriptionsListItem({ model, d, currentTimeframe, selectedSegmentDescription, visibleSegmentKeys }: { model: VolsegEntryData, d: DescriptionData, currentTimeframe: number, selectedSegmentDescription: DescriptionData | undefined, visibleSegmentKeys: string[] }) { const metadata = useBehavior(model.metadata); if (d.target_kind === 'entry' || !d.target_id || d.is_hidden === true) return; // NOTE: if time is a single number if (d.time && Number.isFinite(d.time) && d.time !== currentTimeframe) return; // NOTE: if time is array if (d.time && Array.isArray(d.time) && d.time.every(i => Number.isFinite(i)) && !(d.time as number[]).includes(currentTimeframe)) return; const segmentKey = createSegmentKey(d.target_id.segment_id, d.target_id.segmentation_id, d.target_kind); const targetDescriptionCurrent = metadata!.raw.annotation!.descriptions[d.id]; d = targetDescriptionCurrent; if (d.target_kind === 'entry' || !d.target_id || d.is_hidden === true) return; return
actionToggleSegment(model, segmentKey)} />
; } export function DescriptionsList({ model, targetSegmentationId, targetKind }: { model: VolsegEntryData, targetSegmentationId: string, targetKind: 'lattice' | 'mesh' | 'primitive' }) { const state = useBehavior(model.currentState); const currentTimeframe = useBehavior(model.currentTimeframe); const metadata = useBehavior(model.metadata); const allDescriptionsForSegmentationId = metadata!.getDescriptions( targetSegmentationId, targetKind, currentTimeframe ); const [filteredDescriptions, setFilteredDescriptions] = useState(allDescriptionsForSegmentationId); const parsedSelectedSegmentKey = parseSegmentKey(state.selectedSegment); const { segmentId, segmentationId, kind } = parsedSelectedSegmentKey; const selectedSegmentDescriptions = model.metadata.value!.getSegmentDescription(segmentId, segmentationId, kind); // NOTE: for now single description const selectedSegmentDescription = selectedSegmentDescriptions ? selectedSegmentDescriptions[0] : undefined; const visibleSegmentKeys = state.visibleSegments.map(seg => seg.segmentKey); return <> {filteredDescriptions.length > 0 &&
{ await sleep(20); await actionToggleAllFilteredSegments(model, targetSegmentationId, targetKind, filteredDescriptions); }} style={{ marginTop: 1 }}> Toggle All segments
{filteredDescriptions.map(d => { return ; } )}
}; } export function SelectedSegmentDescription({ model, targetSegmentationId, targetKind }: { model: VolsegEntryData, targetSegmentationId: string, targetKind: 'lattice' | 'mesh' | 'primitive' }) { const state = useBehavior(model.currentState); useBehavior(model.currentTimeframe); const metadata = useBehavior(model.metadata); const anyDescriptions = metadata!.allDescriptions.length > 0; const parsedSelectedSegmentKey = parseSegmentKey(state.selectedSegment); const { segmentId, segmentationId, kind } = parsedSelectedSegmentKey; const selectedSegmentDescriptions = model.metadata.value!.getSegmentDescription(segmentId, segmentationId, kind); // NOTE: for now single description const selectedSegmentDescription = selectedSegmentDescriptions ? selectedSegmentDescriptions[0] : undefined; return <>{ anyDescriptions &&
{!selectedSegmentDescription && 'No segment selected'} {selectedSegmentDescription && selectedSegmentDescription.target_kind !== 'entry' && selectedSegmentDescription.target_id && Segment {selectedSegmentDescription.target_id.segment_id} from segmentation {selectedSegmentDescription.target_id.segmentation_id}:
{selectedSegmentDescription.name ?? 'Unnamed segment'}
} {selectedSegmentDescription && selectedSegmentDescription.details && } {selectedSegmentDescription?.external_references && }
}; }