diff --git a/LesionTracker/.meteor/packages b/LesionTracker/.meteor/packages
index 0ce8afcad..a4152e136 100644
--- a/LesionTracker/.meteor/packages
+++ b/LesionTracker/.meteor/packages
@@ -51,3 +51,4 @@ check
aldeed:template-extension@4.0.0
zuuk:stale-session
gilbertwat:bootstrap3-daterangepicker
+silentcicero:jszip
diff --git a/LesionTracker/.meteor/versions b/LesionTracker/.meteor/versions
index 3743c3e28..939b745a5 100644
--- a/LesionTracker/.meteor/versions
+++ b/LesionTracker/.meteor/versions
@@ -97,6 +97,7 @@ rwatts:uuid@0.0.2
service-configuration@1.0.5
session@1.1.1
sha@1.0.4
+silentcicero:jszip@0.0.4
spacebars@1.0.7
spacebars-compiler@1.0.7
srp@1.0.4
diff --git a/Packages/lesiontracker/client/components/lesionTrackerWorklistContextMenu/lesionTrackerWorklistContextMenu.html b/Packages/lesiontracker/client/components/lesionTrackerWorklistContextMenu/lesionTrackerWorklistContextMenu.html
index a94b076bc..1d989ae4f 100644
--- a/Packages/lesiontracker/client/components/lesionTrackerWorklistContextMenu/lesionTrackerWorklistContextMenu.html
+++ b/Packages/lesiontracker/client/components/lesionTrackerWorklistContextMenu/lesionTrackerWorklistContextMenu.html
@@ -24,7 +24,9 @@
Delete
Send
- Export
+
+ Export
Download
View Series Details
diff --git a/Packages/lesiontracker/client/components/lesionTrackerWorklistContextMenu/lesionTrackerWorklistContextMenu.js b/Packages/lesiontracker/client/components/lesionTrackerWorklistContextMenu/lesionTrackerWorklistContextMenu.js
index c199ce98f..82e296c16 100644
--- a/Packages/lesiontracker/client/components/lesionTrackerWorklistContextMenu/lesionTrackerWorklistContextMenu.js
+++ b/Packages/lesiontracker/client/components/lesionTrackerWorklistContextMenu/lesionTrackerWorklistContextMenu.js
@@ -5,6 +5,7 @@ var defaultTemplate = 'studyContextMenu';
Template.lesionTrackerWorklistContextMenu.replaces(defaultTemplate);
Worklist.functions['removeTimepointAssociations'] = removeTimepointAssociations;
+Worklist.functions['exportSelectedStudies'] = exportSelectedStudies;
/**
* Removes all present study / timepoint associations from the Clinical Trial
@@ -72,4 +73,38 @@ function removeTimepointAssociations() {
});
}
});
+}
+
+/**
+ * Exports all selected studies on the worklist
+ */
+function exportSelectedStudies() {
+ var selectedStudies = WorklistSelectedStudies.find({}, {
+ sort: {
+ studyDate: 1
+ }
+ }).fetch() || [];
+
+ if (selectedStudies.length < 1) {
+ return;
+ }
+
+ var studiesToExport = [];
+ var numberOfStudiesToQuery = selectedStudies.length;
+
+ progressDialog.show("Querying Studies...", numberOfStudiesToQuery);
+
+ selectedStudies.forEach(function(selectedStudy) {
+ getStudyMetadata(selectedStudy.studyInstanceUid, function(study) {
+ studiesToExport.push(study);
+
+ var numberOfStudiesQueried = studiesToExport.length;
+
+ progressDialog.update(numberOfStudiesQueried);
+
+ if (numberOfStudiesQueried === numberOfStudiesToQuery) {
+ exportStudies(studiesToExport);
+ }
+ });
+ });
}
\ No newline at end of file
diff --git a/Packages/lesiontracker/lib/exportStudies.js b/Packages/lesiontracker/lib/exportStudies.js
new file mode 100644
index 000000000..f5fb1b377
--- /dev/null
+++ b/Packages/lesiontracker/lib/exportStudies.js
@@ -0,0 +1,97 @@
+/**
+ * Exports requested studies
+ * @param studiesToExport Studies to export
+ */
+exportStudies = function(studiesToExport) {
+ var numberOfFilesToExport = getNumberOfFilesToExport(studiesToExport);
+
+ progressDialog.show("Exporting Studies...", numberOfFilesToExport);
+
+ try {
+ exportStudiesInternal(studiesToExport, numberOfFilesToExport);
+ } catch (err) {
+ progressDialog.close();
+ console.error("Failed to export studies: " + err.message);
+ }
+};
+
+function exportStudiesInternal(studiesToExport, numberOfFilesToExport) {
+ var zip = new JSZip();
+
+ var exportFailed = false;
+ var numberOfFilesExported = 0;
+
+ studiesToExport.forEach(function(study) {
+ sortStudy(study);
+
+ var studyFolder = zip.folder(study.studyInstanceUid);
+
+ study.seriesList.forEach(function(series) {
+ var seriesFolder = studyFolder.folder(series.seriesInstanceUid);
+
+ series.instances.forEach(function(instance) {
+ if (!instance.wadouri) {
+ return;
+ }
+
+ // If failed to download a dicom file, skip others
+ if (exportFailed) {
+ return;
+ }
+
+ // Download and Zip the dicom file
+ var xhr = new XMLHttpRequest();
+ xhr.open("GET", instance.wadouri, true);
+ xhr.responseType = "arraybuffer";
+
+ // Downloaded the dicom file completely
+ xhr.onload = function() {
+ // If failed to download a dicom file, skip others
+ if (exportFailed) {
+ return;
+ }
+
+ var responseArrayBuffer = xhr.response;
+ if (responseArrayBuffer) {
+ seriesFolder.file(instance.sopInstanceUid + ".dcm", responseArrayBuffer, { binary: true });
+ }
+
+ numberOfFilesExported++;
+
+ if (numberOfFilesExported === numberOfFilesToExport) {
+ var zipContent = zip.generate({ type: "blob" });
+ saveAs(zipContent, "studies.zip");
+ }
+
+ progressDialog.update(numberOfFilesExported);
+ };
+
+ // Failed to download the dicom file
+ xhr.onerror = function() {
+ exportFailed = true;
+
+ progressDialog.close();
+ console.error("Failed to export studies!");
+ };
+
+ xhr.send(null);
+ });
+ });
+ });
+}
+
+function getNumberOfFilesToExport(studiesToExport) {
+ var numberOFFilesToExport = 0;
+
+ studiesToExport.forEach(function(study) {
+ study.seriesList.forEach(function(series) {
+ series.instances.forEach(function(instance) {
+ if (instance.wadouri) {
+ numberOFFilesToExport++;
+ }
+ });
+ });
+ });
+
+ return numberOFFilesToExport;
+}
diff --git a/Packages/lesiontracker/package.js b/Packages/lesiontracker/package.js
index a11146119..72ca75ad9 100644
--- a/Packages/lesiontracker/package.js
+++ b/Packages/lesiontracker/package.js
@@ -169,6 +169,8 @@ Package.onUse(function(api) {
api.addFiles('lib/handleMeasurementModified.js', 'client');
api.addFiles('lib/handleMeasurementRemoved.js', 'client');
+ api.addFiles('lib/exportStudies.js', 'client');
+
// Export global functions
api.export('pixelSpacingAutorunCheck', 'client');
@@ -191,6 +193,7 @@ Package.onUse(function(api) {
api.export('getTrialCriteriaConstraints', 'client');
api.export('calculateTotalLesionBurden', 'client');
api.export('convertToNonTarget', 'client');
+ api.export('exportStudies', 'client');
// Export global objects
api.export('TrialResponseCriteria', 'client');