From 89d97a7a3a96638ad200ed6996bf39f6268da20c Mon Sep 17 00:00:00 2001 From: Erik Ziegler Date: Sun, 23 Sep 2018 10:57:21 +0200 Subject: [PATCH] chore(dicomweb-client): Switch to dicomweb-client.js to push logic out of OHIF --- LesionTracker/.meteor/versions | 1 - OHIFViewer/.meteor/packages | 1 - OHIFViewer/.meteor/versions | 1 - OHIFViewer/client/config.js | 6 +- Packages/ohif-commands/package.js | 2 +- .../both/lib/DICOMWeb}/getAttribute.js | 4 +- .../lib/DICOMWeb/getAuthorizationHeader.js | 26 ++++ .../both/lib/DICOMWeb}/getModalities.js | 4 +- .../both/lib/DICOMWeb}/getName.js | 0 .../both/lib/DICOMWeb}/getNumber.js | 0 .../both/lib/DICOMWeb}/getString.js | 0 .../both/lib/DICOMWeb}/index.js | 16 +-- Packages/ohif-core/both/lib/index.js | 1 + Packages/ohif-core/both/utils/absoluteUrl.js | 2 +- Packages/ohif-core/main.js | 1 + Packages/ohif-core/package.js | 6 +- Packages/ohif-cornerstone-settings/package.js | 2 +- Packages/ohif-cornerstone/package.js | 2 +- Packages/ohif-design/package.js | 2 +- Packages/ohif-dicomweb-client/package.js | 22 --- Packages/ohif-dicomweb-client/src/get.js | 33 ----- .../src/getAccessToken.js | 14 -- .../ohif-dicomweb-client/src/getBulkData.js | 133 ------------------ Packages/ohif-dicomweb-client/src/getJSON.js | 16 --- .../ohif-dicomweb-client/src/makeRequest.js | 69 --------- Packages/ohif-hanging-protocols/package.js | 2 +- Packages/ohif-header/package.js | 2 +- Packages/ohif-hotkeys/package.js | 2 +- Packages/ohif-lesiontracker/package.js | 2 +- Packages/ohif-log/package.js | 2 +- .../client/configuration/dataExchange.js | 4 +- .../client/utils/handleSR.js | 81 +++++------ .../client/utils/srUtils.js | 30 +--- Packages/ohif-measurement-table/package.js | 7 +- Packages/ohif-measurements/package.js | 2 +- Packages/ohif-metadata/package.js | 2 +- Packages/ohif-polyfill/package.js | 2 +- Packages/ohif-select-tree/package.js | 2 +- Packages/ohif-servers/both/schema/servers.js | 8 +- Packages/ohif-servers/client/startup.js | 1 - Packages/ohif-servers/package.js | 12 +- Packages/ohif-servers/server/startup.js | 1 - .../imports/both/lib/encodeQueryData.js | 18 --- .../ohif-studies/imports/both/lib/index.js | 1 - .../imports/both/services/qido/instances.js | 33 ++--- .../imports/both/services/qido/studies.js | 43 ++++-- .../both/services/wado/retrieveMetadata.js | 112 +++++++++------ Packages/ohif-studies/package.js | 9 +- .../studylistResult/studylistResult.js | 31 ++-- Packages/ohif-study-list/package.js | 2 +- Packages/ohif-themes-common/package.js | 2 +- Packages/ohif-themes/package.js | 2 +- Packages/ohif-user-management/package.js | 2 +- Packages/ohif-viewerbase/package.js | 4 +- Packages/ohif-wadoproxy/package.js | 4 +- .../StandaloneViewer/.meteor/packages | 1 - .../StandaloneViewer/.meteor/versions | 6 - config/orthancDICOMWeb.json | 2 +- 58 files changed, 256 insertions(+), 542 deletions(-) rename Packages/{ohif-dicomweb-client/src => ohif-core/both/lib/DICOMWeb}/getAttribute.js (93%) create mode 100644 Packages/ohif-core/both/lib/DICOMWeb/getAuthorizationHeader.js rename Packages/{ohif-dicomweb-client/src => ohif-core/both/lib/DICOMWeb}/getModalities.js (86%) rename Packages/{ohif-dicomweb-client/src => ohif-core/both/lib/DICOMWeb}/getName.js (100%) rename Packages/{ohif-dicomweb-client/src => ohif-core/both/lib/DICOMWeb}/getNumber.js (100%) rename Packages/{ohif-dicomweb-client/src => ohif-core/both/lib/DICOMWeb}/getString.js (100%) rename Packages/{ohif-dicomweb-client/src => ohif-core/both/lib/DICOMWeb}/index.js (51%) delete mode 100644 Packages/ohif-dicomweb-client/package.js delete mode 100644 Packages/ohif-dicomweb-client/src/get.js delete mode 100644 Packages/ohif-dicomweb-client/src/getAccessToken.js delete mode 100644 Packages/ohif-dicomweb-client/src/getBulkData.js delete mode 100644 Packages/ohif-dicomweb-client/src/getJSON.js delete mode 100644 Packages/ohif-dicomweb-client/src/makeRequest.js delete mode 100644 Packages/ohif-studies/imports/both/lib/encodeQueryData.js diff --git a/LesionTracker/.meteor/versions b/LesionTracker/.meteor/versions index d46d5d135..9539121c6 100644 --- a/LesionTracker/.meteor/versions +++ b/LesionTracker/.meteor/versions @@ -92,7 +92,6 @@ ohif:core@0.0.1 ohif:cornerstone@0.0.1 ohif:cornerstone-settings@0.0.1 ohif:design@0.0.1 -ohif:dicomweb-client@0.0.1 ohif:hanging-protocols@0.0.1 ohif:header@0.0.1 ohif:hotkeys@0.0.1 diff --git a/OHIFViewer/.meteor/packages b/OHIFViewer/.meteor/packages index 6bd0669a1..a229e05c5 100644 --- a/OHIFViewer/.meteor/packages +++ b/OHIFViewer/.meteor/packages @@ -37,7 +37,6 @@ ohif:cornerstone ohif:cornerstone-settings ohif:viewerbase ohif:study-list -ohif:dicomweb-client ohif:hanging-protocols ohif:metadata ohif:user-oidc diff --git a/OHIFViewer/.meteor/versions b/OHIFViewer/.meteor/versions index 43bed6672..e061f8b60 100644 --- a/OHIFViewer/.meteor/versions +++ b/OHIFViewer/.meteor/versions @@ -82,7 +82,6 @@ ohif:core@0.0.1 ohif:cornerstone@0.0.1 ohif:cornerstone-settings@0.0.1 ohif:design@0.0.1 -ohif:dicomweb-client@0.0.1 ohif:hanging-protocols@0.0.1 ohif:header@0.0.1 ohif:hotkeys@0.0.1 diff --git a/OHIFViewer/client/config.js b/OHIFViewer/client/config.js index c726f5a64..bee9e5103 100644 --- a/OHIFViewer/client/config.js +++ b/OHIFViewer/client/config.js @@ -22,10 +22,10 @@ Meteor.startup(function() { cornerstoneWADOImageLoader.configure({ beforeSend: function(xhr) { - const accessToken = OHIF.user.getAccessToken(); + const headers = OHIF.DICOMWeb.getAuthorizationHeader(); - if (accessToken) { - xhr.setRequestHeader("Authorization", `Bearer ${accessToken}`); + if (headers.Authorization) { + xhr.setRequestHeader("Authorization", headers.Authorization); } } }); diff --git a/Packages/ohif-commands/package.js b/Packages/ohif-commands/package.js index f2eac0a1d..9733a1514 100644 --- a/Packages/ohif-commands/package.js +++ b/Packages/ohif-commands/package.js @@ -5,7 +5,7 @@ Package.describe({ }); Package.onUse(function(api) { - api.versionsFrom('1.4'); + api.versionsFrom('1.7'); // Meteor packages api.use([ diff --git a/Packages/ohif-dicomweb-client/src/getAttribute.js b/Packages/ohif-core/both/lib/DICOMWeb/getAttribute.js similarity index 93% rename from Packages/ohif-dicomweb-client/src/getAttribute.js rename to Packages/ohif-core/both/lib/DICOMWeb/getAttribute.js index ea6f316b1..2b04c302e 100644 --- a/Packages/ohif-dicomweb-client/src/getAttribute.js +++ b/Packages/ohif-core/both/lib/DICOMWeb/getAttribute.js @@ -5,7 +5,7 @@ * @param [defaultValue] - The value to return if the element is not present * @returns {*} */ -const getAttribute = function(element, defaultValue) { +export default function getAttribute(element, defaultValue) { if (!element) { return defaultValue; } @@ -42,5 +42,3 @@ function convertToInt(input) { return parseInt(output, 16); } - -export default getAttribute; diff --git a/Packages/ohif-core/both/lib/DICOMWeb/getAuthorizationHeader.js b/Packages/ohif-core/both/lib/DICOMWeb/getAuthorizationHeader.js new file mode 100644 index 000000000..f9d80d93f --- /dev/null +++ b/Packages/ohif-core/both/lib/DICOMWeb/getAuthorizationHeader.js @@ -0,0 +1,26 @@ +import { OHIF } from 'meteor/ohif:core'; +import { btoa } from 'isomorphic-base64'; + +/** + * Returns the Authorization header as part of an Object. + * + * @returns {Object} + */ +export default function getAuthorizationHeader() { + const headers = {}; + + // Check for OHIF.user since this can also be run on the server + const accessToken = OHIF.user && OHIF.user.getAccessToken && OHIF.user.getAccessToken(); + const server = OHIF.servers.getCurrentServer(); + + if (server && + server.requestOptions && + server.requestOptions.auth) { + // HTTP Basic Auth (user:password) + headers.Authorization = `Basic ${btoa(server.requestOptions.auth)}`; + } else if (accessToken) { + headers.Authorization = `Bearer ${accessToken}`; + } + + return headers; +} diff --git a/Packages/ohif-dicomweb-client/src/getModalities.js b/Packages/ohif-core/both/lib/DICOMWeb/getModalities.js similarity index 86% rename from Packages/ohif-dicomweb-client/src/getModalities.js rename to Packages/ohif-core/both/lib/DICOMWeb/getModalities.js index a80525c5a..4c00d9378 100644 --- a/Packages/ohif-dicomweb-client/src/getModalities.js +++ b/Packages/ohif-core/both/lib/DICOMWeb/getModalities.js @@ -1,4 +1,4 @@ -const getModalities = function(modality, modalitiesInStudy) { +export default function getModalities(modality, modalitiesInStudy) { var modalities = {}; if (modality) { modalities = modality; @@ -19,5 +19,3 @@ const getModalities = function(modality, modalitiesInStudy) { } return modalities; }; - -export default getModalities; diff --git a/Packages/ohif-dicomweb-client/src/getName.js b/Packages/ohif-core/both/lib/DICOMWeb/getName.js similarity index 100% rename from Packages/ohif-dicomweb-client/src/getName.js rename to Packages/ohif-core/both/lib/DICOMWeb/getName.js diff --git a/Packages/ohif-dicomweb-client/src/getNumber.js b/Packages/ohif-core/both/lib/DICOMWeb/getNumber.js similarity index 100% rename from Packages/ohif-dicomweb-client/src/getNumber.js rename to Packages/ohif-core/both/lib/DICOMWeb/getNumber.js diff --git a/Packages/ohif-dicomweb-client/src/getString.js b/Packages/ohif-core/both/lib/DICOMWeb/getString.js similarity index 100% rename from Packages/ohif-dicomweb-client/src/getString.js rename to Packages/ohif-core/both/lib/DICOMWeb/getString.js diff --git a/Packages/ohif-dicomweb-client/src/index.js b/Packages/ohif-core/both/lib/DICOMWeb/index.js similarity index 51% rename from Packages/ohif-dicomweb-client/src/index.js rename to Packages/ohif-core/both/lib/DICOMWeb/index.js index cfa9358d5..d983a13b3 100644 --- a/Packages/ohif-dicomweb-client/src/index.js +++ b/Packages/ohif-core/both/lib/DICOMWeb/index.js @@ -1,25 +1,19 @@ -import get from './get.js'; +import { OHIF } from 'meteor/ohif:core'; + import getAttribute from './getAttribute.js'; -import getBulkData from './getBulkData.js'; -import getJSON from './getJSON.js'; +import getAuthorizationHeader from './getAuthorizationHeader.js'; import getModalities from './getModalities.js'; import getName from './getName.js'; import getNumber from './getNumber.js'; import getString from './getString.js'; -import getAccessToken from './getAccessToken.js'; -import makeRequest from './makeRequest.js'; const DICOMWeb = { - get, getAttribute, - getBulkData, - getJSON, + getAuthorizationHeader, getModalities, getName, getNumber, getString, - getAccessToken, - makeRequest }; -export { DICOMWeb }; +OHIF.DICOMWeb = DICOMWeb; diff --git a/Packages/ohif-core/both/lib/index.js b/Packages/ohif-core/both/lib/index.js index 9dac2ed16..a18eb8996 100644 --- a/Packages/ohif-core/both/lib/index.js +++ b/Packages/ohif-core/both/lib/index.js @@ -1 +1,2 @@ import './object.js'; +import './DICOMWeb/'; diff --git a/Packages/ohif-core/both/utils/absoluteUrl.js b/Packages/ohif-core/both/utils/absoluteUrl.js index 4b1dbdf7e..e2239f7ea 100644 --- a/Packages/ohif-core/both/utils/absoluteUrl.js +++ b/Packages/ohif-core/both/utils/absoluteUrl.js @@ -16,4 +16,4 @@ OHIF.utils.absoluteUrl = function(path) { } return absolutePath.replace(/\/\/+/g, '/'); -}; \ No newline at end of file +}; diff --git a/Packages/ohif-core/main.js b/Packages/ohif-core/main.js index 90a0d542a..f79be869c 100644 --- a/Packages/ohif-core/main.js +++ b/Packages/ohif-core/main.js @@ -11,6 +11,7 @@ const OHIF = { viewer: {}, cornerstone: {}, user: {}, + DICOMWeb: {}, // Temporarily added }; // Expose the OHIF object to the client if it is on development mode diff --git a/Packages/ohif-core/package.js b/Packages/ohif-core/package.js index 1970ca2b1..196a1f37e 100644 --- a/Packages/ohif-core/package.js +++ b/Packages/ohif-core/package.js @@ -1,5 +1,6 @@ Npm.depends({ - 'twbs-pagination': '1.4.1' + 'twbs-pagination': '1.4.1', + 'isomorphic-base64': '1.0.2', }); Package.describe({ @@ -9,7 +10,7 @@ Package.describe({ }); Package.onUse(function(api) { - api.versionsFrom('1.4'); + api.versionsFrom('1.7'); api.use('ecmascript'); api.use('standard-app-packages'); @@ -44,5 +45,4 @@ Package.onUse(function(api) { // Client and server imports api.addFiles('both/index.js', ['client', 'server']); - }); diff --git a/Packages/ohif-cornerstone-settings/package.js b/Packages/ohif-cornerstone-settings/package.js index a83f9bf88..df937dbb1 100644 --- a/Packages/ohif-cornerstone-settings/package.js +++ b/Packages/ohif-cornerstone-settings/package.js @@ -5,7 +5,7 @@ Package.describe({ }); Package.onUse(function(api) { - api.versionsFrom('1.5'); + api.versionsFrom('1.7'); api.use('ecmascript'); api.use('ohif:cornerstone'); diff --git a/Packages/ohif-cornerstone/package.js b/Packages/ohif-cornerstone/package.js index 2c69c3259..acc0fc86c 100644 --- a/Packages/ohif-cornerstone/package.js +++ b/Packages/ohif-cornerstone/package.js @@ -15,7 +15,7 @@ Npm.depends({ }); Package.onUse(function(api) { - api.versionsFrom('1.5'); + api.versionsFrom('1.7'); api.use('ecmascript'); diff --git a/Packages/ohif-design/package.js b/Packages/ohif-design/package.js index e4908627a..88fd0e93a 100644 --- a/Packages/ohif-design/package.js +++ b/Packages/ohif-design/package.js @@ -16,7 +16,7 @@ Package.describe({ }); Package.onUse(function(api) { - api.versionsFrom('1.4.2.3'); + api.versionsFrom('1.7'); api.use('ecmascript'); api.use('standard-app-packages'); diff --git a/Packages/ohif-dicomweb-client/package.js b/Packages/ohif-dicomweb-client/package.js deleted file mode 100644 index 60999009f..000000000 --- a/Packages/ohif-dicomweb-client/package.js +++ /dev/null @@ -1,22 +0,0 @@ -Package.describe({ - name: 'ohif:dicomweb-client', - summary: 'DICOM Services: DICOMWeb', - version: '0.0.1' -}); - -Npm.depends({ - 'url-parse': '1.4.1', - 'isomorphic-fetch': '2.2.1', - 'isomorphic-base64': '1.0.2' -}); - -Package.onUse(function(api) { - api.versionsFrom('1.6'); - - api.use('ecmascript'); - - // DICOMWeb functions - api.mainModule('src/index.js'); - - api.export('DICOMWeb'); -}); diff --git a/Packages/ohif-dicomweb-client/src/get.js b/Packages/ohif-dicomweb-client/src/get.js deleted file mode 100644 index 3bceb0661..000000000 --- a/Packages/ohif-dicomweb-client/src/get.js +++ /dev/null @@ -1,33 +0,0 @@ -import makeRequest from "./makeRequest"; - -/** - * Make a request to the URL given a set of options. - * This function will add optional timing, request, and respone logging. - * - * @param {String} url - * @param {Object} options - * @return {Promise<*>} - */ -const get = async function get(url, options) { - if (options.logRequests) { - console.log(url); - } - - if (options.logTiming) { - console.time(url); - } - - const result = await makeRequest(url, options); - - if (options.logTiming) { - console.timeEnd(url); - } - - if (options.logResponses) { - console.info(result); - } - - return result; -} - -export default get; diff --git a/Packages/ohif-dicomweb-client/src/getAccessToken.js b/Packages/ohif-dicomweb-client/src/getAccessToken.js deleted file mode 100644 index c8306fc38..000000000 --- a/Packages/ohif-dicomweb-client/src/getAccessToken.js +++ /dev/null @@ -1,14 +0,0 @@ -import { OHIF } from 'meteor/ohif:core'; - -export default function getAccessToken() { - if (!global.window || !window.sessionStorage || !sessionStorage) { - return; - } - - const userAccessToken = OHIF.user.getAccessToken(); - if (userAccessToken) { - return userAccessToken; - } - - return sessionStorage.token; -} diff --git a/Packages/ohif-dicomweb-client/src/getBulkData.js b/Packages/ohif-dicomweb-client/src/getBulkData.js deleted file mode 100644 index dc576fc17..000000000 --- a/Packages/ohif-dicomweb-client/src/getBulkData.js +++ /dev/null @@ -1,133 +0,0 @@ -import get from './get.js'; - -const ASCII = 'ascii'; - -function getMultipartContentInfo(headers) { - const multipartRegex = /^\s*multipart\/[^;]+/g; - const contentType = headers.get('content-type'); - let dict = null; - - if (typeof contentType === 'string' && multipartRegex.test(contentType)) { - let match; - let pairRegex = /;\s*([^=]+)=([^;\r\n]+)/g; - - pairRegex.lastIndex = multipartRegex.lastIndex; - while ((match = pairRegex.exec(contentType)) !== null) { - let key = match[1] - let value = match[2]; - - if (dict === null) { - dict = {}; - } - dict[key] = value; - } - } - - return dict; -} - -function parseContentHeader(data, offset) { - const endOfHeader = data.indexOf('\r\n\r\n', offset); - - if (endOfHeader < 0 || endOfHeader <= offset || endOfHeader > data.length) { - throw new Error('End of content header cannot be determined...'); - } - - const header = { - start: offset, - end: endOfHeader + 4, - fields: {} - }; - const headerRegex = /([\w\-]+):\s*([^\r\n]+)(?:\r\n)?/g; - const headerContentRegex = /\t([^\r\n]+)(?:\r\n)?/g; - const headerString = data.slice(offset, endOfHeader); - - let match; - - while ((match = headerRegex.exec(headerString)) !== null) { - const key = match[1].toLowerCase(), value = match[2]; - - while (headerString.charAt(headerRegex.lastIndex) === '\t') { - headerContentRegex.lastIndex = headerRegex.lastIndex; - - if ((match = headerContentRegex.exec(headerString)) !== null) { - headerRegex.lastIndex = headerContentRegex.lastIndex; - value += ' ' + match[1]; - continue; - } - - break; - } - header.fields[key] = value; - } - - return header; - -} - -function toBytes(input) { - const data = []; - for (let i = 0; i < input.length; i++){ - data.push(input.charCodeAt(i)); - } - - return data; -} - - -function parseResponse(headers, data) { - const contentInfo = getMultipartContentInfo(headers); - - if (!contentInfo || !contentInfo.boundary) { - throw new Error('Content boundary not specified...'); - } - - const boundary = contentInfo.boundary; - const delimiter = '--' + boundary + '\r\n'; - let index = data.indexOf(delimiter, 0, ASCII); - - if (index < 0) { - throw new Error('DICOMWeb: The specified boundary could not be found...'); - } - - let closingIndex - let closingDelimiter = '\r\n--' + boundary + '--'; - - index += delimiter.length; - if (data[index] !== 0x0D || data[index + 1] !== 0x0A) { - // multipart content headers are present, so let's parse them... - let contentHeader = parseContentHeader(data, index); - if (contentHeader && contentHeader.end > index) { - if (contentHeader.fields['content-length'] > 0) { - let endOfData = contentHeader.end + parseInt(contentHeader.fields['content-length'], 10); - if (endOfData === data.indexOf(closingDelimiter, endOfData)) { - // content-length is valid... - return data.slice(contentHeader.end, endOfData); - } - } - index = contentHeader.end; - } - } else { - // no headers, the content comes right after... - index += 2; - } - - closingIndex = data.indexOf(closingDelimiter, index); - if (closingIndex < 0 || closingIndex < index) { - throw new Error('DICOMWeb: The end of the content could not be determined...') - } - - return toBytes(data.slice(index, closingIndex)); -} - -const getBulkData = async function(url, options = {}) { - options.headers = options.headers || {}; - options.headers.Accept = 'multipart/related; type=application/octet-stream'; - - const response = await get(url, options); - const data = await response.text(); - - return parseResponse(response.headers, data); -} - -export default getBulkData; diff --git a/Packages/ohif-dicomweb-client/src/getJSON.js b/Packages/ohif-dicomweb-client/src/getJSON.js deleted file mode 100644 index 69480f0ba..000000000 --- a/Packages/ohif-dicomweb-client/src/getJSON.js +++ /dev/null @@ -1,16 +0,0 @@ -import get from './get.js'; -import getAttribute from "./getAttribute"; - -const getJSON = async function (url, options) { - options.headers = options.headers || {}; - options.headers.Accept = 'application/json'; - return get(url, options).then(response => { - if (!(response instanceof Response)) { - return ''; - } - - return response.json(); - }); -}; - -export default getJSON; diff --git a/Packages/ohif-dicomweb-client/src/makeRequest.js b/Packages/ohif-dicomweb-client/src/makeRequest.js deleted file mode 100644 index dd367ff1d..000000000 --- a/Packages/ohif-dicomweb-client/src/makeRequest.js +++ /dev/null @@ -1,69 +0,0 @@ -import { Meteor } from "meteor/meteor"; -import URL from 'url-parse'; -import 'isomorphic-fetch'; -import { btoa } from 'isomorphic-base64'; -import getAccessToken from './getAccessToken.js'; - -async function makeRequest(url, options) { - const parsed = new URL(url); - - let requestOpt = { - method: 'GET', - headers: {} - }; - - const accessToken = getAccessToken(); - if (accessToken) { - requestOpt.headers = { - Authorization: `Bearer ${accessToken}` - }; - } else if (options.auth) { - requestOpt.headers = { - Authorization: `Basic ${btoa(options.auth)}` - }; - } - - if (options.headers) { - Object.keys(options.headers).forEach(key => { - requestOpt.headers[key] = options.headers[key]; - }); - } - - if(options.method) { - requestOpt.method = options.method; - } - - if (options.method === 'POST' && options.body) { - requestOpt.body = options.body; - } - - return new Promise((resolve, reject) => { - // TODO: Kept getting weird build errors from RegExp - const isAbsolute = parsed.href.indexOf('http://') === 0 || parsed.href.indexOf('https://') === 0; - - let url = parsed.href; - - if (isAbsolute === false) { - url = Meteor.absoluteUrl(parsed.href); - } - - fetch(url, requestOpt).then((response) => { - if (response.status >= 400) { - reject(new Error(response.status)); - } - - if (response.status === 204) { - resolve([]); - } else { - // TODO: Handle 204 no content - resolve(response); - } - }, (error) => { - console.error('There was an error in the DICOMWeb Server'); - - reject(new Error(error)); - }); - }); -} - -export default makeRequest; diff --git a/Packages/ohif-hanging-protocols/package.js b/Packages/ohif-hanging-protocols/package.js index 29a7b3c8c..887e01e9b 100755 --- a/Packages/ohif-hanging-protocols/package.js +++ b/Packages/ohif-hanging-protocols/package.js @@ -9,7 +9,7 @@ Npm.depends({ }); Package.onUse(function(api) { - api.versionsFrom('1.4'); + api.versionsFrom('1.7'); api.use('ecmascript'); api.use('standard-app-packages'); diff --git a/Packages/ohif-header/package.js b/Packages/ohif-header/package.js index 640b5c340..bc67eae33 100644 --- a/Packages/ohif-header/package.js +++ b/Packages/ohif-header/package.js @@ -5,7 +5,7 @@ Package.describe({ }); Package.onUse(function(api) { - api.versionsFrom('1.4.2.3'); + api.versionsFrom('1.7'); // Meteor packages api.use('ecmascript'); diff --git a/Packages/ohif-hotkeys/package.js b/Packages/ohif-hotkeys/package.js index 933549260..3d3949651 100644 --- a/Packages/ohif-hotkeys/package.js +++ b/Packages/ohif-hotkeys/package.js @@ -9,7 +9,7 @@ Npm.depends({ }); Package.onUse(function(api) { - api.versionsFrom('1.4'); + api.versionsFrom('1.7'); // Meteor packages api.use([ diff --git a/Packages/ohif-lesiontracker/package.js b/Packages/ohif-lesiontracker/package.js index 30d9c47f3..8e63f1572 100644 --- a/Packages/ohif-lesiontracker/package.js +++ b/Packages/ohif-lesiontracker/package.js @@ -5,7 +5,7 @@ Package.describe({ }); Package.onUse(function(api) { - api.versionsFrom('1.4'); + api.versionsFrom('1.7'); api.use('ecmascript'); api.use('standard-app-packages'); diff --git a/Packages/ohif-log/package.js b/Packages/ohif-log/package.js index 8c319c55b..4ba86b763 100644 --- a/Packages/ohif-log/package.js +++ b/Packages/ohif-log/package.js @@ -9,7 +9,7 @@ Npm.depends({ }); Package.onUse(function(api) { - api.versionsFrom('1.4'); + api.versionsFrom('1.7'); api.use('ecmascript'); api.use('standard-app-packages'); diff --git a/Packages/ohif-measurement-table/client/configuration/dataExchange.js b/Packages/ohif-measurement-table/client/configuration/dataExchange.js index 2a9ce7a9f..7d0b32de1 100644 --- a/Packages/ohif-measurement-table/client/configuration/dataExchange.js +++ b/Packages/ohif-measurement-table/client/configuration/dataExchange.js @@ -18,7 +18,7 @@ export const retrieveMeasurements = (patientId, timepointIds) => { export const storeMeasurements = (measurementData, timepointIds) => { OHIF.log.info('storeMeasurements'); - + const server = OHIF.servers.getCurrentServer(); if (!server || server.type !== 'dicomWeb') { return Promise.resolve({}); @@ -28,6 +28,8 @@ export const storeMeasurements = (measurementData, timepointIds) => { return stowSRFromMeasurements(measurementData).then( () => { OHIF.studies.deleteStudyMetadataPromise(studyInstanceUid); + }, error => { + throw new Error(error); }); }; diff --git a/Packages/ohif-measurement-table/client/utils/handleSR.js b/Packages/ohif-measurement-table/client/utils/handleSR.js index a13165df1..2e60ceba4 100644 --- a/Packages/ohif-measurement-table/client/utils/handleSR.js +++ b/Packages/ohif-measurement-table/client/utils/handleSR.js @@ -1,60 +1,51 @@ import { dcmjs } from 'meteor/ohif:cornerstone'; import retrieveDataFromSR from './retrieveDataFromSR'; import retrieveDataFromMeasurements from './retrieveDataFromMeasurements'; -import { - multipartEncode -} from './srUtils'; + +import DICOMwebClient from 'dicomweb-client'; const retrieveMeasurementFromSR = async (series) => { - const instance = series.getFirstInstance(); - const options = { - method: 'GET', - responseType: 'arraybuffer', - }; - const url = instance.getDataProperty('wadouri'); + const server = OHIF.servers.getCurrentServer(); + const url = WADOProxy.convertURL(server.wadoRoot, server); - try { - const result = await DICOMWeb.makeRequest(url, options); - const data = await result.arrayBuffer(); - const measurementData = retrieveDataFromSR(data); - return Promise.resolve(measurementData); - } catch(error) { - return Promise.reject(error); - } + const config = { + url, + headers: OHIF.DICOMWeb.getAuthorizationHeader() + }; + + const dicomWeb = new DICOMwebClient.api.DICOMwebClient(config); + + const instance = series.getFirstInstance(); + const options = { + studyInstanceUID: instance.getStudyInstanceUID(), + seriesInstanceUID: instance.getSeriesInstanceUID(), + sopInstanceUID: instance.getSOPInstanceUID(), + }; + + return dicomWeb.retrieveInstance(options).then(retrieveDataFromSR); }; -/** - * Retrieve the DICOMWeb STOW-RS URL for the current server. - * - * See ftp://medical.nema.org/medical/dicom/current/output/html/part18.html#sect_6.6.1.1 - * - * @return {string|null} The URL, rerouted to the proxy if the WADOProxy is enabled. - */ -function getStowRsUrl() { - const server = OHIF.servers.getCurrentServer(); - const url = `${server.wadoRoot}/studies`; - - return WADOProxy.convertURL(url, server); -} - const stowSRFromMeasurements = async (measurements) => { - const serverUrl = getStowRsUrl(); + const server = OHIF.servers.getCurrentServer(); + const url = WADOProxy.convertURL(server.wadoRoot, server); const reportDataset = retrieveDataFromMeasurements(measurements); - const boundary = dcmjs.data.DicomMetaDictionary.uid(); - const options = { - method: 'POST', - body: multipartEncode(reportDataset, boundary), - headers: { - 'Content-Type': `multipart/related; type=application/dicom; boundary=${boundary}` - } + const denaturalizedMetaheader = dcmjs.data.DicomMetaDictionary.denaturalizeDataset(dataset._meta); + const dicomDict = new dcmjs.data.DicomDict(denaturalizedMetaheader); + + dicomDict.dict = dcmjs.data.DicomMetaDictionary.denaturalizeDataset(dataset); + + const part10Buffer = dicomDict.write(); + const config = { + url, + headers: OHIF.DICOMWeb.getAuthorizationHeader() }; - try { - await DICOMWeb.makeRequest(serverUrl, options); - return Promise.resolve(); - } catch(error) { - return Promise.reject(error); - } + const dicomWeb = new DICOMwebClient.api.DICOMwebClient(config); + const options = { + datasets: [part10Buffer] + }; + + return dicomWeb.storeInstances(options); }; export { diff --git a/Packages/ohif-measurement-table/client/utils/srUtils.js b/Packages/ohif-measurement-table/client/utils/srUtils.js index a82eb2e33..81149c323 100644 --- a/Packages/ohif-measurement-table/client/utils/srUtils.js +++ b/Packages/ohif-measurement-table/client/utils/srUtils.js @@ -55,7 +55,7 @@ const getLatestSRSeries = () => { if (supportedSopClassUIDs.includes(sopClassUid)) { if(!latestSeries) { latestSeries = series; - } else if (series._data.seriesDate > latestSeries._data.seriesDate || + } else if (series._data.seriesDate > latestSeries._data.seriesDate || (series._data.seriesDate === latestSeries._data.seriesDate && series._data.seriesTime > latestSeries._data.seriesTime)) { latestSeries = series; } @@ -70,36 +70,10 @@ const stringToArray = (string) => { return Uint8Array.from(Array.from(string).map(letter => letter.charCodeAt(0))) }; -const multipartEncode = (dataset, boundary) => { - - const denaturalizedMetaheader = dcmjs.data.DicomMetaDictionary.denaturalizeDataset(dataset._meta); - const dicomDict = new dcmjs.data.DicomDict(denaturalizedMetaheader); - - dicomDict.dict = dcmjs.data.DicomMetaDictionary.denaturalizeDataset(dataset); - - const part10Buffer = dicomDict.write(); - - const header = `\r\n--${boundary}\r\nContent-Type: application/dicom\r\n\r\n`; - const footer = `\r\n--${boundary}--`; - - headerArray = stringToArray(header); - contentArray = new Uint8Array(part10Buffer); - footerArray = stringToArray(footer); - - const multipartArray = new Uint8Array(headerArray.length + contentArray.length + footerArray.length); - - multipartArray.set(headerArray, 0); - multipartArray.set(contentArray, headerArray.length); - multipartArray.set(footerArray, headerArray.length + contentArray.length); - - return(multipartArray.buffer); -}; - export { codeMeaningEquals, getAllDisplaySets, getInstanceMetadata, getLatestSRSeries, - multipartEncode, toArray -} \ No newline at end of file +} diff --git a/Packages/ohif-measurement-table/package.js b/Packages/ohif-measurement-table/package.js index 6e5c0ccda..a6293d55c 100644 --- a/Packages/ohif-measurement-table/package.js +++ b/Packages/ohif-measurement-table/package.js @@ -4,8 +4,13 @@ Package.describe({ version: '0.0.1' }); +Npm.depends({ + 'dicomweb-client': '0.3.2', + 'xhr2': '0.1.4' +}); + Package.onUse(function(api) { - api.versionsFrom('1.6'); + api.versionsFrom('1.7'); api.use('ecmascript'); diff --git a/Packages/ohif-measurements/package.js b/Packages/ohif-measurements/package.js index 6fa4e30ba..220b754ed 100644 --- a/Packages/ohif-measurements/package.js +++ b/Packages/ohif-measurements/package.js @@ -11,7 +11,7 @@ Package.describe({ }); Package.onUse(function(api) { - api.versionsFrom('1.4'); + api.versionsFrom('1.7'); api.use('ecmascript'); api.use('standard-app-packages'); diff --git a/Packages/ohif-metadata/package.js b/Packages/ohif-metadata/package.js index 1e69589cd..13a0e2ac7 100644 --- a/Packages/ohif-metadata/package.js +++ b/Packages/ohif-metadata/package.js @@ -5,7 +5,7 @@ Package.describe({ }); Package.onUse(function(api) { - api.versionsFrom('1.4'); + api.versionsFrom('1.7'); api.use('ecmascript'); diff --git a/Packages/ohif-polyfill/package.js b/Packages/ohif-polyfill/package.js index ab843b5e9..c249242b3 100644 --- a/Packages/ohif-polyfill/package.js +++ b/Packages/ohif-polyfill/package.js @@ -5,7 +5,7 @@ Package.describe({ }); Package.onUse(function(api) { - api.versionsFrom('1.4'); + api.versionsFrom('1.7'); // Meteor packages api.use('ecmascript'); diff --git a/Packages/ohif-select-tree/package.js b/Packages/ohif-select-tree/package.js index 353c20118..e9706b277 100644 --- a/Packages/ohif-select-tree/package.js +++ b/Packages/ohif-select-tree/package.js @@ -5,7 +5,7 @@ Package.describe({ }); Package.onUse(function(api) { - api.versionsFrom('1.4'); + api.versionsFrom('1.7'); // Meteor packages api.use([ diff --git a/Packages/ohif-servers/both/schema/servers.js b/Packages/ohif-servers/both/schema/servers.js index 71988598d..d12820095 100644 --- a/Packages/ohif-servers/both/schema/servers.js +++ b/Packages/ohif-servers/both/schema/servers.js @@ -64,15 +64,15 @@ export const DICOMWebServer = new SimpleSchema({ imageRendering: { type: String, label: 'Image rendering', - allowedValues: ['wadouri', 'wadors', 'orthanc'], - valuesLabels: ['WADO URI', 'WADO RS', 'ORTHANC'], + allowedValues: ['wadouri', 'wadors'], + valuesLabels: ['WADO URI', 'WADO RS'], defaultValue: 'wadouri' }, thumbnailRendering: { type: String, label: 'Thumbnail rendering', - allowedValues: ['wadouri', 'wadors', 'orthanc'], - valuesLabels: ['WADO URI', 'WADO RS', 'ORTHANC'], + allowedValues: ['wadouri', 'wadors'], + valuesLabels: ['WADO URI', 'WADO RS'], defaultValue: 'wadouri' }, qidoRoot: { diff --git a/Packages/ohif-servers/client/startup.js b/Packages/ohif-servers/client/startup.js index de120dcc1..39004107c 100644 --- a/Packages/ohif-servers/client/startup.js +++ b/Packages/ohif-servers/client/startup.js @@ -14,7 +14,6 @@ if (Meteor.settings && const endpoints = servers[serverType]; endpoints.forEach((endpoint) => { const server = Object.assign({}, endpoint); - server.origin = 'json'; server.type = serverType; Servers.insert(server); diff --git a/Packages/ohif-servers/package.js b/Packages/ohif-servers/package.js index 574de1674..465d7ef52 100644 --- a/Packages/ohif-servers/package.js +++ b/Packages/ohif-servers/package.js @@ -5,14 +5,14 @@ Package.describe({ }); Package.onUse(function(api) { - api.versionsFrom('1.4'); + api.versionsFrom('1.7'); api.use('ecmascript'); - api.use('templating'); - api.use('jquery'); - api.use('stylus'); - api.use('aldeed:simple-schema'); - api.use('aldeed:collection2'); + api.use('templating', 'client'); + api.use('jquery', 'client'); + api.use('stylus', 'client'); + api.use('aldeed:simple-schema@1.5.4'); + api.use('aldeed:collection2@2.10.0'); // Our custom packages api.use('ohif:core'); diff --git a/Packages/ohif-servers/server/startup.js b/Packages/ohif-servers/server/startup.js index e34a2cca4..efcfec539 100644 --- a/Packages/ohif-servers/server/startup.js +++ b/Packages/ohif-servers/server/startup.js @@ -2,7 +2,6 @@ import { Meteor } from 'meteor/meteor'; import { _ } from 'meteor/underscore'; import { OHIF } from 'meteor/ohif:core'; import { Servers } from 'meteor/ohif:servers/both/collections'; -import { ServerConfiguration } from 'meteor/ohif:servers/both/schema/servers.js'; // Check the servers on meteor startup if (Meteor.settings && diff --git a/Packages/ohif-studies/imports/both/lib/encodeQueryData.js b/Packages/ohif-studies/imports/both/lib/encodeQueryData.js deleted file mode 100644 index f466b3a20..000000000 --- a/Packages/ohif-studies/imports/both/lib/encodeQueryData.js +++ /dev/null @@ -1,18 +0,0 @@ -/** - * Converts the properties to URL query parameters. Based on: - * http://stackoverflow.com/questions/111529/create-query-parameters-in-javascript - * - * @param data - * @returns {string} - */ -encodeQueryData = function(data) { - var ret = []; - - for (var d in data) { - if (data[d]) { - ret.push(encodeURIComponent(d) + '=' + encodeURIComponent(data[d])); - } - } - - return ret.join('&'); -}; diff --git a/Packages/ohif-studies/imports/both/lib/index.js b/Packages/ohif-studies/imports/both/lib/index.js index 8271ccc98..f53464cd4 100644 --- a/Packages/ohif-studies/imports/both/lib/index.js +++ b/Packages/ohif-studies/imports/both/lib/index.js @@ -1,2 +1 @@ -import './encodeQueryData.js'; import './parseFloatArray.js'; diff --git a/Packages/ohif-studies/imports/both/services/qido/instances.js b/Packages/ohif-studies/imports/both/services/qido/instances.js index e13ae54ea..aadf5db91 100644 --- a/Packages/ohif-studies/imports/both/services/qido/instances.js +++ b/Packages/ohif-studies/imports/both/services/qido/instances.js @@ -1,15 +1,7 @@ import { OHIF } from 'meteor/ohif:core'; -import { DICOMWeb } from 'meteor/ohif:dicomweb-client'; +import DICOMwebClient from 'dicomweb-client'; -/** - * Creates a QIDO URL given the server settings and a study instance UID - * @param server - * @param studyInstanceUid - * @returns {string} URL to be used for QIDO calls - */ -function buildUrl(server, studyInstanceUid) { - return server.qidoRoot + '/studies/' + studyInstanceUid + '/instances'; -} +const { DICOMWeb } = OHIF; /** * Parses data returned from a QIDO search and transforms it into @@ -76,20 +68,23 @@ function resultDataToStudyMetadata(server, studyInstanceUid, resultData) { * @returns {{wadoUriRoot: String, studyInstanceUid: String, seriesList: Array}} */ OHIF.studies.services.QIDO.Instances = function(server, studyInstanceUid) { - var url = buildUrl(server, studyInstanceUid); + // TODO: Are we using this function anywhere?? Can we remove it? - try { - var result = DICOMWeb.getJSON(url, server.requestOptions); + const config = { + url: server.qidoRoot, + headers: OHIF.DICOMWeb.getAuthorizationHeader() + }; + const dicomWeb = new DICOMwebClient.api.DICOMwebClient(config); + const queryParams = getQIDOQueryParams(filter, server.qidoSupportsIncludeField); + const options = { + studyInstanceUID: studyInstanceUid + }; + return dicomWeb.searchForInstances(options).then(result => { return { wadoUriRoot: server.wadoUriRoot, studyInstanceUid: studyInstanceUid, seriesList: resultDataToStudyMetadata(server, studyInstanceUid, result.data) }; - } catch (error) { - OHIF.log.trace(); - - throw error; - } - + }); }; diff --git a/Packages/ohif-studies/imports/both/services/qido/studies.js b/Packages/ohif-studies/imports/both/services/qido/studies.js index b7ff4f97b..6950a2597 100644 --- a/Packages/ohif-studies/imports/both/services/qido/studies.js +++ b/Packages/ohif-studies/imports/both/services/qido/studies.js @@ -1,5 +1,14 @@ import { OHIF } from 'meteor/ohif:core'; -import { DICOMWeb } from 'meteor/ohif:dicomweb-client'; +import DICOMwebClient from 'dicomweb-client'; + +const { DICOMWeb } = OHIF; + +// TODO: Is there an easier way to do this? +if (Meteor.isServer) { + var XMLHttpRequest = require('xhr2'); + + global.XMLHttpRequest = XMLHttpRequest; +} /** * Creates a QIDO date string for a date range query @@ -27,7 +36,7 @@ function dateToString(date) { * @param filter * @returns {string} The URL with encoded filter query data */ -function filterToQIDOURL(server, filter) { +function getQIDOQueryParams(filter, serverSupportsQIDOIncludeField) { const commaSeparatedFields = [ '00081030', // Study Description '00080060' //Modality @@ -41,7 +50,7 @@ function filterToQIDOURL(server, filter) { StudyDescription: filter.studyDescription, ModalitiesInStudy: filter.modalitiesInStudy, limit: filter.limit, - includefield: server.qidoSupportsIncludeField ? 'all' : commaSeparatedFields + includefield: serverSupportsQIDOIncludeField ? commaSeparatedFields : 'all' }; // build the StudyDate range parameter @@ -59,7 +68,16 @@ function filterToQIDOURL(server, filter) { parameters.StudyInstanceUID = studyUids; } - return server.qidoRoot + '/studies?' + encodeQueryData(parameters); + // Clean query params of undefined values. + const params = {}; + Object.keys(parameters).forEach(key => { + if (parameters[key] !== undefined && + parameters[key] !== "") { + params[key] = parameters[key]; + } + }); + + return params; } /** @@ -98,13 +116,16 @@ function resultDataToStudies(resultData) { } OHIF.studies.services.QIDO.Studies = (server, filter) => { - const url = filterToQIDOURL(server, filter); + const config = { + url: server.qidoRoot, + headers: OHIF.DICOMWeb.getAuthorizationHeader() + }; - return new Promise((resolve, reject) => { - DICOMWeb.getJSON(url, server.requestOptions).then(result => { - const studies = resultDataToStudies(result); + const dicomWeb = new DICOMwebClient.api.DICOMwebClient(config); + const queryParams = getQIDOQueryParams(filter, server.qidoSupportsIncludeField); + const options = { + queryParams + }; - resolve(studies); - }, reject); - }); + return dicomWeb.searchForStudies(options).then(resultDataToStudies); }; diff --git a/Packages/ohif-studies/imports/both/services/wado/retrieveMetadata.js b/Packages/ohif-studies/imports/both/services/wado/retrieveMetadata.js index 05d75657f..a4c9f8904 100644 --- a/Packages/ohif-studies/imports/both/services/wado/retrieveMetadata.js +++ b/Packages/ohif-studies/imports/both/services/wado/retrieveMetadata.js @@ -1,7 +1,10 @@ import { OHIF } from 'meteor/ohif:core'; -import { DICOMWeb } from 'meteor/ohif:dicomweb-client'; +import DICOMwebClient from 'dicomweb-client'; + import { parseFloatArray } from '../../lib/parseFloatArray'; +const { DICOMWeb } = OHIF; + /** * Simple cache schema for retrieved color palettes. */ @@ -39,17 +42,6 @@ const paletteColorCache = { } }; -/** - * Creates a URL for a WADO search - * - * @param server - * @param studyInstanceUid - * @returns {string} - */ -function buildUrl(server, studyInstanceUid) { - return server.wadoRoot + '/studies/' + studyInstanceUid + '/metadata'; -} - /** Returns a WADO url for an instance * * @param studyInstanceUid @@ -58,6 +50,7 @@ function buildUrl(server, studyInstanceUid) { * @returns {string} */ function buildInstanceWadoUrl(server, studyInstanceUid, seriesInstanceUid, sopInstanceUid) { + // TODO: This can be removed, since DICOMWebClient has the same function. Not urgent, though const params = []; params.push('requestType=WADO'); @@ -102,23 +95,47 @@ function getSourceImageInstanceUid(instance) { } function getPaletteColor(server, instance, tag, lutDescriptor) { - const lut = []; const numLutEntries = lutDescriptor[0]; const bits = lutDescriptor[2]; - const uri = WADOProxy.convertURL(instance[tag].BulkDataURI, server) - const bulkDataPromise = DICOMWeb.getBulkData(uri); - return bulkDataPromise.then(data => { - for (var i = 0; i < numLutEntries; i++) { - if(bits === 16) { - lut[i] = data[i * 65536] + data[i + 1]; + let uri = WADOProxy.convertURL(instance[tag].BulkDataURI, server) + + // TODO: Workaround for dcm4chee behind SSL-terminating proxy returning + // incorrect bulk data URIs + if (server.wadoRoot.indexOf('https') === 0 && + !uri.includes('https')) { + uri = uri.replace('http', 'https'); + } + + const config = { + url: server.wadoRoot, //BulkDataURI is absolute, so this isn't used + headers: OHIF.DICOMWeb.getAuthorizationHeader() + }; + const dicomWeb = new DICOMwebClient.api.DICOMwebClient(config); + const options = { + BulkDataURI: uri + }; + + const readUInt16 = (byteArray, position) => { + return byteArray[position] + (byteArray[position + 1] * 256); + } + + const arrayBufferToPaletteColorLUT = (arraybuffer) =>{ + const byteArray = new Uint8Array(arraybuffer); + const lut = []; + + for (let i = 0; i < numLutEntries; i++) { + if (bits === 16) { + lut[i] = readUInt16(byteArray, i * 2); } else { - lut[i] = data[i]; + lut[i] = byteArray[i]; } } return lut; - }) + } + + return dicomWeb.retrieveBulkData(options).then(arrayBufferToPaletteColorLUT) } /** @@ -129,13 +146,15 @@ function getPaletteColor(server, instance, tag, lutDescriptor) { * @returns {String} The ReferenceSOPInstanceUID */ async function getPaletteColors(server, instance, lutDescriptor) { - let entry = null; let paletteUID = DICOMWeb.getString(instance['00281199']); return new Promise((resolve, reject) => { if (paletteColorCache.isValidUID(paletteUID)) { - entry = paletteColorCache.get(paletteUID); - return resolve(entry); + const entry = paletteColorCache.get(paletteUID); + + if (entry) { + return resolve(entry); + } } // no entry in cache... Fetch remote data. @@ -146,7 +165,11 @@ async function getPaletteColors(server, instance, lutDescriptor) { const promises = [r, g, b]; Promise.all(promises).then((args) => { - entry = { red: r, green: g, blue: b }; + entry = { + red: args[0], + green: args[1], + blue: args[2] + }; // when paletteUID is present, the entry can be cached... entry.uid = paletteUID; @@ -202,9 +225,6 @@ function getRadiopharmaceuticalInfo(instance) { * @returns {{seriesList: Array, patientName: *, patientId: *, accessionNumber: *, studyDate: *, modalities: *, studyDescription: *, imageCount: *, studyInstanceUid: *}} */ async function resultDataToStudyMetadata(server, studyInstanceUid, resultData) { - const seriesMap = {}; - const seriesList = []; - if (!resultData.length) { return; } @@ -215,7 +235,9 @@ async function resultDataToStudyMetadata(server, studyInstanceUid, resultData) { } const studyData = { - seriesList, + seriesList: [], + studyInstanceUid, + wadoUriRoot: server.wadoUriRoot, patientName: DICOMWeb.getName(anInstance['00100010']), patientId: DICOMWeb.getString(anInstance['00100020']), patientAge: DICOMWeb.getNumber(anInstance['00101010']), @@ -230,9 +252,12 @@ async function resultDataToStudyMetadata(server, studyInstanceUid, resultData) { institutionName: DICOMWeb.getString(anInstance['00080080']) }; + const seriesMap = {}; + await Promise.all(resultData.map(async function(instance) { - var seriesInstanceUid = DICOMWeb.getString(instance['0020000E']); - var series = seriesMap[seriesInstanceUid]; + const seriesInstanceUid = DICOMWeb.getString(instance['0020000E']); + let series = seriesMap[seriesInstanceUid]; + if (!series) { series = { seriesDescription: DICOMWeb.getString(instance['0008103E']), @@ -244,7 +269,7 @@ async function resultDataToStudyMetadata(server, studyInstanceUid, resultData) { instances: [] }; seriesMap[seriesInstanceUid] = series; - seriesList.push(series); + studyData.seriesList.push(series); } const sopInstanceUid = DICOMWeb.getString(instance['00080018']); @@ -331,22 +356,23 @@ async function resultDataToStudyMetadata(server, studyInstanceUid, resultData) { } /** - * Retrieved Study MetaData from a DICOM server using a WADO call + * Retrieve Study MetaData from a DICOM server using a WADO call + * * @param server * @param studyInstanceUid * @returns {Promise} */ OHIF.studies.services.WADO.RetrieveMetadata = async function(server, studyInstanceUid) { - const url = buildUrl(server, studyInstanceUid); + const config = { + url: server.wadoRoot, + headers: OHIF.DICOMWeb.getAuthorizationHeader() + }; + const dicomWeb = new DICOMwebClient.api.DICOMwebClient(config); + const options = { + studyInstanceUID: studyInstanceUid + }; - return new Promise((resolve, reject) => { - DICOMWeb.getJSON(url, server.requestOptions).then(result => { - resultDataToStudyMetadata(server, studyInstanceUid, result).then((study) => { - study.wadoUriRoot = server.wadoUriRoot; - study.studyInstanceUid = studyInstanceUid; - - resolve(study); - }, reject); - }, reject); + return dicomWeb.retrieveStudyMetadata(options).then(result => { + return resultDataToStudyMetadata(server, studyInstanceUid, result); }); }; diff --git a/Packages/ohif-studies/package.js b/Packages/ohif-studies/package.js index ffab3eff3..69bae79c1 100644 --- a/Packages/ohif-studies/package.js +++ b/Packages/ohif-studies/package.js @@ -5,11 +5,13 @@ Package.describe({ }); Npm.depends({ - dimse: '0.0.2' -}) + dimse: '0.0.2', + 'dicomweb-client': '0.3.2', + 'xhr2': '0.1.4' +}); Package.onUse(function(api) { - api.versionsFrom('1.6'); + api.versionsFrom('1.7'); api.use([ 'ecmascript', @@ -24,7 +26,6 @@ Package.onUse(function(api) { 'ohif:core', 'ohif:log', 'ohif:servers', - 'ohif:dicomweb-client', 'ohif:viewerbase', 'ohif:wadoproxy' ]); diff --git a/Packages/ohif-study-list/client/components/studylist/studylistResult/studylistResult.js b/Packages/ohif-study-list/client/components/studylist/studylistResult/studylistResult.js index 43b15a52e..38b4743c7 100644 --- a/Packages/ohif-study-list/client/components/studylist/studylistResult/studylistResult.js +++ b/Packages/ohif-study-list/client/components/studylist/studylistResult/studylistResult.js @@ -15,7 +15,6 @@ Template.studylistResult.helpers({ */ studies() { const instance = Template.instance(); - let studies; let sortOption = { patientName: 1, studyDate: 1 @@ -32,7 +31,7 @@ Template.studylistResult.helpers({ const offset = rowsPerPage * currentPage; const limit = offset + rowsPerPage; - studies = OHIF.studylist.collections.Studies.find({}, { + const studies = OHIF.studylist.collections.Studies.find({}, { sort: sortOption }).fetch(); @@ -90,17 +89,6 @@ function getFilter(filter) { return filter; } -/** - * Search for a value in a string - */ -function isIndexOf(mainVal, searchVal) { - if (mainVal === undefined || mainVal === '' || mainVal.indexOf(searchVal) > -1){ - return true; - } - - return false; -} - /** * Replace object if undefined */ @@ -167,10 +155,21 @@ function search() { // Loop through all identified studies studies.forEach(study => { + // TODO: Why is this Modality filter different from QIDO? + if (modality !== "" && study.modalities.includes(modality)) { + return; + } + + // Sometimes DICOM studies have incorrect Date entries with + // periods such as '1990.10.04' + let studyDate = study.studyDate; + if (studyDate && studyDate.includes('.')) { + studyDate = studyDate.replace('.', ''); + } + // Search the rest of the parameters that aren't done via the server call - if (isIndexOf(study.modalities, modality) && - (new Date(studyDateFrom).setHours(0, 0, 0, 0) <= convertStringToStudyDate(study.studyDate) || !studyDateFrom || studyDateFrom === '') && - (convertStringToStudyDate(study.studyDate) <= new Date(studyDateTo).setHours(0, 0, 0, 0) || !studyDateTo || studyDateTo === '')) { + if ((new Date(studyDateFrom).setHours(0, 0, 0, 0) <= studyDate || !studyDateFrom ) && + (studyDate <= new Date(studyDateTo).setHours(0, 0, 0, 0) || !studyDateTo || studyDateTo === '')) { // Convert numberOfStudyRelatedInstance string into integer study.numberOfStudyRelatedInstances = !isNaN(study.numberOfStudyRelatedInstances) ? parseInt(study.numberOfStudyRelatedInstances) : undefined; diff --git a/Packages/ohif-study-list/package.js b/Packages/ohif-study-list/package.js index 9f789e59c..cfdcbfdd5 100644 --- a/Packages/ohif-study-list/package.js +++ b/Packages/ohif-study-list/package.js @@ -10,7 +10,7 @@ Package.describe({ }); Package.onUse(function(api) { - api.versionsFrom('1.4'); + api.versionsFrom('1.7'); api.use('ecmascript'); api.use('standard-app-packages'); diff --git a/Packages/ohif-themes-common/package.js b/Packages/ohif-themes-common/package.js index b8eb59f6e..2fb05c568 100644 --- a/Packages/ohif-themes-common/package.js +++ b/Packages/ohif-themes-common/package.js @@ -5,7 +5,7 @@ Package.describe({ }); Package.onUse(function(api) { - api.versionsFrom('1.4.2.3'); + api.versionsFrom('1.7'); api.use('ecmascript'); api.use('templating'); diff --git a/Packages/ohif-themes/package.js b/Packages/ohif-themes/package.js index 53b9805cc..be52f8bda 100644 --- a/Packages/ohif-themes/package.js +++ b/Packages/ohif-themes/package.js @@ -5,7 +5,7 @@ Package.describe({ }); Package.onUse(function(api) { - api.versionsFrom('1.4.2.3'); + api.versionsFrom('1.7'); api.use('stylus'); diff --git a/Packages/ohif-user-management/package.js b/Packages/ohif-user-management/package.js index bd7a6c296..901e0bc65 100644 --- a/Packages/ohif-user-management/package.js +++ b/Packages/ohif-user-management/package.js @@ -5,7 +5,7 @@ Package.describe({ }); Package.onUse(function(api) { - api.versionsFrom('1.4'); + api.versionsFrom('1.7'); api.use('ecmascript'); api.use('standard-app-packages'); diff --git a/Packages/ohif-viewerbase/package.js b/Packages/ohif-viewerbase/package.js index 416021dae..82e4dbc5b 100644 --- a/Packages/ohif-viewerbase/package.js +++ b/Packages/ohif-viewerbase/package.js @@ -5,7 +5,7 @@ Package.describe({ }); Package.onUse(function(api) { - api.versionsFrom('1.4'); + api.versionsFrom('1.7'); api.use(['ecmascript', 'standard-app-packages', @@ -218,7 +218,7 @@ Package.onUse(function(api) { }); Package.onTest(function(api) { - api.versionsFrom('1.4'); + api.versionsFrom('1.7'); /* * Really important dependencies to the project diff --git a/Packages/ohif-wadoproxy/package.js b/Packages/ohif-wadoproxy/package.js index 4ec4c1f0b..26e9fa51a 100755 --- a/Packages/ohif-wadoproxy/package.js +++ b/Packages/ohif-wadoproxy/package.js @@ -10,7 +10,7 @@ Npm.depends({ }); Package.onUse(function(api) { - api.versionsFrom('1.4'); + api.versionsFrom('1.7'); api.use('ecmascript'); api.use('clinical:router@2.0.19'); @@ -22,7 +22,7 @@ Package.onUse(function(api) { api.addFiles('both/convertURL.js', ['client', 'server']); api.addFiles('both/initialize.js', ['client', 'server']); api.addFiles('server/routes.js', 'server'); - + // Global exports api.export('WADOProxy'); }); diff --git a/StandaloneViewer/StandaloneViewer/.meteor/packages b/StandaloneViewer/StandaloneViewer/.meteor/packages index 588291bca..e34b01fa5 100644 --- a/StandaloneViewer/StandaloneViewer/.meteor/packages +++ b/StandaloneViewer/StandaloneViewer/.meteor/packages @@ -27,7 +27,6 @@ ohif:cornerstone-settings ohif:viewerbase ohif:metadata ohif:study-list -ohif:dicomweb-client ohif:measurement-table aldeed:template-extension diff --git a/StandaloneViewer/StandaloneViewer/.meteor/versions b/StandaloneViewer/StandaloneViewer/.meteor/versions index 96bdf2aad..f5b9647da 100644 --- a/StandaloneViewer/StandaloneViewer/.meteor/versions +++ b/StandaloneViewer/StandaloneViewer/.meteor/versions @@ -1,4 +1,3 @@ -accounts-base@1.4.2 aldeed:collection2@2.10.0 aldeed:collection2-core@1.2.0 aldeed:schema-deny@1.1.0 @@ -28,7 +27,6 @@ cultofcoders:persistent-session@0.4.5 ddp@1.4.0 ddp-client@2.3.3 ddp-common@1.4.0 -ddp-rate-limiter@1.0.7 ddp-server@2.2.0 deps@1.0.12 diff-sequence@1.1.0 @@ -54,7 +52,6 @@ iron:layout@1.0.12 jquery@1.11.11 launch-screen@1.1.1 livedata@1.0.18 -localstorage@1.2.0 logging@1.1.20 mdg:validation-error@0.5.1 meteor@1.9.2 @@ -81,7 +78,6 @@ ohif:core@0.0.1 ohif:cornerstone@0.0.1 ohif:cornerstone-settings@0.0.1 ohif:design@0.0.1 -ohif:dicomweb-client@0.0.1 ohif:hanging-protocols@0.0.1 ohif:header@0.0.1 ohif:hotkeys@0.0.1 @@ -102,13 +98,11 @@ ordered-dict@1.1.0 promise@0.11.1 raix:eventemitter@0.1.3 random@1.1.0 -rate-limit@1.0.9 reactive-dict@1.2.0 reactive-var@1.0.11 reload@1.2.0 retry@1.1.0 routepolicy@1.0.13 -service-configuration@1.0.11 session@1.1.7 shell-server@0.3.1 silentcicero:jszip@0.0.4 diff --git a/config/orthancDICOMWeb.json b/config/orthancDICOMWeb.json index 42ecf2060..5b899835d 100644 --- a/config/orthancDICOMWeb.json +++ b/config/orthancDICOMWeb.json @@ -6,7 +6,7 @@ "wadoUriRoot": "http://localhost:8042/wado", "qidoRoot": "http://localhost:8042/dicom-web", "wadoRoot": "http://localhost:8042/dicom-web", - "qidoSupportsIncludeField": false, + "qidoSupportsIncludeField": true, "imageRendering": "wadouri", "thumbnailRendering": "wadouri", "requestOptions": {