Work-in-progress on study/timepoint association modal and multi-study selection (LT-60, LT-116)

This commit is contained in:
Erik Ziegler 2016-01-12 21:56:07 +01:00
parent 10be1b0336
commit 41b75de814
21 changed files with 505 additions and 58 deletions

View File

@ -18,8 +18,18 @@ Router.configure({
Router.onBeforeAction('loading'); Router.onBeforeAction('loading');
var data = {
additionalTemplates: [
'associationModal'
]
};
var routerOptions = {
data: data
};
Router.route('/', function() { Router.route('/', function() {
this.render('worklist'); this.render('worklist', routerOptions);
}); });
Router.route('/viewer/:_id', { Router.route('/viewer/:_id', {
@ -39,7 +49,7 @@ Router.route('/viewer/:_id', {
return; return;
} }
this.render('worklist'); this.render('worklist', routerOptions);
openNewTab(studyInstanceUid); openNewTab(studyInstanceUid);
} }
}); });

View File

@ -0,0 +1,19 @@
<template name="associationModal">
<div class="modal" id="associationModal" tabindex="-1" role="dialog" aria-labelledby="associationModalLabel">
<div class="modal-dialog" role="document">
<div class="modal-content">
<div class="modal-header">
<button type="button" class="close" data-dismiss="modal" aria-label="Close"><span aria-hidden="true">&times;</span></button>
<h4 class="modal-title" id="associationModalLabel">Study Association</h4>
</div>
<div class="modal-body">
{{ >studyAssociationTable }}
</div>
<div class="modal-footer">
<button type="button" class="btn btn-primary" id="saveAssociations" data-dismiss="modal" data-toggle="modal" data-target="#associationModal">Save</button>
<button type="button" class="btn btn-secondary" data-dismiss="modal">Cancel</button>
</div>
</div>
</div>
</div>
</template>

View File

@ -0,0 +1,5 @@
Template.associationModal.events({
'click #saveAssociations': function(e) {
log.info("Saving associations");
}
});

View File

@ -0,0 +1,3 @@
#associationModal
.modal-dialog
width: 80%

View File

@ -12,6 +12,12 @@ function closeHandler() {
setFocusToActiveViewport(); setFocusToActiveViewport();
} }
/**
* Displays the confirmation dialog template and the removable backdrop element
*
* @param doneCallback A callback
* @param options
*/
showConfirmDialog = function(doneCallback, options) { showConfirmDialog = function(doneCallback, options) {
// Show the backdrop // Show the backdrop
options = options || {}; options = options || {};

View File

@ -24,9 +24,6 @@ function setLesionNumberCallback(measurementData, eventData, doneCallback) {
return; return;
} }
// TODO: Get patientId
// TODO: add measurement data according to patientId to get correct lesion number for each patient
measurementData.timepointID = timepoint.timepointID; measurementData.timepointID = timepoint.timepointID;
// Get a lesion number for this lesion, depending on whether or not the same lesion previously // Get a lesion number for this lesion, depending on whether or not the same lesion previously

View File

@ -0,0 +1,50 @@
<template name="studyAssociationTable">
<div id="studyAssociationTable">
<div class="row">
<div class="col-md-12">
<h4>Instructions</h4>
<p>Associate the selected studies with timepoints in the clinical trial.</p>
</div>
</div>
<table class="table table-striped">
<thead>
<tr>
<th class="center">Include Study?</th>
<th class="center">Study Date</th>
<th class="center">Study Description</th>
<th class="center">Timepoint Type</th>
</tr>
</thead>
<tbody>
{{ #each relevantStudies }}
<tr>
<td class="center">
<input type="checkbox" class="includeStudy" checked/>
</td>
<td class="center">
{{ #if autoselected}}
<p class="studyDate autoselected"
title="This study was automatically added to your list due to its
similarity with your other selected studies">
{{formatDA studyDate}}
</p>
{{ else }}
<p class="studyDate">{{formatDA studyDate}}</p>
{{ /if }}
</td>
<td>
<p>{{studyDescription}}</p>
</td>
<td class="timepointOptions center">
{{ #each timepointOptions }}
<label><input type="radio" name="{{_id}}" value={{type}}> {{name}}</label>
{{ /each }}
</td>
</tr>
{{ /each }}
</tbody>
</table>
</div>
</template>

View File

@ -0,0 +1,36 @@
function autoSelectStudies() {
return [];
}
Template.studyAssociationTable.helpers({
/**
* This helpers includes the user-selected and autoselected studies
* to be associated.
*
* @returns {Array.<T>}
*/
relevantStudies: function() {
var userSelectedStudies = WorklistSelectedStudies.find().fetch() || [];
var autoselected = autoSelectStudies(userSelectedStudies);
return userSelectedStudies.concat(autoselected);
},
/**
* This helper returns the list of Timepoint types the user can set for this study
*
* @returns {Array.<T>}
*/
timepointOptions: function() {
return [
{
value: 'baseline',
name: 'Baseline'
},
{
value: 'followup',
name: 'Follow-up'
}
];
}
});
//trial criteria!

View File

@ -0,0 +1,16 @@
#studyAssociationTable
.header
text-align: center
.center
text-align: center
table
tbody
tr
td.timepointOptions
input
margin: 0 3px
label
padding: 0 5px

View File

@ -30,9 +30,9 @@ getLineIntersection = function(point1, point2, point3, point4) {
* same side of line 1, the line segments do not intersect. * same side of line 1, the line segments do not intersect.
*/ */
if (r3 != 0 && if (r3 !== 0 &&
r4 != 0 && r4 !== 0 &&
sign(r3) == sign(r4)) { sign(r3) === sign(r4)) {
intersectionPoint.x = 0; intersectionPoint.x = 0;
intersectionPoint.y = 0; intersectionPoint.y = 0;
intersectionPoint.intersected = false; intersectionPoint.intersected = false;
@ -55,9 +55,9 @@ getLineIntersection = function(point1, point2, point3, point4) {
* not intersect. * not intersect.
*/ */
if (r1 != 0 && if (r1 !== 0 &&
r2 != 0 && r2 !== 0 &&
sign(r1) == sign(r2)) { sign(r1) === sign(r2)) {
intersectionPoint.x = 0; intersectionPoint.x = 0;
intersectionPoint.y = 0; intersectionPoint.y = 0;
intersectionPoint.intersected = false; intersectionPoint.intersected = false;
@ -103,7 +103,7 @@ getDistanceFromPointToLine = function(ptTest, pt1, pt2) {
var dy = pt2.y - pt1.y; var dy = pt2.y - pt1.y;
// It's a point, not a line // It's a point, not a line
if (dx == 0 && dy == 0) { if (dx === 0 && dy === 0) {
ptNearest.x = pt1.x; ptNearest.x = pt1.x;
ptNearest.y = pt1.y; ptNearest.y = pt1.y;
} else { } else {

View File

@ -36,6 +36,10 @@ Package.onUse(function(api) {
bare: true bare: true
}); });
api.addFiles('client/components/associationModal/associationModal.html', 'client');
api.addFiles('client/components/associationModal/associationModal.styl', 'client');
api.addFiles('client/components/associationModal/associationModal.js', 'client');
api.addFiles('client/components/lesionLocationDialog/lesionLocationDialog.html', 'client'); api.addFiles('client/components/lesionLocationDialog/lesionLocationDialog.html', 'client');
api.addFiles('client/components/lesionLocationDialog/lesionLocationDialog.js', 'client'); api.addFiles('client/components/lesionLocationDialog/lesionLocationDialog.js', 'client');
api.addFiles('client/components/lesionLocationDialog/lesionLocationDialog.styl', 'client'); api.addFiles('client/components/lesionLocationDialog/lesionLocationDialog.styl', 'client');
@ -63,6 +67,10 @@ Package.onUse(function(api) {
api.addFiles('client/components/studyDateList/studyDateList.styl', 'client'); api.addFiles('client/components/studyDateList/studyDateList.styl', 'client');
api.addFiles('client/components/studyDateList/studyDateList.js', 'client'); api.addFiles('client/components/studyDateList/studyDateList.js', 'client');
api.addFiles('client/components/studyAssociationTable/studyAssociationTable.html', 'client');
api.addFiles('client/components/studyAssociationTable/studyAssociationTable.styl', 'client');
api.addFiles('client/components/studyAssociationTable/studyAssociationTable.js', 'client');
api.addFiles('client/components/confirmDeleteDialog/confirmDeleteDialog.html', 'client'); api.addFiles('client/components/confirmDeleteDialog/confirmDeleteDialog.html', 'client');
api.addFiles('client/components/confirmDeleteDialog/confirmDeleteDialog.styl', 'client'); api.addFiles('client/components/confirmDeleteDialog/confirmDeleteDialog.styl', 'client');
api.addFiles('client/components/confirmDeleteDialog/confirmDeleteDialog.js', 'client'); api.addFiles('client/components/confirmDeleteDialog/confirmDeleteDialog.js', 'client');

View File

@ -0,0 +1,28 @@
<template name="studyContextMenu">
<div id="studyContextMenu" class="studyContextMenu noselect"
oncontextmenu='return false;'
unselectable='on'
onselectstart='return false;'>
<ul>
<li>
<!--<a id="deleteTool">Delete</a>-->
<!-- TODO: Make this dynamically accept options-->
<a id="launchStudyAssociation" type="button"
data-toggle="modal"
data-target="#associationModal"
title="Launch Study Association">
<i class="fa fa-calendar-plus-o fa-lg"></i>
Associate
</a>
<a><span class="fa-stack fa-lg">
<i class="fa fa-user fa-stack-1x"></i>
<i class="fa fa-ban fa-stack-2x text-danger"></i>
</span> Anonymize
</a>
<a><i class="fa fa-trash fa-lg"></i> Delete</a>
<a><i class="fa fa-share fa-lg"></i> Share</a>
<a><i class="fa fa-download fa-lg"></i> Download</a>
</li>
</ul>
</div>
</template>

View File

@ -0,0 +1,79 @@
function closeHandler(dialog) {
// Hide the dialog
$(dialog).css('display', 'none');
// Remove the backdrop
$('.removableBackdrop').remove();
}
/**
* This function is used inside the Worklist package to define a right click callback
*
* @param e
* @param template
*/
openStudyContextMenu = function(e, template) {
var study = $(e.currentTarget);
Template.studyContextMenu.study = study;
var dialog = $('#studyContextMenu');
// Show the nonTargetLesion dialog above
var dialogProperty = {
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;
} else {
dialogProperty.top = e.pageY;// - dialog.outerHeight() - 40;
dialogProperty.left = e.pageX;// - dialog.outerWidth() / 2;
var pageHeight = $(window).height();
dialogProperty.top = Math.max(dialogProperty.top, 0);
dialogProperty.top = Math.min(dialogProperty.top, pageHeight - dialog.outerHeight());
var pageWidth = $(window).width();
dialogProperty.left = Math.max(dialogProperty.left, 0);
dialogProperty.left = Math.min(dialogProperty.left, pageWidth - dialog.outerWidth());
}
dialog.css(dialogProperty);
dialog.focus();
log.info(e);
log.info(template);
// 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);
});
};
// Temporary for now
functionList = {};
Template.studyContextMenu.events({
'click a': function(e) {
var study = Template.studyContextMenu.study;
var id = $(e.currentTarget).attr('id');
var fn = functionList[id];
if (fn && typeof(fn) === 'function') {
fn(study);
}
var dialog = $('#studyContextMenu');
closeHandler(dialog);
}
});

View File

@ -0,0 +1,51 @@
.studyContextMenu
z-index: 10000
display: none
position: absolute
color: whitesmoke
background-color: #2d2d2d
width: -moz-fit-content
width: -webkit-fit-content
width: fit-content
height: -moz-fit-content
height: -webkit-fit-content
height: fit-content
min-width: 100px
font-size: 14px
text-align: left
-webkit-background-clip: padding-box
background-clip: padding-box
border: 1px solid rgba(0, 0, 0, .15)
border-radius: 4px
-webkit-box-shadow: 0 6px 12px rgba(0, 0, 0, .175)
box-shadow: 0 6px 12px rgba(0, 0, 0, .175)
ul
width: 100%
margin: 5px 0
list-style: none
padding: 0
li
clear: both
white-space: nowrap
a
padding: 3px 15px
display: block
text-decoration: none
cursor: pointer
line-height: 25px
color: #808080
&:hover
color: #439193
text-decoration: none
background-color: #1d1d1d
.fa-lg
width: 40px
text-align: center

View File

@ -17,4 +17,8 @@
{{ >tabContent }} {{ >tabContent }}
{{ /each }} {{ /each }}
</div> </div>
{{#each additionalTemplates}}
{{> UI.dynamic template=this}}
{{/each}}
{{ >studyContextMenu }}
</template> </template>

View File

@ -65,17 +65,17 @@ getStudyMetadata = function(studyInstanceUid, doneCallback) {
* @param contentId The unique ID of the tab to be switched to * @param contentId The unique ID of the tab to be switched to
*/ */
switchToTab = function(contentId) { switchToTab = function(contentId) {
log.info("Switching to tab: " + contentId); log.info('Switching to tab: ' + contentId);
// Use Bootstrap's Tab JavaScript to show the contents of the current tab // Use Bootstrap's Tab JavaScript to show the contents of the current tab
// Unless it is the worklist, it is currently an empty div // Unless it is the worklist, it is currently an empty div
$('.tabTitle a[data-target="#' + contentId + '"]').tab('show'); $('.tabTitle a[data-target="#' + contentId + '"]').tab('show');
// Remove any previous Viewers from the DOM // Remove any previous Viewers from the DOM
$("#viewer").remove(); $('#viewer').remove();
// Update the 'activeContentId' variable in Session // Update the 'activeContentId' variable in Session
Session.set("activeContentId", contentId); Session.set('activeContentId', contentId);
// If we are switching to the Worklist tab, reset any CSS styles // If we are switching to the Worklist tab, reset any CSS styles
// that have been applied to prevent scrolling in the Viewer. // that have been applied to prevent scrolling in the Viewer.
@ -90,7 +90,7 @@ switchToTab = function(contentId) {
// Get tab content container given the contentId string // Get tab content container given the contentId string
// If no such container exists, stop here because something is wrong // If no such container exists, stop here because something is wrong
var container = $('.tab-content').find("#" + contentId).get(0); var container = $('.tab-content').find('#' + contentId).get(0);
if (!container) { if (!container) {
log.warn('No container present with the contentId: ' + contentId); log.warn('No container present with the contentId: ' + contentId);
return; return;
@ -117,18 +117,18 @@ switchToTab = function(contentId) {
} }
// Remove the loading text template that is inside the tab container by default // Remove the loading text template that is inside the tab container by default
container.innerHTML = ""; container.innerHTML = '';
// Use Blaze to render the Viewer Template into the container // Use Blaze to render the Viewer Template into the container
UI.renderWithData(Template.viewer, data, container); UI.renderWithData(Template.viewer, data, container);
// Retrieve the DOM element of the viewer // Retrieve the DOM element of the viewer
var imageViewer = $("#viewer"); var imageViewer = $('#viewer');
// If it is present in the DOM (it should be), then apply // If it is present in the DOM (it should be), then apply
// styles to prevent page scrolling and overscrolling on mobile devices // styles to prevent page scrolling and overscrolling on mobile devices
if (imageViewer) { if (imageViewer) {
document.body.style.overflow = "hidden"; document.body.style.overflow = 'hidden';
document.body.style.height = '100%'; document.body.style.height = '100%';
document.body.style.width = '100%'; document.body.style.width = '100%';
document.body.style.minWidth = 0; document.body.style.minWidth = 0;
@ -171,21 +171,20 @@ openNewTab = function(studyInstanceUid, title) {
Template.worklist.onRendered(function() { Template.worklist.onRendered(function() {
// If there is a tab set as active in the Session, // If there is a tab set as active in the Session,
// switch to that now. // switch to that now.
var contentId = Session.get("activeContentId"); var contentId = Session.get('activeContentId');
if (contentId) { if (contentId) {
switchToTab(contentId); switchToTab(contentId);
} }
}); });
Template.worklist.helpers({ Template.worklist.helpers({
/** /**
* Returns the current set of Worklist Tabs * Returns the current set of Worklist Tabs
* @returns Meteor.Collection The current state of the WorklistTabs Collection * @returns Meteor.Collection The current state of the WorklistTabs Collection
*/ */
'worklistTabs': function() { worklistTabs: function() {
return WorklistTabs.find(); return WorklistTabs.find();
} },
}); });
Template.worklist.events({ Template.worklist.events({
@ -193,12 +192,12 @@ Template.worklist.events({
// If this tab is already active, do nothing // If this tab is already active, do nothing
var tabButton = $(e.currentTarget); var tabButton = $(e.currentTarget);
var tabTitle = tabButton.parents('.tabTitle'); var tabTitle = tabButton.parents('.tabTitle');
if (tabTitle.hasClass("active")) { if (tabTitle.hasClass('active')) {
return; return;
} }
// Otherwise, switch to the tab // Otherwise, switch to the tab
var contentId = tabButton.data('target').replace("#", ""); var contentId = tabButton.data('target').replace('#', '');
switchToTab(contentId); switchToTab(contentId);
} }
}); });

View File

@ -8,7 +8,12 @@ Template.worklistResult.helpers({
* by Patient name and Study Date in Ascending order. * by Patient name and Study Date in Ascending order.
*/ */
studies: function() { studies: function() {
return WorklistStudies.find({}, {sort: {patientName : 1, studyDate : 1}}); return WorklistStudies.find({}, {
sort: {
patientName: 1,
studyDate: 1
}
});
}, },
isTouchDevice: function() { isTouchDevice: function() {
@ -36,6 +41,7 @@ function getFilter(filter) {
if (filter && filter.length && filter.substr(filter.length - 1) !== '*') { if (filter && filter.length && filter.substr(filter.length - 1) !== '*') {
filter += '*'; filter += '*';
} }
return filter; return filter;
} }
@ -46,6 +52,7 @@ function isIndexOf(mainVal, searchVal) {
if (mainVal === undefined || mainVal === '' || mainVal.indexOf(searchVal) > -1){ if (mainVal === undefined || mainVal === '' || mainVal.indexOf(searchVal) > -1){
return true; return true;
} }
return false; return false;
} }
@ -53,8 +60,8 @@ function isIndexOf(mainVal, searchVal) {
* Replace object if undefined * Replace object if undefined
*/ */
function replaceUndefinedColumnValue (text) { function replaceUndefinedColumnValue (text) {
if (text == undefined || text === "undefined") { if (text == undefined || text === 'undefined') {
return ""; return '';
} else { } else {
return text; return text;
} }
@ -67,7 +74,7 @@ function convertStringToStudyDate (dateStr) {
var y = dateStr.substring(0,4); var y = dateStr.substring(0,4);
var m = dateStr.substring(4,6); var m = dateStr.substring(4,6);
var d = dateStr.substring(6,8); var d = dateStr.substring(6,8);
var newDateStr = y+"/"+m+"/"+d; var newDateStr = y + '/' + m + '/' + d;
return new Date(newDateStr); return new Date(newDateStr);
} }
@ -111,13 +118,12 @@ function search() {
} }
Template.worklistResult.events({ Template.worklistResult.events({
'keydown': function(event) { 'keydown input': function(event) {
if (event.keyCode === 13) { // Enter if (event.keyCode === 13) { // Enter
search(); search();
} }
}, },
'onsearch': function(event) { 'onsearch input': function(event) {
search(); search();
} }
}); });

View File

@ -10,19 +10,24 @@ table#tblStudyList
&:hover &:hover
color: #888888 color: #888888
tbody > tr tbody
tr
padding: 4px padding: 4px
border: 1px solid #282828 border: 1px solid #282828
background-color: black background-color: black
&:hover, &:active, &.active
background-color: #009BD2
color: white
td td
white-space:nowrap // This selector is necessary to override bootstrap's 'table' class
color: white
background-color: #009BD2
&:nth-of-type(odd) &:nth-of-type(odd)
background-color: #202020 background-color: #202020
&:hover td
background-color: #009BD2 white-space: nowrap
color: white

View File

@ -11,7 +11,6 @@
{{accessionNumber}} {{accessionNumber}}
</td> </td>
{{/unless}} {{/unless}}
<td> <td>
{{formatDA studyDate}} {{formatDA studyDate}}
</td> </td>

View File

@ -1,8 +1,129 @@
Worklist = {};
Worklist.previouslySelected = undefined;
// Maybe we should use regular Worklist collection?
WorklistSelectedStudies = new Meteor.Collection(null);
function handleShiftClick(studyRow, data) {
log.info('shiftKey');
var studyInstanceUid = studyRow.attr('studyInstanceUid');
// Select all rows in between these two rows
if (Worklist.previouslySelected) {
var previous = $(Worklist.previouslySelected);
var rowsInBetween;
if (previous.index() < studyRow.index()) {
// The previously selected row is above (lower index) the
// currently selected row.
// Fill in the rows upwards from the previously selected row
rowsInBetween = previous.nextAll('tr');
} else if (previous.index() > studyRow.index()) {
// The previously selected row is below the currently
// selected row.
// Fill in the rows upwards from the previously selected row
rowsInBetween = previous.prevAll('tr');
} else {
// The rows are the same, deselect the current row.
// TODO: CHECK THIS, pretty sure this is the wrong behaviour
WorklistSelectedStudies.remove({});
Worklist.previouslySelected = undefined;
return;
}
// Loop through the rows in between current and previous selected studies
rowsInBetween.each(function(index, row) {
if ($(row).is(studyRow)) {
// When we reach the currently clicked-on row, stop
return false;
} else if ($(row).hasClass('active')) {
// If we find one that is already selected, do nothing
return;
}
// Get the relevant studyInstanceUid
var studyInstanceUid = $(row).attr('studyInstanceUid');
// Set the current study as selected
WorklistSelectedStudies.insert(data);
studyRow.addClass('active');
return true;
});
} else {
// Set the current study as selected
WorklistSelectedStudies.insert(data);
studyRow.addClass('active');
}
}
function handleCtrlClick(studyRow, data) {
log.info('ctrlKey');
var studyInstanceUid = studyRow.attr('studyInstanceUid');
if (studyRow.hasClass('active')) {
studyRow.removeClass('active');
// Find the current studyInstanceUid in the stored list and remove it
WorklistSelectedStudies.remove({
studyInstanceUid: data.studyInstanceUid
});
} else {
// Set the current study as selected
WorklistSelectedStudies.insert(data);
studyRow.addClass('active');
// Set this as the previously selected row, so the user can
// use Shift to select from this point onwards
Worklist.previouslySelected = studyRow;
}
}
Template.worklistStudy.events({ Template.worklistStudy.events({
'click': function () { 'click tr.worklistStudy': function(e) {
var studyRow = $(e.currentTarget);
var data = this;
// Remove the ID so we can directly insert this into our client-side collection
delete data._id;
if (e.shiftKey) {
handleShiftClick(studyRow, data);
} else if (e.ctrlKey || e.metaKey) {
handleCtrlClick(studyRow, data);
} else {
// Select a single study
log.info('Regular click');
// Clear all selected studies
WorklistSelectedStudies.remove({});
$('tr.worklistStudy').removeClass('active');
// Set the previous study to the currently clicked-on study
Worklist.previouslySelected = studyRow;
// Set the current study as selected
WorklistSelectedStudies.insert(data);
studyRow.addClass('active');
}
},
'dblclick tr.worklistStudy': function() {
// Use the formatPN template helper to clean up the patient name // Use the formatPN template helper to clean up the patient name
var title = Blaze._globalHelpers['formatPN'](this.patientName); var title = Blaze._globalHelpers['formatPN'](this.patientName);
// Open a new tab with this study
openNewTab(this.studyInstanceUid, title); openNewTab(this.studyInstanceUid, title);
},
'contextmenu tr.worklistStudy': function(e, template) {
$(e.currentTarget).addClass('active');
if (openStudyContextMenu && typeof openStudyContextMenu === 'function') {
e.preventDefault();
openStudyContextMenu(e, template);
return false;
}
} }
}); });

View File

@ -42,6 +42,10 @@ Package.onUse(function (api) {
api.addFiles('components/worklistResult/worklistResult.js', 'client'); api.addFiles('components/worklistResult/worklistResult.js', 'client');
api.addFiles('components/worklistResult/worklistResult.styl', 'client'); api.addFiles('components/worklistResult/worklistResult.styl', 'client');
api.addFiles('components/studyContextMenu/studyContextMenu.html', 'client');
api.addFiles('components/studyContextMenu/studyContextMenu.js', 'client');
api.addFiles('components/studyContextMenu/studyContextMenu.styl', 'client');
api.addFiles('lib/generateUUID.js', 'client'); api.addFiles('lib/generateUUID.js', 'client');
api.export('generateUUID', 'client'); api.export('generateUUID', 'client');
@ -56,5 +60,6 @@ Package.onUse(function (api) {
// Export the Collections // Export the Collections
api.export('WorklistTabs', 'client'); api.export('WorklistTabs', 'client');
api.export('WorklistStudies', 'client'); api.export('WorklistStudies', 'client');
api.export('WorklistSelectedStudies', 'client');
}); });