diff --git a/extensions/measurement-tracking/src/panels/PanelStudyBrowserTracking/PanelStudyBrowserTracking.jsx b/extensions/measurement-tracking/src/panels/PanelStudyBrowserTracking/PanelStudyBrowserTracking.jsx index 4e09222af..e44d34fb3 100644 --- a/extensions/measurement-tracking/src/panels/PanelStudyBrowserTracking/PanelStudyBrowserTracking.jsx +++ b/extensions/measurement-tracking/src/panels/PanelStudyBrowserTracking/PanelStudyBrowserTracking.jsx @@ -32,12 +32,7 @@ function PanelStudyBrowserTracking({ const [displaySets, setDisplaySets] = useState([]); const [thumbnailImageSrcMap, setThumbnailImageSrcMap] = useState({}); - // Listen for measurement service "adds" (really shouldn't be added until cornerstone-tools "complete") - // const { - // MEASUREMENT_ADDED, - // MEASUREMENT_UPDATED, - // } = measurementService.EVENTS; - + // TODO: Listen for measurement service "adds" (really shouldn't be added until cornerstone-tools "complete") useEffect(() => { const { unsubscribe } = MeasurementService.subscribe( MeasurementService.EVENTS.MEASUREMENT_ADDED, @@ -58,11 +53,7 @@ function PanelStudyBrowserTracking({ ); return unsubscribe; - }, []); - - // TODO: REPLACE ME - useEffect(() => { - }, [sendTrackedMeasurementsEvent]); + }, [MeasurementService, sendTrackedMeasurementsEvent]); const { trackedStudy, trackedSeries } = trackedMeasurements.context; diff --git a/extensions/measurement-tracking/src/viewports/OHIFCornerstoneViewport.js b/extensions/measurement-tracking/src/viewports/OHIFCornerstoneViewport.js index 6a2705873..27c039e9b 100644 --- a/extensions/measurement-tracking/src/viewports/OHIFCornerstoneViewport.js +++ b/extensions/measurement-tracking/src/viewports/OHIFCornerstoneViewport.js @@ -1,4 +1,4 @@ -import React, { Component } from 'react'; +import React, { useEffect, useState } from 'react'; import PropTypes from 'prop-types'; import cornerstone from 'cornerstone-core'; import CornerstoneViewport from 'react-cornerstone-viewport'; @@ -7,6 +7,11 @@ import { ViewportActionBar } from '@ohif/ui'; import debounce from 'lodash.debounce'; import throttle from 'lodash.throttle'; +// const [ +// trackedMeasurements, +// sendTrackedMeasurementsEvent, +// ] = useTrackedMeasurements(); + // const cine = viewportSpecificData.cine; @@ -15,78 +20,22 @@ import throttle from 'lodash.throttle'; const { StackManager } = OHIF.utils; -class OHIFCornerstoneViewport extends Component { - state = { - viewportData: null, - }; - - static defaultProps = { - customProps: {}, - }; - - static propTypes = { - displaySet: PropTypes.object, - viewportIndex: PropTypes.number, - dataSource: PropTypes.object, - children: PropTypes.node, - customProps: PropTypes.object, - }; - - static name = 'OHIFCornerstoneViewport'; - - static init() { - console.log('OHIFCornerstoneViewport init()'); - } - +function OHIFCornerstoneViewport({ + children, + dataSource, + displaySet, + viewportIndex, +}) { + const [viewportData, setViewportData] = useState(null); // TODO: Still needed? Better way than import `OHIF` and destructure? // Why is this managed by `core`? - static destroy() { - console.log('OHIFCornerstoneViewport destroy()'); - StackManager.clearStacks(); - } - - /** - * Obtain the CornerstoneTools Stack for the specified display set. - * - * @param {Object} displaySet - * @param {Object} dataSource - * @return {Object} CornerstoneTools Stack - */ - static getCornerstoneStack(displaySet, dataSource) { - const { frameIndex } = displaySet; - - // Get stack from Stack Manager - const storedStack = StackManager.findOrCreateStack(displaySet, dataSource); - - // Clone the stack here so we don't mutate it - const stack = Object.assign({}, storedStack); - - stack.currentImageIdIndex = frameIndex; - - return stack; - } - - getViewportData = async displaySet => { - let viewportData; - - const { dataSource } = this.props; - - const stack = OHIFCornerstoneViewport.getCornerstoneStack( - displaySet, - dataSource - ); - - viewportData = { - StudyInstanceUID: displaySet.StudyInstanceUID, - displaySetInstanceUID: displaySet.displaySetInstanceUID, - stack, + useEffect(() => { + return () => { + StackManager.clearStacks(); }; + }, []); - return viewportData; - }; - - setStateFromProps() { - const { displaySet } = this.props; + useEffect(() => { const { StudyInstanceUID, displaySetInstanceUID, @@ -103,112 +52,149 @@ class OHIFCornerstoneViewport extends Component { ); } - this.getViewportData(displaySet).then(viewportData => { - this.setState({ - viewportData, - }); + _getViewportData(dataSource, displaySet).then(viewportData => { + setViewportData({ ...viewportData }); + }); + }, [ + displaySet, + displaySet.StudyInstanceUID, + displaySet.displaySetInstanceUID, + displaySet.frameIndex, + ]); + + // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + let childrenWithProps = null; + + if (!viewportData) { + return null; + } + + const { + imageIds, + currentImageIdIndex, + // If this comes from the instance, would be a better default + // `FrameTime` in the instance + // frameRate = 0, + } = viewportData.stack; + + // TODO: Does it make more sense to use Context? + if (children && children.length) { + childrenWithProps = children.map((child, index) => { + return ( + child && + React.cloneElement(child, { + viewportIndex, + key: index, + }) + ); }); } - componentDidMount() { - this.setStateFromProps(); - } + // We have... + // StudyInstanceUid, DisplaySetInstanceUid + // Use displaySetInstanceUid --> SeriesInstanceUid + // Get meta for series, map to actionBar + // const displaySet = DisplaySetService.getDisplaySetByUID( + // dSet.displaySetInstanceUID + // ); + // TODO: This display contains the meta for all instances. + // That can't be right... + console.log('DISPLAYSET', displaySet) + // const seriesMeta = DicomMetadataStore.getSeries(this.props.displaySet.StudyInstanceUID, ''); + // console.log(seriesMeta); - componentDidUpdate(prevProps) { - const { displaySet } = this.props; - const prevDisplaySet = prevProps.displaySet; + const { Modality, SeriesDate, SeriesDescription, SeriesNumber } = displaySet; + const { + PatientID, + PatientName, + PatientSex, + PatientAge, + SliceThickness, + } = displaySet.images[0]; - if ( - displaySet.displaySetInstanceUID !== - prevDisplaySet.displaySetInstanceUID || - displaySet.SOPInstanceUID !== prevDisplaySet.SOPInstanceUID || - displaySet.frameIndex !== prevDisplaySet.frameIndex - ) { - this.setStateFromProps(); - } - } - - render() { - let childrenWithProps = null; - - if (!this.state.viewportData) { - return null; - } - const { viewportIndex } = this.props; - const { - imageIds, - currentImageIdIndex, - // If this comes from the instance, would be a better default - // `FrameTime` in the instance - // frameRate = 0, - } = this.state.viewportData.stack; - - // TODO: Does it make more sense to use Context? - if (this.props.children && this.props.children.length) { - childrenWithProps = this.props.children.map((child, index) => { - return ( - child && - React.cloneElement(child, { - viewportIndex: this.props.viewportIndex, - key: index, - }) - ); - }); - } - - // We have... - // StudyInstanceUid, DisplaySetInstanceUid - // Use displaySetInstanceUid --> SeriesInstanceUid - // Get meta for series, map to actionBar - // const displaySet = DisplaySetService.getDisplaySetByUID( - // dSet.displaySetInstanceUID - // ); - // TODO: This display contains the meta for all instances. - // That can't be right... - console.log('DISPLAYSET', this.props.displaySet) - const seriesMeta = DicomMetadataStore.getSeries(this.props.displaySet.StudyInstanceUID, ''); - console.log(seriesMeta); - - const { Modality, SeriesDate, SeriesDescription, SeriesNumber } = this.props.displaySet; - const { PatientID, PatientName, PatientSex, PatientAge, SliceThickness, } = this.props.displaySet.images[0]; - - return ( - <> - alert(`Series ${direction}`)} - studyData={{ - label: '', - isTracked: false, - isLocked: false, - studyDate: SeriesDate, // TODO: This is series date. Is that ok? - currentSeries: SeriesNumber, - seriesDescription: SeriesDescription, - modality: Modality, - patientInformation: { - patientName: PatientName ? PatientName.Alphabetic || '' : '', - patientSex: PatientSex || '', - patientAge: PatientAge || '', - MRN: PatientID || '', - thickness: `${SliceThickness}mm`, - spacing: '', - scanner: '', - }, - }} - /> - - {childrenWithProps} - - ); - } + return ( + <> + alert(`Series ${direction}`)} + studyData={{ + label: '', + isTracked: false, + isLocked: false, + studyDate: SeriesDate, // TODO: This is series date. Is that ok? + currentSeries: SeriesNumber, + seriesDescription: SeriesDescription, + modality: Modality, + patientInformation: { + patientName: PatientName ? PatientName.Alphabetic || '' : '', + patientSex: PatientSex || '', + patientAge: PatientAge || '', + MRN: PatientID || '', + thickness: `${SliceThickness}mm`, + spacing: '', + scanner: '', + }, + }} + /> + + {childrenWithProps} + + ); } +OHIFCornerstoneViewport.propTypes = { + displaySet: PropTypes.object.isRequired, + viewportIndex: PropTypes.number.isRequired, + dataSource: PropTypes.object, + children: PropTypes.node, + customProps: PropTypes.object, +}; + +OHIFCornerstoneViewport.defaultProps = { + customProps: {}, +}; + +/** + * Obtain the CornerstoneTools Stack for the specified display set. + * + * @param {Object} displaySet + * @param {Object} dataSource + * @return {Object} CornerstoneTools Stack + */ +function _getCornerstoneStack(displaySet, dataSource) { + const { frameIndex } = displaySet; + + // Get stack from Stack Manager + const storedStack = StackManager.findOrCreateStack(displaySet, dataSource); + + // Clone the stack here so we don't mutate it + const stack = Object.assign({}, storedStack); + + stack.currentImageIdIndex = frameIndex; + + return stack; +} + +async function _getViewportData(dataSource, displaySet) { + let viewportData; + + const stack = _getCornerstoneStack(displaySet, dataSource); + + viewportData = { + StudyInstanceUID: displaySet.StudyInstanceUID, + displaySetInstanceUID: displaySet.displaySetInstanceUID, + stack, + }; + + return viewportData; +}; + export default OHIFCornerstoneViewport;