Adding separate save buttons for measurements

This commit is contained in:
Bruno Alves de Faria 2018-01-25 17:20:07 -02:00
parent 5dc2f8dc9c
commit 7da787c3f8
16 changed files with 72 additions and 114 deletions

View File

@ -110,6 +110,9 @@ function keyDownCallback(event, eventData) {
nearbyToolData.toolType, nearbyToolData.toolType,
eventData.element eventData.element
); );
// Notify that viewer suffered changes
OHIF.measurements.triggerTimepointUnsavedChanges('deleted');
}).catch(unlock); }).catch(unlock);
} }
} }

View File

@ -8,8 +8,5 @@
</div> </div>
{{/if}} {{/if}}
{{/if}} {{/if}}
<div class="caseProgressStatus">
{{#button class='btn p-x-2' action='save' disabled=(isFinishDisabled)}}Save{{/button}}
</div>
{{/form}} {{/form}}
</template> </template>

View File

@ -1,7 +1,5 @@
import { Template } from 'meteor/templating'; import { Template } from 'meteor/templating';
import { ReactiveVar } from 'meteor/reactive-var'; import { ReactiveVar } from 'meteor/reactive-var';
import { Session } from 'meteor/session';
import { Tracker } from 'meteor/tracker';
import { OHIF } from 'meteor/ohif:core'; import { OHIF } from 'meteor/ohif:core';
Template.caseProgress.onCreated(() => { Template.caseProgress.onCreated(() => {
@ -11,48 +9,6 @@ Template.caseProgress.onCreated(() => {
instance.progressText = new ReactiveVar(); instance.progressText = new ReactiveVar();
instance.isLocked = new ReactiveVar(false); instance.isLocked = new ReactiveVar(false);
instance.isFollowUp = new ReactiveVar(false); instance.isFollowUp = new ReactiveVar(false);
instance.path = 'viewer.studyViewer.measurements';
instance.saveObserver = new Tracker.Dependency();
instance.api = {
save() {
// 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 = instance.data.measurementApi.storeMeasurements();
promise.then(successHandler).catch(errorHandler);
OHIF.ui.showDialog('dialogLoading', {
promise,
text: 'Saving measurement data'
});
return promise;
}
};
instance.unsavedChangesHandler = () => {
const isNotDisabled = !instance.$('.js-finish-case').hasClass('disabled');
if (isNotDisabled && instance.progressPercent.get() === 100) {
instance.api.save();
}
};
// Attach handler for unsaved changes dialog...
OHIF.ui.unsavedChanges.attachHandler(instance.path, 'save', instance.unsavedChangesHandler);
});
Template.caseProgress.onDestroyed(() => {
const instance = Template.instance();
// Remove unsaved changes handler after this view has been destroyed...
OHIF.ui.unsavedChanges.removeHandler(instance.path, 'save', instance.unsavedChangesHandler);
}); });
Template.caseProgress.onRendered(() => { Template.caseProgress.onRendered(() => {
@ -178,16 +134,5 @@ Template.caseProgress.helpers({
const progressPercent = instance.progressPercent.get(); const progressPercent = instance.progressPercent.get();
return progressPercent === 100; return progressPercent === 100;
},
isFinishDisabled() {
const instance = Template.instance();
// Run this computation on save or every time any measurement / timepoint suffer changes
OHIF.ui.unsavedChanges.depend();
instance.saveObserver.depend();
Session.get('LayoutManagerUpdated');
return OHIF.ui.unsavedChanges.probe('viewer.*') === 0;
} }
}); });

View File

@ -94,10 +94,7 @@ Template.measurementTableRow.events({
_.each($('.imageViewerViewport'), element => cornerstone.updateImage(element)); _.each($('.imageViewerViewport'), element => cornerstone.updateImage(element));
// Notify that viewer suffered changes // Notify that viewer suffered changes
const { timepointId } = measurement; OHIF.measurements.triggerTimepointUnsavedChanges('deleted');
const basePath = 'viewer.studyViewer.measurements';
const timepointPath = timepointId ? `.${timepointId}` : '';
OHIF.ui.unsavedChanges.set(`${basePath}${timepointPath}.deleted`);
}); });
} }
}); });

View File

@ -89,9 +89,6 @@ export default function ({ instance, eventData, tool, toolGroupId, toolGroup })
}); });
} }
// Signal unsaved changes // Notify that viewer suffered changes
const { timepointId } = Collection.findOne(measurementData._id); OHIF.measurements.triggerTimepointUnsavedChanges(eventData.toolType);
const basePath = 'viewer.studyViewer.measurements';
const timepointPath = timepointId ? `.${timepointId}` : '';
OHIF.ui.unsavedChanges.set(`${basePath}${timepointPath}.${eventData.toolType}`);
} }

View File

@ -35,9 +35,6 @@ export default function ({ instance, eventData, tool, toolGroupId, toolGroup })
// Update the measurement in the collection // Update the measurement in the collection
Collection.update(measurement._id, { $set: { [tool.attribute]: childMeasurement } }); Collection.update(measurement._id, { $set: { [tool.attribute]: childMeasurement } });
// Signal unsaved changes // Notify that viewer suffered changes
const { timepointId } = Collection.findOne(measurementData._id); OHIF.measurements.triggerTimepointUnsavedChanges(eventData.toolType);
const basePath = 'viewer.studyViewer.measurements';
const timepointPath = timepointId ? `.${timepointId}` : '';
OHIF.ui.unsavedChanges.set(`${basePath}${timepointPath}.${eventData.toolType}`);
} }

View File

@ -35,9 +35,6 @@ export default function ({ instance, eventData, tool, toolGroupId, toolGroup })
// Repaint the images on all viewports without the removed measurements // Repaint the images on all viewports without the removed measurements
_.each($('.imageViewerViewport'), element => cornerstone.updateImage(element)); _.each($('.imageViewerViewport'), element => cornerstone.updateImage(element));
// Signal unsaved changes // Notify that viewer suffered changes
const { timepointId } = Collection.findOne(measurementData._id); OHIF.measurements.triggerTimepointUnsavedChanges(eventData.toolType);
const basePath = 'viewer.studyViewer.measurements';
const timepointPath = timepointId ? `.${timepointId}` : '';
OHIF.ui.unsavedChanges.set(`${basePath}${timepointPath}.${eventData.toolType}`);
} }

View File

@ -48,9 +48,6 @@ export default function ({ instance, eventData, tool }) {
cornerstone.updateImage(OHIF.viewerbase.viewportUtils.getActiveViewportElement()); cornerstone.updateImage(OHIF.viewerbase.viewportUtils.getActiveViewportElement());
}); });
// Signal unsaved changes // Notify that viewer suffered changes
const { timepointId } = Collection.findOne(measurementData._id); OHIF.measurements.triggerTimepointUnsavedChanges(eventData.toolType);
const basePath = 'viewer.studyViewer.measurements';
const timepointPath = timepointId ? `.${timepointId}` : '';
OHIF.ui.unsavedChanges.set(`${basePath}${timepointPath}.${eventData.toolType}`);
} }

View File

@ -37,9 +37,6 @@ export default function ({ instance, eventData, tool, toolGroupId, toolGroup })
// Update the measurement in the collection // Update the measurement in the collection
Collection.update(measurementId, { $set: measurement }); Collection.update(measurementId, { $set: measurement });
// Signal unsaved changes // Notify that viewer suffered changes
const { timepointId } = Collection.findOne(measurementData._id); OHIF.measurements.triggerTimepointUnsavedChanges(eventData.toolType);
const basePath = 'viewer.studyViewer.measurements';
const timepointPath = timepointId ? `.${timepointId}` : '';
OHIF.ui.unsavedChanges.set(`${basePath}${timepointPath}.${eventData.toolType}`);
} }

View File

@ -32,8 +32,6 @@ export default function({ instance, eventData, tool, toolGroupId, toolGroup }) {
// Repaint the images on all viewports without the removed measurements // Repaint the images on all viewports without the removed measurements
_.each($('.imageViewerViewport'), element => cornerstone.updateImage(element)); _.each($('.imageViewerViewport'), element => cornerstone.updateImage(element));
// Signal unsaved changes // Notify that viewer suffered changes
const basePath = 'viewer.studyViewer.measurements'; OHIF.measurements.triggerTimepointUnsavedChanges(eventData.toolType);
const timepointPath = timepointId ? `.${timepointId}` : '';
OHIF.ui.unsavedChanges.set(`${basePath}${timepointPath}.${eventData.toolType}`);
} }

View File

@ -0,0 +1,13 @@
import { Session } from 'meteor/session';
import { OHIF } from 'meteor/ohif:core';
/**
* Extensible method to get the timepoint of the active viewport
*
* @returns {Object} - Timepoint data for the active viewport
*/
OHIF.measurements.getActiveTimepoint = () => {
const activeViewportIndex = Session.get('activeViewport');
const { studyInstanceUid } = OHIF.viewerbase.layoutManager.viewportData[activeViewportIndex];
return OHIF.viewer.timepointApi.study(studyInstanceUid)[0];
};

View File

@ -4,6 +4,7 @@ import './clearCornerstoneToolState';
import './deactivateAllToolData'; import './deactivateAllToolData';
import './exportPdf'; import './exportPdf';
import './findAndRenderDisplaySet'; import './findAndRenderDisplaySet';
import './getActiveTimepoint';
import './getImageDataUrl'; import './getImageDataUrl';
import './getMeasurementsGroupedByNumber'; import './getMeasurementsGroupedByNumber';
import './getLocationLabel'; import './getLocationLabel';
@ -15,3 +16,4 @@ import './MeasurementManager';
import './navigateOverLesions'; import './navigateOverLesions';
import './syncMeasurementAndToolData'; import './syncMeasurementAndToolData';
import './toggleLabelButton'; import './toggleLabelButton';
import './triggerTimepointUnsavedChanges';

View File

@ -60,10 +60,7 @@ OHIF.measurements.toggleLabelButton = options => {
options.measurement.description = description; options.measurement.description = description;
// Notify that viewer suffered changes // Notify that viewer suffered changes
const { timepointId } = measurement; OHIF.measurements.triggerTimepointUnsavedChanges('renamed');
const basePath = 'viewer.studyViewer.measurements';
const timepointPath = timepointId ? `.${timepointId}` : '';
OHIF.ui.unsavedChanges.set(`${basePath}${timepointPath}.renamed`);
} }
}; };
buttonView = Blaze.renderWithData(Template.measureFlow, data, document.body); buttonView = Blaze.renderWithData(Template.measureFlow, data, document.body);

View File

@ -0,0 +1,15 @@
import { OHIF } from 'meteor/ohif:core';
/**
* Extensible method to trigger unsaved changes on the active timepoint
*
* @param {String} subpath - The unsaved changes subpath that will come after the timepoint ID
*/
OHIF.measurements.triggerTimepointUnsavedChanges = (subpath='changed') => {
const basePath = 'viewer.studyViewer.measurements';
const activeTimepoint = OHIF.measurements.getActiveTimepoint();
if (!activeTimepoint) return;
const { timepointId } = activeTimepoint;
const timepointPath = timepointId ? `.${timepointId}` : '';
OHIF.ui.unsavedChanges.set(`${basePath}${timepointPath}.${subpath}`);
};

View File

@ -8,13 +8,13 @@ const loadPreviousActivePanel = () => {
let currentIndex = Session.get('activeViewport'); let currentIndex = Session.get('activeViewport');
currentIndex--; currentIndex--;
const viewports = $('.imageViewerViewport'); const $viewports = $('.imageViewerViewport');
const numViewports = viewports.length; const numViewports = $viewports.length;
if (currentIndex < 0) { if (currentIndex < 0) {
currentIndex = numViewports - 1; currentIndex = numViewports - 1;
} }
const element = viewports.get(currentIndex); const element = $viewports.get(currentIndex);
if (!element) { if (!element) {
return; return;
} }
@ -27,13 +27,13 @@ const loadNextActivePanel = () => {
let currentIndex = Session.get('activeViewport'); let currentIndex = Session.get('activeViewport');
currentIndex++; currentIndex++;
const viewports = $('.imageViewerViewport'); const $viewports = $('.imageViewerViewport');
const numViewports = viewports.length; const numViewports = $viewports.length;
if (currentIndex >= numViewports) { if (currentIndex >= numViewports) {
currentIndex = 0; currentIndex = 0;
} }
const element = viewports.get(currentIndex); const element = $viewports.get(currentIndex);
if (!element) { if (!element) {
return; return;
} }

View File

@ -8,24 +8,30 @@ import { displayReferenceLines } from './displayReferenceLines';
/** /**
* Sets a viewport element active * Sets a viewport element active
* @param {node} element DOM element to be activated * @param {node} element DOM element to be activated or viewportIndex
*/ */
export function setActiveViewport(element) { export function setActiveViewport(element) {
if (!element) { const $viewerports = $('.imageViewerViewport');
let viewportIndex;
if (typeof element === 'number') {
viewportIndex = element;
} else {
viewportIndex = $viewerports.index(element);
}
const $element = $viewerports.eq(viewportIndex);
if (!$element.length) {
OHIF.log.info('setActiveViewport element does not exist'); OHIF.log.info('setActiveViewport element does not exist');
return; return;
} }
const viewerports = $('.imageViewerViewport');
const viewportIndex = viewerports.index(element);
const jQueryElement = $(element);
OHIF.log.info(`setActiveViewport setting viewport index: ${viewportIndex}`); OHIF.log.info(`setActiveViewport setting viewport index: ${viewportIndex}`);
// If viewport is not active // If viewport is not active
if(!jQueryElement.parents('.viewportContainer').hasClass('active')) { if (!$element.parents('.viewportContainer').hasClass('active')) {
// Trigger an event for compatibility with other systems // Trigger an event for compatibility with other systems
jQueryElement.trigger('OHIFBeforeActivateViewport'); $element.trigger('OHIFBeforeActivateViewport');
} }
// When an OHIFActivateViewport event is fired, update the Meteor Session // When an OHIFActivateViewport event is fired, update the Meteor Session
@ -42,15 +48,15 @@ export function setActiveViewport(element) {
// Add the 'active' class to the parent container to highlight the active viewport // Add the 'active' class to the parent container to highlight the active viewport
$('#imageViewerViewports .viewportContainer').removeClass('active'); $('#imageViewerViewports .viewportContainer').removeClass('active');
jQueryElement.parents('.viewportContainer').addClass('active'); $element.parents('.viewportContainer').addClass('active');
// Finally, enable stack prefetching and hide the reference lines from // Finally, enable stack prefetching and hide the reference lines from
// the newly activated viewport that has a canvas // the newly activated viewport that has a canvas
if (jQueryElement.find('canvas').length) { if ($element.find('canvas').length) {
// Cornerstone Tools compare DOM elements (check getEnabledElement cornerstone function) // Cornerstone Tools compare DOM elements (check getEnabledElement cornerstone function)
// so we can't pass a jQuery object as an argument, otherwise it throws an excepetion // so we can't pass a jQuery object as an argument, otherwise it throws an excepetion
const domElement = jQueryElement.get(0); const domElement = $element.get(0);
displayReferenceLines(domElement); displayReferenceLines(domElement);
StudyPrefetcher.getInstance().prefetch(); StudyPrefetcher.getInstance().prefetch();
@ -63,10 +69,10 @@ export function setActiveViewport(element) {
// Set the div to focused, so keypress events are handled // Set the div to focused, so keypress events are handled
//$(element).focus(); //$(element).focus();
//.focus() event breaks in FF&IE //.focus() event breaks in FF&IE
jQueryElement.triggerHandler('focus'); $element.triggerHandler('focus');
// Trigger OHIFAfterActivateViewport event on activated instance // Trigger OHIFAfterActivateViewport event on activated instance
// for compatibility with other systems // for compatibility with other systems
jQueryElement.trigger('OHIFAfterActivateViewport'); $element.trigger('OHIFAfterActivateViewport');
} }