Associate the selected studies with timepoints in the clinical trial.
+
We have automatically retrieved all studies within 14 days ({{formatDA earliestDate}} to {{formatDA latestDate}}) of your selected studies, in case you forgot to
+ select a study.
@@ -12,6 +14,7 @@
Include Study?
Study Date
+
Patient Name
Study Description
Timepoint Type
@@ -21,25 +24,34 @@
{{ #each relevantStudies }}
-
+
-
+
{{ #if autoselected}}
+ data-toggle="tooltip"
+ title="This study was autoselected.">
{{formatDA studyDate}}
{{ else }}
{{formatDA studyDate}}
{{ /if }}
-
+
+
{{formatPN patientName}}
+
+
{{studyDescription}}
-
+
{{ #each timepointOptions }}
-
+
{{ /each }}
diff --git a/Packages/lesiontracker/client/components/studyAssociationTable/studyAssociationTable.js b/Packages/lesiontracker/client/components/studyAssociationTable/studyAssociationTable.js
index df0a69ee2..001c34f8e 100644
--- a/Packages/lesiontracker/client/components/studyAssociationTable/studyAssociationTable.js
+++ b/Packages/lesiontracker/client/components/studyAssociationTable/studyAssociationTable.js
@@ -1,5 +1,72 @@
-function autoSelectStudies() {
- return [];
+/**
+ * Finds related studies within defined time window of =/- 14 days of selected studies
+ * @param selectedStudies
+ * @param range Object
+ */
+function getDateRange(selectedStudies, range) {
+ if (range === undefined) {
+ range = {
+ days: 14
+ };
+ }
+
+ if (!selectedStudies.length) {
+ return;
+ }
+
+ var earliestStudy = selectedStudies[0];
+ var latestStudy = selectedStudies[selectedStudies.length - 1];
+
+ var earliestDate = moment(earliestStudy.studyDate, 'YYYYMMDD');
+ earliestDate.subtract(range);
+
+ var latestDate = moment(latestStudy.studyDate, 'YYYYMMDD');
+ latestDate.add(range);
+
+ return {
+ earliestDate: earliestDate,
+ latestDate: latestDate
+ };
+}
+
+/**
+ *
+ * @returns {Array}
+ */
+function autoSelectStudies(selectedStudies) {
+ if (!selectedStudies.length) {
+ return;
+ }
+
+ var range = getDateRange(selectedStudies);
+
+ var autoselected = WorklistStudies.find({
+ studyDate: {
+ $gte: range.earliestDate.format('YYYYMMDD'),
+ $lte: range.latestDate.format('YYYYMMDD')
+ }
+ }, {
+ sort: {
+ studyDate: 1
+ }
+ }).fetch();
+
+ // Make an array of studyInstanceUids in selectedStudies
+ var studyInstanceUids = selectedStudies.map(function(selectedStudy) {
+ return selectedStudy.studyInstanceUid;
+ });
+
+ autoselected.forEach(function(study) {
+ var exists = studyInstanceUids.indexOf(study.studyInstanceUid);
+ if (exists > -1) {
+ study.autoselected = false;
+ return;
+ }
+
+ study.autoselected = true;
+ });
+
+ return autoselected;
}
Template.studyAssociationTable.helpers({
@@ -10,9 +77,13 @@ Template.studyAssociationTable.helpers({
* @returns {Array.}
*/
relevantStudies: function() {
- var userSelectedStudies = WorklistSelectedStudies.find().fetch() || [];
- var autoselected = autoSelectStudies(userSelectedStudies);
- return userSelectedStudies.concat(autoselected);
+ var selectedStudies = WorklistSelectedStudies.find({}, {
+ sort: {
+ studyDate: 1
+ }
+ }).fetch() || [];
+ var autoselected = autoSelectStudies(selectedStudies);
+ return autoselected;
},
/**
* This helper returns the list of Timepoint types the user can set for this study
@@ -30,7 +101,54 @@ Template.studyAssociationTable.helpers({
name: 'Follow-up'
}
];
+ },
+ earliestDate: function() {
+ var selectedStudies = WorklistSelectedStudies.find({}, {
+ sort: {
+ studyDate: 1
+ }
+ }).fetch();
+ var range = getDateRange(selectedStudies);
+ if (!range) {
+ return;
+ }
+
+ return range.earliestDate;
+ },
+ latestDate: function() {
+ var selectedStudies = WorklistSelectedStudies.find({}, {
+ sort: {
+ studyDate: 1
+ }
+ }).fetch();
+ var range = getDateRange(selectedStudies);
+ if (!range) {
+ return;
+ }
+
+ return range.latestDate;
}
});
-//trial criteria!
\ No newline at end of file
+Template.studyAssociationTable.events({
+ 'change input.includeStudy': function(e) {
+ var checkbox = e.currentTarget;
+ var studyDataCells = $(checkbox).parents('tr').find('td.studyDataCell');
+ if (checkbox.checked === true) {
+ studyDataCells.removeClass('disabled');
+ studyDataCells.find('input').attr('disabled', false);
+ } else {
+ studyDataCells.addClass('disabled');
+ studyDataCells.find('input').attr('disabled', true);
+ }
+ }
+});
+
+//trial criteria!
+/*There shall be Associate option in right-click dialog
+If associated, double-click shall go to image view.
+ If not associated, user shall be directed to Associate Time Points Dialog
+Use shall also be allowed to select multiple studies from study list to associate
+Associate Time Point dialog shall present selected studies and studies within defined time window of =/- 14 days of selected studies
+User should only be able to associate one time point at a time (user should not be able to select both BL and F/U for different studies in associate dialog)
+ */
\ No newline at end of file
diff --git a/Packages/lesiontracker/client/components/studyAssociationTable/studyAssociationTable.styl b/Packages/lesiontracker/client/components/studyAssociationTable/studyAssociationTable.styl
index b041bc84c..c24334156 100644
--- a/Packages/lesiontracker/client/components/studyAssociationTable/studyAssociationTable.styl
+++ b/Packages/lesiontracker/client/components/studyAssociationTable/studyAssociationTable.styl
@@ -13,4 +13,7 @@
margin: 0 3px
label
- padding: 0 5px
\ No newline at end of file
+ padding: 0 5px
+
+ td.disabled
+ opacity: 0.2
\ No newline at end of file
diff --git a/Packages/viewerbase/lib/helpers/inlineIf.js b/Packages/viewerbase/lib/helpers/inlineIf.js
new file mode 100644
index 000000000..2143dd472
--- /dev/null
+++ b/Packages/viewerbase/lib/helpers/inlineIf.js
@@ -0,0 +1,10 @@
+/**
+ * Helper for setting checkboxes as checked or unchecked inside templates,
+ * based on another variable's value
+ */
+UI.registerHelper("inlineIf", function (value, match, attributeName) {
+ if(value === match) {
+ return attributeName;
+ }
+ return '';
+});
diff --git a/Packages/viewerbase/package.js b/Packages/viewerbase/package.js
index a3f622361..e8550ec7d 100644
--- a/Packages/viewerbase/package.js
+++ b/Packages/viewerbase/package.js
@@ -155,6 +155,7 @@ Package.onUse(function (api) {
api.addFiles('lib/helpers/formatNumberPrecision.js', 'client');
api.addFiles('lib/helpers/formatPN.js', 'client');
api.addFiles('lib/helpers/formatTM.js', 'client');
+ api.addFiles('lib/helpers/inlineIf.js', 'client');
// Server-side functions
api.addFiles('server/seed.js', 'server');
diff --git a/Packages/worklist/components/studyContextMenu/studyContextMenu.html b/Packages/worklist/components/studyContextMenu/studyContextMenu.html
index bd4255250..ebf19fb34 100644
--- a/Packages/worklist/components/studyContextMenu/studyContextMenu.html
+++ b/Packages/worklist/components/studyContextMenu/studyContextMenu.html
@@ -20,8 +20,10 @@
Anonymize
Delete
- Share
+ Send
+ Export Download
+ View Series Details
diff --git a/Packages/worklist/components/studyContextMenu/studyContextMenu.js b/Packages/worklist/components/studyContextMenu/studyContextMenu.js
index cbd417041..e8ee6a122 100644
--- a/Packages/worklist/components/studyContextMenu/studyContextMenu.js
+++ b/Packages/worklist/components/studyContextMenu/studyContextMenu.js
@@ -36,11 +36,11 @@ openStudyContextMenu = function(e, template) {
dialogProperty.top = e.pageY;// - dialog.outerHeight() - 40;
dialogProperty.left = e.pageX;// - dialog.outerWidth() / 2;
- var pageHeight = $(window).height();
+ var pageHeight = $(document.body).height();
dialogProperty.top = Math.max(dialogProperty.top, 0);
dialogProperty.top = Math.min(dialogProperty.top, pageHeight - dialog.outerHeight());
- var pageWidth = $(window).width();
+ var pageWidth = $(document.body).width();
dialogProperty.left = Math.max(dialogProperty.left, 0);
dialogProperty.left = Math.min(dialogProperty.left, pageWidth - dialog.outerWidth());
}
diff --git a/Packages/worklist/components/worklistStudy/worklistStudy.js b/Packages/worklist/components/worklistStudy/worklistStudy.js
index 6d2b20c2a..b0d5aa263 100644
--- a/Packages/worklist/components/worklistStudy/worklistStudy.js
+++ b/Packages/worklist/components/worklistStudy/worklistStudy.js
@@ -33,21 +33,28 @@ function handleShiftClick(studyRow, data) {
}
// 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')) {
+ rowsInBetween.each(function() {
+ var row = $(this);
+
+ if (row.hasClass('active')) {
// If we find one that is already selected, do nothing
return;
}
// Get the relevant studyInstanceUid
- var studyInstanceUid = $(row).attr('studyInstanceUid');
+ var studyInstanceUid = row.attr('studyInstanceUid');
+
+ // Retrieve the data context through Blaze
+ var data = Blaze.getData(this);
// Set the current study as selected
WorklistSelectedStudies.insert(data);
- studyRow.addClass('active');
+ row.addClass('active');
+
+ // When we reach the currently clicked-on row, stop the loop
+ if (row.is(studyRow)) {
+ return false;
+ }
return true;
});
@@ -77,6 +84,7 @@ function handleCtrlClick(studyRow, data) {
// Set this as the previously selected row, so the user can
// use Shift to select from this point onwards
Worklist.previouslySelected = studyRow;
+ log.info('Worklist PreviouslySelected set: ' + studyRow.index());
}
}
@@ -102,6 +110,7 @@ Template.worklistStudy.events({
// Set the previous study to the currently clicked-on study
Worklist.previouslySelected = studyRow;
+ log.info('Worklist PreviouslySelected set: ' + studyRow.index());
// Set the current study as selected
WorklistSelectedStudies.insert(data);