Add some WIP changes to Lesion Tracker dialogs
This commit is contained in:
1 parent
e4c24608af
commit
da197368bf
37 files changed
+915
-595
No files matched your search
@@ -51,12 +51,6 @@ Template.viewer.onCreated(function() {
|
|||||||
}
|
}
|
||||||
OHIF.viewer.isPlaying[viewportIndex] = !OHIF.viewer.isPlaying[viewportIndex];
|
OHIF.viewer.isPlaying[viewportIndex] = !OHIF.viewer.isPlaying[viewportIndex];
|
||||||
Session.set('UpdateCINE', Random.id());
|
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;
|
var patientId = this.data.studies[0].patientId;
|
||||||
Session.set('patientId', patientId);
|
Session.set('patientId', patientId);
|
||||||
|
|
||||||
initialized = false;
|
|
||||||
self.autorun(function() {
|
self.autorun(function() {
|
||||||
var patientId = Session.get('patientId');
|
var patientId = Session.get('patientId');
|
||||||
self.subscribe('timepoints', patientId);
|
self.subscribe('timepoints', patientId);
|
||||||
@@ -113,38 +106,35 @@ Template.viewer.onCreated(function() {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (initialized === true) {
|
ViewerStudies.find().observe({
|
||||||
return;
|
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 timepointID = uuid.v4();
|
||||||
var timepoint = Timepoints.findOne({timepointName: study.studyDate});
|
|
||||||
if (timepoint) {
|
var testTimepoint = Timepoints.findOne({});
|
||||||
log.warn("A timepoint with that study date already exists!");
|
if (testTimepoint && testTimepoint.patientId !== study.patientId) {
|
||||||
return;
|
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
|
// This is used to re-add tools from the database into the
|
||||||
// Cornerstone ToolData structure
|
// Cornerstone ToolData structure
|
||||||
Measurements.find().observe({
|
Measurements.find().observe({
|
||||||
added: function (data) {
|
added: function (data) {
|
||||||
|
|
||||||
if (data.toolDataInsertedManually === true) {
|
if (data.toolDataInsertedManually === true) {
|
||||||
|
|
||||||
// Activate first measurements in image box as default if exists
|
// Activate first measurements in image box as default if exists
|
||||||
@@ -156,19 +146,40 @@ Template.viewer.onCreated(function() {
|
|||||||
}
|
}
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
log.info('Measurement added');
|
log.info('Measurement added');
|
||||||
|
|
||||||
addMeasurementAsToolData(data);
|
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);
|
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) {
|
function addMeasurementAsToolData(data) {
|
||||||
// Check what toolType we should be adding this to, based on the isTarget value
|
// Check what toolType we should be adding this to, based on the isTarget value
|
||||||
// of the stored Measurement
|
// of the stored Measurement
|
||||||
@@ -184,10 +195,41 @@ function addMeasurementAsToolData(data) {
|
|||||||
toolState[imageId] = {};
|
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]) {
|
if (!toolState[imageId][toolType]) {
|
||||||
toolState[imageId][toolType] = {
|
toolState[imageId][toolType] = {
|
||||||
data: []
|
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
|
// Create measurementData structure based on the lesion data at this timepoint
|
||||||
@@ -204,6 +246,7 @@ function addMeasurementAsToolData(data) {
|
|||||||
measurementData.visible = data.visible;
|
measurementData.visible = data.visible;
|
||||||
measurementData.active = data.active;
|
measurementData.active = data.active;
|
||||||
measurementData.uid = data.uid;
|
measurementData.uid = data.uid;
|
||||||
|
measurementData.id = data._id;
|
||||||
|
|
||||||
toolState[imageId][toolType].data.push(measurementData);
|
toolState[imageId][toolType].data.push(measurementData);
|
||||||
});
|
});
|
||||||
@@ -215,6 +258,46 @@ Template.viewer.onDestroyed(function() {
|
|||||||
OHIF.viewer.updateImageSynchronizer.destroy();
|
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
|
// Avoid doing DOM manipulation during the resize handler
|
||||||
// because it is fired very often.
|
// because it is fired very often.
|
||||||
// Resizing is therefore performed 100 ms after the resize event stops.
|
// Resizing is therefore performed 100 ms after the resize event stops.
|
||||||
|
|||||||
@@ -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: ""
|
||||||
|
});
|
||||||
@@ -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: ""
|
||||||
|
});
|
||||||
+56
-6
@@ -71,7 +71,7 @@ var cornerstoneTools = (function($, cornerstone, cornerstoneMath, cornerstoneToo
|
|||||||
cornerstoneTools.removeToolState(element, toolType, measurementData);
|
cornerstoneTools.removeToolState(element, toolType, measurementData);
|
||||||
} else {
|
} else {
|
||||||
// Set lesionMeasurementData Session
|
// Set lesionMeasurementData Session
|
||||||
config.getLesionLocationCallback(measurementData, mouseEventData);
|
config.getLesionLocationCallback(measurementData, mouseEventData, doneCallback);
|
||||||
}
|
}
|
||||||
|
|
||||||
$(element).on('CornerstoneToolsMouseMove', eventData, cornerstoneTools.lesion.mouseMoveCallback);
|
$(element).on('CornerstoneToolsMouseMove', eventData, cornerstoneTools.lesion.mouseMoveCallback);
|
||||||
@@ -157,7 +157,8 @@ var cornerstoneTools = (function($, cornerstone, cornerstoneMath, cornerstoneToo
|
|||||||
pointNearHandle: pointNearTextBox,
|
pointNearHandle: pointNearTextBox,
|
||||||
active: false,
|
active: false,
|
||||||
movesIndependently: true,
|
movesIndependently: true,
|
||||||
drawnIndependently: true
|
drawnIndependently: true,
|
||||||
|
allowedOutsideImage: true
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
imageId: imageId,
|
imageId: imageId,
|
||||||
@@ -282,10 +283,7 @@ var cornerstoneTools = (function($, cornerstone, cornerstoneMath, cornerstoneToo
|
|||||||
// Set measurement text to show lesion table
|
// Set measurement text to show lesion table
|
||||||
data.measurementText = length.toFixed(1);
|
data.measurementText = length.toFixed(1);
|
||||||
|
|
||||||
|
|
||||||
context.restore();
|
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
|
// module exports
|
||||||
cornerstoneTools.lesion = cornerstoneTools.mouseButtonTool({
|
cornerstoneTools.lesion = cornerstoneTools.mouseButtonTool({
|
||||||
@@ -309,6 +358,7 @@ var cornerstoneTools = (function($, cornerstone, cornerstoneMath, cornerstoneToo
|
|||||||
addNewMeasurement: addNewMeasurement,
|
addNewMeasurement: addNewMeasurement,
|
||||||
onImageRendered: onImageRendered,
|
onImageRendered: onImageRendered,
|
||||||
pointNearTool: pointNearTool,
|
pointNearTool: pointNearTool,
|
||||||
|
mouseDoubleClickCallback: doubleClickCallback,
|
||||||
toolType: toolType
|
toolType: toolType
|
||||||
});
|
});
|
||||||
|
|
||||||
+4
-6
@@ -46,12 +46,9 @@ var measurementManagerDAL = (function() {
|
|||||||
lesionDataObject.timepoints = timepointsObject;
|
lesionDataObject.timepoints = timepointsObject;
|
||||||
|
|
||||||
// Is there a use for this?
|
// 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.id = Measurements.insert(lesionDataObject);
|
||||||
lesionDataObject.toolDataInsertedManually = true;
|
|
||||||
|
|
||||||
Measurements.insert(lesionDataObject);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Update timepoint data in Measurements collection
|
// Update timepoint data in Measurements collection
|
||||||
@@ -82,6 +79,7 @@ var measurementManagerDAL = (function() {
|
|||||||
timepoints[timepointID].studyInstanceUid = lesionData.studyInstanceUid;
|
timepoints[timepointID].studyInstanceUid = lesionData.studyInstanceUid;
|
||||||
timepoints[timepointID].handles = lesionData.handles;
|
timepoints[timepointID].handles = lesionData.handles;
|
||||||
|
|
||||||
|
lesionData.id = measurement._id;
|
||||||
|
|
||||||
Measurements.update(measurement._id, {
|
Measurements.update(measurement._id, {
|
||||||
$set: {
|
$set: {
|
||||||
@@ -133,7 +131,7 @@ var measurementManagerDAL = (function() {
|
|||||||
|
|
||||||
if (!timepoints[timepointID]) {
|
if (!timepoints[timepointID]) {
|
||||||
// Find lesion number for this timepointID
|
// Find lesion number for this timepointID
|
||||||
return measurement.lesionNumber
|
return measurement.lesionNumber;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (timepoints[timepointID].longestDiameter === '') {
|
if (timepoints[timepointID].longestDiameter === '') {
|
||||||
+2
-1
@@ -118,7 +118,8 @@
|
|||||||
pointNearHandle: pointNearTextBox,
|
pointNearHandle: pointNearTextBox,
|
||||||
active: false,
|
active: false,
|
||||||
movesIndependently: true,
|
movesIndependently: true,
|
||||||
drawnIndependently: true
|
drawnIndependently: true,
|
||||||
|
allowedOutsideImage: true
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
imageId: imageId,
|
imageId: imageId,
|
||||||
+37
@@ -0,0 +1,37 @@
|
|||||||
|
<template name="lesionLocationDialog">
|
||||||
|
<div id="lesionLocationDialog">
|
||||||
|
<div class="dialogHeader">
|
||||||
|
<h4>Select Lesion Location</h4>
|
||||||
|
</div>
|
||||||
|
<div class="dialogContent">
|
||||||
|
<div class="lesionLocation">
|
||||||
|
<label>Lesion Location</label>
|
||||||
|
<select class="selectLesionLocation">
|
||||||
|
<option value="-1"></option>
|
||||||
|
{{ #each lesionLocations}}
|
||||||
|
<option value='{{_id}}'>{{location}}</option>
|
||||||
|
{{ /each}}
|
||||||
|
</select>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div id="lesionLocationRelabelDialog">
|
||||||
|
<div class="dialogHeader">
|
||||||
|
<h4>Change Lesion Location</h4>
|
||||||
|
</div>
|
||||||
|
<a></a>
|
||||||
|
<div class="dialogContent">
|
||||||
|
<div class="lesionLocation">
|
||||||
|
<label>Lesion Location</label>
|
||||||
|
<select class="selectLesionLocation">
|
||||||
|
<option value="-1"></option>
|
||||||
|
{{ #each lesionLocations}}
|
||||||
|
<option value='{{_id}}' selected={{selected}}>{{location}}</option>
|
||||||
|
{{ /each}}
|
||||||
|
</select>
|
||||||
|
</div>
|
||||||
|
<button id="removeLesion" class="btn btn-link">Remove</button>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
+247
@@ -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();
|
||||||
|
}
|
||||||
|
});
|
||||||
+40
@@ -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
|
||||||
File renamed without changes.
+11
-5
@@ -41,6 +41,11 @@ activateLesion = function(measurementId, templateData) {
|
|||||||
$(".imageViewerViewport").each(function(viewportIndex, element) {
|
$(".imageViewerViewport").each(function(viewportIndex, element) {
|
||||||
// Stop if we run out of timepoints before viewports
|
// Stop if we run out of timepoints before viewports
|
||||||
if (viewportIndex >= timepointsWithEntries.length) {
|
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;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -57,6 +62,10 @@ activateLesion = function(measurementId, templateData) {
|
|||||||
|
|
||||||
// If there is no measurement data to display, stop here
|
// If there is no measurement data to display, stop here
|
||||||
if (!measurementAtTimepoint) {
|
if (!measurementAtTimepoint) {
|
||||||
|
// Update the element anyway, to remove any other highlights that are present
|
||||||
|
deactivateAllToolData(element, 'lesion');
|
||||||
|
deactivateAllToolData(element, 'nonTarget');
|
||||||
|
cornerstone.updateImage(element);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -247,7 +256,6 @@ Template.lesionTable.events({
|
|||||||
|
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
});
|
});
|
||||||
|
|
||||||
Template.lesionTable.onCreated(function(){
|
Template.lesionTable.onCreated(function(){
|
||||||
@@ -275,14 +283,13 @@ Tracker.autorun(function () {
|
|||||||
dates: []
|
dates: []
|
||||||
};
|
};
|
||||||
|
|
||||||
$("#"+contentId+" .imageViewerViewport").each(function(viewportIndex, element) {
|
$(".imageViewerViewport").each(function(viewportIndex, element) {
|
||||||
var enabledElement = cornerstone.getEnabledElement(element);
|
var enabledElement = cornerstone.getEnabledElement(element);
|
||||||
if(enabledElement && enabledElement.image){
|
if(enabledElement && enabledElement.image){
|
||||||
var imageId = enabledElement.image.imageId;
|
var imageId = enabledElement.image.imageId;
|
||||||
var study = cornerstoneTools.metaData.get('study', imageId);
|
var study = cornerstoneTools.metaData.get('study', imageId);
|
||||||
var studyDate = study.studyDate;
|
var studyDate = study.studyDate;
|
||||||
var patientId = study.patientId;
|
loadedStudyDates.patientId = study.patientId;
|
||||||
loadedStudyDates.patientId = patientId;
|
|
||||||
// Check studyDate is added before
|
// Check studyDate is added before
|
||||||
if (loadedStudyDates.dates.indexOf(studyDate) < 0) {
|
if (loadedStudyDates.dates.indexOf(studyDate) < 0) {
|
||||||
loadedStudyDates.dates.push(studyDate);
|
loadedStudyDates.dates.push(studyDate);
|
||||||
@@ -306,7 +313,6 @@ Tracker.autorun(function () {
|
|||||||
$set: {
|
$set: {
|
||||||
timepointLoaded: timepointLoaded
|
timepointLoaded: timepointLoaded
|
||||||
}
|
}
|
||||||
|
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
+40
@@ -0,0 +1,40 @@
|
|||||||
|
<template name="nonTargetLesionDialog">
|
||||||
|
<div id="nonTargetLesionLocationDialog">
|
||||||
|
<div class="dialogHeader">
|
||||||
|
<div class="dialogHeader">
|
||||||
|
<div><h4>Select Lesion Location</h4></div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="dialogContent">
|
||||||
|
<div class="lesionLocation">
|
||||||
|
<div class="elementContainer">
|
||||||
|
<label>Lesion Location</label>
|
||||||
|
</div>
|
||||||
|
<div class="elementContainer">
|
||||||
|
<select id="selectNonTargetLesionLocation">
|
||||||
|
<option value="-1"></option>
|
||||||
|
{{ #each lesionLocations}}
|
||||||
|
<option value='{{_id}}'>{{location}}</option>
|
||||||
|
{{ /each}}
|
||||||
|
</select>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="locationResponse">
|
||||||
|
<div class="elementContainer">
|
||||||
|
<label>Response</label>
|
||||||
|
</div>
|
||||||
|
<div class="elementContainer">
|
||||||
|
<select id="selectNonTargetLesionLocationResponse">
|
||||||
|
<option value="-1"></option>
|
||||||
|
{{ #each locationResponses}}
|
||||||
|
<option value='{{code}}'>{{code}} - {{text}}</option>
|
||||||
|
{{ /each}}
|
||||||
|
</select>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="locationOK">
|
||||||
|
<button class="btn btn-primary" id="nonTargetLesionOK">OK</button>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
+105
-142
@@ -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) {
|
function setLesionNumberCallback(measurementData, eventData, doneCallback) {
|
||||||
// Get the current element's timepointID from the study date metadata
|
// Get the current element's timepointID from the study date metadata
|
||||||
var element = eventData.element;
|
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
|
// This event determines whether or not to show the Non-Target lesion dialog
|
||||||
// If there already exists a lesion with this specific lesion number,
|
// If there already exists a lesion with this specific lesion number,
|
||||||
// related to the chosen location.
|
// related to the chosen location.
|
||||||
|
|
||||||
function getNonTargetLesionLocationCallback(measurementData, eventData) {
|
function getNonTargetLesionLocationCallback(measurementData, eventData) {
|
||||||
|
Template.nonTargetLesionDialog.measurementData = measurementData;
|
||||||
|
|
||||||
// Get the non-target lesion location dialog
|
// 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
|
// Find the select option box
|
||||||
var selectorLocation = nonTargetlesionDialog.find("select#selectNonTargetLesionLocation");
|
var selectorLocation = dialog.find("select#selectNonTargetLesionLocation");
|
||||||
var selectorResponse = nonTargetlesionDialog.find("select#selectNonTargetLesionLocationResponse");
|
var selectorResponse = dialog.find("select#selectNonTargetLesionLocationResponse");
|
||||||
|
|
||||||
// OK button
|
selectorLocation.find("option:first").prop("selected", "selected");
|
||||||
var btnOK = nonTargetlesionDialog.find("button#nonTargetLesionOK");
|
selectorResponse.find("option:first").prop("selected", "selected");
|
||||||
|
|
||||||
|
// Allow location selection
|
||||||
// If selector location is disabled, make it enable
|
selectorLocation.removeAttr("disabled");
|
||||||
enableLocationSelection();
|
|
||||||
|
|
||||||
// Find out if this lesion number is already added in the lesion manager for another timepoint
|
// Find out if this lesion number is already added in the lesion manager for another timepoint
|
||||||
// If it is, disable selector location
|
// If it is, disable selector location
|
||||||
var locationUID = measurementManagerDAL.lesionNumberExists(measurementData);
|
var locationUID = measurementManagerDAL.lesionNumberExists(measurementData);
|
||||||
if (locationUID) {
|
if (locationUID) {
|
||||||
|
// Add an ID value to the tool data to link it to the Measurements collection
|
||||||
|
measurementData.id = 'notready';
|
||||||
|
|
||||||
measurementData.locationUID = locationUID;
|
measurementData.locationUID = locationUID;
|
||||||
// Disable the selection of a new location
|
// Disable the selection of a new location
|
||||||
disableLocationSelection(measurementData.locationUID);
|
disableLocationSelection(measurementData.locationUID);
|
||||||
@@ -58,48 +81,16 @@ function getNonTargetLesionLocationCallback(measurementData, eventData) {
|
|||||||
// Disable selector location to prevent selecting a new location
|
// Disable selector location to prevent selecting a new location
|
||||||
function disableLocationSelection(locationUID) {
|
function disableLocationSelection(locationUID) {
|
||||||
var locationName = measurementManagerDAL.getLocationName(locationUID);
|
var locationName = measurementManagerDAL.getLocationName(locationUID);
|
||||||
selectorLocation.find('option').each(function()
|
selectorLocation.find('option').each(function() {
|
||||||
{
|
|
||||||
if ($(this).text() === locationName) {
|
if ($(this).text() === locationName) {
|
||||||
// Select location in locations dropdown list
|
// Select location in locations dropdown list
|
||||||
selectorLocation.find('option').eq($(this).index()).prop("selected", true);
|
selectorLocation.find('option').eq($(this).index()).prop("selected", true);
|
||||||
return;
|
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
selectorLocation.prop("disabled", true);
|
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
|
// Show the nonTargetLesion dialog above
|
||||||
var dialogProperty = {
|
var dialogProperty = {
|
||||||
top: eventData.currentPoints.page.y,
|
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 device is touch device, set position center of screen vertically and horizontally
|
||||||
if (isTouchDevice()) {
|
if (isTouchDevice()) {
|
||||||
// add dialogMobile class to provide a black,transparent background
|
// add dialogMobile class to provide a black,transparent background
|
||||||
$(nonTargetlesionDialog).addClass("dialogMobile");
|
dialog.addClass("dialogMobile");
|
||||||
dialogProperty.top = 0;
|
dialogProperty.top = 0;
|
||||||
dialogProperty.left = 0;
|
dialogProperty.left = 0;
|
||||||
dialogProperty.right = 0;
|
dialogProperty.right = 0;
|
||||||
dialogProperty.bottom = 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
|
// Get the current value of the selector
|
||||||
var selectedOptionId = selectorLocation.find("option:selected").val();
|
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)
|
// If the selected option is still the default (-1)
|
||||||
// then stop here
|
// then stop here
|
||||||
@@ -141,7 +145,7 @@ function getNonTargetLesionLocationCallback(measurementData, eventData) {
|
|||||||
|
|
||||||
// If the selected response option is still the default (-1)
|
// If the selected response option is still the default (-1)
|
||||||
// then stop here
|
// then stop here
|
||||||
if (responseOptionCode < 0) {
|
if (responseOptionId < 0) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -157,102 +161,61 @@ function getNonTargetLesionLocationCallback(measurementData, eventData) {
|
|||||||
id = PatientLocations.insert({location: locationObj.location});
|
id = PatientLocations.insert({location: locationObj.location});
|
||||||
}
|
}
|
||||||
|
|
||||||
// Link locationUID with active lesion measurementData
|
if (!measurementData.id) {
|
||||||
measurementData.locationUID = 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
|
// Link locationUID with active lesion measurementData
|
||||||
measurementData.isTarget = false;
|
measurementData.locationUID = id;
|
||||||
|
|
||||||
// measurementText is set from location response list
|
/// Set the isTarget value to true, since this is the target-lesion dialog callback
|
||||||
measurementData.measurementText = responseOptionCode;
|
measurementData.isTarget = false;
|
||||||
|
|
||||||
// Adds lesion data to timepoints array
|
// measurementText is set from location response list
|
||||||
measurementManagerDAL.addLesionData(measurementData);
|
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
|
// 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) {
|
if (doneCallback && typeof doneCallback === 'function') {
|
||||||
doneCallback(prompt('Change your lesion location:'));
|
var deleteTool = true;
|
||||||
}
|
doneCallback(measurementData, deleteTool);
|
||||||
|
}
|
||||||
|
|
||||||
var config = {
|
closeHandler(dialog);
|
||||||
setLesionNumberCallback: setLesionNumberCallback,
|
},
|
||||||
getNonTargetLesionLocationCallback: getNonTargetLesionLocationCallback,
|
'click #btnCloseLesionPopup': function() {
|
||||||
changeNonTargetLesionLocationCallback: changeNonTargetLesionLocationCallback
|
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({
|
Template.nonTargetLesionDialog.helpers({
|
||||||
'lesionLocations': function() {
|
'lesionLocations': function() {
|
||||||
return LesionLocations.find();
|
return LesionLocations.find();
|
||||||
+35
@@ -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
|
||||||
|
|
||||||
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
@@ -1,20 +0,0 @@
|
|||||||
<template name="lesionLocationDialog">
|
|
||||||
<div id="lesionLocationDialog">
|
|
||||||
<div class="lesionContentWrapper">
|
|
||||||
<div class="dialogHeader">
|
|
||||||
<h4>Select Lesion Location</h4>
|
|
||||||
</div>
|
|
||||||
<div class="dialogContent">
|
|
||||||
<div class="lesionLocation">
|
|
||||||
<label>Lesion Location</label>
|
|
||||||
<select id="selectLesionLocation">
|
|
||||||
<option value="-1"></option>
|
|
||||||
{{ #each lesionLocations}}
|
|
||||||
<option value='{{_id}}'>{{location}}</option>
|
|
||||||
{{ /each}}
|
|
||||||
</select>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</template>
|
|
||||||
@@ -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();
|
|
||||||
}
|
|
||||||
});
|
|
||||||
@@ -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
|
|
||||||
|
|
||||||
@@ -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;
|
|
||||||
}
|
|
||||||
@@ -1,45 +0,0 @@
|
|||||||
<template name="nonTargetLesionDialog">
|
|
||||||
<div id="nonTargetLesionLocationDialog">
|
|
||||||
<div class="contentWrapper">
|
|
||||||
<div class="dialogHeader">
|
|
||||||
<div class="dialogHeader">
|
|
||||||
<div><h4>Select Lesion Location</h4></div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
<div class="dialogContent">
|
|
||||||
<div class="lesionLocation">
|
|
||||||
<div class="elementContainer">
|
|
||||||
<label>Lesion Location</label>
|
|
||||||
</div>
|
|
||||||
<div class="elementContainer">
|
|
||||||
<select id="selectNonTargetLesionLocation">
|
|
||||||
<option value="-1"></option>
|
|
||||||
{{ #each lesionLocations}}
|
|
||||||
<option value='{{_id}}'>{{location}}</option>
|
|
||||||
{{ /each}}
|
|
||||||
</select>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<div class="locationResponse">
|
|
||||||
<div class="elementContainer">
|
|
||||||
<label>Response</label>
|
|
||||||
</div>
|
|
||||||
<div class="elementContainer">
|
|
||||||
<select id="selectNonTargetLesionLocationResponse">
|
|
||||||
<option value="-1"></option>
|
|
||||||
{{ #each locationResponses}}
|
|
||||||
<option value='{{code}}'>{{code}} - {{text}}</option>
|
|
||||||
{{ /each}}
|
|
||||||
</select>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<div class="locationOK">
|
|
||||||
<button class="btn" id="nonTargetLesionOK">OK</button>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
</template>
|
|
||||||
@@ -17,38 +17,41 @@ Package.onUse(function (api) {
|
|||||||
|
|
||||||
api.addFiles('log.js', ['client', 'server']);
|
api.addFiles('log.js', ['client', 'server']);
|
||||||
|
|
||||||
api.addFiles('compatibility/lesionTool.js', 'client', {bare: true});
|
api.addFiles('client/collections/LesionLocations.js', 'client');
|
||||||
api.addFiles('compatibility/nonTargetTool.js', 'client', {bare: true});
|
api.addFiles('client/collections/LocationResponses.js', 'client');
|
||||||
api.addFiles('compatibility/measurementManagerDAL.js', 'client', {bare: true});
|
|
||||||
|
|
||||||
api.addFiles('components/lesionLocationDialog/lesionLocationDialog.html', 'client');
|
api.addFiles('client/compatibility/lesionTool.js', 'client', {bare: true});
|
||||||
api.addFiles('components/lesionLocationDialog/lesionLocationDialog.js', 'client');
|
api.addFiles('client/compatibility/nonTargetTool.js', 'client', {bare: true});
|
||||||
api.addFiles('components/lesionLocationDialog/lesionLocationDialog.styl', 'client');
|
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('client/components/lesionTable/lesionTable.html', 'client');
|
||||||
api.addFiles('components/lesionTable/lesionTable.styl', 'client');
|
api.addFiles('client/components/lesionTable/lesionTable.styl', 'client');
|
||||||
api.addFiles('components/lesionTable/lesionTable.js', 'client');
|
api.addFiles('client/components/lesionTable/lesionTable.js', 'client');
|
||||||
|
|
||||||
api.addFiles('components/lesionTableRow/lesionTableRow.html', 'client');
|
api.addFiles('client/components/lesionTableRow/lesionTableRow.html', 'client');
|
||||||
api.addFiles('components/lesionTableRow/lesionTableRow.js', 'client');
|
api.addFiles('client/components/lesionTableRow/lesionTableRow.js', 'client');
|
||||||
|
|
||||||
api.addFiles('components/lesionTableTimepointCell/lesionTableTimepointCell.html', 'client');
|
api.addFiles('client/components/lesionTableTimepointCell/lesionTableTimepointCell.html', 'client');
|
||||||
api.addFiles('components/lesionTableTimepointCell/lesionTableTimepointCell.js', 'client');
|
api.addFiles('client/components/lesionTableTimepointCell/lesionTableTimepointCell.js', 'client');
|
||||||
|
|
||||||
api.addFiles('components/lesionTableTimepointHeader/lesionTableTimepointHeader.html', 'client');
|
api.addFiles('client/components/lesionTableTimepointHeader/lesionTableTimepointHeader.html', 'client');
|
||||||
api.addFiles('components/lesionTableTimepointHeader/lesionTableTimepointHeader.js', 'client');
|
api.addFiles('client/components/lesionTableTimepointHeader/lesionTableTimepointHeader.js', 'client');
|
||||||
api.addFiles('components/lesionTableTimepointHeader/lesionTableTimepointHeader.styl', 'client');
|
api.addFiles('client/components/lesionTableTimepointHeader/lesionTableTimepointHeader.styl', 'client');
|
||||||
|
|
||||||
api.addFiles('components/nonTargetLesionDialog/nonTargetLesionDialog.html', 'client');
|
api.addFiles('client/components/nonTargetLesionDialog/nonTargetLesionDialog.html', 'client');
|
||||||
api.addFiles('components/nonTargetLesionDialog/nonTargetLesionDialog.css', 'client');
|
api.addFiles('client/components/nonTargetLesionDialog/nonTargetLesionDialog.styl', 'client');
|
||||||
api.addFiles('components/nonTargetLesionDialog/nonTargetLesionDialog.js', 'client');
|
api.addFiles('client/components/nonTargetLesionDialog/nonTargetLesionDialog.js', 'client');
|
||||||
|
|
||||||
api.addFiles('components/studyDateList/studyDateList.html', 'client');
|
api.addFiles('client/components/studyDateList/studyDateList.html', 'client');
|
||||||
api.addFiles('components/studyDateList/studyDateList.styl', 'client');
|
api.addFiles('client/components/studyDateList/studyDateList.styl', 'client');
|
||||||
api.addFiles('components/studyDateList/studyDateList.js', 'client');
|
api.addFiles('client/components/studyDateList/studyDateList.js', 'client');
|
||||||
|
|
||||||
api.addFiles('components/timepointTextDialog/timepointTextDialog.html', 'client');
|
api.addFiles('client/components/timepointTextDialog/timepointTextDialog.html', 'client');
|
||||||
api.addFiles('components/timepointTextDialog/timepointTextDialog.styl', 'client');
|
api.addFiles('client/components/timepointTextDialog/timepointTextDialog.styl', 'client');
|
||||||
|
|
||||||
// Server functions
|
// Server functions
|
||||||
api.addFiles('server/collections.js', 'server');
|
api.addFiles('server/collections.js', 'server');
|
||||||
@@ -57,7 +60,6 @@ Package.onUse(function (api) {
|
|||||||
// Both client and server functions
|
// Both client and server functions
|
||||||
api.addFiles('both/collections.js', ['client', 'server']);
|
api.addFiles('both/collections.js', ['client', 'server']);
|
||||||
|
|
||||||
|
|
||||||
// Library functions
|
// Library functions
|
||||||
api.addFiles('lib/uuid.js', 'client');
|
api.addFiles('lib/uuid.js', 'client');
|
||||||
api.addFiles('lib/resizeViewportElements.js', 'client');
|
api.addFiles('lib/resizeViewportElements.js', 'client');
|
||||||
@@ -66,7 +68,14 @@ Package.onUse(function (api) {
|
|||||||
// Export lesionTable function for activate measurements
|
// Export lesionTable function for activate measurements
|
||||||
api.export('activateLesion','client');
|
api.export('activateLesion','client');
|
||||||
api.export('resizeViewportElements','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('Measurements', ['client', 'server']);
|
||||||
api.export('Timepoints', ['client', 'server']);
|
api.export('Timepoints', ['client', 'server']);
|
||||||
});
|
});
|
||||||
@@ -121,7 +121,7 @@ var savedSeriesData,
|
|||||||
savedViewportColumns;
|
savedViewportColumns;
|
||||||
|
|
||||||
Template.imageViewerViewports.events({
|
Template.imageViewerViewports.events({
|
||||||
'dblclick .imageViewerViewport': function(e) {
|
'CornerstoneMouseDoubleClick .imageViewerViewport': function(e) {
|
||||||
var container = $(".viewerMain").get(0);
|
var container = $(".viewerMain").get(0);
|
||||||
var data;
|
var data;
|
||||||
var contentId = this.contentId || $("#viewer").parents(".tab-pane.active").attr('id');
|
var contentId = this.contentId || $("#viewer").parents(".tab-pane.active").attr('id');
|
||||||
@@ -140,7 +140,7 @@ Template.imageViewerViewports.events({
|
|||||||
|
|
||||||
data = {
|
data = {
|
||||||
viewportRows: ViewerData[contentId].viewportRows,
|
viewportRows: ViewerData[contentId].viewportRows,
|
||||||
viewportColumns: ViewerData[contentId].viewportColumns,
|
viewportColumns: ViewerData[contentId].viewportColumns
|
||||||
};
|
};
|
||||||
|
|
||||||
// Render the imageViewerViewports template with these settings
|
// Render the imageViewerViewports template with these settings
|
||||||
@@ -181,7 +181,6 @@ Template.imageViewerViewports.events({
|
|||||||
|
|
||||||
// Add the 'zoomed' class to the lone remaining viewport
|
// Add the 'zoomed' class to the lone remaining viewport
|
||||||
$('.imageViewerViewport').eq(0).addClass('zoomed');
|
$('.imageViewerViewport').eq(0).addClass('zoomed');
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
@@ -1,3 +1,3 @@
|
|||||||
// Create package logger using loglevel
|
// Create package logger using loglevel
|
||||||
// https://atmospherejs.com/spacejamio/loglevel
|
// https://atmospherejs.com/spacejamio/loglevel
|
||||||
log = loglevel.createPackageLogger('viewerbase', defaultLevel = 'info');
|
log = loglevel.createPackageLogger('viewerbase', defaultLevel = 'warn');
|
||||||
@@ -4,7 +4,7 @@
|
|||||||
{
|
{
|
||||||
"name": "Orthanc",
|
"name": "Orthanc",
|
||||||
"wadoUriRootNOTE" : "either this uri is not correct for wado-uri or wado-uri is not configured on orthanc currently",
|
"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",
|
"qidoRoot": "http://localhost:8042/dicom-web",
|
||||||
"wadoRoot": "http://localhost:8042/dicom-web",
|
"wadoRoot": "http://localhost:8042/dicom-web",
|
||||||
"qidoSupportsIncludeField": false,
|
"qidoSupportsIncludeField": false,
|
||||||
|
|||||||
@@ -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);
|
||||||
|
});
|
||||||
Reference in new issue
Block a user