Updates for Timepoint assocation (LT-60) and Conformance Checks (LT-92, LT-93, LT-94)

This commit is contained in:
Erik Ziegler committed 2016-02-08 19:59:39 +01:00
1 parent 6c4eae3699
commit beaa56c0b3
144 files changed
+5050 -2416

No files matched your search

-13
View File
@@ -1,13 +0,0 @@
/**
*
* @returns {string}
*/
generateUUID = function() {
var d = new Date().getTime();
var uuid = 'xxxxxxxx'.replace(/[xy]/g, function(c) {
var r =(d + Math.random()*8)%8 | 0;
d = Math.floor(d/8);
return(c=='x' ? r :(r&0x3|0x8)).toString(8);
});
return uuid;
};
@@ -0,0 +1,62 @@
/**
* Retrieves metaData for multiple studies at once.
*
* This function calls getStudyMetadata several times, asynchronously,
* and waits for all of the results to be returned.
*
* @param studyInstanceUids The UIDs of the Studies to be retrieved
* @param doneCallback The callback function to be executed when the study retrieval has finished
* @param failCallback The callback function to be executed when the study retrieval has failed
*/
getStudiesMetadata = function(studyInstanceUids, doneCallback, failCallback) {
// Check to make sure studyInstanceUids were actually input
if (!studyInstanceUids || !studyInstanceUids.length) {
if (failCallback && typeof failCallback === 'function') {
failCallback('No studyInstanceUids were input');
}
return;
}
// Create an empty array to store the Promises for each metaData
// retrieval call
var promises = [];
// Create an empty array to hold all the results of the promises
var studies = [];
// Loop through the array of studyInstanceUids
studyInstanceUids.forEach(function(studyInstanceUid) {
// Create a new Deferred to monitor the progress of the asynchronous
// metaData retrieval
var deferred = new $.Deferred();
// Send the call, and attach doneCallbacks and failCallbacks
// which can resolve or reject the related promise based on its outcome
getStudyMetadata(studyInstanceUid, function(study) {
deferred.resolve(study);
}, function(error) {
deferred.reject(error);
});
// Add the current promise to the array of promises
promises.push(deferred.promise());
});
// When all of the promises are complete, this callback runs
$.when.apply($, promises).done(function() {
// Convert the Arguments Array-like Object to an actual array
var studies = $.makeArray(arguments);
// Pass the studies array to the doneCallback, if one exists
if (doneCallback && typeof doneCallback === 'function') {
doneCallback(studies);
}
}).fail(function(error) {
log.warn(error);
if (failCallback && typeof failCallback === 'function') {
failCallback(error);
}
});
};
+45
View File
@@ -0,0 +1,45 @@
// Define the StudyMetaData object. This is used as a cache
// to store study meta data information to prevent unnecessary
// calls to the server
var StudyMetaData = {};
/**
* Retrieves study metadata using a server call, and fires a callback
* when completed.
*
* @params {string} studyInstanceUid The UID of the Study to be retrieved
* @params {function} doneCallback The callback function to be executed when the study retrieval has finished
* @param failCallback The callback function to be executed when the study retrieval has failed
*/
getStudyMetadata = function(studyInstanceUid, doneCallback, failCallback) {
log.info('worklistStudy getStudyMetadata');
// If the StudyMetaData cache already has data related to this
// studyInstanceUid, then we should fire the doneCallback with this data
// and stop here.
var study = StudyMetaData[studyInstanceUid];
if (study) {
doneCallback(study);
return;
}
// If no study metadata is in the cache variable, we need to retrieve it from
// the server with a call.
Meteor.call('GetStudyMetadata', studyInstanceUid, function(error, study) {
if (error) {
log.warn(error);
failCallback(error);
return;
}
// Once we have retrieved the data, we sort the series' by series
// and instance number in ascending order
sortStudy(study);
// Then we store this data in the cache variable
StudyMetaData[studyInstanceUid] = study;
// Finally, we fire the doneCallback with this study meta data
doneCallback(study);
});
};
+30
View File
@@ -0,0 +1,30 @@
/**
* Opens a new tab in the tabbed worklist environment using
* a given study and new tab title.
*
* @param studyInstanceUid The UID of the Study to be opened
* @param title The title to be used for the tab heading
*/
openNewTab = function(studyInstanceUid, title) {
// Generate a unique ID to represent this tab
// We can't just use the Mongo entry ID because
// then it will change after hot-reloading.
var contentid = uuid.new();
// Create a new entry in the WorklistTabs Collection
WorklistTabs.insert({
title: title,
contentid: contentid,
active: false
});
// Update the ViewerData global object
ViewerData[contentid] = {
title: title,
contentid: contentid,
studyInstanceUids: [studyInstanceUid]
};
// Switch to the new tab
switchToTab(contentid);
};
+90
View File
@@ -0,0 +1,90 @@
/**
* Switches to a new tab in the tabbed worklist container
* This function renders either the Worklist or the Viewer template with new data.
*
* @param contentId The unique ID of the tab to be switched to
*/
switchToTab = function(contentId) {
if (!contentId) {
return;
}
log.info('Switching to tab: ' + contentId);
// Use Bootstrap's Tab JavaScript to show the contents of the current tab
// Unless it is the worklist, it is currently an empty div
$('.tabTitle a[data-target="#' + contentId + '"]').tab('show');
// Remove any previous Viewers from the DOM
$('#viewer').remove();
// Update the 'activeContentId' variable in Session
Session.set('activeContentId', contentId);
// If we are switching to the Worklist tab, reset any CSS styles
// that have been applied to prevent scrolling in the Viewer.
// Then stop here, since nothing needs to be re-rendered.
if (contentId === 'worklistTab') {
document.body.style.overflow = null;
document.body.style.height = null;
document.body.style.minWidth = null;
document.body.style.position = null;
return;
}
// Tab was closed at some point, stop here
if (!ViewerData[contentId]) {
return;
}
// Use the stored ViewerData global object to retrieve the studyInstanceUid
// related to this tab
var studyInstanceUids = ViewerData[contentId].studyInstanceUids;
// Attempt to retrieve the meta data (it might be cached)
getStudiesMetadata(studyInstanceUids, function(studies) {
// Tab closed while study data was being retrieved, stop here
if (!ViewerData[contentId]) {
log.warn('Tab closed while study data was being retrieved');
return;
}
// Once we have the study data, store it in a structure with
// any other saved data about this tab (e.g. layout structure)
var data = jQuery.extend({}, ViewerData[contentId]);
data.studies = studies;
data.contentId = contentId;
if (ViewerData[contentId].studies && ViewerData[contentId].studies.length) {
data.studies = ViewerData[contentId].studies;
}
// Get tab content container given the contentId string
// If no such container exists, stop here because something is wrong
var container = $('.tab-content').find('#' + contentId).get(0);
if (!container) {
log.warn('No container present with the contentId: ' + contentId);
return;
}
// Remove the loading text template that is inside the tab container by default
container.innerHTML = '';
// Use Blaze to render the Viewer Template into the container
UI.renderWithData(Template.viewer, data, container);
// Retrieve the DOM element of the viewer
var imageViewer = $('#viewer');
// If it is present in the DOM (it should be), then apply
// styles to prevent page scrolling and overscrolling on mobile devices
if (imageViewer) {
document.body.style.overflow = 'hidden';
document.body.style.height = '100%';
document.body.style.width = '100%';
document.body.style.minWidth = 0;
// Prevent overscroll on mobile devices
document.body.style.position = 'fixed';
}
});
};
+13
View File
@@ -0,0 +1,13 @@
Worklist = {
functions: {},
callbacks: {}
};
Worklist.callbacks.dblClickOnStudy = dblClickOnStudy;
Worklist.callbacks.middleClickOnStudy = dblClickOnStudy;
function dblClickOnStudy(data) {
// Use the formatPN template helper to clean up the patient name
var title = formatPN(data.patientName);
openNewTab(data.studyInstanceUid, title);
}