diff --git a/extensions/measurement-tracking/src/_shared/createReportAsync.js b/extensions/measurement-tracking/src/_shared/createReportAsync.js new file mode 100644 index 000000000..326ad249b --- /dev/null +++ b/extensions/measurement-tracking/src/_shared/createReportAsync.js @@ -0,0 +1,47 @@ +import React from 'react'; +import { DICOMSR } from '@ohif/core'; + +async function createReportAsync(servicesManager, dataSource, measurements) { + const { + UINotificationService, + UIDialogService, + DisplaySetService, + } = servicesManager.services; + const loadingDialogId = UIDialogService.create({ + showOverlay: true, + isDraggable: false, + centralize: true, + // TODO: Create a loading indicator component + zeplin design? + content: Loading, + }); + + try { + const naturalizedReport = await DICOMSR.storeMeasurements( + measurements, + dataSource + ); + + DisplaySetService.makeDisplaySets([naturalizedReport], { + madeInClient: true, + }); + UINotificationService.show({ + title: 'STOW SR', + message: 'Measurements saved successfully', + type: 'success', + }); + } catch (error) { + UINotificationService.show({ + title: 'STOW SR', + message: error.message || 'Failed to store measurements', + type: 'error', + }); + } finally { + UIDialogService.dismiss({ id: loadingDialogId }); + } +} + +function Loading() { + return
Loading...
; +} + +export default createReportAsync; diff --git a/extensions/measurement-tracking/src/contexts/TrackedMeasurementsContext/TrackedMeasurementsContext.jsx b/extensions/measurement-tracking/src/contexts/TrackedMeasurementsContext/TrackedMeasurementsContext.jsx index 5081deaad..3ff87f663 100644 --- a/extensions/measurement-tracking/src/contexts/TrackedMeasurementsContext/TrackedMeasurementsContext.jsx +++ b/extensions/measurement-tracking/src/contexts/TrackedMeasurementsContext/TrackedMeasurementsContext.jsx @@ -19,25 +19,33 @@ const useTrackedMeasurements = () => useContext(TrackedMeasurementsContext); * @param {*} param0 */ function TrackedMeasurementsContextProvider( - UIViewportDialogService, - { children } + { servicesManager, extensionManager }, // Bound by consumer + { children } // Component props ) { const machineOptions = Object.assign({}, defaultOptions); machineOptions.services = Object.assign({}, machineOptions.services, { - promptBeginTracking: promptBeginTracking.bind( - null, - UIViewportDialogService - ), - promptTrackNewSeries: promptTrackNewSeries.bind( - null, - UIViewportDialogService - ), - promptTrackNewStudy: promptTrackNewStudy.bind( - null, - UIViewportDialogService - ), + promptBeginTracking: promptBeginTracking.bind(null, { + servicesManager, + extensionManager, + }), + promptTrackNewSeries: promptTrackNewSeries.bind(null, { + servicesManager, + extensionManager, + }), + promptTrackNewStudy: promptTrackNewStudy.bind(null, { + servicesManager, + extensionManager, + }), }); + // TODO: IMPROVE + // - Add measurement_updated to cornerstone; debounced? (ext side, or consumption?) + // - Friendlier transition/api in front of measurementTracking machine? + // - Blocked: viewport overlay shouldn't clip when resized + // TODO: PRIORITY + // - Fix "ellipses" series description dynamic truncate length + // - Fix viewport border resize + // - created/destroyed hooks for extensions (cornerstone measurement subscriptions in it's `init`) const measurementTrackingMachine = Machine( machineConfiguration, @@ -61,6 +69,8 @@ function TrackedMeasurementsContextProvider( TrackedMeasurementsContextProvider.propTypes = { children: PropTypes.oneOf([PropTypes.func, PropTypes.node]), + servicesManager: PropTypes.object.isRequired, + extensionManager: PropTypes.object.isRequired, }; export { diff --git a/extensions/measurement-tracking/src/contexts/TrackedMeasurementsContext/promptBeginTracking.js b/extensions/measurement-tracking/src/contexts/TrackedMeasurementsContext/promptBeginTracking.js index 657c24e66..57a6188fd 100644 --- a/extensions/measurement-tracking/src/contexts/TrackedMeasurementsContext/promptBeginTracking.js +++ b/extensions/measurement-tracking/src/contexts/TrackedMeasurementsContext/promptBeginTracking.js @@ -6,7 +6,8 @@ const RESPONSE = { SET_STUDY_AND_SERIES: 3, }; -function promptUser(UIViewportDialogService, ctx, evt) { +function promptUser({ servicesManager }, ctx, evt) { + const { UIViewportDialogService } = servicesManager.services; const { viewportIndex, StudyInstanceUID, SeriesInstanceUID } = evt; return new Promise(async function(resolve, reject) { diff --git a/extensions/measurement-tracking/src/contexts/TrackedMeasurementsContext/promptTrackNewSeries.js b/extensions/measurement-tracking/src/contexts/TrackedMeasurementsContext/promptTrackNewSeries.js index 4a6f7dcc1..2370ef65d 100644 --- a/extensions/measurement-tracking/src/contexts/TrackedMeasurementsContext/promptTrackNewSeries.js +++ b/extensions/measurement-tracking/src/contexts/TrackedMeasurementsContext/promptTrackNewSeries.js @@ -1,3 +1,5 @@ +import createReportAsync from './../../_shared/createReportAsync.js'; + const RESPONSE = { NO_NEVER: -1, CANCEL: 0, @@ -6,8 +8,13 @@ const RESPONSE = { SET_STUDY_AND_SERIES: 3, }; -function promptUser(UIViewportDialogService, ctx, evt) { +function promptUser({ servicesManager, extensionManager }, ctx, evt) { + const { + UIViewportDialogService, + MeasurementService, + } = servicesManager.services; const { viewportIndex, StudyInstanceUID, SeriesInstanceUID } = evt; + const { trackedStudy, trackedSeries } = ctx; return new Promise(async function(resolve, reject) { let promptResult = await _askShouldAddMeasurements( @@ -22,9 +29,19 @@ function promptUser(UIViewportDialogService, ctx, evt) { ); } - // TODO: Hook into @JamesAPetts createReport if (promptResult === RESPONSE.CREATE_REPORT) { - window.alert('CREATE REPORT'); + // TODO -> Eventually deal with multiple dataSources. + // Would need some way of saying which one is the "push" dataSource + const dataSources = extensionManager.getDataSources(); + const dataSource = dataSources[0]; + const measurements = MeasurementService.getMeasurements(); + const trackedMeasurements = measurements.filter( + m => + trackedStudy === m.referenceStudyUID && + trackedSeries.includes(m.referenceSeriesUID) + ); + + createReportAsync(servicesManager, dataSource, trackedMeasurements); } resolve({ diff --git a/extensions/measurement-tracking/src/contexts/TrackedMeasurementsContext/promptTrackNewStudy.js b/extensions/measurement-tracking/src/contexts/TrackedMeasurementsContext/promptTrackNewStudy.js index 0f8842a31..62513f0cd 100644 --- a/extensions/measurement-tracking/src/contexts/TrackedMeasurementsContext/promptTrackNewStudy.js +++ b/extensions/measurement-tracking/src/contexts/TrackedMeasurementsContext/promptTrackNewStudy.js @@ -1,3 +1,5 @@ +import createReportAsync from './../../_shared/createReportAsync.js'; + const RESPONSE = { NO_NEVER: -1, CANCEL: 0, @@ -6,8 +8,13 @@ const RESPONSE = { SET_STUDY_AND_SERIES: 3, }; -function promptUser(UIViewportDialogService, ctx, evt) { +function promptUser({ servicesManager, extensionManager }, ctx, evt) { + const { + UIViewportDialogService, + MeasurementService, + } = servicesManager.services; const { viewportIndex, StudyInstanceUID, SeriesInstanceUID } = evt; + const { trackedStudy, trackedSeries } = ctx; return new Promise(async function(resolve, reject) { let promptResult = await _askTrackMeasurements( @@ -22,9 +29,19 @@ function promptUser(UIViewportDialogService, ctx, evt) { ); } - // TODO: Hook into @JamesAPetts createReport if (promptResult === RESPONSE.CREATE_REPORT) { - window.alert('CREATE REPORT'); + // TODO -> Eventually deal with multiple dataSources. + // Would need some way of saying which one is the "push" dataSource + const dataSources = extensionManager.getDataSources(); + const dataSource = dataSources[0]; + const measurements = MeasurementService.getMeasurements(); + const trackedMeasurements = measurements.filter( + m => + trackedStudy === m.referenceStudyUID && + trackedSeries.includes(m.referenceSeriesUID) + ); + + createReportAsync(servicesManager, dataSource, trackedMeasurements); } resolve({ diff --git a/extensions/measurement-tracking/src/getContextModule.js b/extensions/measurement-tracking/src/getContextModule.js index 573a00fa2..29acdc402 100644 --- a/extensions/measurement-tracking/src/getContextModule.js +++ b/extensions/measurement-tracking/src/getContextModule.js @@ -4,11 +4,10 @@ import { useTrackedMeasurements, } from './contexts'; -function getContextModule({ servicesManager }) { - const { UIViewportDialogService } = servicesManager.services; +function getContextModule({ servicesManager, extensionManager }) { const BoundTrackedMeasurementsContextProvider = TrackedMeasurementsContextProvider.bind( null, - UIViewportDialogService + { servicesManager, extensionManager } ); return [ diff --git a/extensions/measurement-tracking/src/panels/PanelMeasurementTableTracking/index.js b/extensions/measurement-tracking/src/panels/PanelMeasurementTableTracking/index.js index e8381f39f..1200d2dfa 100644 --- a/extensions/measurement-tracking/src/panels/PanelMeasurementTableTracking/index.js +++ b/extensions/measurement-tracking/src/panels/PanelMeasurementTableTracking/index.js @@ -5,6 +5,7 @@ import { DicomMetadataStore, DICOMSR } from '@ohif/core'; import { useDebounce } from '@hooks'; import ActionButtons from './ActionButtons'; import { useTrackedMeasurements } from '../../getContextModule'; +import createReportAsync from './../../_shared/createReportAsync.js'; const DISPLAY_STUDY_SUMMARY_INITIAL_VALUE = { key: undefined, // @@ -21,12 +22,7 @@ function PanelMeasurementTableTracking({ servicesManager, extensionManager }) { measurementChangeTimestamp, 200 ); - const { - MeasurementService, - UINotificationService, - UIDialogService, - DisplaySetService, - } = servicesManager.services; + const { MeasurementService } = servicesManager.services; const [ trackedMeasurements, sendTrackedMeasurementsEvent, @@ -103,9 +99,24 @@ function PanelMeasurementTableTracking({ servicesManager, extensionManager }) { }; }, [MeasurementService, sendTrackedMeasurementsEvent]); - const activeMeasurementItem = 0; + function createReport() { + // TODO -> Eventually deal with multiple dataSources. + // Would need some way of saying which one is the "push" dataSource + const dataSources = extensionManager.getDataSources(); + const dataSource = dataSources[0]; + const measurements = MeasurementService.getMeasurements(); + const trackedMeasurements = measurements.filter( + m => + trackedStudy === m.referenceStudyUID && + trackedSeries.includes(m.referenceSeriesUID) + ); - const exportReport = () => { + return createReportAsync(servicesManager, dataSource, trackedMeasurements); + } + + function exportReport() { + const dataSources = extensionManager.getDataSources(); + const dataSource = dataSources[0]; const measurements = MeasurementService.getMeasurements(); const trackedMeasurements = measurements.filter( m => @@ -115,53 +126,7 @@ function PanelMeasurementTableTracking({ servicesManager, extensionManager }) { // TODO -> local download. DICOMSR.downloadReport(trackedMeasurements, dataSource); - }; - - const createReport = async () => { - const loadingDialogId = UIDialogService.create({ - showOverlay: true, - isDraggable: false, - centralize: true, - // TODO: Create a loading indicator component + zeplin design? - content: () =>
Loading...
, - }); - - try { - const measurements = MeasurementService.getMeasurements(); - const trackedMeasurements = measurements.filter( - m => - trackedStudy === m.referenceStudyUID && - trackedSeries.includes(m.referenceSeriesUID) - ); - - const dataSources = extensionManager.getDataSources(); - // TODO -> Eventually deal with multiple dataSources. - // Would need some way of saying which one is the "push" dataSource - const dataSource = dataSources[0]; - - const naturalizedReport = await DICOMSR.storeMeasurements( - trackedMeasurements, - dataSource - ); - - DisplaySetService.makeDisplaySets([naturalizedReport], { - madeInClient: true, - }); - UINotificationService.show({ - title: 'STOW SR', - message: 'Measurements saved successfully', - type: 'success', - }); - } catch (error) { - UINotificationService.show({ - title: 'STOW SR', - message: error.message || 'Failed to store measurements', - type: 'error', - }); - } finally { - UIDialogService.dismiss({ id: loadingDialogId }); - } - }; + } return ( <>