changeset 4853:b3d0a3a4d890

Added links to download attachments from the Orthanc Explorer
author Alain Mazy <am@osimis.io>
date Thu, 16 Dec 2021 14:48:46 +0100
parents abb0e1c2b88d
children 8bd1f0d9506e
files NEWS OrthancServer/OrthancExplorer/explorer.html OrthancServer/OrthancExplorer/explorer.js OrthancServer/Sources/OrthancRestApi/OrthancRestResources.cpp
diffstat 4 files changed, 65 insertions(+), 9 deletions(-) [+]
line wrap: on
line diff
--- a/NEWS	Tue Dec 14 22:52:59 2021 +0100
+++ b/NEWS	Thu Dec 16 14:48:46 2021 +0100
@@ -12,6 +12,7 @@
 * New configuration option "ZipLoaderThreads" to configure the number of threads used
   to read instances from storage when createing a Zip archive/media.
 * Support decoding of black-and-white images (with 1 bit per pixel), notably DICOM SEG
+* Added links to download attachments from the Orthanc Explorer
 
 Maintenance
 -----------
@@ -33,6 +34,7 @@
 * "/instances/{...}/frames/{...}/numpy": Download the frame as a Python numpy array
 * "/instances/{...}/numpy": Download the instance as a Python numpy array
 * "/series/{...}/numpy": Download the series as a Python numpy array
+* Added a ?full option to "/patients|studies|series|instances/{...}/attachments route
 
 Lua
 ---
--- a/OrthancServer/OrthancExplorer/explorer.html	Tue Dec 14 22:52:59 2021 +0100
+++ b/OrthancServer/OrthancExplorer/explorer.html	Thu Dec 16 14:48:46 2021 +0100
@@ -252,7 +252,7 @@
               <li data-icon="star"><a href="#" id="patient-anonymize">Anonymize</a></li>
             </ul>
 
-            <ul data-role="listview" data-inset="true" data-theme="d" data-divider-theme="c">
+            <ul data-role="listview" data-inset="true" data-theme="d" data-divider-theme="c" id="patient-access">
               <li data-role="list-divider">Access</li>
               <li data-icon="info" data-theme="e" style="display:none">
                 <a href="#" id="patient-anonymized-from">Before anonymization</a>
@@ -306,7 +306,7 @@
               <li data-icon="star"><a href="#" id="study-anonymize">Anonymize</a></li>
             </ul>
 
-            <ul data-role="listview" data-inset="true" data-theme="d" data-divider-theme="c">
+            <ul data-role="listview" data-inset="true" data-theme="d" data-divider-theme="c" id="study-access">
               <li data-role="list-divider">Access</li>
               <li data-icon="info" data-theme="e" style="display:none">
                 <a href="#" id="study-anonymized-from">Before anonymization</a>
@@ -361,7 +361,7 @@
               <li data-icon="star"><a href="#" id="series-anonymize">Anonymize</a></li>
             </ul>
 
-            <ul data-role="listview" data-inset="true" data-theme="d" data-divider-theme="c">
+            <ul data-role="listview" data-inset="true" data-theme="d" data-divider-theme="c" id="series-access">
               <li data-role="list-divider">Access</li>
               <li data-icon="info" data-theme="e" style="display:none">
                 <a href="#" id="series-anonymized-from">Before anonymization</a>
@@ -417,7 +417,7 @@
               <li data-icon="forward"><a href="#" id="instance-store">Send to DICOM modality</a></li>
             </ul>
 
-            <ul data-role="listview" data-inset="true" data-theme="d" data-divider-theme="c">
+            <ul data-role="listview" data-inset="true" data-theme="d" data-divider-theme="c" id="instance-access">
               <li data-role="list-divider">Access</li>
               <li data-icon="info" data-theme="e" style="display:none">
                 <a href="#" id="instance-anonymized-from">Before anonymization</a>
--- a/OrthancServer/OrthancExplorer/explorer.js	Tue Dec 14 22:52:59 2021 +0100
+++ b/OrthancServer/OrthancExplorer/explorer.js	Thu Dec 16 14:48:46 2021 +0100
@@ -701,7 +701,19 @@
   }
 }
 
+function SetupAttachments(accessSelector, liClass, resourceId, resourceType) {
+  GetResource('/' + resourceType + '/' + resourceId + '/attachments?full', function(attachments) {
+    target = $(accessSelector);
+    $('.' + liClass).remove();
+    for (var key in attachments) {
+      if (attachments[key] >= 1024) {
+        target.append('<li data-icon="gear" class="' + liClass + '"><a href="#" id="' + attachments[key] + '">Download ' + key + '</a></li>')
+      }
+    }
+    target.listview('refresh');
+  });
 
+}
 
 function RefreshPatient()
 {
@@ -738,6 +750,7 @@
 
         SetupAnonymizedOrModifiedFrom('#patient-anonymized-from', patient, 'patient', ANONYMIZED_FROM);
         SetupAnonymizedOrModifiedFrom('#patient-modified-from', patient, 'patient', MODIFIED_FROM);
+        SetupAttachments('#patient-access', 'patient-attachment', pageData.uuid, 'patients');
 
         target.listview('refresh');
 
@@ -785,6 +798,7 @@
 
           SetupAnonymizedOrModifiedFrom('#study-anonymized-from', study, 'study', ANONYMIZED_FROM);
           SetupAnonymizedOrModifiedFrom('#study-modified-from', study, 'study', MODIFIED_FROM);
+          SetupAttachments('#study-access', 'study-attachment', pageData.uuid, 'studies');
 
           target = $('#list-series');
           $('li', target).remove();
@@ -802,6 +816,7 @@
           }
           target.listview('refresh');
 
+
           currentPage = 'study';
           currentUuid = pageData.uuid;
         });
@@ -839,6 +854,7 @@
 
             SetupAnonymizedOrModifiedFrom('#series-anonymized-from', series, 'series', ANONYMIZED_FROM);
             SetupAnonymizedOrModifiedFrom('#series-modified-from', series, 'series', MODIFIED_FROM);
+            SetupAttachments('#series-access', 'series-attachment', pageData.uuid, 'series');
 
             target = $('#list-instances');
             $('li', target).remove();
@@ -978,6 +994,8 @@
             SetupAnonymizedOrModifiedFrom('#instance-anonymized-from', instance, 'instance', ANONYMIZED_FROM);
             SetupAnonymizedOrModifiedFrom('#instance-modified-from', instance, 'instance', MODIFIED_FROM);
 
+            SetupAttachments('#instance-access', 'instance-attachment', pageData.uuid, 'instances');
+
             currentPage = 'instance';
             currentUuid = pageData.uuid;
           });
@@ -1347,7 +1365,25 @@
   window.location.href = '../series/' + $.mobile.pageData.uuid + '/media';
 });
 
+$('.patient-attachment').live('click', function(e) {
+  e.preventDefault();  //stop the browser from following
+  window.location.href = '../patients/' + $.mobile.pageData.uuid + '/attachments/' + e.target.id + '/data';
+});
 
+$('.study-attachment').live('click', function(e) {
+  e.preventDefault();  //stop the browser from following
+  window.location.href = '../studies/' + $.mobile.pageData.uuid + '/attachments/' + e.target.id + '/data';
+});
+
+$('.series-attachment').live('click', function(e) {
+  e.preventDefault();  //stop the browser from following
+  window.location.href = '../series/' + $.mobile.pageData.uuid + '/attachments/' + e.target.id + '/data';
+});
+
+$('.instance-attachment').live('click', function(e) {
+  e.preventDefault();  //stop the browser from following
+  window.location.href = '../instances/' + $.mobile.pageData.uuid + '/attachments/' + e.target.id + '/data';
+});
 
 $('#protection').live('change', function(e) {
   var isProtected = e.target.value == "on";
--- a/OrthancServer/Sources/OrthancRestApi/OrthancRestResources.cpp	Tue Dec 14 22:52:59 2021 +0100
+++ b/OrthancServer/Sources/OrthancRestApi/OrthancRestResources.cpp	Thu Dec 16 14:48:46 2021 +0100
@@ -1928,6 +1928,8 @@
         .SetSummary("List attachments")
         .SetDescription("Get the list of attachments that are associated with the given " + r)
         .SetUriArgument("id", "Orthanc identifier of the " + r + " of interest")
+        .SetHttpGetArgument("full", RestApiCallDocumentation::Type_String,
+                            "If present, retrieve the attachments list and their numerical ids", false)
         .AddAnswerType(MimeType_Json, "JSON array containing the names of the attachments")
         .SetHttpGetSample(GetDocumentationSampleResource(t) + "/attachments", true);
       return;
@@ -1938,12 +1940,28 @@
     std::set<FileContentType> attachments;
     OrthancRestApi::GetIndex(call).ListAvailableAttachments(attachments, publicId, StringToResourceType(resourceType.c_str()));
 
-    Json::Value result = Json::arrayValue;
-
-    for (std::set<FileContentType>::const_iterator 
-           it = attachments.begin(); it != attachments.end(); ++it)
+    Json::Value result;
+
+    if (call.HasArgument("full"))
     {
-      result.append(EnumerationToString(*it));
+      result = Json::objectValue;
+      
+      for (std::set<FileContentType>::const_iterator 
+            it = attachments.begin(); it != attachments.end(); ++it)
+      {
+        std::string key = EnumerationToString(*it);
+        result[key] = static_cast<uint16_t>(*it);
+      }
+    }
+    else
+    {
+      result = Json::arrayValue;
+      
+      for (std::set<FileContentType>::const_iterator 
+            it = attachments.begin(); it != attachments.end(); ++it)
+      {
+        result.append(EnumerationToString(*it));
+      }
     }
 
     call.GetOutput().AnswerJson(result);