Add some WIP changes to Lesion Tracker dialogs

This commit is contained in:
Erik Ziegler 2015-12-07 17:15:14 +01:00
parent e4c24608af
commit da197368bf
37 changed files with 915 additions and 595 deletions

View File

@ -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.

View File

@ -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: ""
});

View File

@ -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: ""
});

View File

@ -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
});

View File

@ -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 === '') {

View File

@ -118,7 +118,8 @@
pointNearHandle: pointNearTextBox,
active: false,
movesIndependently: true,
drawnIndependently: true
drawnIndependently: true,
allowedOutsideImage: true
}
},
imageId: imageId,

View File

@ -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>

View File

@ -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();
}
});

View File

@ -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

View File

@ -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
}
});
});
}

View File

@ -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>

View File

@ -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();

View File

@ -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

View File

@ -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>

View File

@ -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();
}
});

View File

@ -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

View File

@ -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;
}

View File

@ -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>

View File

@ -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']);
});

View File

@ -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');
}
}
});

View File

@ -1,3 +1,3 @@
// Create package logger using loglevel
// https://atmospherejs.com/spacejamio/loglevel
log = loglevel.createPackageLogger('viewerbase', defaultLevel = 'info');
log = loglevel.createPackageLogger('viewerbase', defaultLevel = 'warn');

View File

@ -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,

20
etc/OrthancProxy.js Normal file
View File

@ -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);
});