diff --git a/LesionTracker/client/components/viewer.js b/LesionTracker/client/components/viewer.js
index 4119605ca..43b4d63b7 100644
--- a/LesionTracker/client/components/viewer.js
+++ b/LesionTracker/client/components/viewer.js
@@ -51,12 +51,6 @@ Template.viewer.onCreated(function() {
}
OHIF.viewer.isPlaying[viewportIndex] = !OHIF.viewer.isPlaying[viewportIndex];
Session.set('UpdateCINE', Random.id());
- },
- previousPresentationGroup: function() {
- WindowManager.previousPresentationGroup();
- },
- nextPresentationGroup: function() {
- WindowManager.nextPresentationGroup();
}
};
@@ -103,7 +97,6 @@ Template.viewer.onCreated(function() {
var patientId = this.data.studies[0].patientId;
Session.set('patientId', patientId);
- initialized = false;
self.autorun(function() {
var patientId = Session.get('patientId');
self.subscribe('timepoints', patientId);
@@ -113,38 +106,35 @@ Template.viewer.onCreated(function() {
return;
}
- if (initialized === true) {
- return;
- }
+ ViewerStudies.find().observe({
+ added: function(study) {
+ var timepoint = Timepoints.findOne({timepointName: study.studyDate});
+ if (timepoint) {
+ log.warn("A timepoint with that study date already exists!");
+ return;
+ }
- ViewerStudies.find().forEach(function(study) {
- var timepoint = Timepoints.findOne({timepointName: study.studyDate});
- if (timepoint) {
- log.warn("A timepoint with that study date already exists!");
- return;
+ var timepointID = uuid.v4();
+
+ var testTimepoint = Timepoints.findOne({});
+ if (testTimepoint && testTimepoint.patientId !== study.patientId) {
+ log.warn("Timepoints collection related to the wrong subject");
+ return;
+ }
+
+ log.info('Inserting a new timepoint');
+ Timepoints.insert({
+ patientId: study.patientId,
+ timepointID: timepointID,
+ timepointName: study.studyDate
+ });
}
-
- var timepointID = uuid.v4();
-
- var testTimepoint = Timepoints.findOne({});
- if (testTimepoint && testTimepoint.patientId !== study.patientId) {
- log.warn("Timepoints collection related to the wrong subject");
- return;
- }
-
- log.info('Inserting a new timepoint');
- Timepoints.insert({
- patientId: study.patientId,
- timepointID: timepointID,
- timepointName: study.studyDate
- });
});
// This is used to re-add tools from the database into the
// Cornerstone ToolData structure
Measurements.find().observe({
added: function (data) {
-
if (data.toolDataInsertedManually === true) {
// Activate first measurements in image box as default if exists
@@ -156,19 +146,40 @@ Template.viewer.onCreated(function() {
}
return;
}
-
log.info('Measurement added');
addMeasurementAsToolData(data);
+
+ updateRelatedElements(data.imageId);
+ },
+ changed: function(data) {
+ log.info('Measurement changed');
+ updateRelatedElements(data.imageId);
+ },
+ removed: function(data) {
+ log.info('Measurement removed');
+ updateRelatedElements(data.imageId);
}
});
-
- initialized = true;
});
OHIF.viewer.updateImageSynchronizer = new cornerstoneTools.Synchronizer("CornerstoneNewImage", cornerstoneTools.updateImageSynchronizer);
});
+function updateRelatedElements(imageId) {
+ // Get all on-screen elements with this imageId
+ var enabledElements = cornerstone.getEnabledElementsByImageId(imageId);
+
+ // TODO=Check original event to prevent duplicate updateImage calls
+
+ // Loop through these elements
+ enabledElements.forEach(function(enabledElement) {
+ // Update the display so the tool is removed
+ var element = enabledElement.element;
+ cornerstone.updateImage(element)
+ });
+}
+
function addMeasurementAsToolData(data) {
// Check what toolType we should be adding this to, based on the isTarget value
// of the stored Measurement
@@ -184,10 +195,41 @@ function addMeasurementAsToolData(data) {
toolState[imageId] = {};
}
+ // This is probably not the best approach to prevent duplicates
+ if (toolState[imageId][toolType] && toolState[imageId][toolType].data) {
+ var measurementHasNoIdYet = false;
+ toolState[imageId][toolType].data.forEach(function(measurement) {
+ if (measurement.id === 'notready') {
+ measurementHasNoIdYet = true;
+ return false;
+ }
+ });
+
+ // Stop here if it appears that we are creating this measurement right now,
+ // and would not like this function to add another copy of it to the toolData
+ if (measurementHasNoIdYet === true) {
+ return;
+ }
+ }
+
if (!toolState[imageId][toolType]) {
toolState[imageId][toolType] = {
data: []
};
+ } else {
+ var alreadyExists = false;
+ if (toolState[imageId][toolType].data.length) {
+ toolState[imageId][toolType].data.forEach(function(measurement) {
+ if (measurement.id === data._id) {
+ alreadyExists = true;
+ return false;
+ }
+ });
+ }
+
+ if (alreadyExists === true) {
+ return;
+ }
}
// Create measurementData structure based on the lesion data at this timepoint
@@ -204,6 +246,7 @@ function addMeasurementAsToolData(data) {
measurementData.visible = data.visible;
measurementData.active = data.active;
measurementData.uid = data.uid;
+ measurementData.id = data._id;
toolState[imageId][toolType].data.push(measurementData);
});
@@ -215,6 +258,46 @@ Template.viewer.onDestroyed(function() {
OHIF.viewer.updateImageSynchronizer.destroy();
});
+Template.viewer.events({
+ 'CornerstoneToolsMeasurementModified .imageViewerViewport': function(e, template, eventData) {
+ handleMeasurementModified(e, eventData);
+ },
+ 'CornerstoneToolsMeasurementRemoved .imageViewerViewport': function(e, template, eventData) {
+ handleMeasurementRemoved(e, eventData);
+ }
+});
+
+function handleMeasurementModified(e, eventData) {
+ log.info('CornerstoneToolsMeasurementModified');
+ var measurementData = eventData.measurementData;
+
+ switch (eventData.toolType) {
+ case 'nonTarget':
+ case 'lesion':
+ measurementManagerDAL.updateTimepointData(measurementData);
+ break;
+ }
+}
+
+function handleMeasurementRemoved(e, eventData) {
+ log.info('CornerstoneToolsMeasurementRemoved');
+ var measurementData = eventData.measurementData;
+ var databaseEntry;
+
+ switch (eventData.toolType) {
+ case 'nonTarget':
+ case 'lesion':
+ databaseEntry = Measurements.findOne(measurementData.id, {reactive: false});
+ if (!databaseEntry) {
+ return;
+ }
+
+ // TODO= Fix this when we have Findings that relate to more than one viewport
+ Measurements.remove(databaseEntry._id);
+ break;
+ }
+}
+
// Avoid doing DOM manipulation during the resize handler
// because it is fired very often.
// Resizing is therefore performed 100 ms after the resize event stops.
diff --git a/Packages/lesiontracker/client/collections/LesionLocations.js b/Packages/lesiontracker/client/collections/LesionLocations.js
new file mode 100644
index 000000000..f2ae38e5d
--- /dev/null
+++ b/Packages/lesiontracker/client/collections/LesionLocations.js
@@ -0,0 +1,108 @@
+LesionLocations = new Meteor.Collection(null);
+
+LesionLocations.insert({
+ id: 'liverLeft',
+ group: 'liver',
+ location: "Liver Left",
+ hasDescription: false,
+ description: "",
+ selected: false
+});
+
+LesionLocations.insert({
+ id: 'liverRight',
+ group: 'liver',
+ location: "Liver Right",
+ hasDescription: false,
+ description: "",
+ selected: false
+});
+
+LesionLocations.insert({
+ id: 'liverCaudate',
+ group: 'liver',
+ location: "Liver Caudate",
+ hasDescription: false,
+ description: "",
+ selected: false
+});
+
+LesionLocations.insert({
+ id: 'lungLLL',
+ group: 'lung',
+ location: "Lung LLL",
+ hasDescription: false,
+ description: "",
+ selected: false
+});
+
+LesionLocations.insert({
+ id: 'lungLUL',
+ group: 'lung',
+ location: "Lung LUL",
+ hasDescription: false,
+ description: "",
+ selected: false
+});
+
+LesionLocations.insert({
+ id: 'lungRLL',
+ group: 'lung',
+ location: "Lung RLL",
+ hasDescription: false,
+ description: "",
+ selected: false
+});
+
+LesionLocations.insert({
+ id: 'lungRML',
+ group: 'lung',
+ location: "Lung RML",
+ hasDescription: false,
+ description: "",
+ selected: false
+});
+
+LesionLocations.insert({
+ id: 'lungRUL',
+ group: 'lung',
+ location: "Lung RUL",
+ hasDescription: false,
+ description: "",
+ selected: false
+});
+
+LesionLocations.insert({
+ id: 'pleuraLeft',
+ group: 'pleura',
+ location: "Pleura Left",
+ hasDescription: false,
+ description: "",
+ selected: false
+});
+
+LesionLocations.insert({
+ id: 'pleuraRight',
+ group: 'pleura',
+ location: "Pleura Right",
+ hasDescription: false,
+ description: "",
+ selected: false
+});
+
+LesionLocations.insert({
+ id: 'kidneyLeft',
+ group: 'kidney',
+ location: "Kidney Left",
+ hasDescription: false,
+ description: "",
+ selected: false
+});
+
+LesionLocations.insert({
+ id: 'kidneyRight',
+ group: 'kidney',
+ location: "Kidney Right",
+ hasDescription: false,
+ description: ""
+});
\ No newline at end of file
diff --git a/Packages/lesiontracker/client/collections/LocationResponses.js b/Packages/lesiontracker/client/collections/LocationResponses.js
new file mode 100644
index 000000000..485bd6cc4
--- /dev/null
+++ b/Packages/lesiontracker/client/collections/LocationResponses.js
@@ -0,0 +1,55 @@
+LocationResponses = new Meteor.Collection(null);
+
+LocationResponses.insert({
+ text: "Complete response",
+ code: "CR",
+ description: ""
+});
+
+LocationResponses.insert({
+ text: "Progressive disease",
+ code: "PD",
+ description: ""
+});
+
+LocationResponses.insert({
+ text: "Complete response",
+ code: "CR",
+ description: ""
+});
+
+LocationResponses.insert({
+ text: "Stable disease",
+ code: "SD",
+ description: ""
+});
+
+LocationResponses.insert({
+ text: "Non-measurable",
+ code: "NM",
+ description: ""
+});
+
+LocationResponses.insert({
+ text: "Unknown",
+ code: "UN",
+ description: ""
+});
+
+LocationResponses.insert({
+ text: "Not Evaluable",
+ code: "NE",
+ description: ""
+});
+
+LocationResponses.insert({
+ text: "Non-CR/Non-PD",
+ code: "NN",
+ description: ""
+});
+
+LocationResponses.insert({
+ text: "Excluded",
+ code: "EX",
+ description: ""
+});
\ No newline at end of file
diff --git a/Packages/lesiontracker/compatibility/lesionTool.js b/Packages/lesiontracker/client/compatibility/lesionTool.js
similarity index 85%
rename from Packages/lesiontracker/compatibility/lesionTool.js
rename to Packages/lesiontracker/client/compatibility/lesionTool.js
index 356c22c55..06dc959e4 100644
--- a/Packages/lesiontracker/compatibility/lesionTool.js
+++ b/Packages/lesiontracker/client/compatibility/lesionTool.js
@@ -71,7 +71,7 @@ var cornerstoneTools = (function($, cornerstone, cornerstoneMath, cornerstoneToo
cornerstoneTools.removeToolState(element, toolType, measurementData);
} else {
// Set lesionMeasurementData Session
- config.getLesionLocationCallback(measurementData, mouseEventData);
+ config.getLesionLocationCallback(measurementData, mouseEventData, doneCallback);
}
$(element).on('CornerstoneToolsMouseMove', eventData, cornerstoneTools.lesion.mouseMoveCallback);
@@ -157,7 +157,8 @@ var cornerstoneTools = (function($, cornerstone, cornerstoneMath, cornerstoneToo
pointNearHandle: pointNearTextBox,
active: false,
movesIndependently: true,
- drawnIndependently: true
+ drawnIndependently: true,
+ allowedOutsideImage: true
}
},
imageId: imageId,
@@ -282,10 +283,7 @@ var cornerstoneTools = (function($, cornerstone, cornerstoneMath, cornerstoneToo
// Set measurement text to show lesion table
data.measurementText = length.toFixed(1);
-
context.restore();
-
- updateLesionCollection(toolData.data[i]);
}
}
@@ -301,7 +299,58 @@ var cornerstoneTools = (function($, cornerstone, cornerstoneMath, cornerstoneToo
}
}
- ///////// END IMAGE RENDERING ///////
+ function doubleClickCallback(e, eventData) {
+ // Prevent other double click handlers from firing after this one
+ //e.stopImmediatePropagation();
+
+ var element = eventData.element;
+ var data;
+
+ function doneCallback(data, deleteTool) {
+ if (deleteTool === true) {
+ cornerstoneTools.removeToolState(element, toolType, data);
+ cornerstone.updateImage(element);
+ //return;
+ }
+
+ /*// TODO= Find a better way to do this! This is very messy
+ config.setLesionNumberCallback(data, eventData, function(lesionNumber) {
+ data.lesionName = "Target " + lesionNumber;
+ data.lesionNumber = lesionNumber;
+ data.active = false;
+ cornerstone.updateImage(element);
+ });*/
+ }
+
+ if (e.data && e.data.mouseButtonMask && !cornerstoneTools.isMouseButtonEnabled(eventData.which, e.data.mouseButtonMask)) {
+ return false;
+ }
+
+ var config = cornerstoneTools.lesion.getConfiguration();
+
+ var coords = eventData.currentPoints.canvas;
+ var toolData = cornerstoneTools.getToolState(element, toolType);
+
+ // now check to see if there is a handle we can move
+ if (!toolData) {
+ return false;
+ }
+
+ for (var i = 0; i < toolData.data.length; i++) {
+ data = toolData.data[i];
+ if (pointNearTool(element, data, coords)) {
+ data.active = true;
+ cornerstone.updateImage(element);
+ // Allow relabelling via a callback
+ config.changeLesionLocationCallback(data, eventData, doneCallback);
+
+ e.stopImmediatePropagation();
+ return false;
+ }
+ }
+
+ return false; // false = causes jquery to preventDefault() and stopPropagation() this event
+ }
// module exports
cornerstoneTools.lesion = cornerstoneTools.mouseButtonTool({
@@ -309,6 +358,7 @@ var cornerstoneTools = (function($, cornerstone, cornerstoneMath, cornerstoneToo
addNewMeasurement: addNewMeasurement,
onImageRendered: onImageRendered,
pointNearTool: pointNearTool,
+ mouseDoubleClickCallback: doubleClickCallback,
toolType: toolType
});
diff --git a/Packages/lesiontracker/compatibility/measurementManagerDAL.js b/Packages/lesiontracker/client/compatibility/measurementManagerDAL.js
similarity index 94%
rename from Packages/lesiontracker/compatibility/measurementManagerDAL.js
rename to Packages/lesiontracker/client/compatibility/measurementManagerDAL.js
index 175a9445e..423e3a2d5 100644
--- a/Packages/lesiontracker/compatibility/measurementManagerDAL.js
+++ b/Packages/lesiontracker/client/compatibility/measurementManagerDAL.js
@@ -46,12 +46,9 @@ var measurementManagerDAL = (function() {
lesionDataObject.timepoints = timepointsObject;
// Is there a use for this?
- lesionDataObject.number = Measurements.find().count() + 1;
+ lesionDataObject.number = Measurements.find().count() + 1;
- // TODO=Fix this workaround to prevent the observe hook from adding another set of toolData
- lesionDataObject.toolDataInsertedManually = true;
-
- Measurements.insert(lesionDataObject);
+ lesionDataObject.id = Measurements.insert(lesionDataObject);
}
// Update timepoint data in Measurements collection
@@ -82,6 +79,7 @@ var measurementManagerDAL = (function() {
timepoints[timepointID].studyInstanceUid = lesionData.studyInstanceUid;
timepoints[timepointID].handles = lesionData.handles;
+ lesionData.id = measurement._id;
Measurements.update(measurement._id, {
$set: {
@@ -133,7 +131,7 @@ var measurementManagerDAL = (function() {
if (!timepoints[timepointID]) {
// Find lesion number for this timepointID
- return measurement.lesionNumber
+ return measurement.lesionNumber;
}
if (timepoints[timepointID].longestDiameter === '') {
diff --git a/Packages/lesiontracker/compatibility/nonTargetTool.js b/Packages/lesiontracker/client/compatibility/nonTargetTool.js
similarity index 99%
rename from Packages/lesiontracker/compatibility/nonTargetTool.js
rename to Packages/lesiontracker/client/compatibility/nonTargetTool.js
index 6b57c6770..26f3414e2 100644
--- a/Packages/lesiontracker/compatibility/nonTargetTool.js
+++ b/Packages/lesiontracker/client/compatibility/nonTargetTool.js
@@ -118,7 +118,8 @@
pointNearHandle: pointNearTextBox,
active: false,
movesIndependently: true,
- drawnIndependently: true
+ drawnIndependently: true,
+ allowedOutsideImage: true
}
},
imageId: imageId,
diff --git a/Packages/lesiontracker/client/components/lesionLocationDialog/lesionLocationDialog.html b/Packages/lesiontracker/client/components/lesionLocationDialog/lesionLocationDialog.html
new file mode 100644
index 000000000..ed3b15d86
--- /dev/null
+++ b/Packages/lesiontracker/client/components/lesionLocationDialog/lesionLocationDialog.html
@@ -0,0 +1,37 @@
+
+
+
+
Select Lesion Location
+
+
+
+
+
+
+
+
+
+
+
+
Change Lesion Location
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/Packages/lesiontracker/client/components/lesionLocationDialog/lesionLocationDialog.js b/Packages/lesiontracker/client/components/lesionLocationDialog/lesionLocationDialog.js
new file mode 100644
index 000000000..9f2f4bf89
--- /dev/null
+++ b/Packages/lesiontracker/client/components/lesionLocationDialog/lesionLocationDialog.js
@@ -0,0 +1,247 @@
+function closeHandler(dialog) {
+ // Hide the lesion dialog
+ $(dialog).css('display', 'none');
+
+ // Remove the backdrop
+ $(".removableBackdrop").remove();
+}
+
+// This event sets lesion number for new lesion
+function setLesionNumberCallback(measurementData, eventData, doneCallback) {
+ // Get the current element's timepointID from the study date metadata
+ var element = eventData.element;
+ var enabledElement = cornerstone.getEnabledElement(element);
+ var imageId = enabledElement.image.imageId;
+
+ var study = cornerstoneTools.metaData.get('study', imageId);
+ var timepoint = Timepoints.findOne({timepointName: study.studyDate});
+ if (!timepoint) {
+ return;
+ }
+
+ measurementData.timepointID = timepoint.timepointID;
+
+ // Get a lesion number for this lesion, depending on whether or not the same lesion previously
+ // exists at a different timepoint
+ var lesionNumber = measurementManagerDAL.getNewLesionNumber(measurementData.timepointID, isTarget=true);
+ measurementData.lesionNumber = lesionNumber;
+
+ // Set lesion number
+ doneCallback(lesionNumber);
+}
+
+// This event determines whether or not to show the lesion dialog
+// If there already exists a lesion with this specific lesion number,
+// related to the chosen location.
+function getLesionLocationCallback(measurementData, eventData) {
+ Template.lesionLocationDialog.measurementData = measurementData;
+
+ // Reset the doneCallback saved in the template so we don't call the change event's done callback
+ Template.lesionLocationDialog.doneCallback = undefined;
+
+ // Get the lesion location dialog
+ var dialog = $("#lesionLocationDialog");
+ Template.lesionLocationDialog.dialog = dialog;
+
+ // Show the backdrop
+ UI.render(Template.removableBackdrop, document.body);
+
+ // Make sure the context menu is closed when the user clicks away
+ $(".removableBackdrop").one('mousedown touchstart', function() {
+ closeHandler(dialog);
+ });
+
+ // Select the first option for now
+ var selector = dialog.find("select.selectLesionLocation");
+ selector.find("option:first").prop("selected", true);
+
+ // Find out if this lesion number is already added in the lesion manager for another timepoint
+ // If it is, stop here because we don't need the dialog.
+ var locationUID = measurementManagerDAL.lesionNumberExists(measurementData);
+ if (locationUID) {
+ // Add an ID value to the tool data to link it to the Measurements collection
+ measurementData.id = 'notready';
+
+ measurementData.locationUID = locationUID;
+ measurementManagerDAL.updateTimepointData(measurementData);
+ closeHandler();
+ return;
+ }
+ // If it isn't, continue to open the dialog and have the user choose a lesion location
+
+ // Show the lesion location dialog above
+ var dialogProperty = {
+ top: eventData.currentPoints.page.y - dialog.outerHeight() - 40,
+ left: eventData.currentPoints.page.x - dialog.outerWidth() / 2,
+ display: 'block'
+ };
+
+ // Device is touch device or not
+ // If device is touch device, set position center of screen vertically and horizontally
+ if (isTouchDevice()) {
+ // add dialogMobile class to provide a black,transparent background
+ dialog.addClass("dialogMobile");
+ dialogProperty.top = 0;
+ dialogProperty.left = 0;
+ dialogProperty.right = 0;
+ dialogProperty.bottom = 0;
+ }
+
+ dialog.css(dialogProperty);
+}
+
+function changeLesionLocationCallback(measurementData, eventData, doneCallback) {
+ Template.lesionLocationDialog.measurementData = measurementData;
+ Template.lesionLocationDialog.doneCallback = doneCallback;
+
+ // Get the lesion location dialog
+ var dialog = $("#lesionLocationRelabelDialog");
+ Template.lesionLocationDialog.dialog = dialog;
+
+ // Show the backdrop
+ UI.render(Template.removableBackdrop, document.body);
+
+ // Make sure the context menu is closed when the user clicks away
+ $(".removableBackdrop").one('mousedown touchstart', function() {
+ closeHandler(dialog);
+ });
+
+ // Show the lesion location dialog above
+ var dialogProperty = {
+ top: eventData.currentPoints.page.y - dialog.outerHeight() - 40,
+ left: eventData.currentPoints.page.x - dialog.outerWidth() / 2,
+ display: 'block'
+ };
+
+ // Device is touch device or not
+ // If device is touch device, set position center of screen vertically and horizontally
+ if (isTouchDevice()) {
+ // add dialogMobile class to provide a black,transparent background
+ dialog.addClass("dialogMobile");
+ dialogProperty.top = 0;
+ dialogProperty.left = 0;
+ dialogProperty.right = 0;
+ dialogProperty.bottom = 0;
+ }
+
+ dialog.css(dialogProperty);
+
+ var measurement = Measurements.findOne(measurementData.id);
+ if (!measurement) {
+ return;
+ }
+
+ var currentLocation = LesionLocations.findOne({
+ id: measurement.locationId
+ });
+
+ LesionLocations.update({},
+ {$set: {selected: false}},
+ { multi: true });
+
+ LesionLocations.update(currentLocation._id, {
+ $set: {
+ selected: true
+ }
+ });
+}
+
+var config = {
+ setLesionNumberCallback: setLesionNumberCallback,
+ getLesionLocationCallback: getLesionLocationCallback,
+ changeLesionLocationCallback: changeLesionLocationCallback
+};
+
+cornerstoneTools.lesion.setConfiguration(config);
+
+Template.lesionLocationDialog.events({
+ 'change .selectLesionLocation': function(e) {
+ var measurementData = Template.lesionLocationDialog.measurementData;
+ var doneCallback = Template.lesionLocationDialog.doneCallback;
+ var dialog = Template.lesionLocationDialog.dialog;
+
+ // Get the current value of the selector
+ var selectedOptionId = e.currentTarget.value;
+
+ // If the selected option is still the default (-1)
+ // then stop here
+ if (selectedOptionId < 0) {
+ return;
+ }
+
+ // Get selected location data
+ var locationObj = LesionLocations.findOne({_id: selectedOptionId});
+
+ var id;
+ var existingLocation = PatientLocations.findOne({location: locationObj.location});
+ if (existingLocation) {
+ id = existingLocation._id;
+ } else {
+ // Adds location data to PatientLocation and retrieve the location ID
+ id = PatientLocations.insert({
+ location: locationObj.location,
+ locationId: locationObj._id
+ });
+ }
+
+ // Add an ID value to the tool data to link it to the Measurements collection
+ if (!measurementData.id) {
+ measurementData.id = 'notready';
+
+ // Link locationUID with active lesion measurementData
+ measurementData.locationId = locationObj.id;
+ measurementData.locationUID = id;
+
+ /// Set the isTarget value to true, since this is the target-lesion dialog callback
+ measurementData.isTarget = true;
+
+ // Adds lesion data to timepoints array
+ measurementManagerDAL.addLesionData(measurementData);
+ } else {
+ Measurements.update(measurementData.id, {
+ $set: {
+ location: locationObj.location,
+ locationId: locationObj.id,
+ locationUID: id
+ }
+ });
+ }
+
+ // Close the dialog
+ closeHandler(dialog);
+
+ if (doneCallback && typeof doneCallback === 'function') {
+ doneCallback(measurementData);
+ }
+ },
+ 'click #removeLesion': function() {
+ var measurementData = Template.lesionLocationDialog.measurementData;
+ var doneCallback = Template.lesionLocationDialog.doneCallback;
+ var dialog = Template.lesionLocationDialog.dialog;
+
+ if (doneCallback && typeof doneCallback === 'function') {
+ var deleteTool = true;
+ doneCallback(measurementData, deleteTool);
+ }
+
+ closeHandler(dialog);
+ },
+ 'click #btnCloseLesionPopup': function() {
+ var dialog = Template.lesionLocationDialog.dialog;
+ closeHandler(dialog);
+ },
+ 'keypress #lesionLocationDialog, keypress #lesionLocationRelabelDialog': function(e) {
+ var dialog = Template.lesionLocationDialog.dialog;
+
+ // If Enter is pressed, close the dialog
+ if (e.which === 13) {
+ closeHandler(dialog);
+ }
+ }
+});
+
+Template.lesionLocationDialog.helpers({
+ 'lesionLocations': function() {
+ return LesionLocations.find();
+ }
+});
\ No newline at end of file
diff --git a/Packages/lesiontracker/client/components/lesionLocationDialog/lesionLocationDialog.styl b/Packages/lesiontracker/client/components/lesionLocationDialog/lesionLocationDialog.styl
new file mode 100644
index 000000000..172924edf
--- /dev/null
+++ b/Packages/lesiontracker/client/components/lesionLocationDialog/lesionLocationDialog.styl
@@ -0,0 +1,40 @@
+#lesionLocationDialog, #lesionLocationRelabelDialog
+ display: none
+ position: absolute
+ top: 0
+ bottom: 0
+ left: 0
+ right: 0
+ z-index: 100
+ width: 300px
+ border-radius: 5px
+ padding: 10px 20px 10px 20px
+ background-color: rgba(255,255,255,1)
+
+ /* dialogMobile is added to #lesionLocationDialog when touchDevices is detected */
+ .dialogMobile
+ margin: 0 auto
+ float: none
+ background-color: rgba(0,0,0,0.5)
+ text-align: center
+
+ #closeLesionPopup
+ outline: none
+ border: none
+ background-color: transparent
+
+ #selectLesionLocation
+ margin-top: 5px
+
+ .dialogContent
+ margin-bottom: 10px
+
+ #removeLesion
+ outline: none
+ text-decoration: none
+
+#lesionLocationDialog
+ height: 110px
+
+#lesionLocationRelabelDialog
+ height: 125px
\ No newline at end of file
diff --git a/Packages/lesiontracker/components/lesionTable/lesionTable.html b/Packages/lesiontracker/client/components/lesionTable/lesionTable.html
similarity index 100%
rename from Packages/lesiontracker/components/lesionTable/lesionTable.html
rename to Packages/lesiontracker/client/components/lesionTable/lesionTable.html
diff --git a/Packages/lesiontracker/components/lesionTable/lesionTable.js b/Packages/lesiontracker/client/components/lesionTable/lesionTable.js
similarity index 94%
rename from Packages/lesiontracker/components/lesionTable/lesionTable.js
rename to Packages/lesiontracker/client/components/lesionTable/lesionTable.js
index 2b1020645..a9005b906 100644
--- a/Packages/lesiontracker/components/lesionTable/lesionTable.js
+++ b/Packages/lesiontracker/client/components/lesionTable/lesionTable.js
@@ -41,6 +41,11 @@ activateLesion = function(measurementId, templateData) {
$(".imageViewerViewport").each(function(viewportIndex, element) {
// Stop if we run out of timepoints before viewports
if (viewportIndex >= timepointsWithEntries.length) {
+ // Update the element anyway, to remove any other highlights that are present
+ deactivateAllToolData(element, 'lesion');
+ deactivateAllToolData(element, 'nonTarget');
+ cornerstone.updateImage(element);
+
return false;
}
@@ -57,6 +62,10 @@ activateLesion = function(measurementId, templateData) {
// If there is no measurement data to display, stop here
if (!measurementAtTimepoint) {
+ // Update the element anyway, to remove any other highlights that are present
+ deactivateAllToolData(element, 'lesion');
+ deactivateAllToolData(element, 'nonTarget');
+ cornerstone.updateImage(element);
return;
}
@@ -247,7 +256,6 @@ Template.lesionTable.events({
});
}
-
});
Template.lesionTable.onCreated(function(){
@@ -275,14 +283,13 @@ Tracker.autorun(function () {
dates: []
};
- $("#"+contentId+" .imageViewerViewport").each(function(viewportIndex, element) {
+ $(".imageViewerViewport").each(function(viewportIndex, element) {
var enabledElement = cornerstone.getEnabledElement(element);
if(enabledElement && enabledElement.image){
var imageId = enabledElement.image.imageId;
var study = cornerstoneTools.metaData.get('study', imageId);
var studyDate = study.studyDate;
- var patientId = study.patientId;
- loadedStudyDates.patientId = patientId;
+ loadedStudyDates.patientId = study.patientId;
// Check studyDate is added before
if (loadedStudyDates.dates.indexOf(studyDate) < 0) {
loadedStudyDates.dates.push(studyDate);
@@ -306,7 +313,6 @@ Tracker.autorun(function () {
$set: {
timepointLoaded: timepointLoaded
}
-
});
});
}
diff --git a/Packages/lesiontracker/components/lesionTable/lesionTable.styl b/Packages/lesiontracker/client/components/lesionTable/lesionTable.styl
similarity index 100%
rename from Packages/lesiontracker/components/lesionTable/lesionTable.styl
rename to Packages/lesiontracker/client/components/lesionTable/lesionTable.styl
diff --git a/Packages/lesiontracker/components/lesionTableRow/lesionTableRow.html b/Packages/lesiontracker/client/components/lesionTableRow/lesionTableRow.html
similarity index 100%
rename from Packages/lesiontracker/components/lesionTableRow/lesionTableRow.html
rename to Packages/lesiontracker/client/components/lesionTableRow/lesionTableRow.html
diff --git a/Packages/lesiontracker/components/lesionTableRow/lesionTableRow.js b/Packages/lesiontracker/client/components/lesionTableRow/lesionTableRow.js
similarity index 100%
rename from Packages/lesiontracker/components/lesionTableRow/lesionTableRow.js
rename to Packages/lesiontracker/client/components/lesionTableRow/lesionTableRow.js
diff --git a/Packages/lesiontracker/components/lesionTableTimepointCell/lesionTableTimepointCell.html b/Packages/lesiontracker/client/components/lesionTableTimepointCell/lesionTableTimepointCell.html
similarity index 100%
rename from Packages/lesiontracker/components/lesionTableTimepointCell/lesionTableTimepointCell.html
rename to Packages/lesiontracker/client/components/lesionTableTimepointCell/lesionTableTimepointCell.html
diff --git a/Packages/lesiontracker/components/lesionTableTimepointCell/lesionTableTimepointCell.js b/Packages/lesiontracker/client/components/lesionTableTimepointCell/lesionTableTimepointCell.js
similarity index 100%
rename from Packages/lesiontracker/components/lesionTableTimepointCell/lesionTableTimepointCell.js
rename to Packages/lesiontracker/client/components/lesionTableTimepointCell/lesionTableTimepointCell.js
diff --git a/Packages/lesiontracker/components/lesionTableTimepointHeader/lesionTableTimepointHeader.html b/Packages/lesiontracker/client/components/lesionTableTimepointHeader/lesionTableTimepointHeader.html
similarity index 100%
rename from Packages/lesiontracker/components/lesionTableTimepointHeader/lesionTableTimepointHeader.html
rename to Packages/lesiontracker/client/components/lesionTableTimepointHeader/lesionTableTimepointHeader.html
diff --git a/Packages/lesiontracker/components/lesionTableTimepointHeader/lesionTableTimepointHeader.js b/Packages/lesiontracker/client/components/lesionTableTimepointHeader/lesionTableTimepointHeader.js
similarity index 100%
rename from Packages/lesiontracker/components/lesionTableTimepointHeader/lesionTableTimepointHeader.js
rename to Packages/lesiontracker/client/components/lesionTableTimepointHeader/lesionTableTimepointHeader.js
diff --git a/Packages/lesiontracker/components/lesionTableTimepointHeader/lesionTableTimepointHeader.styl b/Packages/lesiontracker/client/components/lesionTableTimepointHeader/lesionTableTimepointHeader.styl
similarity index 100%
rename from Packages/lesiontracker/components/lesionTableTimepointHeader/lesionTableTimepointHeader.styl
rename to Packages/lesiontracker/client/components/lesionTableTimepointHeader/lesionTableTimepointHeader.styl
diff --git a/Packages/lesiontracker/client/components/nonTargetLesionDialog/nonTargetLesionDialog.html b/Packages/lesiontracker/client/components/nonTargetLesionDialog/nonTargetLesionDialog.html
new file mode 100644
index 000000000..44575ec7b
--- /dev/null
+++ b/Packages/lesiontracker/client/components/nonTargetLesionDialog/nonTargetLesionDialog.html
@@ -0,0 +1,40 @@
+
+
+
+
+
Select Lesion Location
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/Packages/lesiontracker/components/nonTargetLesionDialog/nonTargetLesionDialog.js b/Packages/lesiontracker/client/components/nonTargetLesionDialog/nonTargetLesionDialog.js
similarity index 55%
rename from Packages/lesiontracker/components/nonTargetLesionDialog/nonTargetLesionDialog.js
rename to Packages/lesiontracker/client/components/nonTargetLesionDialog/nonTargetLesionDialog.js
index f5946a44b..deafa1b60 100644
--- a/Packages/lesiontracker/components/nonTargetLesionDialog/nonTargetLesionDialog.js
+++ b/Packages/lesiontracker/client/components/nonTargetLesionDialog/nonTargetLesionDialog.js
@@ -1,5 +1,12 @@
-// This event sets lesion number for new lesion
+function closeHandler(dialog) {
+ // Hide the lesion dialog
+ $(dialog).css('display', 'none');
+ // Remove the backdrop
+ $(".removableBackdrop").remove();
+}
+
+// This event sets lesion number for new lesion
function setLesionNumberCallback(measurementData, eventData, doneCallback) {
// Get the current element's timepointID from the study date metadata
var element = eventData.element;
@@ -29,27 +36,43 @@ function setLesionNumberCallback(measurementData, eventData, doneCallback) {
// This event determines whether or not to show the Non-Target lesion dialog
// If there already exists a lesion with this specific lesion number,
// related to the chosen location.
-
function getNonTargetLesionLocationCallback(measurementData, eventData) {
+ Template.nonTargetLesionDialog.measurementData = measurementData;
// Get the non-target lesion location dialog
- var nonTargetlesionDialog = $("#nonTargetLesionLocationDialog");
+ var dialog = $("#nonTargetLesionLocationDialog");
+ Template.nonTargetLesionDialog.dialog = dialog;
+
+ // Show the backdrop
+ UI.render(Template.removableBackdrop, document.body);
+
+ // Make sure the context menu is closed when the user clicks away
+ $(".removableBackdrop").one('mousedown touchstart', function() {
+ closeHandler(dialog);
+
+ if (doneCallback && typeof doneCallback === 'function') {
+ var deleteTool = true;
+ doneCallback(measurementData, deleteTool);
+ }
+ });
// Find the select option box
- var selectorLocation = nonTargetlesionDialog.find("select#selectNonTargetLesionLocation");
- var selectorResponse = nonTargetlesionDialog.find("select#selectNonTargetLesionLocationResponse");
+ var selectorLocation = dialog.find("select#selectNonTargetLesionLocation");
+ var selectorResponse = dialog.find("select#selectNonTargetLesionLocationResponse");
- // OK button
- var btnOK = nonTargetlesionDialog.find("button#nonTargetLesionOK");
+ selectorLocation.find("option:first").prop("selected", "selected");
+ selectorResponse.find("option:first").prop("selected", "selected");
-
- // If selector location is disabled, make it enable
- enableLocationSelection();
+ // Allow location selection
+ selectorLocation.removeAttr("disabled");
// Find out if this lesion number is already added in the lesion manager for another timepoint
// If it is, disable selector location
var locationUID = measurementManagerDAL.lesionNumberExists(measurementData);
if (locationUID) {
+ // Add an ID value to the tool data to link it to the Measurements collection
+ measurementData.id = 'notready';
+
measurementData.locationUID = locationUID;
// Disable the selection of a new location
disableLocationSelection(measurementData.locationUID);
@@ -58,48 +81,16 @@ function getNonTargetLesionLocationCallback(measurementData, eventData) {
// Disable selector location to prevent selecting a new location
function disableLocationSelection(locationUID) {
var locationName = measurementManagerDAL.getLocationName(locationUID);
- selectorLocation.find('option').each(function()
- {
+ selectorLocation.find('option').each(function() {
if ($(this).text() === locationName) {
// Select location in locations dropdown list
selectorLocation.find('option').eq($(this).index()).prop("selected", true);
- return;
}
});
selectorLocation.prop("disabled", true);
}
- // Enable selector location
- function enableLocationSelection() {
- selectorLocation.removeAttr("disabled");
- }
-
- function closeHandler() {
-
- // Hide the lesion dialog
- nonTargetlesionDialog.css('display', 'none');
- // Enable selector location
- enableLocationSelection();
-
- // Get the current value of the select option box
- selectorLocation.find("option:first").prop("selected", "selected");
- selectorResponse.find("option:first").prop("selected", "selected");
-
- }
-
- // Attach keypress handlers so the user can close with the Enter button
- nonTargetlesionDialog.off("keypress");
- nonTargetlesionDialog.on('keypress', keyPressHandler);
-
- // This is the keypress callback function
- function keyPressHandler(e) {
- // If Enter is pressed, close the dialog
- if (e.which === 13) {
- closeHandler();
- }
- }
-
// Show the nonTargetLesion dialog above
var dialogProperty = {
top: eventData.currentPoints.page.y,
@@ -111,27 +102,40 @@ function getNonTargetLesionLocationCallback(measurementData, eventData) {
// If device is touch device, set position center of screen vertically and horizontally
if (isTouchDevice()) {
// add dialogMobile class to provide a black,transparent background
- $(nonTargetlesionDialog).addClass("dialogMobile");
+ dialog.addClass("dialogMobile");
dialogProperty.top = 0;
dialogProperty.left = 0;
dialogProperty.right = 0;
dialogProperty.bottom = 0;
- $(".contentWrapper").css({
- left: ($(window).width() - $(".contentWrapper").width()) / 2,
- top: ($(window).height() - $(".contentWrapper").height()) / 2
-
- });
}
- nonTargetlesionDialog.css(dialogProperty);
+ dialog.css(dialogProperty);
+}
+
+function changeNonTargetLesionLocationCallback(measurementData, eventData, doneCallback) {
+ doneCallback(prompt('Change your lesion location:'));
+}
+
+var config = {
+ setLesionNumberCallback: setLesionNumberCallback,
+ getNonTargetLesionLocationCallback: getNonTargetLesionLocationCallback,
+ changeNonTargetLesionLocationCallback: changeNonTargetLesionLocationCallback
+};
+
+cornerstoneTools.nonTarget.setConfiguration(config);
+
+Template.nonTargetLesionDialog.events({
+ 'click #nonTargetLesionOK': function() {
+ var dialog = Template.nonTargetLesionDialog.dialog;
+ var measurementData = Template.nonTargetLesionDialog.measurementData;
+
+ // Find the select option box
+ var selectorLocation = dialog.find("select#selectNonTargetLesionLocation");
+ var selectorResponse = dialog.find("select#selectNonTargetLesionLocationResponse");
- // Click OK button
- // Add lesion to lesion table
- btnOK.off('click');
- btnOK.on('click', function(e) {
// Get the current value of the selector
var selectedOptionId = selectorLocation.find("option:selected").val();
- var responseOptionCode = nonTargetlesionDialog.find("select#selectNonTargetLesionLocationResponse option:selected").val();
+ var responseOptionId = selectorResponse.find("option:selected").val();
// If the selected option is still the default (-1)
// then stop here
@@ -141,7 +145,7 @@ function getNonTargetLesionLocationCallback(measurementData, eventData) {
// If the selected response option is still the default (-1)
// then stop here
- if (responseOptionCode < 0) {
+ if (responseOptionId < 0) {
return;
}
@@ -157,102 +161,61 @@ function getNonTargetLesionLocationCallback(measurementData, eventData) {
id = PatientLocations.insert({location: locationObj.location});
}
- // Link locationUID with active lesion measurementData
- measurementData.locationUID = id;
+ if (!measurementData.id) {
+ // Add an ID value to the tool data to link it to the Measurements collection
+ measurementData.id = 'notready';
- /// Set the isTarget value to true, since this is the target-lesion dialog callback
- measurementData.isTarget = false;
+ // Link locationUID with active lesion measurementData
+ measurementData.locationUID = id;
- // measurementText is set from location response list
- measurementData.measurementText = responseOptionCode;
+ /// Set the isTarget value to true, since this is the target-lesion dialog callback
+ measurementData.isTarget = false;
- // Adds lesion data to timepoints array
- measurementManagerDAL.addLesionData(measurementData);
+ // measurementText is set from location response list
+ measurementData.measurementText = responseOptionId;
+
+ // Adds lesion data to timepoints array
+ measurementManagerDAL.addLesionData(measurementData);
+ } else {
+ Measurements.update(measurementData.id, {
+ $set: {
+ location: locationObj.location,
+ locationId: locationObj.id,
+ locationUID: id
+ }
+ });
+ }
// Close the dialog
- closeHandler();
- });
-}
+ closeHandler(dialog);
+ },
+ 'click #removeLesion': function() {
+ var measurementData = Template.nonTargetLesionDialog.measurementData;
+ var doneCallback = Template.nonTargetLesionDialog.doneCallback;
+ var dialog = Template.nonTargetLesionDialog.dialog;
-function changeNonTargetLesionLocationCallback(measurementData, eventData, doneCallback) {
- doneCallback(prompt('Change your lesion location:'));
-}
+ if (doneCallback && typeof doneCallback === 'function') {
+ var deleteTool = true;
+ doneCallback(measurementData, deleteTool);
+ }
-var config = {
- setLesionNumberCallback: setLesionNumberCallback,
- getNonTargetLesionLocationCallback: getNonTargetLesionLocationCallback,
- changeNonTargetLesionLocationCallback: changeNonTargetLesionLocationCallback
-};
+ closeHandler(dialog);
+ },
+ 'click #btnCloseLesionPopup': function() {
+ var dialog = Template.nonTargetLesionDialog.dialog;
+ closeHandler(dialog);
+ },
+ 'keypress #lesionLocationDialog, keypress #lesionLocationRelabelDialog': function(e) {
+ var dialog = Template.nonTargetLesionDialog.dialog;
-cornerstoneTools.nonTarget.setConfiguration(config);
+ // If Enter is pressed, close the dialog
+ if (e.which === 13) {
+ closeHandler(dialog);
+ }
+ }
+});
-LocationResponses = new Meteor.Collection(null);
-
-LocationResponses.insert(
- {
- text: "Complete response",
- code: "CR",
- description: ""
- }
-);
-LocationResponses.insert(
- {
- text: "Progressive disease",
- code: "PD",
- description: ""
- }
-);
-LocationResponses.insert(
- {
- text: "Complete response",
- code: "CR",
- description: ""
- }
-);
-LocationResponses.insert(
- {
- text: "Stable disease",
- code: "SD",
- description: ""
- }
-);
-LocationResponses.insert(
- {
- text: "Non-measurable",
- code: "NM",
- description: ""
- }
-);
-LocationResponses.insert(
- {
- text: "Unknown",
- code: "UN",
- description: ""
- }
-);
-LocationResponses.insert(
- {
- text: "Not Evaluable",
- code: "NE",
- description: ""
- }
-);
-LocationResponses.insert(
- {
- text: "Non-CR/Non-PD",
- code: "NN",
- description: ""
- }
-);
-LocationResponses.insert(
- {
- text: "Excluded",
- code: "EX",
- description: ""
- }
-);
-
Template.nonTargetLesionDialog.helpers({
'lesionLocations': function() {
return LesionLocations.find();
diff --git a/Packages/lesiontracker/client/components/nonTargetLesionDialog/nonTargetLesionDialog.styl b/Packages/lesiontracker/client/components/nonTargetLesionDialog/nonTargetLesionDialog.styl
new file mode 100644
index 000000000..8ad3005af
--- /dev/null
+++ b/Packages/lesiontracker/client/components/nonTargetLesionDialog/nonTargetLesionDialog.styl
@@ -0,0 +1,35 @@
+#nonTargetLesionLocationDialog
+ display: none
+ position: absolute
+ top: 0
+ bottom: 0
+ left: 0
+ right: 0
+ z-index: 100
+ width: 300px
+ height: 230px
+ border-radius: 5px
+ padding: 10px 20px 10px 20px
+ background-color: rgba(255,255,255,1)
+
+ /* dialogMobile is added to #nonTargetLesionLocationDialog when touchDevices is detected */
+ .dialogMobile
+ margin: 0 auto
+ float: none
+ background-color: rgba(0,0,0,0.5)
+ text-align: center
+
+ #selectNonTargetLesionLocation, #selectNonTargetLesionLocationResponse
+ width: 100%
+
+ .dialogContent, .lesionLocation, .locationResponse
+ margin-bottom: 20px
+
+ .elementContainer
+ width: 100%
+ margin: 0 auto
+ float: none
+
+ .locationOK
+ text-align: center
+
\ No newline at end of file
diff --git a/Packages/lesiontracker/components/studyDateList/studyDateList.html b/Packages/lesiontracker/client/components/studyDateList/studyDateList.html
similarity index 100%
rename from Packages/lesiontracker/components/studyDateList/studyDateList.html
rename to Packages/lesiontracker/client/components/studyDateList/studyDateList.html
diff --git a/Packages/lesiontracker/components/studyDateList/studyDateList.js b/Packages/lesiontracker/client/components/studyDateList/studyDateList.js
similarity index 100%
rename from Packages/lesiontracker/components/studyDateList/studyDateList.js
rename to Packages/lesiontracker/client/components/studyDateList/studyDateList.js
diff --git a/Packages/lesiontracker/components/studyDateList/studyDateList.styl b/Packages/lesiontracker/client/components/studyDateList/studyDateList.styl
similarity index 100%
rename from Packages/lesiontracker/components/studyDateList/studyDateList.styl
rename to Packages/lesiontracker/client/components/studyDateList/studyDateList.styl
diff --git a/Packages/lesiontracker/components/timepointTextDialog/timepointTextDialog.html b/Packages/lesiontracker/client/components/timepointTextDialog/timepointTextDialog.html
similarity index 100%
rename from Packages/lesiontracker/components/timepointTextDialog/timepointTextDialog.html
rename to Packages/lesiontracker/client/components/timepointTextDialog/timepointTextDialog.html
diff --git a/Packages/lesiontracker/components/timepointTextDialog/timepointTextDialog.styl b/Packages/lesiontracker/client/components/timepointTextDialog/timepointTextDialog.styl
similarity index 100%
rename from Packages/lesiontracker/components/timepointTextDialog/timepointTextDialog.styl
rename to Packages/lesiontracker/client/components/timepointTextDialog/timepointTextDialog.styl
diff --git a/Packages/lesiontracker/components/lesionLocationDialog/lesionLocationDialog.html b/Packages/lesiontracker/components/lesionLocationDialog/lesionLocationDialog.html
deleted file mode 100644
index 869487863..000000000
--- a/Packages/lesiontracker/components/lesionLocationDialog/lesionLocationDialog.html
+++ /dev/null
@@ -1,20 +0,0 @@
-
-
-
-
-
Select Lesion Location
-
-
-
-
-
-
-
-
-
-
\ No newline at end of file
diff --git a/Packages/lesiontracker/components/lesionLocationDialog/lesionLocationDialog.js b/Packages/lesiontracker/components/lesionLocationDialog/lesionLocationDialog.js
deleted file mode 100644
index 9085a9041..000000000
--- a/Packages/lesiontracker/components/lesionLocationDialog/lesionLocationDialog.js
+++ /dev/null
@@ -1,226 +0,0 @@
-// This event sets lesion number for new lesion
-
-function setLesionNumberCallback(measurementData, eventData, doneCallback) {
- // Get the current element's timepointID from the study date metadata
- var element = eventData.element;
- var enabledElement = cornerstone.getEnabledElement(element);
- var imageId = enabledElement.image.imageId;
-
- var study = cornerstoneTools.metaData.get('study', imageId);
- var timepoint = Timepoints.findOne({timepointName: study.studyDate});
- if (!timepoint) {
- return;
- }
-
- measurementData.timepointID = timepoint.timepointID;
-
- // Get a lesion number for this lesion, depending on whether or not the same lesion previously
- // exists at a different timepoint
- var lesionNumber = measurementManagerDAL.getNewLesionNumber(measurementData.timepointID, isTarget=true);
- measurementData.lesionNumber = lesionNumber;
-
- // Set lesion number
- doneCallback(lesionNumber);
-}
-
-// This event determines whether or not to show the lesion dialog
-// If there already exists a lesion with this specific lesion number,
-// related to the chosen location.
-function getLesionLocationCallback(measurementData, eventData) {
- // Get the lesion location dialog
- var lesionDialog = $("#lesionLocationDialog");
-
- // Find the select option box
- var selector = lesionDialog.find("select#selectLesionLocation");
-
- // Find out if this lesion number is already added in the lesion manager for another timepoint
- // If it is, stop here because we don't need the dialog.
- var locationUID = measurementManagerDAL.lesionNumberExists(measurementData);
- if (locationUID) {
- measurementData.locationUID = locationUID;
- measurementManagerDAL.updateTimepointData(measurementData);
- closeHandler();
- return;
- }
- // If it isn't, continue to open the dialog and have the user choose a lesion location
-
- // Attach close handler if the user clicks the close button
- var close = lesionDialog.find("#btnCloseLesionPopup");
- close.off('click');
- close.on('click', function() {
- closeHandler();
- });
-
- function closeHandler() {
- // Hide the lesion dialog
- lesionDialog.css('display', 'none');
-
- // Select the first option for the next time the dialog is opened
- selector.find("option:first").prop("selected", true);
-
- }
-
- // Attach keypress handlers so the user can close with the Enter button
- lesionDialog.off("keypress");
- lesionDialog.on('keypress', keyPressHandler);
-
- // This is the keypress callback function
- function keyPressHandler(e) {
- // If Enter is pressed, close the dialog
- if (e.which === 13) {
- closeHandler();
- }
- }
-
- // Show the lesion location dialog above
-
- var dialogProperty = {
- top: eventData.currentPoints.page.y - lesionDialog.outerHeight() - 40,
- left: eventData.currentPoints.page.x - lesionDialog.outerWidth() / 2,
- display: 'block'
- };
-
- // Device is touch device or not
- // If device is touch device, set position center of screen vertically and horizontally
- if (isTouchDevice()) {
- // add dialogMobile class to provide a black,transparent background
- $(lesionDialog).addClass("dialogMobile");
- dialogProperty.top = 0;
- dialogProperty.left = 0;
- dialogProperty.right = 0;
- dialogProperty.bottom = 0;
- $(".lesionContentWrapper").css({
- left: ($(window).width() - $(".lesionContentWrapper").width()) / 2,
- top: ($(window).height() - $(".lesionContentWrapper").height()) / 2
-
- });
- }
-
- lesionDialog.css(dialogProperty);
-
- // Attach a callback for the select box
- selector.off('change');
- selector.on('change', function(e) {
- // Get the current value of the selector
- var selectedOptionId = this.value;
-
- // If the selected option is still the default (-1)
- // then stop here
- if (selectedOptionId < 0) {
- return;
- }
-
- // Get selected location data
- var locationObj = LesionLocations.findOne({_id: selectedOptionId});
-
-
- var id;
- var existingLocation = PatientLocations.findOne({location: locationObj.location});
- if (existingLocation) {
- id = existingLocation._id;
- } else {
- // Adds location data to PatientLocation and retrieve the location ID
- id = PatientLocations.insert({location: locationObj.location});
- }
-
- // Link locationUID with active lesion measurementData
- measurementData.locationUID = id;
-
- /// Set the isTarget value to true, since this is the target-lesion dialog callback
- measurementData.isTarget = true;
-
- // Adds lesion data to timepoints array
- measurementManagerDAL.addLesionData(measurementData);
-
- // Close the dialog
- closeHandler();
- });
-}
-
-function changeLesionLocationCallback(measurementData, eventData, doneCallback) {
- doneCallback(prompt('Change your lesion location:'));
-}
-
-var config = {
- setLesionNumberCallback: setLesionNumberCallback,
- getLesionLocationCallback: getLesionLocationCallback,
- changeLesionLocationCallback: changeLesionLocationCallback
-};
-
-cornerstoneTools.lesion.setConfiguration(config);
-
-
-LesionLocations = new Meteor.Collection(null);
-
-LesionLocations.insert({
- location: "Liver Left",
- hasDescription: false,
- description: ""
-});
-
-LesionLocations.insert({
- location: "Liver Right",
- hasDescription: false,
- description: ""
-});
-
-LesionLocations.insert({
- location: "Liver Caudate",
- hasDescription: false,
- description: ""
-});
-
-LesionLocations.insert({
- location: "Lung LLL",
- hasDescription: false,
- description: ""
-});
-
-LesionLocations.insert({
- location: "Lung LUL",
- hasDescription: false,
- description: ""
-});
-
-LesionLocations.insert({
- location: "Lung RLL",
- hasDescription: false,
- description: ""
-});
-LesionLocations.insert({
- location: "Lung RML",
- hasDescription: false,
- description: ""
-});
-LesionLocations.insert({
- location: "Lung RUL",
- hasDescription: false,
- description: ""
-});
-LesionLocations.insert({
- location: "Pleura Left",
- hasDescription: false,
- description: ""
-});
-LesionLocations.insert({
- location: "Pleura Right",
- hasDescription: false,
- description: ""
-});
-
-LesionLocations.insert({
- location: "Kidney Left",
- hasDescription: false,
- description: ""
-});
-LesionLocations.insert({
- location: "Kidney Right",
- hasDescription: false,
- description: ""
-});
-
-Template.lesionLocationDialog.helpers({
- 'lesionLocations': function() {
- return LesionLocations.find();
- }
-});
\ No newline at end of file
diff --git a/Packages/lesiontracker/components/lesionLocationDialog/lesionLocationDialog.styl b/Packages/lesiontracker/components/lesionLocationDialog/lesionLocationDialog.styl
deleted file mode 100644
index 6c62f51c3..000000000
--- a/Packages/lesiontracker/components/lesionLocationDialog/lesionLocationDialog.styl
+++ /dev/null
@@ -1,32 +0,0 @@
-#lesionLocationDialog
- display: none
- position: absolute
- z-index: 100
-
-/* dialogMobile is added to #lesionLocationDialog when touchDevices is detected */
-.dialogMobile
- margin: 0 auto;
- float: none;
- background-color: rgba(0,0,0,0.5);
- text-align: center;
-
-.lesionContentWrapper
- position: absolute;
- width: 250px;
- height: 150px;
- border-radius: 10px;
- padding: 10px 20px 10px 20px;
- background-color: rgba(255,255,255,1);
- text-align: left
-
-#closeLesionPopup
- outline: 0
- border: none
- background-color: transparent
-
-#selectLesionLocation
- margin-top: 5px
-
-.dialogContent
- margin-bottom: 20px
-
diff --git a/Packages/lesiontracker/components/nonTargetLesionDialog/nonTargetLesionDialog.css b/Packages/lesiontracker/components/nonTargetLesionDialog/nonTargetLesionDialog.css
deleted file mode 100644
index 36a555cfc..000000000
--- a/Packages/lesiontracker/components/nonTargetLesionDialog/nonTargetLesionDialog.css
+++ /dev/null
@@ -1,48 +0,0 @@
-#nonTargetLesionLocationDialog {
- display: none;
- position: absolute;
- z-index: 100;
-}
-
-/* dialogMobile is added to #nonTargetLesionLocationDialog when touchDevices is detected */
-.dialogMobile {
- margin: 0 auto;
- float: none;
- background-color: rgba(0,0,0,0.5);
- text-align: center;
-}
-
-.contentWrapper {
- position: absolute;
- width: 250px;
- height: 250px;
- border-radius: 10px;
- padding: 10px 20px 10px 20px;
- background-color: rgba(255,255,255,1);
- text-align: left;
-}
-
-#selectNonTargetLesionLocation, #selectNonTargetLesionLocationResponse {
- width: 100%;
-}
-
-.dialogContent, .lesionLocation, .locationResponse {
- margin-bottom: 20px;
-}
-
-.elementContainer {
- width: 100%;
- margin: 0 auto;
- float: none;
- text-align: left;
-}
-
-.locationOK {
- text-align: center;
-}
-
-.btn{
- background-color: #bbb;
- border: 1px solid #888;
- color: #000000;
-}
diff --git a/Packages/lesiontracker/components/nonTargetLesionDialog/nonTargetLesionDialog.html b/Packages/lesiontracker/components/nonTargetLesionDialog/nonTargetLesionDialog.html
deleted file mode 100644
index 095f5fed0..000000000
--- a/Packages/lesiontracker/components/nonTargetLesionDialog/nonTargetLesionDialog.html
+++ /dev/null
@@ -1,45 +0,0 @@
-
-
-
-
-
-
Select Lesion Location
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
\ No newline at end of file
diff --git a/Packages/lesiontracker/package.js b/Packages/lesiontracker/package.js
index 945c8c21b..753d0e741 100644
--- a/Packages/lesiontracker/package.js
+++ b/Packages/lesiontracker/package.js
@@ -17,38 +17,41 @@ Package.onUse(function (api) {
api.addFiles('log.js', ['client', 'server']);
- api.addFiles('compatibility/lesionTool.js', 'client', {bare: true});
- api.addFiles('compatibility/nonTargetTool.js', 'client', {bare: true});
- api.addFiles('compatibility/measurementManagerDAL.js', 'client', {bare: true});
+ api.addFiles('client/collections/LesionLocations.js', 'client');
+ api.addFiles('client/collections/LocationResponses.js', 'client');
- api.addFiles('components/lesionLocationDialog/lesionLocationDialog.html', 'client');
- api.addFiles('components/lesionLocationDialog/lesionLocationDialog.js', 'client');
- api.addFiles('components/lesionLocationDialog/lesionLocationDialog.styl', 'client');
+ api.addFiles('client/compatibility/lesionTool.js', 'client', {bare: true});
+ api.addFiles('client/compatibility/nonTargetTool.js', 'client', {bare: true});
+ api.addFiles('client/compatibility/measurementManagerDAL.js', 'client', {bare: true});
+
+ api.addFiles('client/components/lesionLocationDialog/lesionLocationDialog.html', 'client');
+ api.addFiles('client/components/lesionLocationDialog/lesionLocationDialog.js', 'client');
+ api.addFiles('client/components/lesionLocationDialog/lesionLocationDialog.styl', 'client');
- api.addFiles('components/lesionTable/lesionTable.html', 'client');
- api.addFiles('components/lesionTable/lesionTable.styl', 'client');
- api.addFiles('components/lesionTable/lesionTable.js', 'client');
+ api.addFiles('client/components/lesionTable/lesionTable.html', 'client');
+ api.addFiles('client/components/lesionTable/lesionTable.styl', 'client');
+ api.addFiles('client/components/lesionTable/lesionTable.js', 'client');
- api.addFiles('components/lesionTableRow/lesionTableRow.html', 'client');
- api.addFiles('components/lesionTableRow/lesionTableRow.js', 'client');
+ api.addFiles('client/components/lesionTableRow/lesionTableRow.html', 'client');
+ api.addFiles('client/components/lesionTableRow/lesionTableRow.js', 'client');
- api.addFiles('components/lesionTableTimepointCell/lesionTableTimepointCell.html', 'client');
- api.addFiles('components/lesionTableTimepointCell/lesionTableTimepointCell.js', 'client');
+ api.addFiles('client/components/lesionTableTimepointCell/lesionTableTimepointCell.html', 'client');
+ api.addFiles('client/components/lesionTableTimepointCell/lesionTableTimepointCell.js', 'client');
- api.addFiles('components/lesionTableTimepointHeader/lesionTableTimepointHeader.html', 'client');
- api.addFiles('components/lesionTableTimepointHeader/lesionTableTimepointHeader.js', 'client');
- api.addFiles('components/lesionTableTimepointHeader/lesionTableTimepointHeader.styl', 'client');
+ api.addFiles('client/components/lesionTableTimepointHeader/lesionTableTimepointHeader.html', 'client');
+ api.addFiles('client/components/lesionTableTimepointHeader/lesionTableTimepointHeader.js', 'client');
+ api.addFiles('client/components/lesionTableTimepointHeader/lesionTableTimepointHeader.styl', 'client');
- api.addFiles('components/nonTargetLesionDialog/nonTargetLesionDialog.html', 'client');
- api.addFiles('components/nonTargetLesionDialog/nonTargetLesionDialog.css', 'client');
- api.addFiles('components/nonTargetLesionDialog/nonTargetLesionDialog.js', 'client');
+ api.addFiles('client/components/nonTargetLesionDialog/nonTargetLesionDialog.html', 'client');
+ api.addFiles('client/components/nonTargetLesionDialog/nonTargetLesionDialog.styl', 'client');
+ api.addFiles('client/components/nonTargetLesionDialog/nonTargetLesionDialog.js', 'client');
- api.addFiles('components/studyDateList/studyDateList.html', 'client');
- api.addFiles('components/studyDateList/studyDateList.styl', 'client');
- api.addFiles('components/studyDateList/studyDateList.js', 'client');
+ api.addFiles('client/components/studyDateList/studyDateList.html', 'client');
+ api.addFiles('client/components/studyDateList/studyDateList.styl', 'client');
+ api.addFiles('client/components/studyDateList/studyDateList.js', 'client');
- api.addFiles('components/timepointTextDialog/timepointTextDialog.html', 'client');
- api.addFiles('components/timepointTextDialog/timepointTextDialog.styl', 'client');
+ api.addFiles('client/components/timepointTextDialog/timepointTextDialog.html', 'client');
+ api.addFiles('client/components/timepointTextDialog/timepointTextDialog.styl', 'client');
// Server functions
api.addFiles('server/collections.js', 'server');
@@ -57,7 +60,6 @@ Package.onUse(function (api) {
// Both client and server functions
api.addFiles('both/collections.js', ['client', 'server']);
-
// Library functions
api.addFiles('lib/uuid.js', 'client');
api.addFiles('lib/resizeViewportElements.js', 'client');
@@ -66,7 +68,14 @@ Package.onUse(function (api) {
// Export lesionTable function for activate measurements
api.export('activateLesion','client');
api.export('resizeViewportElements','client');
+ api.export('measurementManagerDAL', 'client');
+ // Export client-side collections
+ api.export('LesionLocations', 'client');
+ api.export('LocationResponses', 'client');
+ api.export('PatientLocations', 'client');
+
+ // Export collections spanning both client and server
api.export('Measurements', ['client', 'server']);
api.export('Timepoints', ['client', 'server']);
});
\ No newline at end of file
diff --git a/Packages/viewerbase/components/viewer/imageViewerViewports/imageViewerViewports.js b/Packages/viewerbase/components/viewer/imageViewerViewports/imageViewerViewports.js
index 41c333fde..96ce8ae14 100644
--- a/Packages/viewerbase/components/viewer/imageViewerViewports/imageViewerViewports.js
+++ b/Packages/viewerbase/components/viewer/imageViewerViewports/imageViewerViewports.js
@@ -121,7 +121,7 @@ var savedSeriesData,
savedViewportColumns;
Template.imageViewerViewports.events({
- 'dblclick .imageViewerViewport': function(e) {
+ 'CornerstoneMouseDoubleClick .imageViewerViewport': function(e) {
var container = $(".viewerMain").get(0);
var data;
var contentId = this.contentId || $("#viewer").parents(".tab-pane.active").attr('id');
@@ -140,7 +140,7 @@ Template.imageViewerViewports.events({
data = {
viewportRows: ViewerData[contentId].viewportRows,
- viewportColumns: ViewerData[contentId].viewportColumns,
+ viewportColumns: ViewerData[contentId].viewportColumns
};
// Render the imageViewerViewports template with these settings
@@ -181,7 +181,6 @@ Template.imageViewerViewports.events({
// Add the 'zoomed' class to the lone remaining viewport
$('.imageViewerViewport').eq(0).addClass('zoomed');
-
}
}
});
\ No newline at end of file
diff --git a/Packages/viewerbase/log.js b/Packages/viewerbase/log.js
index bb7ba9220..e188235f2 100644
--- a/Packages/viewerbase/log.js
+++ b/Packages/viewerbase/log.js
@@ -1,3 +1,3 @@
// Create package logger using loglevel
// https://atmospherejs.com/spacejamio/loglevel
-log = loglevel.createPackageLogger('viewerbase', defaultLevel = 'info');
\ No newline at end of file
+log = loglevel.createPackageLogger('viewerbase', defaultLevel = 'warn');
\ No newline at end of file
diff --git a/config/localhostOrthanc.json b/config/localhostOrthanc.json
index 0ded25ff0..0097b2f56 100644
--- a/config/localhostOrthanc.json
+++ b/config/localhostOrthanc.json
@@ -4,7 +4,7 @@
{
"name": "Orthanc",
"wadoUriRootNOTE" : "either this uri is not correct for wado-uri or wado-uri is not configured on orthanc currently",
- "wadoUriRoot" : "http://localhost:8042/wado",
+ "wadoUriRoot" : "http://localhost:8043/wado",
"qidoRoot": "http://localhost:8042/dicom-web",
"wadoRoot": "http://localhost:8042/dicom-web",
"qidoSupportsIncludeField": false,
diff --git a/etc/OrthancProxy.js b/etc/OrthancProxy.js
new file mode 100644
index 000000000..be7c16053
--- /dev/null
+++ b/etc/OrthancProxy.js
@@ -0,0 +1,20 @@
+// This sets up a proxy to work around CORS.
+// See http://chafey.blogspot.be/2014/09/working-around-cors.html
+// For more information
+var http = require('http'),
+ httpProxy = require('http-proxy');
+
+var proxy = httpProxy.createProxyServer({
+ target: 'http://localhost:8042',
+ auth: 'orthanc:orthanc'
+}).listen(8043);
+
+proxy.on('proxyRes', function(proxyReq, req, res, options) {
+ // add the CORS header to the response
+ res.setHeader('Access-Control-Allow-Origin', '*');
+});
+
+proxy.on('error', function(e) {
+ // suppress errors
+ console.log(e);
+});