diff --git a/LesionTracker/client/components/viewer/viewer.html b/LesionTracker/client/components/viewer/viewer.html
index 574fc0b80..c4653644a 100644
--- a/LesionTracker/client/components/viewer/viewer.html
+++ b/LesionTracker/client/components/viewer/viewer.html
@@ -3,7 +3,7 @@
{{>confirmDeleteDialog}}
{{>measurementLocationDialog (clone this)}}
- {{>nonTargetMeasurementDialog (clone this)}}
+ {{! >nonTargetMeasurementDialog (clone this)}}
{{>nonTargetResponseDialog (clone this)}}
{{>measurementTableHUD (clone this)}}
{{>cineDialog}}
diff --git a/Packages/ohif-design/styles/common/global.styl b/Packages/ohif-design/styles/common/global.styl
index afe263a0a..b5ff2d1bb 100644
--- a/Packages/ohif-design/styles/common/global.styl
+++ b/Packages/ohif-design/styles/common/global.styl
@@ -59,3 +59,7 @@ label.form-group
.modal-header, .modal-footer
theme('border-color', '$uiBorderColor')
+
+ button.close
+ theme('color', '$textSecondaryColor')
+ opacity: 1
diff --git a/Packages/ohif-lesiontracker/both/configuration/nonTarget.js b/Packages/ohif-lesiontracker/both/configuration/nonTarget.js
index 8de6c1a2a..24ab328ad 100644
--- a/Packages/ohif-lesiontracker/both/configuration/nonTarget.js
+++ b/Packages/ohif-lesiontracker/both/configuration/nonTarget.js
@@ -4,18 +4,18 @@ import { MeasurementSchemaTypes } from 'meteor/ohif:measurements/both/schema/mea
const CornerstoneHandleSchema = MeasurementSchemaTypes.CornerstoneHandleSchema;
const NonTargetHandlesSchema = new SimpleSchema({
- start: {
- type: CornerstoneHandleSchema,
- label: 'Start'
- },
- end: {
- type: CornerstoneHandleSchema,
- label: 'End'
- },
- textBox: {
- type: CornerstoneHandleSchema,
- label: 'Text Box'
- }
+ start: {
+ type: CornerstoneHandleSchema,
+ label: 'Start'
+ },
+ end: {
+ type: CornerstoneHandleSchema,
+ label: 'End'
+ },
+ textBox: {
+ type: CornerstoneHandleSchema,
+ label: 'Text Box'
+ }
});
const NonTargetSchema = new SimpleSchema([MeasurementSchemaTypes.CornerstoneToolMeasurement, {
@@ -24,10 +24,15 @@ const NonTargetSchema = new SimpleSchema([MeasurementSchemaTypes.CornerstoneTool
label: 'Handles'
},
response: {
- type: String,
- label: 'Response',
+ type: String,
+ label: 'Response',
optional: true // Optional because it is added after initial drawing, via a callback
},
+ location: {
+ type: String,
+ label: 'Location',
+ optional: true
+ },
locationUid: {
type: String,
label: 'Location UID',
@@ -50,6 +55,6 @@ export const nonTarget = {
measurementTableOptions: {
displayFunction: displayFunction
},
- includeInCaseProgress: true,
+ includeInCaseProgress: true,
},
-}
\ No newline at end of file
+};
diff --git a/Packages/ohif-lesiontracker/both/schema/fields.js b/Packages/ohif-lesiontracker/both/schema/fields.js
new file mode 100644
index 000000000..e9f6d5624
--- /dev/null
+++ b/Packages/ohif-lesiontracker/both/schema/fields.js
@@ -0,0 +1,60 @@
+export const FieldLesionLocation = {
+ type: String,
+ label: 'Lesion Location',
+ allowedValues: [
+ '',
+ 'Abdominal/Chest Wall',
+ 'Adrenal',
+ 'Bladder',
+ 'Bone',
+ 'Brain',
+ 'Breast',
+ 'Colon',
+ 'Esophagus',
+ 'Extremities',
+ 'Gallbladder',
+ 'Kidney',
+ 'Liver',
+ 'Lung',
+ 'Lymph Node',
+ 'Mediastinum/Hilum',
+ 'Muscle',
+ 'Neck',
+ 'Other: Soft Tissue',
+ 'Ovary',
+ 'Pancreas',
+ 'Pelvis',
+ 'Peritoneum/Omentum',
+ 'Prostate',
+ 'Retroperitoneum',
+ 'Small Bowel',
+ 'Spleen',
+ 'Stomach',
+ 'Subcutaneous'
+ ]
+};
+
+export const FieldLesionLocationResponse = {
+ type: String,
+ label: 'Lesion Location Response',
+ allowedValues: [
+ '',
+ '-1',
+ 'PD',
+ 'SD',
+ 'Present',
+ 'NE',
+ 'NN',
+ 'EX'
+ ],
+ valuesLabels: [
+ '',
+ 'CR - Complete response',
+ 'PD - Progressive disease',
+ 'SD - Stable disease',
+ 'Present - Present',
+ 'NE - Not Evaluable',
+ 'NN - Non-CR/Non-PD',
+ 'EX - Excluded from Assessment'
+ ]
+};
diff --git a/Packages/ohif-lesiontracker/both/schema/index.js b/Packages/ohif-lesiontracker/both/schema/index.js
new file mode 100644
index 000000000..fe2407f77
--- /dev/null
+++ b/Packages/ohif-lesiontracker/both/schema/index.js
@@ -0,0 +1 @@
+export * from './fields.js';
diff --git a/Packages/ohif-lesiontracker/client/compatibility/nonTargetTool.js b/Packages/ohif-lesiontracker/client/compatibility/nonTargetTool.js
index 808f132bb..9dfe2faa3 100644
--- a/Packages/ohif-lesiontracker/client/compatibility/nonTargetTool.js
+++ b/Packages/ohif-lesiontracker/client/compatibility/nonTargetTool.js
@@ -5,9 +5,8 @@
var toolType = 'nonTarget';
var configuration = {
- setMeasurementNumberCallback: setMeasurementNumberCallback,
- getmeasurementLocationCallback: getmeasurementLocationCallback,
- changemeasurementLocationCallback: changemeasurementLocationCallback,
+ getMeasurementLocationCallback: getMeasurementLocationCallback,
+ changeMeasurementLocationCallback: changeMeasurementLocationCallback,
drawHandles: false,
drawHandlesOnHover: true,
arrowFirst: true
@@ -17,20 +16,20 @@
var keys = {
ESC: 27
};
-
- // Set measurement number
- // Get Non-Target measurements on image
- function setMeasurementNumberCallback(measurementData, eventData, doneCallback) {
- var measurementNumber = 1;
- doneCallback(measurementNumber);
- }
// Define a callback to get your text annotation
// This could be used, e.g. to open a modal
- function getmeasurementLocationCallback(measurementData, eventData, doneCallback) {
- doneCallback(prompt('Enter your measurement location:'));
+ function getMeasurementLocationCallback(measurementData, eventData, doneCallback) {
+ const dialogSettings = {
+ title: 'Select Lesion Location',
+ measurementData,
+ eventData
+ };
+ OHIF.ui.showFormDialog('dialogNonTargetMeasurement', dialogSettings).then(formData => {
+ doneCallback(formData.measurementNumber);
+ });
}
- function changemeasurementLocationCallback(measurementData, eventData, doneCallback) {
+ function changeMeasurementLocationCallback(measurementData, eventData, doneCallback) {
doneCallback(prompt('Change your measurement location:'));
}
@@ -53,11 +52,6 @@
var config = cornerstoneTools.nonTarget.getConfiguration();
- // Set measurement number and measurement name
- if (measurementData.measurementNumber === undefined) {
- config.setMeasurementNumberCallback(measurementData, mouseEventData, doneCallback);
- }
-
// associate this data with this imageId so we can render it and manipulate it
cornerstoneTools.addToolState(mouseEventData.element, toolType, measurementData);
@@ -92,7 +86,7 @@
// delete the measurement
cornerstoneTools.removeToolState(mouseEventData.element, toolType, measurementData);
} else {
- config.getmeasurementLocationCallback(measurementData, mouseEventData, doneCallback);
+ config.getMeasurementLocationCallback(measurementData, mouseEventData, doneCallback);
}
// Unbind the Esc keydown hook
@@ -103,8 +97,6 @@
$(element).on('CornerstoneToolsMouseDownActivate', eventData, cornerstoneTools.nonTarget.mouseDownActivateCallback);
$(element).on('CornerstoneToolsMouseDoubleClick', eventData, doubleClickCallback);
- $(element).off('keydown', cancelCallback);
-
cornerstone.updateImage(mouseEventData.element);
});
}
@@ -272,11 +264,6 @@
$(element).off('CornerstoneToolsTap', cornerstoneTools.nonTargetTouch.tapCallback);
var config = cornerstoneTools.nonTarget.getConfiguration();
- // Set measurement number and measurement name
- if (measurementData.measurementName === undefined) {
- config.setMeasurementNumberCallback(measurementData, touchEventData, doneCallback);
- }
-
cornerstone.updateImage(element);
cornerstoneTools.moveNewHandleTouch(touchEventData, toolType, measurementData, measurementData.handles.end, function() {
@@ -287,7 +274,7 @@
cornerstoneTools.removeToolState(element, toolType, measurementData);
}
- config.getmeasurementLocationCallback(measurementData, touchEventData, doneCallback);
+ config.getMeasurementLocationCallback(measurementData, touchEventData, doneCallback);
$(element).on('CornerstoneToolsTouchDrag', cornerstoneTools.nonTargetTouch.touchMoveHandle);
$(element).on('CornerstoneToolsDragStartActive', cornerstoneTools.nonTargetTouch.touchDownActivateCallback);
@@ -330,7 +317,7 @@
data.active = true;
cornerstone.updateImage(element);
// Allow relabelling via a callback
- config.changemeasurementLocationCallback(data, eventData, doneCallback);
+ config.changeMeasurementLocationCallback(data, eventData, doneCallback);
e.stopImmediatePropagation();
return false;
diff --git a/Packages/ohif-lesiontracker/client/components/dialog/nonTargetMeasurement.html b/Packages/ohif-lesiontracker/client/components/dialog/nonTargetMeasurement.html
new file mode 100644
index 000000000..02dc1f7f2
--- /dev/null
+++ b/Packages/ohif-lesiontracker/client/components/dialog/nonTargetMeasurement.html
@@ -0,0 +1,9 @@
+
+ {{#dialogForm (extend this dialogClass='modal-sm' schema=(choose this.schema instance.schema))}}
+ {{>inputHidden key='measurementNumber'}}
+ {{>inputSelect labelClass='form-group' key='location' hideSearch=true
+ options=(clone placeholder='Choose a lesion location')}}
+ {{>inputSelect labelClass='form-group' key='response' hideSearch=true
+ options=(clone placeholder='Choose a lesion location response')}}
+ {{/dialogForm}}
+
diff --git a/Packages/ohif-lesiontracker/client/components/dialog/nonTargetMeasurement.js b/Packages/ohif-lesiontracker/client/components/dialog/nonTargetMeasurement.js
new file mode 100644
index 000000000..799e13623
--- /dev/null
+++ b/Packages/ohif-lesiontracker/client/components/dialog/nonTargetMeasurement.js
@@ -0,0 +1,69 @@
+import { Template } from 'meteor/templating';
+import { Blaze } from 'meteor/blaze';
+import { SimpleSchema } from 'meteor/aldeed:simple-schema';
+import { _ } from 'meteor/underscore';
+import { FieldLesionLocation, FieldLesionLocationResponse } from 'meteor/ohif:lesiontracker/both/schema/fields';
+
+Template.dialogNonTargetMeasurement.onCreated(() => {
+ const instance = Template.instance();
+
+ instance.schema = new SimpleSchema({
+ location: FieldLesionLocation,
+ response: FieldLesionLocationResponse,
+ measurementNumber: {
+ type: Number
+ }
+ });
+});
+
+Template.dialogNonTargetMeasurement.onRendered(() => {
+ const instance = Template.instance();
+
+ const form = instance.$('form').data('component');
+
+ const viewerMain = $(instance.data.eventData.element).closest('.viewerMain')[0];
+ const viewerData = Blaze.getData(viewerMain);
+ console.warn('>>>>dialogData/viewerData', instance.data, viewerData);
+
+ const measurementApi = viewerData.measurementApi;
+
+ const measurementTypeId = 'nonTargets';
+ const measurementData = instance.data.measurementData;
+ const collection = measurementApi[measurementTypeId];
+
+ // Get the current inserted measurement from the collection
+ const currentMeasurement = collection.findOne({
+ _id: measurementData._id
+ });
+
+ // Synchronize the measurement number with the one inserted in the collection
+ measurementData.measurementNumber = currentMeasurement.measurementNumber;
+
+ // Delete the measurement if dialog is closed
+ instance.data.promise.catch(() => {
+ viewerData.measurementApi.deleteMeasurements('nonTargets', {
+ _id: measurementData._id
+ });
+
+ // Repaint the images on all viewports without the removed measurements
+ _.each($('.imageViewerViewport'), element => cornerstone.updateImage(element));
+ });
+
+ // Update the location and response after confirming the dialog data
+ instance.data.promise.then(formData => {
+ collection.update({
+ _id: measurementData._id,
+ }, {
+ $set: {
+ location: formData.location,
+ response: formData.response
+ }
+ });
+ });
+
+ // Inject the measurement number in form data to enable the tool from getting the value
+ form.value({
+ measurementNumber: currentMeasurement.measurementNumber
+ });
+
+});
diff --git a/Packages/ohif-lesiontracker/client/components/index.js b/Packages/ohif-lesiontracker/client/components/index.js
index 6c151dd94..c534fbb27 100644
--- a/Packages/ohif-lesiontracker/client/components/index.js
+++ b/Packages/ohif-lesiontracker/client/components/index.js
@@ -1,3 +1,6 @@
+import './dialog/nonTargetMeasurement.html';
+import './dialog/nonTargetMeasurement.js';
+
import './optionsModal/optionsModal.html';
import './optionsModal/optionsModal.styl';
import './optionsModal/optionsModal.js';
diff --git a/Packages/ohif-lesiontracker/client/components/nonTargetMeasurementDialog/nonTargetMeasurementDialog.js b/Packages/ohif-lesiontracker/client/components/nonTargetMeasurementDialog/nonTargetMeasurementDialog.js
index 347dc83ac..de2043668 100644
--- a/Packages/ohif-lesiontracker/client/components/nonTargetMeasurementDialog/nonTargetMeasurementDialog.js
+++ b/Packages/ohif-lesiontracker/client/components/nonTargetMeasurementDialog/nonTargetMeasurementDialog.js
@@ -68,11 +68,10 @@ function selectNonTargetResponse(responseCode) {
// If there already exists a measurement with this specific measurement number,
// related to the chosen location.
function getMeasurementLocationCallback(measurementData, eventData) {
- return 'Test Location';
Template.nonTargetMeasurementDialog.measurementData = measurementData;
// Get the non-target measurement location dialog
- var dialog = $('#nonTargetMeasurementLocationDialog');
+ var dialog = $('#nonTargetMeasurementDialog');
Template.nonTargetMeasurementDialog.dialog = dialog;
// Show the backdrop
@@ -89,7 +88,7 @@ function getMeasurementLocationCallback(measurementData, eventData) {
selectorLocation.find('option:first').prop('selected', 'selected');
// LT-112 "Non-target response shall default to non-measurable on baseline, present on follow-up"
- var timepoint = Timepoints.findOne({
+ var timepoint = StudyList.timepointApi.timepoints.findOne({
timepointId: measurementData.timepointId
});
@@ -104,7 +103,7 @@ function getMeasurementLocationCallback(measurementData, eventData) {
// Find out if this measurement number is already added in the measurement manager for another timepoint
// If it is, disable selector location
- var locationId = OHIF.measurements.MeasurementManager.getLocationIdIfMeasurementExists(measurementData);
+ var locationId = OHIF.measurements.MeasurementManager.getLocationIdIfMeasurementExists(measurementData, StudyList.timepointApi.timepoints);
if (locationId) {
// Add an ID value to the tool data to link it to the Measurements collection
measurementData.id = 'notready';
@@ -156,6 +155,7 @@ function getMeasurementLocationCallback(measurementData, eventData) {
dialogProperty.margin = 'auto';
}
+ console.warn('>>>>SHOW DIALOG', dialog);
dialog.css(dialogProperty);
}
diff --git a/Packages/ohif-measurements/both/configuration/measurements.js b/Packages/ohif-measurements/both/configuration/measurements.js
index f979e3d43..c8b9a7d07 100644
--- a/Packages/ohif-measurements/both/configuration/measurements.js
+++ b/Packages/ohif-measurements/both/configuration/measurements.js
@@ -90,18 +90,16 @@ class MeasurementApi {
});
}
- deleteMeasurements(measurementTypeId, toolType, measurementNumber) {
+ deleteMeasurements(measurementTypeId, filter) {
const collection = this[measurementTypeId];
- const filter = {
- toolType,
- measurementNumber
- };
-
// Get the entries information before removing them
const entries = collection.find(filter).fetch();
collection.remove(filter);
+ // If the filter doesn't have the measurement number, get it from the first entry
+ const measurementNumber = filter.measurementNumber || entries[0].measurementNumber;
+
// Synchronize the new data with cornerstone tools
const toolState = cornerstoneTools.globalImageIdSpecificToolStateManager.toolState;
_.each(entries, entry => {
diff --git a/Packages/ohif-measurements/client/components/measurementTable/measurementTableRow/measurementTableRow.js b/Packages/ohif-measurements/client/components/measurementTable/measurementTableRow/measurementTableRow.js
index 850d7be4e..f664c665e 100644
--- a/Packages/ohif-measurements/client/components/measurementTable/measurementTableRow/measurementTableRow.js
+++ b/Packages/ohif-measurements/client/components/measurementTable/measurementTableRow/measurementTableRow.js
@@ -58,7 +58,10 @@ Template.measurementTableRow.events({
const api = instance.data.measurementApi;
// Remove all the measurements with the given type and number
- api.deleteMeasurements(measurementTypeId, toolType, measurementNumber);
+ api.deleteMeasurements(measurementTypeId, {
+ toolType,
+ measurementNumber
+ });
// Repaint the images on all viewports without the removed measurements
_.each($('.imageViewerViewport'), element => cornerstone.updateImage(element));