Merge pull request #1843 from dannyrb/dannyrb/polish-viewport-notification-save-round-trip
Dannyrb/polish viewport notification save round trip
This commit is contained in:
commit
25de9046b3
@ -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 <div className="text-primary-active">Loading...</div>;
|
||||||
|
}
|
||||||
|
|
||||||
|
export default createReportAsync;
|
||||||
@ -19,25 +19,33 @@ const useTrackedMeasurements = () => useContext(TrackedMeasurementsContext);
|
|||||||
* @param {*} param0
|
* @param {*} param0
|
||||||
*/
|
*/
|
||||||
function TrackedMeasurementsContextProvider(
|
function TrackedMeasurementsContextProvider(
|
||||||
UIViewportDialogService,
|
{ servicesManager, extensionManager }, // Bound by consumer
|
||||||
{ children }
|
{ children } // Component props
|
||||||
) {
|
) {
|
||||||
const machineOptions = Object.assign({}, defaultOptions);
|
const machineOptions = Object.assign({}, defaultOptions);
|
||||||
machineOptions.services = Object.assign({}, machineOptions.services, {
|
machineOptions.services = Object.assign({}, machineOptions.services, {
|
||||||
promptBeginTracking: promptBeginTracking.bind(
|
promptBeginTracking: promptBeginTracking.bind(null, {
|
||||||
null,
|
servicesManager,
|
||||||
UIViewportDialogService
|
extensionManager,
|
||||||
),
|
}),
|
||||||
promptTrackNewSeries: promptTrackNewSeries.bind(
|
promptTrackNewSeries: promptTrackNewSeries.bind(null, {
|
||||||
null,
|
servicesManager,
|
||||||
UIViewportDialogService
|
extensionManager,
|
||||||
),
|
}),
|
||||||
promptTrackNewStudy: promptTrackNewStudy.bind(
|
promptTrackNewStudy: promptTrackNewStudy.bind(null, {
|
||||||
null,
|
servicesManager,
|
||||||
UIViewportDialogService
|
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(
|
const measurementTrackingMachine = Machine(
|
||||||
machineConfiguration,
|
machineConfiguration,
|
||||||
@ -61,6 +69,8 @@ function TrackedMeasurementsContextProvider(
|
|||||||
|
|
||||||
TrackedMeasurementsContextProvider.propTypes = {
|
TrackedMeasurementsContextProvider.propTypes = {
|
||||||
children: PropTypes.oneOf([PropTypes.func, PropTypes.node]),
|
children: PropTypes.oneOf([PropTypes.func, PropTypes.node]),
|
||||||
|
servicesManager: PropTypes.object.isRequired,
|
||||||
|
extensionManager: PropTypes.object.isRequired,
|
||||||
};
|
};
|
||||||
|
|
||||||
export {
|
export {
|
||||||
|
|||||||
@ -6,7 +6,8 @@ const RESPONSE = {
|
|||||||
SET_STUDY_AND_SERIES: 3,
|
SET_STUDY_AND_SERIES: 3,
|
||||||
};
|
};
|
||||||
|
|
||||||
function promptUser(UIViewportDialogService, ctx, evt) {
|
function promptUser({ servicesManager }, ctx, evt) {
|
||||||
|
const { UIViewportDialogService } = servicesManager.services;
|
||||||
const { viewportIndex, StudyInstanceUID, SeriesInstanceUID } = evt;
|
const { viewportIndex, StudyInstanceUID, SeriesInstanceUID } = evt;
|
||||||
|
|
||||||
return new Promise(async function(resolve, reject) {
|
return new Promise(async function(resolve, reject) {
|
||||||
|
|||||||
@ -1,3 +1,5 @@
|
|||||||
|
import createReportAsync from './../../_shared/createReportAsync.js';
|
||||||
|
|
||||||
const RESPONSE = {
|
const RESPONSE = {
|
||||||
NO_NEVER: -1,
|
NO_NEVER: -1,
|
||||||
CANCEL: 0,
|
CANCEL: 0,
|
||||||
@ -6,8 +8,13 @@ const RESPONSE = {
|
|||||||
SET_STUDY_AND_SERIES: 3,
|
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 { viewportIndex, StudyInstanceUID, SeriesInstanceUID } = evt;
|
||||||
|
const { trackedStudy, trackedSeries } = ctx;
|
||||||
|
|
||||||
return new Promise(async function(resolve, reject) {
|
return new Promise(async function(resolve, reject) {
|
||||||
let promptResult = await _askShouldAddMeasurements(
|
let promptResult = await _askShouldAddMeasurements(
|
||||||
@ -22,9 +29,19 @@ function promptUser(UIViewportDialogService, ctx, evt) {
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
// TODO: Hook into @JamesAPetts createReport
|
|
||||||
if (promptResult === RESPONSE.CREATE_REPORT) {
|
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({
|
resolve({
|
||||||
|
|||||||
@ -1,3 +1,5 @@
|
|||||||
|
import createReportAsync from './../../_shared/createReportAsync.js';
|
||||||
|
|
||||||
const RESPONSE = {
|
const RESPONSE = {
|
||||||
NO_NEVER: -1,
|
NO_NEVER: -1,
|
||||||
CANCEL: 0,
|
CANCEL: 0,
|
||||||
@ -6,8 +8,13 @@ const RESPONSE = {
|
|||||||
SET_STUDY_AND_SERIES: 3,
|
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 { viewportIndex, StudyInstanceUID, SeriesInstanceUID } = evt;
|
||||||
|
const { trackedStudy, trackedSeries } = ctx;
|
||||||
|
|
||||||
return new Promise(async function(resolve, reject) {
|
return new Promise(async function(resolve, reject) {
|
||||||
let promptResult = await _askTrackMeasurements(
|
let promptResult = await _askTrackMeasurements(
|
||||||
@ -22,9 +29,19 @@ function promptUser(UIViewportDialogService, ctx, evt) {
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
// TODO: Hook into @JamesAPetts createReport
|
|
||||||
if (promptResult === RESPONSE.CREATE_REPORT) {
|
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({
|
resolve({
|
||||||
|
|||||||
@ -4,11 +4,10 @@ import {
|
|||||||
useTrackedMeasurements,
|
useTrackedMeasurements,
|
||||||
} from './contexts';
|
} from './contexts';
|
||||||
|
|
||||||
function getContextModule({ servicesManager }) {
|
function getContextModule({ servicesManager, extensionManager }) {
|
||||||
const { UIViewportDialogService } = servicesManager.services;
|
|
||||||
const BoundTrackedMeasurementsContextProvider = TrackedMeasurementsContextProvider.bind(
|
const BoundTrackedMeasurementsContextProvider = TrackedMeasurementsContextProvider.bind(
|
||||||
null,
|
null,
|
||||||
UIViewportDialogService
|
{ servicesManager, extensionManager }
|
||||||
);
|
);
|
||||||
|
|
||||||
return [
|
return [
|
||||||
|
|||||||
@ -5,6 +5,7 @@ import { DicomMetadataStore, DICOMSR } from '@ohif/core';
|
|||||||
import { useDebounce } from '@hooks';
|
import { useDebounce } from '@hooks';
|
||||||
import ActionButtons from './ActionButtons';
|
import ActionButtons from './ActionButtons';
|
||||||
import { useTrackedMeasurements } from '../../getContextModule';
|
import { useTrackedMeasurements } from '../../getContextModule';
|
||||||
|
import createReportAsync from './../../_shared/createReportAsync.js';
|
||||||
|
|
||||||
const DISPLAY_STUDY_SUMMARY_INITIAL_VALUE = {
|
const DISPLAY_STUDY_SUMMARY_INITIAL_VALUE = {
|
||||||
key: undefined, //
|
key: undefined, //
|
||||||
@ -21,12 +22,7 @@ function PanelMeasurementTableTracking({ servicesManager, extensionManager }) {
|
|||||||
measurementChangeTimestamp,
|
measurementChangeTimestamp,
|
||||||
200
|
200
|
||||||
);
|
);
|
||||||
const {
|
const { MeasurementService } = servicesManager.services;
|
||||||
MeasurementService,
|
|
||||||
UINotificationService,
|
|
||||||
UIDialogService,
|
|
||||||
DisplaySetService,
|
|
||||||
} = servicesManager.services;
|
|
||||||
const [
|
const [
|
||||||
trackedMeasurements,
|
trackedMeasurements,
|
||||||
sendTrackedMeasurementsEvent,
|
sendTrackedMeasurementsEvent,
|
||||||
@ -103,9 +99,24 @@ function PanelMeasurementTableTracking({ servicesManager, extensionManager }) {
|
|||||||
};
|
};
|
||||||
}, [MeasurementService, sendTrackedMeasurementsEvent]);
|
}, [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 measurements = MeasurementService.getMeasurements();
|
||||||
const trackedMeasurements = measurements.filter(
|
const trackedMeasurements = measurements.filter(
|
||||||
m =>
|
m =>
|
||||||
@ -115,53 +126,7 @@ function PanelMeasurementTableTracking({ servicesManager, extensionManager }) {
|
|||||||
|
|
||||||
// TODO -> local download.
|
// TODO -> local download.
|
||||||
DICOMSR.downloadReport(trackedMeasurements, dataSource);
|
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: () => <div className="text-primary-active">Loading...</div>,
|
|
||||||
});
|
|
||||||
|
|
||||||
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 (
|
return (
|
||||||
<>
|
<>
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user