diff --git a/LesionTracker/client/components/toolbarSection/toolbarSection.html b/LesionTracker/client/components/toolbarSection/toolbarSection.html index 45e1098d2..f58f85209 100644 --- a/LesionTracker/client/components/toolbarSection/toolbarSection.html +++ b/LesionTracker/client/components/toolbarSection/toolbarSection.html @@ -7,9 +7,6 @@ {{>toolbarSectionTools toolbarButtons=toolbarButtons}} -
- {{>caseProgress}} -
{{>roundedButtonGroup rightSidebarToggleButtonData}}
diff --git a/LesionTracker/client/lib/customCommands.js b/LesionTracker/client/lib/customCommands.js index 65e8057d3..1c4f3e674 100644 --- a/LesionTracker/client/lib/customCommands.js +++ b/LesionTracker/client/lib/customCommands.js @@ -33,38 +33,21 @@ Meteor.startup(() => { id: 'linkStackScroll', name: 'Link', action: OHIF.viewerbase.viewportUtils.linkStackScroll + }, { + id: 'saveMeasurements', + name: 'Save measurements', + hotkey: 'CTRL+S', + action() { + const activeTimepoint = OHIF.measurements.getActiveTimepoint(); + if (!activeTimepoint) return; + OHIF.measurements.saveMeasurements(OHIF.viewer.measurementApi, activeTimepoint.timepointId); + } }]; customCommands.forEach(command => { - _.defaults(OHIF.hotkeys.defaults[contextName], { [command.id]: '' }); + _.defaults(OHIF.hotkeys.defaults[contextName], { [command.id]: command.hotkey || '' }); OHIF.commands.register(contextName, command.id, { name: command.name, action: command.action || (() => toolManager.setActiveTool(command.id)) }); }); - - // Add the save command - OHIF.commands.register(contextName, 'storeMeasurements', () => { - // Register the hotkey default - _.defaults(OHIF.hotkeys.defaults[contextName], { storeMeasurements: '' }); - - // Clear signaled unsaved changes... - const successHandler = () => { - OHIF.ui.unsavedChanges.clear(`${instance.path}.*`); - instance.saveObserver.changed(); - }; - - // Display the error messages - const errorHandler = data => { - OHIF.ui.showDialog('dialogInfo', Object.assign({ class: 'themed' }, data)); - }; - - const promise = OHIF.viewer.measurementApi.storeMeasurements(); - promise.then(successHandler).catch(errorHandler); - OHIF.ui.showDialog('dialogLoading', { - promise, - text: 'Saving measurement data' - }); - - return promise; - }); }); diff --git a/Packages/ohif-measurements/both/configuration/measurements.js b/Packages/ohif-measurements/both/configuration/measurements.js index e323d0a4a..1f09c03f5 100644 --- a/Packages/ohif-measurements/both/configuration/measurements.js +++ b/Packages/ohif-measurements/both/configuration/measurements.js @@ -246,7 +246,7 @@ class MeasurementApi { }); } - storeMeasurements() { + storeMeasurements(timepointId) { const storeFn = configuration.dataExchange.store; if (!_.isFunction(storeFn)) { return; @@ -263,7 +263,8 @@ class MeasurementApi { }); }); - const timepoints = this.timepointApi.all(); + const timepointFilter = timepointId ? { timepointId } : {}; + const timepoints = this.timepointApi.all(timepointFilter); const timepointIds = timepoints.map(t => t.timepointId); const patientId = timepoints[0].patientId; const filter = { diff --git a/Packages/ohif-measurements/client/components/caseProgress/caseProgress.js b/Packages/ohif-measurements/client/components/caseProgress/caseProgress.js index 45286f9d9..e0d9f25dd 100644 --- a/Packages/ohif-measurements/client/components/caseProgress/caseProgress.js +++ b/Packages/ohif-measurements/client/components/caseProgress/caseProgress.js @@ -13,7 +13,7 @@ Template.caseProgress.onCreated(() => { Template.caseProgress.onRendered(() => { const instance = Template.instance(); - const { timepointApi, measurementApi } = instance.data; + const { timepointApi, measurementApi, timepointId } = instance.data; // Stop here if we have no current timepoint ID (and therefore no defined timepointAPI) if (!timepointApi) { @@ -22,8 +22,13 @@ Template.caseProgress.onRendered(() => { } // Get the current and prior timepoints - const current = timepointApi.current(); - const prior = timepointApi.prior(); + const current = timepointApi.timepoints.findOne({ timepointId }); + const priorFilter = { + latestDate: { $lt: current.latestDate }, + patientId: current.patientId + }; + const priorSorting = { sort: { latestDate: -1 } }; + const prior = timepointApi.timepoints.findOne(priorFilter, priorSorting); // Stop here if timepoint is locked if (current && current.isLocked) { diff --git a/Packages/ohif-measurements/client/components/caseProgress/caseProgress.styl b/Packages/ohif-measurements/client/components/caseProgress/caseProgress.styl index 75fe38230..f2970c8e1 100644 --- a/Packages/ohif-measurements/client/components/caseProgress/caseProgress.styl +++ b/Packages/ohif-measurements/client/components/caseProgress/caseProgress.styl @@ -1,4 +1,4 @@ -@import "{ohif:design}/app" +@require '{ohif:design}/app' .caseProgress transition(all 0.3 ease) @@ -14,7 +14,7 @@ h5 theme('color', '$textPrimaryColor') - line-height: 46px + line-height: 40px margin: 0 font-size: 15px font-weight: bold diff --git a/Packages/ohif-measurements/client/components/caseProgress/radialProgressBar/radialProgressBar.html b/Packages/ohif-measurements/client/components/caseProgress/radialProgressBar/radialProgressBar.html index 3002f9137..d554892b4 100644 --- a/Packages/ohif-measurements/client/components/caseProgress/radialProgressBar/radialProgressBar.html +++ b/Packages/ohif-measurements/client/components/caseProgress/radialProgressBar/radialProgressBar.html @@ -1,27 +1,27 @@ diff --git a/Packages/ohif-measurements/client/components/measurementTable/measurementTableTimepointHeader/measurementTableTimepointHeader.styl b/Packages/ohif-measurements/client/components/measurementTable/measurementTableTimepointHeader/measurementTableTimepointHeader.styl index 149f9210b..881d3b83a 100644 --- a/Packages/ohif-measurements/client/components/measurementTable/measurementTableTimepointHeader/measurementTableTimepointHeader.styl +++ b/Packages/ohif-measurements/client/components/measurementTable/measurementTableTimepointHeader/measurementTableTimepointHeader.styl @@ -1,10 +1,12 @@ -@import "{ohif:design}/app" +@require '{ohif:design}/app' .measurementTableTimepointHeader flex: 1 justify-content: space-around + padding-top: 2px + position: relative - div + .timepointName, .timepointDate theme('border-left', '%s solid $uiBorderColor' % $uiBorderThickness) font-weight: 400 padding-left: 12px @@ -20,3 +22,8 @@ font-size: 14px line-height: 20px padding-bottom: 6px + + .case-progress-container + position: absolute + right: 4px + top: 0 diff --git a/Packages/ohif-measurements/client/lib/index.js b/Packages/ohif-measurements/client/lib/index.js index 3e490ae55..520504dbb 100644 --- a/Packages/ohif-measurements/client/lib/index.js +++ b/Packages/ohif-measurements/client/lib/index.js @@ -14,6 +14,7 @@ import './hangingProtocolCustomizations'; import './MeasurementHandlers'; import './MeasurementManager'; import './navigateOverLesions'; +import './saveMeasurements'; import './syncMeasurementAndToolData'; import './toggleLabelButton'; import './triggerTimepointUnsavedChanges'; diff --git a/Packages/ohif-measurements/client/lib/saveMeasurements.js b/Packages/ohif-measurements/client/lib/saveMeasurements.js new file mode 100644 index 000000000..6b178da83 --- /dev/null +++ b/Packages/ohif-measurements/client/lib/saveMeasurements.js @@ -0,0 +1,31 @@ +import { OHIF } from 'meteor/ohif:core'; + +OHIF.measurements.saveMeasurements = (measurementApi, timepointId) => { + const { unsavedChanges, notifications, showDialog } = OHIF.ui; + const basePath = `viewer.studyViewer.measurements.${timepointId}`; + + // Stop here if there were no changes to the timepoint + if (unsavedChanges.probe(basePath) === 0) return; + + // Clear unsaved changes state and display success message + const successHandler = () => { + unsavedChanges.clear(basePath, true); + notifications.success({ text: 'The measurement data was successfully saved' }); + }; + + // Display the error messages + const errorHandler = data => { + showDialog('dialogInfo', Object.assign({ class: 'themed' }, data)); + }; + + // Call the storage method and display a loading overlay + const promise = measurementApi.storeMeasurements(timepointId); + promise.then(successHandler).catch(errorHandler); + showDialog('dialogLoading', { + promise, + text: 'Saving measurement data' + }); + + // Return the save promise + return promise; +};