@ohif/app 3.8.0-beta.8 → 3.8.0-beta.80
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/{220.bundle.f7e1c96c94245e70f2be.js → 109.bundle.b4fee2a22b622839baf5.js} +4466 -3715
- package/dist/{471.bundle.49c8d281adbae4a2c4df.js → 121.bundle.787f5a848ed632a4d5fc.js} +90 -112
- package/dist/141.bundle.556b4c1e4cab770417ac.js +8620 -0
- package/dist/{687.bundle.9065db35c01823286f08.js → 164.bundle.d4598e491783753a8b6b.js} +22 -38
- package/dist/17dd54813d5acc10bf8f.wasm +0 -0
- package/dist/183.bundle.72bf18ad23ee6624986d.js +30394 -0
- package/dist/{506.bundle.5731bb4349e266491225.js → 188.bundle.b80554ec7df7dcd435a5.js} +23 -28
- package/dist/{342.bundle.e7c3d500f86fdfcc62b5.js → 206.bundle.f957e0d1cdff66dbac69.js} +1963 -1142
- package/dist/20fc4c659b85ccd2a9c0.wasm +0 -0
- package/dist/217.bundle.be1cc412f8e26be87d21.js +115079 -0
- package/dist/{451.bundle.57c21db5d003c75e9d61.js → 295.bundle.6f734abf8fa85b1a310d.js} +107 -127
- package/dist/{125.bundle.253395f320b72180da63.js → 297.bundle.194d8985ab974839b5b6.js} +7 -8
- package/dist/{19.bundle.f77c5787b6d8ac0b638b.js → 325.bundle.84909a08305556e9f924.js} +479 -371
- package/dist/335.bundle.c39d4aefe33aecab958f.js +2590 -0
- package/dist/{202.bundle.d3490836f71e001dd30f.js → 342.bundle.e6d0bba29351b5650a8c.js} +566 -868
- package/dist/{776.bundle.a2dedb405a12ffd7699b.js → 41.bundle.7c943bb857ed37831905.js} +7295 -3536
- package/dist/422.bundle.bd6529c536f59807fbee.js +881 -0
- package/dist/{957.bundle.9ea4506963ef8b2d84ba.js → 433.bundle.4c77c1fe8fc90ac14218.js} +14737 -27555
- package/dist/445.bundle.38c6d2af64e41cd7c614.js +7835 -0
- package/dist/{126.bundle.6e7111d58bcc937ffd80.js → 448.bundle.deedeff5744e77510734.js} +362 -430
- package/dist/487.bundle.7890ca42826941ebcd60.js +1875 -0
- package/dist/{886.bundle.c8dd3ecc42a4253de278.js → 530.bundle.7c94543955552475c56a.js} +98 -127
- package/dist/{663.bundle.d7be28450db14266cdd0.js → 540.bundle.079d43a6717e95c24392.js} +225 -188
- package/dist/{250.bundle.aea3335667054bdefe36.js → 544.bundle.1c1f57118560046649c1.js} +37 -62
- package/dist/574.bundle.be075ac52fb52b442a8b.js +2641 -0
- package/dist/{181.css → 574.css} +1 -1
- package/dist/{410.bundle.15c855b0ff4a1a674fb8.js → 594.bundle.0b1165661dd638820082.js} +183 -221
- package/dist/{221.bundle.aef554202c58483cb34e.js → 633.bundle.c1658e76f104cbd14cab.js} +349 -552
- package/dist/{774.bundle.4b2dc46a35012b898e1a.js → 644.bundle.1e77691d2eeb96a423b0.js} +1852 -8945
- package/dist/699.bundle.4f01772e7ce6637de339.js +768 -0
- package/dist/702.bundle.963481fbf871984b646f.js +8426 -0
- package/dist/722.bundle.afab1fe6bfcd569130ac.js +1083 -0
- package/dist/{359.bundle.45ecb3d28e8c22142606.js → 724.bundle.e5794460c391ee9cba2c.js} +164 -259
- package/dist/{757.bundle.ec8301d8e70d2b990f65.js → 726.bundle.0b3d9277d22fe7e15b89.js} +512 -879
- package/dist/{530.bundle.a03b6f942ace3e1baa1e.js → 835.bundle.15aff0b7433bb0dd6d6d.js} +37 -30
- package/dist/{822.bundle.82cdc418f8f56da6060b.js → 862.bundle.c0ee6e1d4d97e1353213.js} +77 -96
- package/dist/{236.bundle.4e9924934a747afac132.js → 889.bundle.7858e4b7ca1a2b12b64f.js} +207 -199
- package/dist/{281.bundle.deb7492d143e7768d8bf.js → 905.bundle.170908fe660fc6b40649.js} +157 -124
- package/dist/{814.bundle.c8c951d20039b63b865a.js → 907.bundle.dee4e30420caf07caea6.js} +16 -30
- package/dist/{417.bundle.af0a207c29b109f84159.js → 931.bundle.d270a1fda9a2836c3cc5.js} +26 -26
- package/dist/{686.bundle.dccef1f36e4bc79bcc48.js → 939.bundle.9d93b2e47c52338747a2.js} +7 -8
- package/dist/94.bundle.c452d9b0645277c2cf4e.js +784 -0
- package/dist/{12.bundle.b5ca13e5363f170ecb3b.js → 961.bundle.aaaaaba0ec015a3b85d8.js} +20 -33
- package/dist/app-config.js +1 -0
- package/dist/{app.bundle.a978edc59b9d82f2eb22.js → app.bundle.6c090a2d6d3ccc97a81d.js} +183240 -87650
- package/dist/app.bundle.css +16 -13
- package/dist/assets/images/CT-AAA.png +0 -0
- package/dist/assets/images/CT-AAA2.png +0 -0
- package/dist/assets/images/CT-Air.png +0 -0
- package/dist/assets/images/CT-Bone.png +0 -0
- package/dist/assets/images/CT-Bones.png +0 -0
- package/dist/assets/images/CT-Cardiac.png +0 -0
- package/dist/assets/images/CT-Cardiac2.png +0 -0
- package/dist/assets/images/CT-Cardiac3.png +0 -0
- package/dist/assets/images/CT-Chest-Contrast-Enhanced.png +0 -0
- package/dist/assets/images/CT-Chest-Vessels.png +0 -0
- package/dist/assets/images/CT-Coronary-Arteries-2.png +0 -0
- package/dist/assets/images/CT-Coronary-Arteries-3.png +0 -0
- package/dist/assets/images/CT-Coronary-Arteries.png +0 -0
- package/dist/assets/images/CT-Cropped-Volume-Bone.png +0 -0
- package/dist/assets/images/CT-Fat.png +0 -0
- package/dist/assets/images/CT-Liver-Vasculature.png +0 -0
- package/dist/assets/images/CT-Lung.png +0 -0
- package/dist/assets/images/CT-MIP.png +0 -0
- package/dist/assets/images/CT-Muscle.png +0 -0
- package/dist/assets/images/CT-Pulmonary-Arteries.png +0 -0
- package/dist/assets/images/CT-Soft-Tissue.png +0 -0
- package/dist/assets/images/DTI-FA-Brain.png +0 -0
- package/dist/assets/images/MR-Angio.png +0 -0
- package/dist/assets/images/MR-Default.png +0 -0
- package/dist/assets/images/MR-MIP.png +0 -0
- package/dist/assets/images/MR-T2-Brain.png +0 -0
- package/dist/assets/images/VolumeRendering.png +0 -0
- package/dist/cornerstoneDICOMImageLoader.min.js +1 -1
- package/dist/cornerstoneDICOMImageLoader.min.js.map +1 -1
- package/dist/{dicom-microscopy-viewer.bundle.2c146384eb9466d02ff8.js → dicom-microscopy-viewer.bundle.d3a56dc9f62df5e11019.js} +3 -3
- package/dist/histogram-worker.bundle.829e14ec12c2b41a4323.js +359 -0
- package/dist/index.html +1 -1
- package/dist/{index.worker.e62ecca63f1a2e124230.worker.js → index.worker.64c896c4316fcd506666.worker.js} +2 -2
- package/dist/index.worker.64c896c4316fcd506666.worker.js.map +1 -0
- package/dist/polySeg.bundle.63011312c3c79e717ea9.js +249 -0
- package/dist/serve.json +12 -0
- package/dist/sw.js +1 -1
- package/package.json +26 -22
- package/dist/181.bundle.a62b9f0ec692299acb35.js +0 -1527
- package/dist/23.bundle.e008ad788170f2ed5569.js +0 -900
- package/dist/604.bundle.a51f83e64004bca5f497.js +0 -1848
- package/dist/613.bundle.9e7072e5b575354fe51e.js +0 -532
- package/dist/743.bundle.489f7df3a089d4d374e1.js +0 -78007
- package/dist/75788f12450d4c5ed494.wasm +0 -0
- package/dist/775.bundle.2285e7e0e67878948c0d.js +0 -1009
- package/dist/788.bundle.207ac23c0dfa70cbe3fb.js +0 -2682
- package/dist/82.bundle.d6fdcca0f67540bb226a.js +0 -1049
- package/dist/index.worker.e62ecca63f1a2e124230.worker.js.map +0 -1
- /package/dist/{19.css → 325.css} +0 -0
- /package/dist/{776.css → 41.css} +0 -0
- /package/dist/{579.css → 481.css} +0 -0
- /package/dist/{250.css → 544.css} +0 -0
- /package/dist/{221.css → 633.css} +0 -0
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
"use strict";
|
|
2
|
-
(
|
|
2
|
+
(globalThis["webpackChunk"] = globalThis["webpackChunk"] || []).push([[206],{
|
|
3
3
|
|
|
4
|
-
/***/
|
|
4
|
+
/***/ 7206:
|
|
5
5
|
/***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => {
|
|
6
6
|
|
|
7
7
|
// ESM COMPAT FLAG
|
|
@@ -11,6 +11,7 @@ __webpack_require__.r(__webpack_exports__);
|
|
|
11
11
|
__webpack_require__.d(__webpack_exports__, {
|
|
12
12
|
ContextMenuController: () => (/* reexport */ ContextMenuController),
|
|
13
13
|
CustomizableContextMenuTypes: () => (/* reexport */ types_namespaceObject),
|
|
14
|
+
StaticWadoClient: () => (/* reexport */ StaticWadoClient),
|
|
14
15
|
createReportAsync: () => (/* reexport */ Actions_createReportAsync),
|
|
15
16
|
createReportDialogPrompt: () => (/* reexport */ CreateReportDialogPrompt),
|
|
16
17
|
"default": () => (/* binding */ default_src),
|
|
@@ -30,11 +31,11 @@ __webpack_require__.d(utils_namespaceObject, {
|
|
|
30
31
|
});
|
|
31
32
|
|
|
32
33
|
// EXTERNAL MODULE: ../../../node_modules/dicomweb-client/build/dicomweb-client.es.js
|
|
33
|
-
var dicomweb_client_es = __webpack_require__(
|
|
34
|
-
// EXTERNAL MODULE: ../../core/src/index.ts +
|
|
35
|
-
var src = __webpack_require__(
|
|
34
|
+
var dicomweb_client_es = __webpack_require__(36922);
|
|
35
|
+
// EXTERNAL MODULE: ../../core/src/index.ts + 70 modules
|
|
36
|
+
var src = __webpack_require__(55411);
|
|
36
37
|
// EXTERNAL MODULE: ../../core/src/utils/sortStudy.ts
|
|
37
|
-
var sortStudy = __webpack_require__(
|
|
38
|
+
var sortStudy = __webpack_require__(45476);
|
|
38
39
|
;// CONCATENATED MODULE: ../../../extensions/default/src/DicomWebDataSource/qido.js
|
|
39
40
|
/**
|
|
40
41
|
* QIDO - Query based on ID for DICOM Objects
|
|
@@ -125,7 +126,7 @@ function processSeriesResults(qidoSeries) {
|
|
|
125
126
|
description: getString(qidoSeries['0008103E'])
|
|
126
127
|
}));
|
|
127
128
|
}
|
|
128
|
-
(0,sortStudy/* sortStudySeries */.
|
|
129
|
+
(0,sortStudy/* sortStudySeries */.LM)(series);
|
|
129
130
|
return series;
|
|
130
131
|
}
|
|
131
132
|
|
|
@@ -179,8 +180,7 @@ function searchStudies(server, filter) {
|
|
|
179
180
|
* @param serverSupportsQIDOIncludeField
|
|
180
181
|
* @returns {string} The URL with encoded filter query data
|
|
181
182
|
*/
|
|
182
|
-
function mapParams(params) {
|
|
183
|
-
let options = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : {};
|
|
183
|
+
function mapParams(params, options = {}) {
|
|
184
184
|
if (!params) {
|
|
185
185
|
return;
|
|
186
186
|
}
|
|
@@ -354,13 +354,12 @@ function buildInstanceWadoUrl(config, instance) {
|
|
|
354
354
|
* @param thumbnail
|
|
355
355
|
* @returns {string} The imageId to be used by Cornerstone
|
|
356
356
|
*/
|
|
357
|
-
function getImageId(
|
|
358
|
-
|
|
359
|
-
|
|
360
|
-
|
|
361
|
-
|
|
362
|
-
|
|
363
|
-
} = _ref;
|
|
357
|
+
function getImageId({
|
|
358
|
+
instance,
|
|
359
|
+
frame,
|
|
360
|
+
config,
|
|
361
|
+
thumbnail = false
|
|
362
|
+
}) {
|
|
364
363
|
if (!instance) {
|
|
365
364
|
return;
|
|
366
365
|
}
|
|
@@ -380,7 +379,7 @@ function getImageId(_ref) {
|
|
|
380
379
|
}
|
|
381
380
|
}
|
|
382
381
|
// EXTERNAL MODULE: ../../../node_modules/dcmjs/build/dcmjs.es.js
|
|
383
|
-
var dcmjs_es = __webpack_require__(
|
|
382
|
+
var dcmjs_es = __webpack_require__(31426);
|
|
384
383
|
;// CONCATENATED MODULE: ../../../extensions/default/src/DicomWebDataSource/wado/retrieveMetadataLoader.js
|
|
385
384
|
/**
|
|
386
385
|
* Class to define inheritance of load retrieve strategy.
|
|
@@ -395,13 +394,11 @@ class RetrieveMetadataLoader {
|
|
|
395
394
|
* @param {Object} client The dicomweb-client.
|
|
396
395
|
* @param {Array} studyInstanceUID Study instance ui to be retrieved
|
|
397
396
|
* @param {Object} [filters] - Object containing filters to be applied on retrieve metadata process
|
|
398
|
-
* @param {string} [
|
|
399
|
-
* @param {
|
|
397
|
+
* @param {string} [filters.seriesInstanceUID] - series instance uid to filter results against
|
|
398
|
+
* @param {Object} [sortCriteria] - Custom sort criteria used for series
|
|
399
|
+
* @param {Function} [sortFunction] - Custom sort function for series
|
|
400
400
|
*/
|
|
401
|
-
constructor(client, studyInstanceUID) {
|
|
402
|
-
let filters = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : {};
|
|
403
|
-
let sortCriteria = arguments.length > 3 ? arguments[3] : undefined;
|
|
404
|
-
let sortFunction = arguments.length > 4 ? arguments[4] : undefined;
|
|
401
|
+
constructor(client, studyInstanceUID, filters = {}, sortCriteria = undefined, sortFunction = undefined) {
|
|
405
402
|
this.client = client;
|
|
406
403
|
this.studyInstanceUID = studyInstanceUID;
|
|
407
404
|
this.filters = filters;
|
|
@@ -422,13 +419,9 @@ class RetrieveMetadataLoader {
|
|
|
422
419
|
async runLoaders(loaders) {
|
|
423
420
|
let result;
|
|
424
421
|
for (const loader of loaders) {
|
|
425
|
-
|
|
426
|
-
|
|
427
|
-
|
|
428
|
-
break; // closes iterator in case data is retrieved successfully
|
|
429
|
-
}
|
|
430
|
-
} catch (e) {
|
|
431
|
-
throw e;
|
|
422
|
+
result = await loader();
|
|
423
|
+
if (result && result.length) {
|
|
424
|
+
break; // closes iterator in case data is retrieved successfully
|
|
432
425
|
}
|
|
433
426
|
}
|
|
434
427
|
if (loaders.next().done && !result) {
|
|
@@ -511,11 +504,64 @@ class RetrieveMetadataLoaderSync extends RetrieveMetadataLoader {
|
|
|
511
504
|
|
|
512
505
|
|
|
513
506
|
|
|
507
|
+
// Series Date, Series Time, Series Description and Series Number to be included
|
|
508
|
+
// in the series metadata query result
|
|
509
|
+
const includeField = ['00080021', '00080031', '0008103E', '00200011'].join(',');
|
|
510
|
+
class DeferredPromise {
|
|
511
|
+
constructor() {
|
|
512
|
+
this.metadata = undefined;
|
|
513
|
+
this.processFunction = undefined;
|
|
514
|
+
this.internalPromise = undefined;
|
|
515
|
+
this.thenFunction = undefined;
|
|
516
|
+
this.rejectFunction = undefined;
|
|
517
|
+
}
|
|
518
|
+
setMetadata(metadata) {
|
|
519
|
+
this.metadata = metadata;
|
|
520
|
+
}
|
|
521
|
+
setProcessFunction(func) {
|
|
522
|
+
this.processFunction = func;
|
|
523
|
+
}
|
|
524
|
+
getPromise() {
|
|
525
|
+
return this.start();
|
|
526
|
+
}
|
|
527
|
+
start() {
|
|
528
|
+
if (this.internalPromise) {
|
|
529
|
+
return this.internalPromise;
|
|
530
|
+
}
|
|
531
|
+
this.internalPromise = this.processFunction();
|
|
532
|
+
// in case then and reject functions called before start
|
|
533
|
+
if (this.thenFunction) {
|
|
534
|
+
this.then(this.thenFunction);
|
|
535
|
+
this.thenFunction = undefined;
|
|
536
|
+
}
|
|
537
|
+
if (this.rejectFunction) {
|
|
538
|
+
this.reject(this.rejectFunction);
|
|
539
|
+
this.rejectFunction = undefined;
|
|
540
|
+
}
|
|
541
|
+
return this.internalPromise;
|
|
542
|
+
}
|
|
543
|
+
then(func) {
|
|
544
|
+
if (this.internalPromise) {
|
|
545
|
+
return this.internalPromise.then(func);
|
|
546
|
+
} else {
|
|
547
|
+
this.thenFunction = func;
|
|
548
|
+
}
|
|
549
|
+
}
|
|
550
|
+
reject(func) {
|
|
551
|
+
if (this.internalPromise) {
|
|
552
|
+
return this.internalPromise.reject(func);
|
|
553
|
+
} else {
|
|
554
|
+
this.rejectFunction = func;
|
|
555
|
+
}
|
|
556
|
+
}
|
|
557
|
+
}
|
|
514
558
|
/**
|
|
515
|
-
* Creates an immutable series loader object which loads each series sequentially using the iterator interface
|
|
559
|
+
* Creates an immutable series loader object which loads each series sequentially using the iterator interface.
|
|
560
|
+
*
|
|
516
561
|
* @param {DICOMWebClient} dicomWebClient The DICOMWebClient instance to be used for series load
|
|
517
562
|
* @param {string} studyInstanceUID The Study Instance UID from which series will be loaded
|
|
518
563
|
* @param {Array} seriesInstanceUIDList A list of Series Instance UIDs
|
|
564
|
+
*
|
|
519
565
|
* @returns {Object} Returns an object which supports loading of instances from each of given Series Instance UID
|
|
520
566
|
*/
|
|
521
567
|
function makeSeriesAsyncLoader(client, studyInstanceUID, seriesInstanceUIDList) {
|
|
@@ -523,12 +569,20 @@ function makeSeriesAsyncLoader(client, studyInstanceUID, seriesInstanceUIDList)
|
|
|
523
569
|
hasNext() {
|
|
524
570
|
return seriesInstanceUIDList.length > 0;
|
|
525
571
|
},
|
|
526
|
-
|
|
527
|
-
const
|
|
528
|
-
|
|
529
|
-
|
|
530
|
-
|
|
572
|
+
next() {
|
|
573
|
+
const {
|
|
574
|
+
seriesInstanceUID,
|
|
575
|
+
metadata
|
|
576
|
+
} = seriesInstanceUIDList.shift();
|
|
577
|
+
const promise = new DeferredPromise();
|
|
578
|
+
promise.setMetadata(metadata);
|
|
579
|
+
promise.setProcessFunction(() => {
|
|
580
|
+
return client.retrieveSeriesMetadata({
|
|
581
|
+
studyInstanceUID,
|
|
582
|
+
seriesInstanceUID
|
|
583
|
+
});
|
|
531
584
|
});
|
|
585
|
+
return promise;
|
|
532
586
|
}
|
|
533
587
|
});
|
|
534
588
|
}
|
|
@@ -552,19 +606,22 @@ class RetrieveMetadataLoaderAsync extends RetrieveMetadataLoader {
|
|
|
552
606
|
} = {},
|
|
553
607
|
client
|
|
554
608
|
} = this;
|
|
609
|
+
|
|
610
|
+
// asking to include Series Date, Series Time, Series Description
|
|
611
|
+
// and Series Number in the series metadata returned to better sort series
|
|
612
|
+
// in preLoad function
|
|
613
|
+
let options = {
|
|
614
|
+
studyInstanceUID,
|
|
615
|
+
queryParams: {
|
|
616
|
+
includefield: includeField
|
|
617
|
+
}
|
|
618
|
+
};
|
|
555
619
|
if (seriesInstanceUID) {
|
|
556
|
-
|
|
557
|
-
studyInstanceUID,
|
|
558
|
-
queryParams: {
|
|
559
|
-
SeriesInstanceUID: seriesInstanceUID
|
|
560
|
-
}
|
|
561
|
-
};
|
|
620
|
+
options.queryParams.SeriesInstanceUID = seriesInstanceUID;
|
|
562
621
|
preLoaders.push(client.searchForSeries.bind(client, options));
|
|
563
622
|
}
|
|
564
623
|
// Fallback preloader
|
|
565
|
-
preLoaders.push(client.searchForSeries.bind(client,
|
|
566
|
-
studyInstanceUID
|
|
567
|
-
}));
|
|
624
|
+
preLoaders.push(client.searchForSeries.bind(client, options));
|
|
568
625
|
yield* preLoaders;
|
|
569
626
|
}
|
|
570
627
|
async preLoad() {
|
|
@@ -574,31 +631,36 @@ class RetrieveMetadataLoaderAsync extends RetrieveMetadataLoader {
|
|
|
574
631
|
const sortFunction = this.sortFunction;
|
|
575
632
|
const {
|
|
576
633
|
naturalizeDataset
|
|
577
|
-
} = dcmjs_es
|
|
634
|
+
} = dcmjs_es/* default.data */.Ay.data.DicomMetaDictionary;
|
|
578
635
|
const naturalized = result.map(naturalizeDataset);
|
|
579
|
-
return (0,sortStudy/* sortStudySeries */.
|
|
636
|
+
return (0,sortStudy/* sortStudySeries */.LM)(naturalized, sortCriteria, sortFunction);
|
|
580
637
|
}
|
|
581
638
|
async load(preLoadData) {
|
|
582
639
|
const {
|
|
583
640
|
client,
|
|
584
641
|
studyInstanceUID
|
|
585
642
|
} = this;
|
|
586
|
-
const seriesInstanceUIDs = preLoadData.map(
|
|
643
|
+
const seriesInstanceUIDs = preLoadData.map(seriesMetadata => {
|
|
644
|
+
return {
|
|
645
|
+
seriesInstanceUID: seriesMetadata.SeriesInstanceUID,
|
|
646
|
+
metadata: seriesMetadata
|
|
647
|
+
};
|
|
648
|
+
});
|
|
587
649
|
const seriesAsyncLoader = makeSeriesAsyncLoader(client, studyInstanceUID, seriesInstanceUIDs);
|
|
588
650
|
const promises = [];
|
|
589
651
|
while (seriesAsyncLoader.hasNext()) {
|
|
590
|
-
|
|
652
|
+
const promise = seriesAsyncLoader.next();
|
|
653
|
+
promises.push(promise);
|
|
591
654
|
}
|
|
592
655
|
return {
|
|
593
656
|
preLoadData,
|
|
594
657
|
promises
|
|
595
658
|
};
|
|
596
659
|
}
|
|
597
|
-
async posLoad(
|
|
598
|
-
|
|
599
|
-
|
|
600
|
-
|
|
601
|
-
} = _ref;
|
|
660
|
+
async posLoad({
|
|
661
|
+
preLoadData,
|
|
662
|
+
promises
|
|
663
|
+
}) {
|
|
602
664
|
return {
|
|
603
665
|
preLoadData,
|
|
604
666
|
promises
|
|
@@ -613,40 +675,91 @@ class RetrieveMetadataLoaderAsync extends RetrieveMetadataLoader {
|
|
|
613
675
|
* Retrieve Study metadata from a DICOM server. If the server is configured to use lazy load, only the first series
|
|
614
676
|
* will be loaded and the property "studyLoader" will be set to let consumer load remaining series as needed.
|
|
615
677
|
*
|
|
616
|
-
* @param {
|
|
617
|
-
* @param {
|
|
618
|
-
* @param {
|
|
619
|
-
* @param {
|
|
620
|
-
* @
|
|
678
|
+
* @param {*} dicomWebClient The DICOMWebClient instance to be used for series load
|
|
679
|
+
* @param {*} StudyInstanceUID The UID of the Study to be retrieved
|
|
680
|
+
* @param {*} enableStudyLazyLoad Whether the study metadata should be loaded asynchronously
|
|
681
|
+
* @param {object} filters Object containing filters to be applied on retrieve metadata process
|
|
682
|
+
* @param {string} [filters.seriesInstanceUID] Series instance uid to filter results against
|
|
683
|
+
* @param {array} [filters.SeriesInstanceUIDs] Series instance uids to filter results against
|
|
684
|
+
* @param {function} [sortCriteria] Sort criteria function
|
|
685
|
+
* @param {function} [sortFunction] Sort function
|
|
686
|
+
*
|
|
687
|
+
* @returns {Promise} A promises that resolves the study descriptor object
|
|
621
688
|
*/
|
|
622
|
-
async function RetrieveMetadata(dicomWebClient,
|
|
623
|
-
let filters = arguments.length > 3 && arguments[3] !== undefined ? arguments[3] : {};
|
|
624
|
-
let sortCriteria = arguments.length > 4 ? arguments[4] : undefined;
|
|
625
|
-
let sortFunction = arguments.length > 5 ? arguments[5] : undefined;
|
|
689
|
+
async function RetrieveMetadata(dicomWebClient, StudyInstanceUID, enableStudyLazyLoad, filters = {}, sortCriteria, sortFunction) {
|
|
626
690
|
const RetrieveMetadataLoader = enableStudyLazyLoad !== false ? RetrieveMetadataLoaderAsync : RetrieveMetadataLoaderSync;
|
|
627
|
-
const retrieveMetadataLoader = new RetrieveMetadataLoader(dicomWebClient,
|
|
691
|
+
const retrieveMetadataLoader = new RetrieveMetadataLoader(dicomWebClient, StudyInstanceUID, filters, sortCriteria, sortFunction);
|
|
628
692
|
const data = await retrieveMetadataLoader.execLoad();
|
|
629
693
|
return data;
|
|
630
694
|
}
|
|
631
695
|
/* harmony default export */ const retrieveMetadata = (RetrieveMetadata);
|
|
696
|
+
;// CONCATENATED MODULE: ../../../extensions/default/src/DicomWebDataSource/utils/retrieveMetadataFiltered.js
|
|
697
|
+
|
|
698
|
+
|
|
699
|
+
/**
|
|
700
|
+
* Retrieve metadata filtered.
|
|
701
|
+
*
|
|
702
|
+
* @param {*} dicomWebClient The DICOMWebClient instance to be used for series load
|
|
703
|
+
* @param {*} StudyInstanceUID The UID of the Study to be retrieved
|
|
704
|
+
* @param {*} enableStudyLazyLoad Whether the study metadata should be loaded asynchronously
|
|
705
|
+
* @param {object} filters Object containing filters to be applied on retrieve metadata process
|
|
706
|
+
* @param {string} [filters.seriesInstanceUID] Series instance uid to filter results against
|
|
707
|
+
* @param {array} [filters.SeriesInstanceUIDs] Series instance uids to filter results against
|
|
708
|
+
* @param {function} [sortCriteria] Sort criteria function
|
|
709
|
+
* @param {function} [sortFunction] Sort function
|
|
710
|
+
*
|
|
711
|
+
* @returns
|
|
712
|
+
*/
|
|
713
|
+
function retrieveMetadataFiltered(dicomWebClient, StudyInstanceUID, enableStudyLazyLoad, filters, sortCriteria, sortFunction) {
|
|
714
|
+
const {
|
|
715
|
+
SeriesInstanceUIDs
|
|
716
|
+
} = filters;
|
|
717
|
+
return new Promise((resolve, reject) => {
|
|
718
|
+
const promises = SeriesInstanceUIDs.map(uid => {
|
|
719
|
+
const seriesSpecificFilters = Object.assign({}, filters, {
|
|
720
|
+
seriesInstanceUID: uid
|
|
721
|
+
});
|
|
722
|
+
return retrieveMetadata(dicomWebClient, StudyInstanceUID, enableStudyLazyLoad, seriesSpecificFilters, sortCriteria, sortFunction);
|
|
723
|
+
});
|
|
724
|
+
Promise.all(promises).then(results => {
|
|
725
|
+
const aggregatedResult = {
|
|
726
|
+
preLoadData: [],
|
|
727
|
+
promises: []
|
|
728
|
+
};
|
|
729
|
+
results.forEach(({
|
|
730
|
+
preLoadData,
|
|
731
|
+
promises
|
|
732
|
+
}) => {
|
|
733
|
+
aggregatedResult.preLoadData = aggregatedResult.preLoadData.concat(preLoadData);
|
|
734
|
+
aggregatedResult.promises = aggregatedResult.promises.concat(promises);
|
|
735
|
+
});
|
|
736
|
+
resolve(aggregatedResult);
|
|
737
|
+
}, reject);
|
|
738
|
+
});
|
|
739
|
+
}
|
|
740
|
+
/* harmony default export */ const utils_retrieveMetadataFiltered = (retrieveMetadataFiltered);
|
|
632
741
|
;// CONCATENATED MODULE: ../../../extensions/default/src/DicomWebDataSource/retrieveStudyMetadata.js
|
|
633
742
|
|
|
743
|
+
|
|
634
744
|
const moduleName = 'RetrieveStudyMetadata';
|
|
635
745
|
// Cache for promises. Prevents unnecessary subsequent calls to the server
|
|
636
746
|
const StudyMetaDataPromises = new Map();
|
|
637
747
|
|
|
638
748
|
/**
|
|
639
|
-
* Retrieves study metadata
|
|
749
|
+
* Retrieves study metadata.
|
|
640
750
|
*
|
|
641
|
-
* @param {Object}
|
|
751
|
+
* @param {Object} dicomWebClient The DICOMWebClient instance to be used for series load
|
|
642
752
|
* @param {string} StudyInstanceUID The UID of the Study to be retrieved
|
|
643
|
-
* @param {boolean}
|
|
644
|
-
* @param {
|
|
645
|
-
* @param {
|
|
646
|
-
* @param {
|
|
753
|
+
* @param {boolean} enableStudyLazyLoad Whether the study metadata should be loaded asynchronously.
|
|
754
|
+
* @param {Object} [filters] Object containing filters to be applied on retrieve metadata process
|
|
755
|
+
* @param {string} [filters.seriesInstanceUID] Series instance uid to filter results against
|
|
756
|
+
* @param {array} [filters.SeriesInstanceUIDs] Series instance uids to filter results against
|
|
757
|
+
* @param {function} [sortCriteria] Sort criteria function
|
|
758
|
+
* @param {function} [sortFunction] Sort function
|
|
759
|
+
*
|
|
647
760
|
* @returns {Promise} that will be resolved with the metadata or rejected with the error
|
|
648
761
|
*/
|
|
649
|
-
function retrieveStudyMetadata(dicomWebClient, StudyInstanceUID, enableStudyLazyLoad, filters, sortCriteria, sortFunction) {
|
|
762
|
+
function retrieveStudyMetadata(dicomWebClient, StudyInstanceUID, enableStudyLazyLoad, filters, sortCriteria, sortFunction, dicomWebConfig = {}) {
|
|
650
763
|
// @TODO: Whenever a study metadata request has failed, its related promise will be rejected once and for all
|
|
651
764
|
// and further requests for that metadata will always fail. On failure, we probably need to remove the
|
|
652
765
|
// corresponding promise from the "StudyMetaDataPromises" map...
|
|
@@ -657,39 +770,157 @@ function retrieveStudyMetadata(dicomWebClient, StudyInstanceUID, enableStudyLazy
|
|
|
657
770
|
if (!StudyInstanceUID) {
|
|
658
771
|
throw new Error(`${moduleName}: Required 'StudyInstanceUID' parameter not provided.`);
|
|
659
772
|
}
|
|
773
|
+
const promiseId = `${dicomWebConfig.name}:${StudyInstanceUID}`;
|
|
660
774
|
|
|
661
775
|
// Already waiting on result? Return cached promise
|
|
662
|
-
if (StudyMetaDataPromises.has(
|
|
663
|
-
return StudyMetaDataPromises.get(
|
|
776
|
+
if (StudyMetaDataPromises.has(promiseId)) {
|
|
777
|
+
return StudyMetaDataPromises.get(promiseId);
|
|
778
|
+
}
|
|
779
|
+
let promise;
|
|
780
|
+
if (filters && filters.SeriesInstanceUIDs) {
|
|
781
|
+
promise = utils_retrieveMetadataFiltered(dicomWebClient, StudyInstanceUID, enableStudyLazyLoad, filters, sortCriteria, sortFunction);
|
|
782
|
+
} else {
|
|
783
|
+
// Create a promise to handle the data retrieval
|
|
784
|
+
promise = new Promise((resolve, reject) => {
|
|
785
|
+
retrieveMetadata(dicomWebClient, StudyInstanceUID, enableStudyLazyLoad, filters, sortCriteria, sortFunction).then(function (data) {
|
|
786
|
+
resolve(data);
|
|
787
|
+
}, reject);
|
|
788
|
+
});
|
|
664
789
|
}
|
|
665
|
-
|
|
666
|
-
// Create a promise to handle the data retrieval
|
|
667
|
-
const promise = new Promise((resolve, reject) => {
|
|
668
|
-
retrieveMetadata(dicomWebClient, StudyInstanceUID, enableStudyLazyLoad, filters, sortCriteria, sortFunction).then(function (data) {
|
|
669
|
-
resolve(data);
|
|
670
|
-
}, reject);
|
|
671
|
-
});
|
|
672
790
|
|
|
673
791
|
// Store the promise in cache
|
|
674
|
-
StudyMetaDataPromises.set(
|
|
792
|
+
StudyMetaDataPromises.set(promiseId, promise);
|
|
675
793
|
return promise;
|
|
676
794
|
}
|
|
677
795
|
|
|
678
796
|
/**
|
|
679
797
|
* Delete the cached study metadata retrieval promise to ensure that the browser will
|
|
680
|
-
* re-retrieve the study metadata when it is next requested
|
|
798
|
+
* re-retrieve the study metadata when it is next requested.
|
|
681
799
|
*
|
|
682
800
|
* @param {String} StudyInstanceUID The UID of the Study to be removed from cache
|
|
683
|
-
*
|
|
684
801
|
*/
|
|
685
802
|
function deleteStudyMetadataPromise(StudyInstanceUID) {
|
|
686
803
|
if (StudyMetaDataPromises.has(StudyInstanceUID)) {
|
|
687
804
|
StudyMetaDataPromises.delete(StudyInstanceUID);
|
|
688
805
|
}
|
|
689
806
|
}
|
|
807
|
+
;// CONCATENATED MODULE: ../../../extensions/default/src/DicomWebDataSource/utils/findIndexOfString.ts
|
|
808
|
+
function checkToken(token, data, dataOffset) {
|
|
809
|
+
if (dataOffset + token.length > data.length) {
|
|
810
|
+
return false;
|
|
811
|
+
}
|
|
812
|
+
let endIndex = dataOffset;
|
|
813
|
+
for (let i = 0; i < token.length; i++) {
|
|
814
|
+
if (token[i] !== data[endIndex++]) {
|
|
815
|
+
return false;
|
|
816
|
+
}
|
|
817
|
+
}
|
|
818
|
+
return true;
|
|
819
|
+
}
|
|
820
|
+
function stringToUint8Array(str) {
|
|
821
|
+
const uint = new Uint8Array(str.length);
|
|
822
|
+
for (let i = 0, j = str.length; i < j; i++) {
|
|
823
|
+
uint[i] = str.charCodeAt(i);
|
|
824
|
+
}
|
|
825
|
+
return uint;
|
|
826
|
+
}
|
|
827
|
+
function findIndexOfString(data, str, offset) {
|
|
828
|
+
offset = offset || 0;
|
|
829
|
+
const token = stringToUint8Array(str);
|
|
830
|
+
for (let i = offset; i < data.length; i++) {
|
|
831
|
+
if (token[0] === data[i]) {
|
|
832
|
+
// console.log('match @', i);
|
|
833
|
+
if (checkToken(token, data, i)) {
|
|
834
|
+
return i;
|
|
835
|
+
}
|
|
836
|
+
}
|
|
837
|
+
}
|
|
838
|
+
return -1;
|
|
839
|
+
}
|
|
840
|
+
/* harmony default export */ const utils_findIndexOfString = (findIndexOfString);
|
|
841
|
+
;// CONCATENATED MODULE: ../../../extensions/default/src/DicomWebDataSource/utils/fixMultipart.ts
|
|
842
|
+
|
|
843
|
+
|
|
844
|
+
/**
|
|
845
|
+
* Fix multipart data coming back from the retrieve bulkdata request, but
|
|
846
|
+
* incorrectly tagged as application/octet-stream. Some servers don't handle
|
|
847
|
+
* the response type correctly, and this method is relatively robust about
|
|
848
|
+
* detecting multipart data correctly. It will only extract one value.
|
|
849
|
+
*/
|
|
850
|
+
function fixMultipart(arrayData) {
|
|
851
|
+
const data = new Uint8Array(arrayData[0]);
|
|
852
|
+
// Don't know the exact minimum length, but it is at least 25 to encode multipart
|
|
853
|
+
if (data.length < 25) {
|
|
854
|
+
return arrayData;
|
|
855
|
+
}
|
|
856
|
+
const dashIndex = utils_findIndexOfString(data, '--');
|
|
857
|
+
if (dashIndex > 6) {
|
|
858
|
+
return arrayData;
|
|
859
|
+
}
|
|
860
|
+
const tokenIndex = utils_findIndexOfString(data, '\r\n\r\n', dashIndex);
|
|
861
|
+
if (tokenIndex > 512) {
|
|
862
|
+
// Allow for 512 characters in the header - there is no apriori limit, but
|
|
863
|
+
// this seems ok for now as we only expect it to have content type in it.
|
|
864
|
+
return arrayData;
|
|
865
|
+
}
|
|
866
|
+
const header = uint8ArrayToString(data, 0, tokenIndex);
|
|
867
|
+
// Now find the boundary marker
|
|
868
|
+
const responseHeaders = header.split('\r\n');
|
|
869
|
+
const boundary = findBoundary(responseHeaders);
|
|
870
|
+
if (!boundary) {
|
|
871
|
+
return arrayData;
|
|
872
|
+
}
|
|
873
|
+
// Start of actual data is 4 characters after the token
|
|
874
|
+
const offset = tokenIndex + 4;
|
|
875
|
+
const endIndex = utils_findIndexOfString(data, boundary, offset);
|
|
876
|
+
if (endIndex === -1) {
|
|
877
|
+
return arrayData;
|
|
878
|
+
}
|
|
879
|
+
return [data.slice(offset, endIndex - 2).buffer];
|
|
880
|
+
}
|
|
881
|
+
function findBoundary(header) {
|
|
882
|
+
for (let i = 0; i < header.length; i++) {
|
|
883
|
+
if (header[i].substr(0, 2) === '--') {
|
|
884
|
+
return header[i];
|
|
885
|
+
}
|
|
886
|
+
}
|
|
887
|
+
}
|
|
888
|
+
function findContentType(header) {
|
|
889
|
+
for (let i = 0; i < header.length; i++) {
|
|
890
|
+
if (header[i].substr(0, 13) === 'Content-Type:') {
|
|
891
|
+
return header[i].substr(13).trim();
|
|
892
|
+
}
|
|
893
|
+
}
|
|
894
|
+
}
|
|
895
|
+
function uint8ArrayToString(data, offset, length) {
|
|
896
|
+
offset = offset || 0;
|
|
897
|
+
length = length || data.length - offset;
|
|
898
|
+
let str = '';
|
|
899
|
+
for (let i = offset; i < offset + length; i++) {
|
|
900
|
+
str += String.fromCharCode(data[i]);
|
|
901
|
+
}
|
|
902
|
+
return str;
|
|
903
|
+
}
|
|
690
904
|
;// CONCATENATED MODULE: ../../../extensions/default/src/DicomWebDataSource/utils/StaticWadoClient.ts
|
|
691
905
|
|
|
692
906
|
|
|
907
|
+
const {
|
|
908
|
+
DICOMwebClient
|
|
909
|
+
} = dicomweb_client_es/* api */.FH;
|
|
910
|
+
const anyDicomwebClient = DICOMwebClient;
|
|
911
|
+
|
|
912
|
+
// Ugly over-ride, but the internals aren't otherwise accessible.
|
|
913
|
+
if (!anyDicomwebClient._orig_buildMultipartAcceptHeaderFieldValue) {
|
|
914
|
+
anyDicomwebClient._orig_buildMultipartAcceptHeaderFieldValue = anyDicomwebClient._buildMultipartAcceptHeaderFieldValue;
|
|
915
|
+
anyDicomwebClient._buildMultipartAcceptHeaderFieldValue = function (mediaTypes, acceptableTypes) {
|
|
916
|
+
if (mediaTypes.length === 1 && mediaTypes[0].mediaType.endsWith('/*')) {
|
|
917
|
+
return '*/*';
|
|
918
|
+
} else {
|
|
919
|
+
return anyDicomwebClient._orig_buildMultipartAcceptHeaderFieldValue(mediaTypes, acceptableTypes);
|
|
920
|
+
}
|
|
921
|
+
};
|
|
922
|
+
}
|
|
923
|
+
|
|
693
924
|
/**
|
|
694
925
|
* An implementation of the static wado client, that fetches data from
|
|
695
926
|
* a static response rather than actually doing real queries. This allows
|
|
@@ -697,10 +928,53 @@ function deleteStudyMetadataPromise(StudyInstanceUID) {
|
|
|
697
928
|
* performing searches doesn't work. This version fixes the query issue
|
|
698
929
|
* by manually implementing a query option.
|
|
699
930
|
*/
|
|
700
|
-
|
|
701
|
-
|
|
702
|
-
|
|
703
|
-
|
|
931
|
+
|
|
932
|
+
class StaticWadoClient extends dicomweb_client_es/* api */.FH.DICOMwebClient {
|
|
933
|
+
constructor(config) {
|
|
934
|
+
super(config);
|
|
935
|
+
this.config = void 0;
|
|
936
|
+
this.staticWado = void 0;
|
|
937
|
+
this.staticWado = config.staticWado;
|
|
938
|
+
this.config = config;
|
|
939
|
+
}
|
|
940
|
+
|
|
941
|
+
/**
|
|
942
|
+
* Handle improperly specified multipart/related return type.
|
|
943
|
+
* Note if the response is SUPPOSED to be multipart encoded already, then this
|
|
944
|
+
* will double-decode it.
|
|
945
|
+
*
|
|
946
|
+
* @param options
|
|
947
|
+
* @returns De-multiparted response data.
|
|
948
|
+
*
|
|
949
|
+
*/
|
|
950
|
+
retrieveBulkData(options) {
|
|
951
|
+
const shouldFixMultipart = this.config.fixBulkdataMultipart !== false;
|
|
952
|
+
const useOptions = {
|
|
953
|
+
...options
|
|
954
|
+
};
|
|
955
|
+
if (this.staticWado) {
|
|
956
|
+
useOptions.mediaTypes = [{
|
|
957
|
+
mediaType: 'application/*'
|
|
958
|
+
}];
|
|
959
|
+
}
|
|
960
|
+
return super.retrieveBulkData(useOptions).then(result => shouldFixMultipart ? fixMultipart(result) : result);
|
|
961
|
+
}
|
|
962
|
+
|
|
963
|
+
/**
|
|
964
|
+
* Retrieves instance frames using the image/* media type when configured
|
|
965
|
+
* to do so (static wado back end).
|
|
966
|
+
*/
|
|
967
|
+
retrieveInstanceFrames(options) {
|
|
968
|
+
if (this.staticWado) {
|
|
969
|
+
return super.retrieveInstanceFrames({
|
|
970
|
+
...options,
|
|
971
|
+
mediaTypes: [{
|
|
972
|
+
mediaType: 'image/*'
|
|
973
|
+
}]
|
|
974
|
+
});
|
|
975
|
+
} else {
|
|
976
|
+
return super.retrieveInstanceFrames(options);
|
|
977
|
+
}
|
|
704
978
|
}
|
|
705
979
|
|
|
706
980
|
/**
|
|
@@ -841,8 +1115,7 @@ class StaticWadoClient extends dicomweb_client_es.api.DICOMwebClient {
|
|
|
841
1115
|
/** Converts the query parameters to lower case query parameters */
|
|
842
1116
|
toLowerParams(queryParams) {
|
|
843
1117
|
const lowerParams = {};
|
|
844
|
-
Object.entries(queryParams).forEach(
|
|
845
|
-
let [key, value] = _ref;
|
|
1118
|
+
Object.entries(queryParams).forEach(([key, value]) => {
|
|
846
1119
|
lowerParams[key.toLowerCase()] = value;
|
|
847
1120
|
});
|
|
848
1121
|
return lowerParams;
|
|
@@ -875,6 +1148,7 @@ StaticWadoClient.seriesFilterKeys = {
|
|
|
875
1148
|
* @param {string} params.defaultType is the mime type of the response
|
|
876
1149
|
* @param {string} params.singlepart is the type of the part to retrieve
|
|
877
1150
|
* @param {string} params.fetchPart unknown?
|
|
1151
|
+
* @param {string} params.url unknown?
|
|
878
1152
|
* @returns an absolute URL to the resource, if the absolute URL can be retrieved as singlepart,
|
|
879
1153
|
* or is already retrieved, or a promise to a URL for such use if a BulkDataURI
|
|
880
1154
|
*/
|
|
@@ -888,8 +1162,12 @@ const getDirectURL = (config, params) => {
|
|
|
888
1162
|
tag = 'PixelData',
|
|
889
1163
|
defaultPath = '/pixeldata',
|
|
890
1164
|
defaultType = 'video/mp4',
|
|
891
|
-
singlepart: fetchPart = 'video'
|
|
1165
|
+
singlepart: fetchPart = 'video',
|
|
1166
|
+
url = null
|
|
892
1167
|
} = params;
|
|
1168
|
+
if (url) {
|
|
1169
|
+
return url;
|
|
1170
|
+
}
|
|
893
1171
|
const value = instance[tag];
|
|
894
1172
|
if (!value) {
|
|
895
1173
|
return undefined;
|
|
@@ -904,7 +1182,11 @@ const getDirectURL = (config, params) => {
|
|
|
904
1182
|
}
|
|
905
1183
|
if (!singlepart || singlepart !== true && singlepart.indexOf(fetchPart) === -1) {
|
|
906
1184
|
if (value.retrieveBulkData) {
|
|
907
|
-
|
|
1185
|
+
// Try the specified retrieve type.
|
|
1186
|
+
const options = {
|
|
1187
|
+
mediaType: defaultType
|
|
1188
|
+
};
|
|
1189
|
+
return value.retrieveBulkData(options).then(arr => {
|
|
908
1190
|
value.DirectRetrieveURL = URL.createObjectURL(new Blob([arr], {
|
|
909
1191
|
type: defaultType
|
|
910
1192
|
}));
|
|
@@ -995,7 +1277,7 @@ function fixBulkDataURI(value, instance, dicomWebConfig) {
|
|
|
995
1277
|
const {
|
|
996
1278
|
DicomMetaDictionary,
|
|
997
1279
|
DicomDict
|
|
998
|
-
} = dcmjs_es
|
|
1280
|
+
} = dcmjs_es/* default.data */.Ay.data;
|
|
999
1281
|
const {
|
|
1000
1282
|
naturalizeDataset,
|
|
1001
1283
|
denaturalizeDataset
|
|
@@ -1006,26 +1288,47 @@ const EXPLICIT_VR_LITTLE_ENDIAN = '1.2.840.10008.1.2.1';
|
|
|
1006
1288
|
const metadataProvider = src.classes.MetadataProvider;
|
|
1007
1289
|
|
|
1008
1290
|
/**
|
|
1291
|
+
* Creates a DICOM Web API based on the provided configuration.
|
|
1009
1292
|
*
|
|
1010
|
-
* @param {
|
|
1011
|
-
* @param {string}
|
|
1012
|
-
* @param {string}
|
|
1013
|
-
* @param {string}
|
|
1014
|
-
* @param {
|
|
1015
|
-
* @param {string}
|
|
1016
|
-
* @param {
|
|
1017
|
-
* @param {
|
|
1018
|
-
* @param {
|
|
1019
|
-
* @param {
|
|
1293
|
+
* @param {object} dicomWebConfig - Configuration for the DICOM Web API
|
|
1294
|
+
* @param {string} dicomWebConfig.name - Data source name
|
|
1295
|
+
* @param {string} dicomWebConfig.wadoUriRoot - Legacy? (potentially unused/replaced)
|
|
1296
|
+
* @param {string} dicomWebConfig.qidoRoot - Base URL to use for QIDO requests
|
|
1297
|
+
* @param {string} dicomWebConfig.wadoRoot - Base URL to use for WADO requests
|
|
1298
|
+
* @param {string} dicomWebConfig.wadoUri - Base URL to use for WADO URI requests
|
|
1299
|
+
* @param {boolean} dicomWebConfig.qidoSupportsIncludeField - Whether QIDO supports the "Include" option to request additional fields in response
|
|
1300
|
+
* @param {string} dicomWebConfig.imageRendering - wadors | ? (unsure of where/how this is used)
|
|
1301
|
+
* @param {string} dicomWebConfig.thumbnailRendering - wadors | ? (unsure of where/how this is used)
|
|
1302
|
+
* @param {boolean} dicomWebConfig.supportsReject - Whether the server supports reject calls (i.e. DCM4CHEE)
|
|
1303
|
+
* @param {boolean} dicomWebConfig.lazyLoadStudy - "enableStudyLazyLoad"; Request series meta async instead of blocking
|
|
1304
|
+
* @param {string|boolean} dicomWebConfig.singlepart - indicates if the retrieves can fetch singlepart. Options are bulkdata, video, image, or boolean true
|
|
1305
|
+
* @param {string} dicomWebConfig.requestTransferSyntaxUID - Transfer syntax to request from the server
|
|
1306
|
+
* @param {object} dicomWebConfig.acceptHeader - Accept header to use for requests
|
|
1307
|
+
* @param {boolean} dicomWebConfig.omitQuotationForMultipartRequest - Whether to omit quotation marks for multipart requests
|
|
1308
|
+
* @param {boolean} dicomWebConfig.supportsFuzzyMatching - Whether the server supports fuzzy matching
|
|
1309
|
+
* @param {boolean} dicomWebConfig.supportsWildcard - Whether the server supports wildcard matching
|
|
1310
|
+
* @param {boolean} dicomWebConfig.supportsNativeDICOMModel - Whether the server supports the native DICOM model
|
|
1311
|
+
* @param {boolean} dicomWebConfig.enableStudyLazyLoad - Whether to enable study lazy loading
|
|
1312
|
+
* @param {boolean} dicomWebConfig.enableRequestTag - Whether to enable request tag
|
|
1313
|
+
* @param {boolean} dicomWebConfig.enableStudyLazyLoad - Whether to enable study lazy loading
|
|
1314
|
+
* @param {boolean} dicomWebConfig.bulkDataURI - Whether to enable bulkDataURI
|
|
1315
|
+
* @param {function} dicomWebConfig.onConfiguration - Function that is called after the configuration is initialized
|
|
1316
|
+
* @param {boolean} dicomWebConfig.staticWado - Whether to use the static WADO client
|
|
1317
|
+
* @param {object} userAuthenticationService - User authentication service
|
|
1318
|
+
* @param {object} userAuthenticationService.getAuthorizationHeader - Function that returns the authorization header
|
|
1319
|
+
* @returns {object} - DICOM Web API object
|
|
1020
1320
|
*/
|
|
1021
|
-
function createDicomWebApi(dicomWebConfig,
|
|
1321
|
+
function createDicomWebApi(dicomWebConfig, servicesManager) {
|
|
1322
|
+
const {
|
|
1323
|
+
userAuthenticationService,
|
|
1324
|
+
customizationService
|
|
1325
|
+
} = servicesManager.services;
|
|
1022
1326
|
let dicomWebConfigCopy, qidoConfig, wadoConfig, qidoDicomWebClient, wadoDicomWebClient, getAuthrorizationHeader, generateWadoHeader;
|
|
1023
1327
|
const implementation = {
|
|
1024
|
-
initialize:
|
|
1025
|
-
|
|
1026
|
-
|
|
1027
|
-
|
|
1028
|
-
} = _ref;
|
|
1328
|
+
initialize: ({
|
|
1329
|
+
params,
|
|
1330
|
+
query
|
|
1331
|
+
}) => {
|
|
1029
1332
|
if (dicomWebConfig.onConfiguration && typeof dicomWebConfig.onConfiguration === 'function') {
|
|
1030
1333
|
dicomWebConfig = dicomWebConfig.onConfiguration(dicomWebConfig, {
|
|
1031
1334
|
params,
|
|
@@ -1055,20 +1358,20 @@ function createDicomWebApi(dicomWebConfig, userAuthenticationService) {
|
|
|
1055
1358
|
staticWado: dicomWebConfig.staticWado,
|
|
1056
1359
|
singlepart: dicomWebConfig.singlepart,
|
|
1057
1360
|
headers: userAuthenticationService.getAuthorizationHeader(),
|
|
1058
|
-
errorInterceptor: src/* errorHandler */.
|
|
1361
|
+
errorInterceptor: src/* errorHandler */.r_.getHTTPErrorHandler()
|
|
1059
1362
|
};
|
|
1060
1363
|
wadoConfig = {
|
|
1061
1364
|
url: dicomWebConfig.wadoRoot,
|
|
1062
1365
|
staticWado: dicomWebConfig.staticWado,
|
|
1063
1366
|
singlepart: dicomWebConfig.singlepart,
|
|
1064
1367
|
headers: userAuthenticationService.getAuthorizationHeader(),
|
|
1065
|
-
errorInterceptor: src/* errorHandler */.
|
|
1368
|
+
errorInterceptor: src/* errorHandler */.r_.getHTTPErrorHandler()
|
|
1066
1369
|
};
|
|
1067
1370
|
|
|
1068
1371
|
// TODO -> Two clients sucks, but its better than 1000.
|
|
1069
1372
|
// TODO -> We'll need to merge auth later.
|
|
1070
|
-
qidoDicomWebClient = dicomWebConfig.staticWado ? new StaticWadoClient(qidoConfig) : new dicomweb_client_es
|
|
1071
|
-
wadoDicomWebClient = dicomWebConfig.staticWado ? new StaticWadoClient(wadoConfig) : new dicomweb_client_es
|
|
1373
|
+
qidoDicomWebClient = dicomWebConfig.staticWado ? new StaticWadoClient(qidoConfig) : new dicomweb_client_es/* api */.FH.DICOMwebClient(qidoConfig);
|
|
1374
|
+
wadoDicomWebClient = dicomWebConfig.staticWado ? new StaticWadoClient(wadoConfig) : new dicomweb_client_es/* api */.FH.DICOMwebClient(wadoConfig);
|
|
1072
1375
|
},
|
|
1073
1376
|
query: {
|
|
1074
1377
|
studies: {
|
|
@@ -1097,11 +1400,10 @@ function createDicomWebApi(dicomWebConfig, userAuthenticationService) {
|
|
|
1097
1400
|
}
|
|
1098
1401
|
// processResults: processResults.bind(),
|
|
1099
1402
|
},
|
|
1100
|
-
|
|
1101
1403
|
instances: {
|
|
1102
1404
|
search: (studyInstanceUid, queryParameters) => {
|
|
1103
1405
|
qidoDicomWebClient.headers = getAuthrorizationHeader();
|
|
1104
|
-
search.call(undefined, qidoDicomWebClient, studyInstanceUid, null, queryParameters);
|
|
1406
|
+
return search.call(undefined, qidoDicomWebClient, studyInstanceUid, null, queryParameters);
|
|
1105
1407
|
}
|
|
1106
1408
|
}
|
|
1107
1409
|
},
|
|
@@ -1123,11 +1425,10 @@ function createDicomWebApi(dicomWebConfig, userAuthenticationService) {
|
|
|
1123
1425
|
singlepart: dicomWebConfig.singlepart
|
|
1124
1426
|
}, params);
|
|
1125
1427
|
},
|
|
1126
|
-
bulkDataURI: async
|
|
1127
|
-
|
|
1128
|
-
|
|
1129
|
-
|
|
1130
|
-
} = _ref2;
|
|
1428
|
+
bulkDataURI: async ({
|
|
1429
|
+
StudyInstanceUID,
|
|
1430
|
+
BulkDataURI
|
|
1431
|
+
}) => {
|
|
1131
1432
|
qidoDicomWebClient.headers = getAuthrorizationHeader();
|
|
1132
1433
|
const options = {
|
|
1133
1434
|
multipart: false,
|
|
@@ -1140,26 +1441,26 @@ function createDicomWebApi(dicomWebConfig, userAuthenticationService) {
|
|
|
1140
1441
|
});
|
|
1141
1442
|
},
|
|
1142
1443
|
series: {
|
|
1143
|
-
metadata: async
|
|
1144
|
-
|
|
1145
|
-
|
|
1146
|
-
|
|
1147
|
-
|
|
1148
|
-
|
|
1149
|
-
|
|
1150
|
-
|
|
1444
|
+
metadata: async ({
|
|
1445
|
+
StudyInstanceUID,
|
|
1446
|
+
filters,
|
|
1447
|
+
sortCriteria,
|
|
1448
|
+
sortFunction,
|
|
1449
|
+
madeInClient = false,
|
|
1450
|
+
returnPromises = false
|
|
1451
|
+
} = {}) => {
|
|
1151
1452
|
if (!StudyInstanceUID) {
|
|
1152
1453
|
throw new Error('Unable to query for SeriesMetadata without StudyInstanceUID');
|
|
1153
1454
|
}
|
|
1154
1455
|
if (dicomWebConfig.enableStudyLazyLoad) {
|
|
1155
|
-
return implementation._retrieveSeriesMetadataAsync(StudyInstanceUID, filters, sortCriteria, sortFunction, madeInClient);
|
|
1456
|
+
return implementation._retrieveSeriesMetadataAsync(StudyInstanceUID, filters, sortCriteria, sortFunction, madeInClient, returnPromises);
|
|
1156
1457
|
}
|
|
1157
1458
|
return implementation._retrieveSeriesMetadataSync(StudyInstanceUID, filters, sortCriteria, sortFunction, madeInClient);
|
|
1158
1459
|
}
|
|
1159
1460
|
}
|
|
1160
1461
|
},
|
|
1161
1462
|
store: {
|
|
1162
|
-
dicom: async (dataset, request) => {
|
|
1463
|
+
dicom: async (dataset, request, dicomDict) => {
|
|
1163
1464
|
wadoDicomWebClient.headers = getAuthrorizationHeader();
|
|
1164
1465
|
if (dataset instanceof ArrayBuffer) {
|
|
1165
1466
|
const options = {
|
|
@@ -1168,18 +1469,22 @@ function createDicomWebApi(dicomWebConfig, userAuthenticationService) {
|
|
|
1168
1469
|
};
|
|
1169
1470
|
await wadoDicomWebClient.storeInstances(options);
|
|
1170
1471
|
} else {
|
|
1171
|
-
|
|
1172
|
-
|
|
1173
|
-
|
|
1174
|
-
|
|
1175
|
-
|
|
1176
|
-
|
|
1177
|
-
|
|
1178
|
-
|
|
1179
|
-
|
|
1180
|
-
|
|
1181
|
-
|
|
1182
|
-
|
|
1472
|
+
let effectiveDicomDict = dicomDict;
|
|
1473
|
+
if (!dicomDict) {
|
|
1474
|
+
const meta = {
|
|
1475
|
+
FileMetaInformationVersion: dataset._meta?.FileMetaInformationVersion?.Value,
|
|
1476
|
+
MediaStorageSOPClassUID: dataset.SOPClassUID,
|
|
1477
|
+
MediaStorageSOPInstanceUID: dataset.SOPInstanceUID,
|
|
1478
|
+
TransferSyntaxUID: EXPLICIT_VR_LITTLE_ENDIAN,
|
|
1479
|
+
ImplementationClassUID,
|
|
1480
|
+
ImplementationVersionName
|
|
1481
|
+
};
|
|
1482
|
+
const denaturalized = denaturalizeDataset(meta);
|
|
1483
|
+
const defaultDicomDict = new DicomDict(denaturalized);
|
|
1484
|
+
defaultDicomDict.dict = denaturalizeDataset(dataset);
|
|
1485
|
+
effectiveDicomDict = defaultDicomDict;
|
|
1486
|
+
}
|
|
1487
|
+
const part10Buffer = effectiveDicomDict.write();
|
|
1183
1488
|
const options = {
|
|
1184
1489
|
datasets: [part10Buffer],
|
|
1185
1490
|
request
|
|
@@ -1192,7 +1497,7 @@ function createDicomWebApi(dicomWebConfig, userAuthenticationService) {
|
|
|
1192
1497
|
const enableStudyLazyLoad = false;
|
|
1193
1498
|
wadoDicomWebClient.headers = generateWadoHeader();
|
|
1194
1499
|
// data is all SOPInstanceUIDs
|
|
1195
|
-
const data = await retrieveStudyMetadata(wadoDicomWebClient, StudyInstanceUID, enableStudyLazyLoad, filters, sortCriteria, sortFunction);
|
|
1500
|
+
const data = await retrieveStudyMetadata(wadoDicomWebClient, StudyInstanceUID, enableStudyLazyLoad, filters, sortCriteria, sortFunction, dicomWebConfig);
|
|
1196
1501
|
|
|
1197
1502
|
// first naturalize the data
|
|
1198
1503
|
const naturalizedInstancesMetadata = data.map(naturalizeDataset);
|
|
@@ -1233,16 +1538,16 @@ function createDicomWebApi(dicomWebConfig, userAuthenticationService) {
|
|
|
1233
1538
|
const seriesMetadata = Object.values(seriesSummaryMetadata);
|
|
1234
1539
|
src.DicomMetadataStore.addSeriesMetadata(seriesMetadata, madeInClient);
|
|
1235
1540
|
Object.keys(instancesPerSeries).forEach(seriesInstanceUID => src.DicomMetadataStore.addInstances(instancesPerSeries[seriesInstanceUID], madeInClient));
|
|
1541
|
+
return seriesSummaryMetadata;
|
|
1236
1542
|
},
|
|
1237
|
-
_retrieveSeriesMetadataAsync: async
|
|
1238
|
-
let madeInClient = arguments.length > 4 && arguments[4] !== undefined ? arguments[4] : false;
|
|
1543
|
+
_retrieveSeriesMetadataAsync: async (StudyInstanceUID, filters, sortCriteria, sortFunction, madeInClient = false, returnPromises = false) => {
|
|
1239
1544
|
const enableStudyLazyLoad = true;
|
|
1240
1545
|
wadoDicomWebClient.headers = generateWadoHeader();
|
|
1241
1546
|
// Get Series
|
|
1242
1547
|
const {
|
|
1243
1548
|
preLoadData: seriesSummaryMetadata,
|
|
1244
1549
|
promises: seriesPromises
|
|
1245
|
-
} = await retrieveStudyMetadata(wadoDicomWebClient, StudyInstanceUID, enableStudyLazyLoad, filters, sortCriteria, sortFunction);
|
|
1550
|
+
} = await retrieveStudyMetadata(wadoDicomWebClient, StudyInstanceUID, enableStudyLazyLoad, filters, sortCriteria, sortFunction, dicomWebConfig);
|
|
1246
1551
|
|
|
1247
1552
|
/**
|
|
1248
1553
|
* naturalizes the dataset, and adds a retrieve bulkdata method
|
|
@@ -1264,10 +1569,13 @@ function createDicomWebApi(dicomWebConfig, userAuthenticationService) {
|
|
|
1264
1569
|
// in which case it isn't necessary to re-read this.
|
|
1265
1570
|
if (value && value.BulkDataURI && !value.Value) {
|
|
1266
1571
|
// Provide a method to fetch bulkdata
|
|
1267
|
-
value.retrieveBulkData = () => {
|
|
1572
|
+
value.retrieveBulkData = (options = {}) => {
|
|
1268
1573
|
// handle the scenarios where bulkDataURI is relative path
|
|
1269
1574
|
fixBulkDataURI(value, naturalized, dicomWebConfig);
|
|
1270
|
-
const
|
|
1575
|
+
const {
|
|
1576
|
+
mediaType
|
|
1577
|
+
} = options;
|
|
1578
|
+
const useOptions = {
|
|
1271
1579
|
// The bulkdata fetches work with either multipart or
|
|
1272
1580
|
// singlepart, so set multipart to false to let the server
|
|
1273
1581
|
// decide which type to respond with.
|
|
@@ -1277,10 +1585,16 @@ function createDicomWebApi(dicomWebConfig, userAuthenticationService) {
|
|
|
1277
1585
|
// is relative - that isn't disallowed by DICOMweb, but
|
|
1278
1586
|
// isn't well specified in the standard, but is needed in
|
|
1279
1587
|
// any implementation that stores static copies of the metadata
|
|
1280
|
-
StudyInstanceUID: naturalized.StudyInstanceUID
|
|
1588
|
+
StudyInstanceUID: naturalized.StudyInstanceUID,
|
|
1589
|
+
mediaTypes: mediaType ? [{
|
|
1590
|
+
mediaType
|
|
1591
|
+
}, {
|
|
1592
|
+
mediaType: 'application/octet-stream'
|
|
1593
|
+
}] : undefined,
|
|
1594
|
+
...options
|
|
1281
1595
|
};
|
|
1282
1596
|
// Todo: this needs to be from wado dicom web client
|
|
1283
|
-
return qidoDicomWebClient.retrieveBulkData(
|
|
1597
|
+
return qidoDicomWebClient.retrieveBulkData(useOptions).then(val => {
|
|
1284
1598
|
// There are DICOM PDF cases where the first ArrayBuffer in the array is
|
|
1285
1599
|
// the bulk data and DICOM video cases where the second ArrayBuffer is
|
|
1286
1600
|
// the bulk data. Here we play it safe and do a find.
|
|
@@ -1299,7 +1613,7 @@ function createDicomWebApi(dicomWebConfig, userAuthenticationService) {
|
|
|
1299
1613
|
const naturalizedInstances = instances.map(addRetrieveBulkData);
|
|
1300
1614
|
|
|
1301
1615
|
// Adding instanceMetadata to OHIF MetadataProvider
|
|
1302
|
-
naturalizedInstances.forEach(
|
|
1616
|
+
naturalizedInstances.forEach(instance => {
|
|
1303
1617
|
instance.wadoRoot = dicomWebConfig.wadoRoot;
|
|
1304
1618
|
instance.wadoUri = dicomWebConfig.wadoUri;
|
|
1305
1619
|
const imageId = implementation.getImageIdsForInstance({
|
|
@@ -1323,7 +1637,10 @@ function createDicomWebApi(dicomWebConfig, userAuthenticationService) {
|
|
|
1323
1637
|
src.DicomMetadataStore.addInstances(naturalizedInstances, madeInClient);
|
|
1324
1638
|
}
|
|
1325
1639
|
function setSuccessFlag() {
|
|
1326
|
-
const study = src.DicomMetadataStore.getStudy(StudyInstanceUID
|
|
1640
|
+
const study = src.DicomMetadataStore.getStudy(StudyInstanceUID);
|
|
1641
|
+
if (!study) {
|
|
1642
|
+
return;
|
|
1643
|
+
}
|
|
1327
1644
|
study.isLoaded = true;
|
|
1328
1645
|
}
|
|
1329
1646
|
|
|
@@ -1333,11 +1650,22 @@ function createDicomWebApi(dicomWebConfig, userAuthenticationService) {
|
|
|
1333
1650
|
aSeries.StudyInstanceUID = StudyInstanceUID;
|
|
1334
1651
|
});
|
|
1335
1652
|
src.DicomMetadataStore.addSeriesMetadata(seriesSummaryMetadata, madeInClient);
|
|
1336
|
-
const seriesDeliveredPromises = seriesPromises.map(promise =>
|
|
1337
|
-
|
|
1338
|
-
|
|
1339
|
-
|
|
1340
|
-
|
|
1653
|
+
const seriesDeliveredPromises = seriesPromises.map(promise => {
|
|
1654
|
+
if (!returnPromises) {
|
|
1655
|
+
promise?.start();
|
|
1656
|
+
}
|
|
1657
|
+
return promise.then(instances => {
|
|
1658
|
+
storeInstances(instances);
|
|
1659
|
+
});
|
|
1660
|
+
});
|
|
1661
|
+
if (returnPromises) {
|
|
1662
|
+
Promise.all(seriesDeliveredPromises).then(() => setSuccessFlag());
|
|
1663
|
+
return seriesPromises;
|
|
1664
|
+
} else {
|
|
1665
|
+
await Promise.all(seriesDeliveredPromises);
|
|
1666
|
+
setSuccessFlag();
|
|
1667
|
+
}
|
|
1668
|
+
return seriesSummaryMetadata;
|
|
1341
1669
|
},
|
|
1342
1670
|
deleteStudyMetadataPromise: deleteStudyMetadataPromise,
|
|
1343
1671
|
getImageIdsForDisplaySet(displaySet) {
|
|
@@ -1365,11 +1693,10 @@ function createDicomWebApi(dicomWebConfig, userAuthenticationService) {
|
|
|
1365
1693
|
});
|
|
1366
1694
|
return imageIds;
|
|
1367
1695
|
},
|
|
1368
|
-
getImageIdsForInstance(
|
|
1369
|
-
|
|
1370
|
-
|
|
1371
|
-
|
|
1372
|
-
} = _ref3;
|
|
1696
|
+
getImageIdsForInstance({
|
|
1697
|
+
instance,
|
|
1698
|
+
frame = undefined
|
|
1699
|
+
}) {
|
|
1373
1700
|
const imageIds = getImageId({
|
|
1374
1701
|
instance,
|
|
1375
1702
|
frame,
|
|
@@ -1380,11 +1707,10 @@ function createDicomWebApi(dicomWebConfig, userAuthenticationService) {
|
|
|
1380
1707
|
getConfig() {
|
|
1381
1708
|
return dicomWebConfigCopy;
|
|
1382
1709
|
},
|
|
1383
|
-
getStudyInstanceUIDs(
|
|
1384
|
-
|
|
1385
|
-
|
|
1386
|
-
|
|
1387
|
-
} = _ref4;
|
|
1710
|
+
getStudyInstanceUIDs({
|
|
1711
|
+
params,
|
|
1712
|
+
query
|
|
1713
|
+
}) {
|
|
1388
1714
|
const {
|
|
1389
1715
|
StudyInstanceUIDs: paramsStudyInstanceUIDs
|
|
1390
1716
|
} = params;
|
|
@@ -1397,7 +1723,7 @@ function createDicomWebApi(dicomWebConfig, userAuthenticationService) {
|
|
|
1397
1723
|
if (dicomWebConfig.supportsReject) {
|
|
1398
1724
|
implementation.reject = dcm4cheeReject(dicomWebConfig.wadoRoot);
|
|
1399
1725
|
}
|
|
1400
|
-
return src/* IWebApiDataSource */.
|
|
1726
|
+
return src/* IWebApiDataSource */.pt.create(implementation);
|
|
1401
1727
|
}
|
|
1402
1728
|
|
|
1403
1729
|
;// CONCATENATED MODULE: ../../../extensions/default/src/DicomJSONDataSource/index.js
|
|
@@ -1405,7 +1731,7 @@ function createDicomWebApi(dicomWebConfig, userAuthenticationService) {
|
|
|
1405
1731
|
|
|
1406
1732
|
|
|
1407
1733
|
|
|
1408
|
-
const DicomJSONDataSource_metadataProvider = src
|
|
1734
|
+
const DicomJSONDataSource_metadataProvider = src/* default.classes */.Ay.classes.MetadataProvider;
|
|
1409
1735
|
const mappings = {
|
|
1410
1736
|
studyInstanceUid: 'StudyInstanceUID',
|
|
1411
1737
|
patientId: 'PatientID'
|
|
@@ -1423,7 +1749,20 @@ let _store = {
|
|
|
1423
1749
|
// }
|
|
1424
1750
|
// }
|
|
1425
1751
|
};
|
|
1426
|
-
|
|
1752
|
+
function wrapSequences(obj) {
|
|
1753
|
+
return Object.keys(obj).reduce((acc, key) => {
|
|
1754
|
+
if (typeof obj[key] === 'object' && obj[key] !== null) {
|
|
1755
|
+
// Recursively wrap sequences for nested objects
|
|
1756
|
+
acc[key] = wrapSequences(obj[key]);
|
|
1757
|
+
} else {
|
|
1758
|
+
acc[key] = obj[key];
|
|
1759
|
+
}
|
|
1760
|
+
if (key.endsWith('Sequence')) {
|
|
1761
|
+
acc[key] = src/* default.utils */.Ay.utils.addAccessors(acc[key]);
|
|
1762
|
+
}
|
|
1763
|
+
return acc;
|
|
1764
|
+
}, Array.isArray(obj) ? [] : {});
|
|
1765
|
+
}
|
|
1427
1766
|
const getMetaDataByURL = url => {
|
|
1428
1767
|
return _store.urls.find(metaData => metaData.url === url);
|
|
1429
1768
|
};
|
|
@@ -1443,11 +1782,10 @@ function createDicomJSONApi(dicomJsonConfig) {
|
|
|
1443
1782
|
wadoRoot
|
|
1444
1783
|
} = dicomJsonConfig;
|
|
1445
1784
|
const implementation = {
|
|
1446
|
-
initialize: async
|
|
1447
|
-
|
|
1448
|
-
|
|
1449
|
-
|
|
1450
|
-
} = _ref;
|
|
1785
|
+
initialize: async ({
|
|
1786
|
+
query,
|
|
1787
|
+
url
|
|
1788
|
+
}) => {
|
|
1451
1789
|
if (!url) {
|
|
1452
1790
|
url = query.get('url');
|
|
1453
1791
|
}
|
|
@@ -1545,15 +1883,14 @@ function createDicomJSONApi(dicomJsonConfig) {
|
|
|
1545
1883
|
* or is already retrieved, or a promise to a URL for such use if a BulkDataURI
|
|
1546
1884
|
*/
|
|
1547
1885
|
directURL: params => {
|
|
1548
|
-
return utils_getDirectURL(
|
|
1886
|
+
return utils_getDirectURL(dicomJsonConfig, params);
|
|
1549
1887
|
},
|
|
1550
1888
|
series: {
|
|
1551
|
-
metadata: async
|
|
1552
|
-
|
|
1553
|
-
|
|
1554
|
-
|
|
1555
|
-
|
|
1556
|
-
} = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : {};
|
|
1889
|
+
metadata: async ({
|
|
1890
|
+
StudyInstanceUID,
|
|
1891
|
+
madeInClient = false,
|
|
1892
|
+
customSort
|
|
1893
|
+
} = {}) => {
|
|
1557
1894
|
if (!StudyInstanceUID) {
|
|
1558
1895
|
throw new Error('Unable to query for SeriesMetadata without StudyInstanceUID');
|
|
1559
1896
|
}
|
|
@@ -1585,8 +1922,13 @@ function createDicomJSONApi(dicomJsonConfig) {
|
|
|
1585
1922
|
const numberOfSeries = series.length;
|
|
1586
1923
|
series.forEach((series, index) => {
|
|
1587
1924
|
const instances = series.instances.map(instance => {
|
|
1925
|
+
// for instance.metadata if the key ends with sequence then
|
|
1926
|
+
// we need to add a proxy to the first item in the sequence
|
|
1927
|
+
// so that we can access the value of the sequence
|
|
1928
|
+
// by using sequenceName.value
|
|
1929
|
+
const modifiedMetadata = wrapSequences(instance.metadata);
|
|
1588
1930
|
const obj = {
|
|
1589
|
-
...
|
|
1931
|
+
...modifiedMetadata,
|
|
1590
1932
|
url: instance.url,
|
|
1591
1933
|
imageId: instance.url,
|
|
1592
1934
|
...series,
|
|
@@ -1636,34 +1978,32 @@ function createDicomJSONApi(dicomJsonConfig) {
|
|
|
1636
1978
|
});
|
|
1637
1979
|
return imageIds;
|
|
1638
1980
|
},
|
|
1639
|
-
getImageIdsForInstance(
|
|
1640
|
-
|
|
1641
|
-
|
|
1642
|
-
|
|
1643
|
-
} = _ref2;
|
|
1981
|
+
getImageIdsForInstance({
|
|
1982
|
+
instance,
|
|
1983
|
+
frame
|
|
1984
|
+
}) {
|
|
1644
1985
|
const imageIds = getImageId({
|
|
1645
1986
|
instance,
|
|
1646
1987
|
frame
|
|
1647
1988
|
});
|
|
1648
1989
|
return imageIds;
|
|
1649
1990
|
},
|
|
1650
|
-
getStudyInstanceUIDs:
|
|
1651
|
-
|
|
1652
|
-
|
|
1653
|
-
|
|
1654
|
-
} = _ref3;
|
|
1991
|
+
getStudyInstanceUIDs: ({
|
|
1992
|
+
params,
|
|
1993
|
+
query
|
|
1994
|
+
}) => {
|
|
1655
1995
|
const url = query.get('url');
|
|
1656
1996
|
return _store.studyInstanceUIDMap.get(url);
|
|
1657
1997
|
}
|
|
1658
1998
|
};
|
|
1659
|
-
return src/* IWebApiDataSource */.
|
|
1999
|
+
return src/* IWebApiDataSource */.pt.create(implementation);
|
|
1660
2000
|
}
|
|
1661
2001
|
|
|
1662
2002
|
;// CONCATENATED MODULE: ../../../extensions/default/src/DicomLocalDataSource/index.js
|
|
1663
2003
|
|
|
1664
2004
|
|
|
1665
2005
|
|
|
1666
|
-
const DicomLocalDataSource_metadataProvider = src
|
|
2006
|
+
const DicomLocalDataSource_metadataProvider = src/* default.classes */.Ay.classes.MetadataProvider;
|
|
1667
2007
|
const {
|
|
1668
2008
|
EVENTS
|
|
1669
2009
|
} = src.DicomMetadataStore;
|
|
@@ -1672,8 +2012,7 @@ const END_MODALITIES = {
|
|
|
1672
2012
|
SEG: true,
|
|
1673
2013
|
DOC: true
|
|
1674
2014
|
};
|
|
1675
|
-
const compareValue =
|
|
1676
|
-
let def = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : 0;
|
|
2015
|
+
const compareValue = (v1, v2, def = 0) => {
|
|
1677
2016
|
if (v1 === v2) {
|
|
1678
2017
|
return def;
|
|
1679
2018
|
}
|
|
@@ -1705,12 +2044,10 @@ function createDicomLocalApi(dicomLocalConfig) {
|
|
|
1705
2044
|
name
|
|
1706
2045
|
} = dicomLocalConfig;
|
|
1707
2046
|
const implementation = {
|
|
1708
|
-
initialize:
|
|
1709
|
-
|
|
1710
|
-
|
|
1711
|
-
|
|
1712
|
-
} = _ref;
|
|
1713
|
-
},
|
|
2047
|
+
initialize: ({
|
|
2048
|
+
params,
|
|
2049
|
+
query
|
|
2050
|
+
}) => {},
|
|
1714
2051
|
query: {
|
|
1715
2052
|
studies: {
|
|
1716
2053
|
mapParams: () => {},
|
|
@@ -1789,11 +2126,10 @@ function createDicomLocalApi(dicomLocalConfig) {
|
|
|
1789
2126
|
}
|
|
1790
2127
|
},
|
|
1791
2128
|
series: {
|
|
1792
|
-
metadata: async
|
|
1793
|
-
|
|
1794
|
-
|
|
1795
|
-
|
|
1796
|
-
} = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : {};
|
|
2129
|
+
metadata: async ({
|
|
2130
|
+
StudyInstanceUID,
|
|
2131
|
+
madeInClient = false
|
|
2132
|
+
} = {}) => {
|
|
1797
2133
|
if (!StudyInstanceUID) {
|
|
1798
2134
|
throw new Error('Unable to query for SeriesMetadata without StudyInstanceUID');
|
|
1799
2135
|
}
|
|
@@ -1839,7 +2175,7 @@ function createDicomLocalApi(dicomLocalConfig) {
|
|
|
1839
2175
|
},
|
|
1840
2176
|
store: {
|
|
1841
2177
|
dicom: naturalizedReport => {
|
|
1842
|
-
const reportBlob = dcmjs_es
|
|
2178
|
+
const reportBlob = dcmjs_es/* default.data */.Ay.data.datasetToBlob(naturalizedReport);
|
|
1843
2179
|
|
|
1844
2180
|
//Create a URL for the binary.
|
|
1845
2181
|
var objectUrl = URL.createObjectURL(reportBlob);
|
|
@@ -1872,11 +2208,10 @@ function createDicomLocalApi(dicomLocalConfig) {
|
|
|
1872
2208
|
});
|
|
1873
2209
|
return imageIds;
|
|
1874
2210
|
},
|
|
1875
|
-
getImageIdsForInstance(
|
|
1876
|
-
|
|
1877
|
-
|
|
1878
|
-
|
|
1879
|
-
} = _ref2;
|
|
2211
|
+
getImageIdsForInstance({
|
|
2212
|
+
instance,
|
|
2213
|
+
frame
|
|
2214
|
+
}) {
|
|
1880
2215
|
const {
|
|
1881
2216
|
StudyInstanceUID,
|
|
1882
2217
|
SeriesInstanceUID,
|
|
@@ -1892,11 +2227,10 @@ function createDicomLocalApi(dicomLocalConfig) {
|
|
|
1892
2227
|
deleteStudyMetadataPromise() {
|
|
1893
2228
|
console.log('deleteStudyMetadataPromise not implemented');
|
|
1894
2229
|
},
|
|
1895
|
-
getStudyInstanceUIDs:
|
|
1896
|
-
|
|
1897
|
-
|
|
1898
|
-
|
|
1899
|
-
} = _ref3;
|
|
2230
|
+
getStudyInstanceUIDs: ({
|
|
2231
|
+
params,
|
|
2232
|
+
query
|
|
2233
|
+
}) => {
|
|
1900
2234
|
const {
|
|
1901
2235
|
StudyInstanceUIDs: paramsStudyInstanceUIDs
|
|
1902
2236
|
} = params;
|
|
@@ -1916,7 +2250,7 @@ function createDicomLocalApi(dicomLocalConfig) {
|
|
|
1916
2250
|
return isStudyInCache ? StudyInstanceUIDsAsArray : [];
|
|
1917
2251
|
}
|
|
1918
2252
|
};
|
|
1919
|
-
return src/* IWebApiDataSource */.
|
|
2253
|
+
return src/* IWebApiDataSource */.pt.create(implementation);
|
|
1920
2254
|
}
|
|
1921
2255
|
|
|
1922
2256
|
;// CONCATENATED MODULE: ../../../extensions/default/src/DicomWebProxyDataSource/index.js
|
|
@@ -1931,17 +2265,16 @@ function createDicomLocalApi(dicomLocalConfig) {
|
|
|
1931
2265
|
* dicomWeb configuration array
|
|
1932
2266
|
*
|
|
1933
2267
|
*/
|
|
1934
|
-
function createDicomWebProxyApi(dicomWebProxyConfig,
|
|
2268
|
+
function createDicomWebProxyApi(dicomWebProxyConfig, servicesManager) {
|
|
1935
2269
|
const {
|
|
1936
2270
|
name
|
|
1937
2271
|
} = dicomWebProxyConfig;
|
|
1938
2272
|
let dicomWebDelegate = undefined;
|
|
1939
2273
|
const implementation = {
|
|
1940
|
-
initialize: async
|
|
1941
|
-
|
|
1942
|
-
|
|
1943
|
-
|
|
1944
|
-
} = _ref;
|
|
2274
|
+
initialize: async ({
|
|
2275
|
+
params,
|
|
2276
|
+
query
|
|
2277
|
+
}) => {
|
|
1945
2278
|
const url = query.get('url');
|
|
1946
2279
|
if (!url) {
|
|
1947
2280
|
throw new Error(`No url for '${name}'`);
|
|
@@ -1951,7 +2284,7 @@ function createDicomWebProxyApi(dicomWebProxyConfig, UserAuthenticationService)
|
|
|
1951
2284
|
if (!data.servers?.dicomWeb?.[0]) {
|
|
1952
2285
|
throw new Error('Invalid configuration returned by url');
|
|
1953
2286
|
}
|
|
1954
|
-
dicomWebDelegate = createDicomWebApi(data.servers.dicomWeb[0].configuration,
|
|
2287
|
+
dicomWebDelegate = createDicomWebApi(data.servers.dicomWeb[0].configuration, servicesManager);
|
|
1955
2288
|
dicomWebDelegate.initialize({
|
|
1956
2289
|
params,
|
|
1957
2290
|
query
|
|
@@ -1963,43 +2296,28 @@ function createDicomWebProxyApi(dicomWebProxyConfig, UserAuthenticationService)
|
|
|
1963
2296
|
search: params => dicomWebDelegate.query.studies.search(params)
|
|
1964
2297
|
},
|
|
1965
2298
|
series: {
|
|
1966
|
-
search:
|
|
1967
|
-
return dicomWebDelegate.query.series.search(...arguments);
|
|
1968
|
-
}
|
|
2299
|
+
search: (...args) => dicomWebDelegate.query.series.search(...args)
|
|
1969
2300
|
},
|
|
1970
2301
|
instances: {
|
|
1971
2302
|
search: (studyInstanceUid, queryParameters) => dicomWebDelegate.query.instances.search(studyInstanceUid, queryParameters)
|
|
1972
2303
|
}
|
|
1973
2304
|
},
|
|
1974
2305
|
retrieve: {
|
|
1975
|
-
directURL:
|
|
1976
|
-
return dicomWebDelegate.retrieve.directURL(...arguments);
|
|
1977
|
-
},
|
|
2306
|
+
directURL: (...args) => dicomWebDelegate.retrieve.directURL(...args),
|
|
1978
2307
|
series: {
|
|
1979
|
-
metadata: async
|
|
1980
|
-
return dicomWebDelegate.retrieve.series.metadata(...arguments);
|
|
1981
|
-
}
|
|
2308
|
+
metadata: async (...args) => dicomWebDelegate.retrieve.series.metadata(...args)
|
|
1982
2309
|
}
|
|
1983
2310
|
},
|
|
1984
2311
|
store: {
|
|
1985
|
-
dicom:
|
|
1986
|
-
return dicomWebDelegate.store(...arguments);
|
|
1987
|
-
}
|
|
1988
|
-
},
|
|
1989
|
-
deleteStudyMetadataPromise: function () {
|
|
1990
|
-
return dicomWebDelegate.deleteStudyMetadataPromise(...arguments);
|
|
1991
|
-
},
|
|
1992
|
-
getImageIdsForDisplaySet: function () {
|
|
1993
|
-
return dicomWebDelegate.getImageIdsForDisplaySet(...arguments);
|
|
2312
|
+
dicom: (...args) => dicomWebDelegate.store(...args)
|
|
1994
2313
|
},
|
|
1995
|
-
|
|
1996
|
-
|
|
1997
|
-
|
|
1998
|
-
getStudyInstanceUIDs(
|
|
1999
|
-
|
|
2000
|
-
|
|
2001
|
-
|
|
2002
|
-
} = _ref2;
|
|
2314
|
+
deleteStudyMetadataPromise: (...args) => dicomWebDelegate.deleteStudyMetadataPromise(...args),
|
|
2315
|
+
getImageIdsForDisplaySet: (...args) => dicomWebDelegate.getImageIdsForDisplaySet(...args),
|
|
2316
|
+
getImageIdsForInstance: (...args) => dicomWebDelegate.getImageIdsForInstance(...args),
|
|
2317
|
+
getStudyInstanceUIDs({
|
|
2318
|
+
params,
|
|
2319
|
+
query
|
|
2320
|
+
}) {
|
|
2003
2321
|
let studyInstanceUIDs = [];
|
|
2004
2322
|
|
|
2005
2323
|
// there seem to be a couple of variations of the case for this parameter
|
|
@@ -2011,7 +2329,278 @@ function createDicomWebProxyApi(dicomWebProxyConfig, UserAuthenticationService)
|
|
|
2011
2329
|
return studyInstanceUIDs;
|
|
2012
2330
|
}
|
|
2013
2331
|
};
|
|
2014
|
-
return src/* IWebApiDataSource */.
|
|
2332
|
+
return src/* IWebApiDataSource */.pt.create(implementation);
|
|
2333
|
+
}
|
|
2334
|
+
|
|
2335
|
+
// EXTERNAL MODULE: ../../../node_modules/lodash/lodash.js
|
|
2336
|
+
var lodash = __webpack_require__(5517);
|
|
2337
|
+
;// CONCATENATED MODULE: ../../../extensions/default/src/MergeDataSource/index.ts
|
|
2338
|
+
|
|
2339
|
+
|
|
2340
|
+
const mergeMap = {
|
|
2341
|
+
'query.studies.search': {
|
|
2342
|
+
mergeKey: 'studyInstanceUid',
|
|
2343
|
+
tagFunc: x => x
|
|
2344
|
+
},
|
|
2345
|
+
'query.series.search': {
|
|
2346
|
+
mergeKey: 'seriesInstanceUid',
|
|
2347
|
+
tagFunc: (series, sourceName) => {
|
|
2348
|
+
series.forEach(series => {
|
|
2349
|
+
series.RetrieveAETitle = sourceName;
|
|
2350
|
+
src.DicomMetadataStore.updateSeriesMetadata(series);
|
|
2351
|
+
});
|
|
2352
|
+
return series;
|
|
2353
|
+
}
|
|
2354
|
+
}
|
|
2355
|
+
};
|
|
2356
|
+
|
|
2357
|
+
/**
|
|
2358
|
+
* Calls all data sources asynchronously and merges the results.
|
|
2359
|
+
* @param {CallForAllDataSourcesAsyncOptions} options - The options for calling all data sources.
|
|
2360
|
+
* @param {string} options.path - The path to the function to be called on each data source.
|
|
2361
|
+
* @param {unknown[]} options.args - The arguments to be passed to the function.
|
|
2362
|
+
* @param {ExtensionManager} options.extensionManager - The extension manager.
|
|
2363
|
+
* @param {string[]} options.dataSourceNames - The names of the data sources to be called.
|
|
2364
|
+
* @param {string} options.defaultDataSourceName - The name of the default data source.
|
|
2365
|
+
* @returns {Promise<unknown[]>} - A promise that resolves to the merged data from all data sources.
|
|
2366
|
+
*/
|
|
2367
|
+
const callForAllDataSourcesAsync = async ({
|
|
2368
|
+
mergeMap,
|
|
2369
|
+
path,
|
|
2370
|
+
args,
|
|
2371
|
+
extensionManager,
|
|
2372
|
+
dataSourceNames,
|
|
2373
|
+
defaultDataSourceName
|
|
2374
|
+
}) => {
|
|
2375
|
+
const {
|
|
2376
|
+
mergeKey,
|
|
2377
|
+
tagFunc
|
|
2378
|
+
} = mergeMap[path] || {
|
|
2379
|
+
tagFunc: x => x
|
|
2380
|
+
};
|
|
2381
|
+
|
|
2382
|
+
/** Sort by default data source */
|
|
2383
|
+
const defs = Object.values(extensionManager.dataSourceDefs);
|
|
2384
|
+
const defaultDataSourceDef = defs.find(def => def.sourceName === defaultDataSourceName);
|
|
2385
|
+
const dataSourceDefs = defs.filter(def => def.sourceName !== defaultDataSourceName);
|
|
2386
|
+
if (defaultDataSourceDef) {
|
|
2387
|
+
dataSourceDefs.unshift(defaultDataSourceDef);
|
|
2388
|
+
}
|
|
2389
|
+
const promises = [];
|
|
2390
|
+
const sourceNames = [];
|
|
2391
|
+
for (const dataSourceDef of dataSourceDefs) {
|
|
2392
|
+
const {
|
|
2393
|
+
configuration,
|
|
2394
|
+
sourceName
|
|
2395
|
+
} = dataSourceDef;
|
|
2396
|
+
if (!!configuration && dataSourceNames.includes(sourceName)) {
|
|
2397
|
+
const [dataSource] = extensionManager.getDataSources(sourceName);
|
|
2398
|
+
const func = (0,lodash.get)(dataSource, path);
|
|
2399
|
+
const promise = func.apply(dataSource, args);
|
|
2400
|
+
promises.push(promise);
|
|
2401
|
+
sourceNames.push(sourceName);
|
|
2402
|
+
}
|
|
2403
|
+
}
|
|
2404
|
+
const data = await Promise.allSettled(promises);
|
|
2405
|
+
const mergedData = data.map((data, i) => tagFunc(data.value, sourceNames[i]));
|
|
2406
|
+
let results = [];
|
|
2407
|
+
if (mergeKey) {
|
|
2408
|
+
results = (0,lodash.uniqBy)(mergedData.flat(), obj => (0,lodash.get)(obj, mergeKey));
|
|
2409
|
+
} else {
|
|
2410
|
+
results = mergedData.flat();
|
|
2411
|
+
}
|
|
2412
|
+
return results;
|
|
2413
|
+
};
|
|
2414
|
+
|
|
2415
|
+
/**
|
|
2416
|
+
* Calls all data sources that match the provided names and merges their data.
|
|
2417
|
+
* @param options - The options for calling all data sources.
|
|
2418
|
+
* @param options.path - The path to the function to be called on each data source.
|
|
2419
|
+
* @param options.args - The arguments to be passed to the function.
|
|
2420
|
+
* @param options.extensionManager - The extension manager instance.
|
|
2421
|
+
* @param options.dataSourceNames - The names of the data sources to be called.
|
|
2422
|
+
* @param options.defaultDataSourceName - The name of the default data source.
|
|
2423
|
+
* @returns The merged data from all the matching data sources.
|
|
2424
|
+
*/
|
|
2425
|
+
const callForAllDataSources = ({
|
|
2426
|
+
path,
|
|
2427
|
+
args,
|
|
2428
|
+
extensionManager,
|
|
2429
|
+
dataSourceNames,
|
|
2430
|
+
defaultDataSourceName
|
|
2431
|
+
}) => {
|
|
2432
|
+
/** Sort by default data source */
|
|
2433
|
+
const defs = Object.values(extensionManager.dataSourceDefs);
|
|
2434
|
+
const defaultDataSourceDef = defs.find(def => def.sourceName === defaultDataSourceName);
|
|
2435
|
+
const dataSourceDefs = defs.filter(def => def.sourceName !== defaultDataSourceName);
|
|
2436
|
+
if (defaultDataSourceDef) {
|
|
2437
|
+
dataSourceDefs.unshift(defaultDataSourceDef);
|
|
2438
|
+
}
|
|
2439
|
+
const mergedData = [];
|
|
2440
|
+
for (const dataSourceDef of dataSourceDefs) {
|
|
2441
|
+
const {
|
|
2442
|
+
configuration,
|
|
2443
|
+
sourceName
|
|
2444
|
+
} = dataSourceDef;
|
|
2445
|
+
if (!!configuration && dataSourceNames.includes(sourceName)) {
|
|
2446
|
+
const [dataSource] = extensionManager.getDataSources(sourceName);
|
|
2447
|
+
const func = (0,lodash.get)(dataSource, path);
|
|
2448
|
+
const data = func.apply(dataSource, args);
|
|
2449
|
+
mergedData.push(data);
|
|
2450
|
+
}
|
|
2451
|
+
}
|
|
2452
|
+
return mergedData.flat();
|
|
2453
|
+
};
|
|
2454
|
+
|
|
2455
|
+
/**
|
|
2456
|
+
* Calls the default data source function specified by the given path with the provided arguments.
|
|
2457
|
+
* @param {CallForDefaultDataSourceOptions} options - The options for calling the default data source.
|
|
2458
|
+
* @param {string} options.path - The path to the function within the default data source.
|
|
2459
|
+
* @param {unknown[]} options.args - The arguments to pass to the function.
|
|
2460
|
+
* @param {string} options.defaultDataSourceName - The name of the default data source.
|
|
2461
|
+
* @param {ExtensionManager} options.extensionManager - The extension manager instance.
|
|
2462
|
+
* @returns {unknown} - The result of calling the default data source function.
|
|
2463
|
+
*/
|
|
2464
|
+
const callForDefaultDataSource = ({
|
|
2465
|
+
path,
|
|
2466
|
+
args,
|
|
2467
|
+
defaultDataSourceName,
|
|
2468
|
+
extensionManager
|
|
2469
|
+
}) => {
|
|
2470
|
+
const [dataSource] = extensionManager.getDataSources(defaultDataSourceName);
|
|
2471
|
+
const func = (0,lodash.get)(dataSource, path);
|
|
2472
|
+
return func.apply(dataSource, args);
|
|
2473
|
+
};
|
|
2474
|
+
|
|
2475
|
+
/**
|
|
2476
|
+
* Calls the data source specified by the RetrieveAETitle of the given display set.
|
|
2477
|
+
* @typedef {Object} CallByRetrieveAETitleOptions
|
|
2478
|
+
* @property {string} path - The path of the method to call on the data source.
|
|
2479
|
+
* @property {any[]} args - The arguments to pass to the method.
|
|
2480
|
+
* @property {string} defaultDataSourceName - The name of the default data source.
|
|
2481
|
+
* @property {ExtensionManager} extensionManager - The extension manager.
|
|
2482
|
+
*/
|
|
2483
|
+
const callByRetrieveAETitle = ({
|
|
2484
|
+
path,
|
|
2485
|
+
args,
|
|
2486
|
+
defaultDataSourceName,
|
|
2487
|
+
extensionManager
|
|
2488
|
+
}) => {
|
|
2489
|
+
const [displaySet] = args;
|
|
2490
|
+
const seriesMetadata = src.DicomMetadataStore.getSeries(displaySet.StudyInstanceUID, displaySet.SeriesInstanceUID);
|
|
2491
|
+
const [dataSource] = extensionManager.getDataSources(seriesMetadata.RetrieveAETitle || defaultDataSourceName);
|
|
2492
|
+
return dataSource[path](...args);
|
|
2493
|
+
};
|
|
2494
|
+
function createMergeDataSourceApi(mergeConfig, servicesManager, extensionManager) {
|
|
2495
|
+
const {
|
|
2496
|
+
seriesMerge
|
|
2497
|
+
} = mergeConfig;
|
|
2498
|
+
const {
|
|
2499
|
+
dataSourceNames,
|
|
2500
|
+
defaultDataSourceName
|
|
2501
|
+
} = seriesMerge;
|
|
2502
|
+
const implementation = {
|
|
2503
|
+
initialize: (...args) => callForAllDataSources({
|
|
2504
|
+
path: 'initialize',
|
|
2505
|
+
args,
|
|
2506
|
+
extensionManager,
|
|
2507
|
+
dataSourceNames,
|
|
2508
|
+
defaultDataSourceName
|
|
2509
|
+
}),
|
|
2510
|
+
query: {
|
|
2511
|
+
studies: {
|
|
2512
|
+
search: (...args) => callForAllDataSourcesAsync({
|
|
2513
|
+
mergeMap,
|
|
2514
|
+
path: 'query.studies.search',
|
|
2515
|
+
args,
|
|
2516
|
+
extensionManager,
|
|
2517
|
+
dataSourceNames,
|
|
2518
|
+
defaultDataSourceName
|
|
2519
|
+
})
|
|
2520
|
+
},
|
|
2521
|
+
series: {
|
|
2522
|
+
search: (...args) => callForAllDataSourcesAsync({
|
|
2523
|
+
mergeMap,
|
|
2524
|
+
path: 'query.series.search',
|
|
2525
|
+
args,
|
|
2526
|
+
extensionManager,
|
|
2527
|
+
dataSourceNames,
|
|
2528
|
+
defaultDataSourceName
|
|
2529
|
+
})
|
|
2530
|
+
},
|
|
2531
|
+
instances: {
|
|
2532
|
+
search: (...args) => callForAllDataSourcesAsync({
|
|
2533
|
+
mergeMap,
|
|
2534
|
+
path: 'query.instances.search',
|
|
2535
|
+
args,
|
|
2536
|
+
extensionManager,
|
|
2537
|
+
dataSourceNames,
|
|
2538
|
+
defaultDataSourceName
|
|
2539
|
+
})
|
|
2540
|
+
}
|
|
2541
|
+
},
|
|
2542
|
+
retrieve: {
|
|
2543
|
+
bulkDataURI: (...args) => callForAllDataSourcesAsync({
|
|
2544
|
+
mergeMap,
|
|
2545
|
+
path: 'retrieve.bulkDataURI',
|
|
2546
|
+
args,
|
|
2547
|
+
extensionManager,
|
|
2548
|
+
dataSourceNames,
|
|
2549
|
+
defaultDataSourceName
|
|
2550
|
+
}),
|
|
2551
|
+
directURL: (...args) => callForDefaultDataSource({
|
|
2552
|
+
path: 'retrieve.directURL',
|
|
2553
|
+
args,
|
|
2554
|
+
defaultDataSourceName,
|
|
2555
|
+
extensionManager
|
|
2556
|
+
}),
|
|
2557
|
+
series: {
|
|
2558
|
+
metadata: (...args) => callForAllDataSourcesAsync({
|
|
2559
|
+
mergeMap,
|
|
2560
|
+
path: 'retrieve.series.metadata',
|
|
2561
|
+
args,
|
|
2562
|
+
extensionManager,
|
|
2563
|
+
dataSourceNames,
|
|
2564
|
+
defaultDataSourceName
|
|
2565
|
+
})
|
|
2566
|
+
}
|
|
2567
|
+
},
|
|
2568
|
+
store: {
|
|
2569
|
+
dicom: (...args) => callForDefaultDataSource({
|
|
2570
|
+
path: 'store.dicom',
|
|
2571
|
+
args,
|
|
2572
|
+
defaultDataSourceName,
|
|
2573
|
+
extensionManager
|
|
2574
|
+
})
|
|
2575
|
+
},
|
|
2576
|
+
deleteStudyMetadataPromise: (...args) => callForAllDataSources({
|
|
2577
|
+
path: 'deleteStudyMetadataPromise',
|
|
2578
|
+
args,
|
|
2579
|
+
extensionManager,
|
|
2580
|
+
dataSourceNames,
|
|
2581
|
+
defaultDataSourceName
|
|
2582
|
+
}),
|
|
2583
|
+
getImageIdsForDisplaySet: (...args) => callByRetrieveAETitle({
|
|
2584
|
+
path: 'getImageIdsForDisplaySet',
|
|
2585
|
+
args,
|
|
2586
|
+
defaultDataSourceName,
|
|
2587
|
+
extensionManager
|
|
2588
|
+
}),
|
|
2589
|
+
getImageIdsForInstance: (...args) => callByRetrieveAETitle({
|
|
2590
|
+
path: 'getImageIdsForDisplaySet',
|
|
2591
|
+
args,
|
|
2592
|
+
defaultDataSourceName,
|
|
2593
|
+
extensionManager
|
|
2594
|
+
}),
|
|
2595
|
+
getStudyInstanceUIDs: (...args) => callForAllDataSources({
|
|
2596
|
+
path: 'getStudyInstanceUIDs',
|
|
2597
|
+
args,
|
|
2598
|
+
extensionManager,
|
|
2599
|
+
dataSourceNames,
|
|
2600
|
+
defaultDataSourceName
|
|
2601
|
+
})
|
|
2602
|
+
};
|
|
2603
|
+
return src/* IWebApiDataSource */.pt.create(implementation);
|
|
2015
2604
|
}
|
|
2016
2605
|
|
|
2017
2606
|
;// CONCATENATED MODULE: ../../../extensions/default/src/getDataSourcesModule.js
|
|
@@ -2024,6 +2613,7 @@ function createDicomWebProxyApi(dicomWebProxyConfig, UserAuthenticationService)
|
|
|
2024
2613
|
|
|
2025
2614
|
|
|
2026
2615
|
|
|
2616
|
+
|
|
2027
2617
|
/**
|
|
2028
2618
|
*
|
|
2029
2619
|
*/
|
|
@@ -2044,77 +2634,66 @@ function getDataSourcesModule() {
|
|
|
2044
2634
|
name: 'dicomlocal',
|
|
2045
2635
|
type: 'localApi',
|
|
2046
2636
|
createDataSource: createDicomLocalApi
|
|
2637
|
+
}, {
|
|
2638
|
+
name: 'merge',
|
|
2639
|
+
type: 'mergeApi',
|
|
2640
|
+
createDataSource: createMergeDataSourceApi
|
|
2047
2641
|
}];
|
|
2048
2642
|
}
|
|
2049
2643
|
/* harmony default export */ const src_getDataSourcesModule = (getDataSourcesModule);
|
|
2050
2644
|
// EXTERNAL MODULE: ../../../node_modules/react/index.js
|
|
2051
|
-
var react = __webpack_require__(
|
|
2645
|
+
var react = __webpack_require__(41766);
|
|
2052
2646
|
// EXTERNAL MODULE: ../../../node_modules/prop-types/index.js
|
|
2053
|
-
var prop_types = __webpack_require__(
|
|
2647
|
+
var prop_types = __webpack_require__(11374);
|
|
2054
2648
|
var prop_types_default = /*#__PURE__*/__webpack_require__.n(prop_types);
|
|
2055
|
-
// EXTERNAL MODULE: ../../ui/src/index.js +
|
|
2056
|
-
var ui_src = __webpack_require__(
|
|
2649
|
+
// EXTERNAL MODULE: ../../ui/src/index.js + 785 modules
|
|
2650
|
+
var ui_src = __webpack_require__(5085);
|
|
2057
2651
|
// EXTERNAL MODULE: ./state/index.js + 1 modules
|
|
2058
|
-
var state = __webpack_require__(
|
|
2652
|
+
var state = __webpack_require__(15575);
|
|
2059
2653
|
// EXTERNAL MODULE: ../node_modules/react-router-dom/dist/index.js
|
|
2060
|
-
var dist = __webpack_require__(
|
|
2654
|
+
var dist = __webpack_require__(37396);
|
|
2061
2655
|
// EXTERNAL MODULE: ../../../node_modules/react-i18next/dist/es/index.js + 15 modules
|
|
2062
|
-
var es = __webpack_require__(
|
|
2656
|
+
var es = __webpack_require__(80619);
|
|
2063
2657
|
// EXTERNAL MODULE: ../node_modules/react-router/dist/index.js
|
|
2064
|
-
var react_router_dist = __webpack_require__(
|
|
2065
|
-
// EXTERNAL MODULE: ../../i18n/src/index.js +
|
|
2066
|
-
var i18n_src = __webpack_require__(
|
|
2067
|
-
// EXTERNAL MODULE: ../../../node_modules/classnames/index.js
|
|
2068
|
-
var classnames = __webpack_require__(44921);
|
|
2069
|
-
var classnames_default = /*#__PURE__*/__webpack_require__.n(classnames);
|
|
2658
|
+
var react_router_dist = __webpack_require__(10971);
|
|
2659
|
+
// EXTERNAL MODULE: ../../i18n/src/index.js + 150 modules
|
|
2660
|
+
var i18n_src = __webpack_require__(912);
|
|
2070
2661
|
;// CONCATENATED MODULE: ../../../extensions/default/src/Toolbar/Toolbar.tsx
|
|
2071
2662
|
function _extends() { _extends = Object.assign ? Object.assign.bind() : function (target) { for (var i = 1; i < arguments.length; i++) { var source = arguments[i]; for (var key in source) { if (Object.prototype.hasOwnProperty.call(source, key)) { target[key] = source[key]; } } } return target; }; return _extends.apply(this, arguments); }
|
|
2072
2663
|
|
|
2073
2664
|
|
|
2074
|
-
|
|
2075
|
-
|
|
2076
|
-
|
|
2077
|
-
|
|
2078
|
-
} = _ref;
|
|
2665
|
+
function Toolbar({
|
|
2666
|
+
servicesManager,
|
|
2667
|
+
buttonSection = 'primary'
|
|
2668
|
+
}) {
|
|
2079
2669
|
const {
|
|
2080
|
-
|
|
2081
|
-
|
|
2082
|
-
|
|
2083
|
-
|
|
2084
|
-
|
|
2085
|
-
|
|
2086
|
-
|
|
2087
|
-
|
|
2088
|
-
|
|
2089
|
-
const {
|
|
2090
|
-
unsubscribe
|
|
2091
|
-
} = toolbarService.subscribe(toolbarService.EVENTS.TOOL_BAR_MODIFIED, updateToolbar);
|
|
2092
|
-
updateToolbar();
|
|
2093
|
-
return () => {
|
|
2094
|
-
unsubscribe();
|
|
2095
|
-
};
|
|
2096
|
-
}, [toolbarService, viewportGrid]);
|
|
2097
|
-
const onInteraction = (0,react.useCallback)(args => toolbarService.recordInteraction(args), [toolbarService]);
|
|
2670
|
+
toolbarButtons,
|
|
2671
|
+
onInteraction
|
|
2672
|
+
} = (0,src/* useToolbar */.tR)({
|
|
2673
|
+
servicesManager,
|
|
2674
|
+
buttonSection
|
|
2675
|
+
});
|
|
2676
|
+
if (!toolbarButtons.length) {
|
|
2677
|
+
return null;
|
|
2678
|
+
}
|
|
2098
2679
|
return /*#__PURE__*/react.createElement(react.Fragment, null, toolbarButtons.map(toolDef => {
|
|
2680
|
+
if (!toolDef) {
|
|
2681
|
+
return null;
|
|
2682
|
+
}
|
|
2099
2683
|
const {
|
|
2100
2684
|
id,
|
|
2101
2685
|
Component,
|
|
2102
2686
|
componentProps
|
|
2103
2687
|
} = toolDef;
|
|
2104
|
-
|
|
2105
|
-
|
|
2106
|
-
|
|
2107
|
-
|
|
2108
|
-
|
|
2109
|
-
|
|
2110
|
-
|
|
2111
|
-
|
|
2112
|
-
|
|
2113
|
-
}, componentProps, {
|
|
2114
|
-
onInteraction: onInteraction,
|
|
2115
|
-
servicesManager: servicesManager
|
|
2116
|
-
})))
|
|
2117
|
-
);
|
|
2688
|
+
const tool = /*#__PURE__*/react.createElement(Component, _extends({
|
|
2689
|
+
key: id,
|
|
2690
|
+
id: id,
|
|
2691
|
+
onInteraction: onInteraction,
|
|
2692
|
+
servicesManager: servicesManager
|
|
2693
|
+
}, componentProps));
|
|
2694
|
+
return /*#__PURE__*/react.createElement("div", {
|
|
2695
|
+
key: id
|
|
2696
|
+
}, tool);
|
|
2118
2697
|
}));
|
|
2119
2698
|
}
|
|
2120
2699
|
;// CONCATENATED MODULE: ../../../extensions/default/src/ViewerLayout/ViewerHeader.tsx
|
|
@@ -2126,21 +2705,19 @@ function Toolbar(_ref) {
|
|
|
2126
2705
|
|
|
2127
2706
|
|
|
2128
2707
|
|
|
2129
|
-
|
|
2130
2708
|
const {
|
|
2131
2709
|
availableLanguages,
|
|
2132
2710
|
defaultLanguage,
|
|
2133
2711
|
currentLanguage
|
|
2134
|
-
} = i18n_src
|
|
2135
|
-
function ViewerHeader(
|
|
2136
|
-
|
|
2137
|
-
|
|
2138
|
-
|
|
2139
|
-
|
|
2140
|
-
|
|
2141
|
-
const
|
|
2142
|
-
const
|
|
2143
|
-
const location = (0,react_router_dist/* useLocation */.TH)();
|
|
2712
|
+
} = i18n_src/* default */.A;
|
|
2713
|
+
function ViewerHeader({
|
|
2714
|
+
hotkeysManager,
|
|
2715
|
+
extensionManager,
|
|
2716
|
+
servicesManager,
|
|
2717
|
+
appConfig
|
|
2718
|
+
}) {
|
|
2719
|
+
const navigate = (0,dist/* useNavigate */.Zp)();
|
|
2720
|
+
const location = (0,react_router_dist/* useLocation */.zy)();
|
|
2144
2721
|
const onClickReturnButton = () => {
|
|
2145
2722
|
const {
|
|
2146
2723
|
pathname
|
|
@@ -2164,34 +2741,35 @@ function ViewerHeader(_ref) {
|
|
|
2164
2741
|
};
|
|
2165
2742
|
const {
|
|
2166
2743
|
t
|
|
2167
|
-
} = (0,es/* useTranslation
|
|
2744
|
+
} = (0,es/* useTranslation */.Bd)();
|
|
2168
2745
|
const {
|
|
2169
2746
|
show,
|
|
2170
2747
|
hide
|
|
2171
|
-
} = (0,ui_src/* useModal */.
|
|
2748
|
+
} = (0,ui_src/* useModal */.hS)();
|
|
2172
2749
|
const {
|
|
2173
2750
|
hotkeyDefinitions,
|
|
2174
2751
|
hotkeyDefaults
|
|
2175
2752
|
} = hotkeysManager;
|
|
2176
|
-
const versionNumber = "3.8.0-beta.
|
|
2177
|
-
const commitHash = "
|
|
2753
|
+
const versionNumber = "3.8.0-beta.80";
|
|
2754
|
+
const commitHash = "e80fc6f47708e1d6b1a1e1de438196a4b74ec637";
|
|
2178
2755
|
const menuOptions = [{
|
|
2179
2756
|
title: t('Header:About'),
|
|
2180
2757
|
icon: 'info',
|
|
2181
2758
|
onClick: () => show({
|
|
2182
|
-
content: ui_src/* AboutModal */.
|
|
2759
|
+
content: ui_src/* AboutModal */.VT,
|
|
2183
2760
|
title: t('AboutModal:About OHIF Viewer'),
|
|
2184
2761
|
contentProps: {
|
|
2185
2762
|
versionNumber,
|
|
2186
2763
|
commitHash
|
|
2187
|
-
}
|
|
2764
|
+
},
|
|
2765
|
+
containerDimensions: 'max-w-4xl max-h-4xl'
|
|
2188
2766
|
})
|
|
2189
2767
|
}, {
|
|
2190
2768
|
title: t('Header:Preferences'),
|
|
2191
2769
|
icon: 'settings',
|
|
2192
2770
|
onClick: () => show({
|
|
2193
2771
|
title: t('UserPreferencesModal:User preferences'),
|
|
2194
|
-
content: ui_src/* UserPreferences */.
|
|
2772
|
+
content: ui_src/* UserPreferences */.im,
|
|
2195
2773
|
contentProps: {
|
|
2196
2774
|
hotkeyDefaults: hotkeysManager.getValidHotkeyDefinitions(hotkeyDefaults),
|
|
2197
2775
|
hotkeyDefinitions,
|
|
@@ -2199,23 +2777,22 @@ function ViewerHeader(_ref) {
|
|
|
2199
2777
|
availableLanguages,
|
|
2200
2778
|
defaultLanguage,
|
|
2201
2779
|
onCancel: () => {
|
|
2202
|
-
src/* hotkeys */.
|
|
2203
|
-
src/* hotkeys */.
|
|
2780
|
+
src/* hotkeys */.ot.stopRecord();
|
|
2781
|
+
src/* hotkeys */.ot.unpause();
|
|
2204
2782
|
hide();
|
|
2205
2783
|
},
|
|
2206
|
-
onSubmit:
|
|
2207
|
-
|
|
2208
|
-
|
|
2209
|
-
|
|
2210
|
-
} = _ref2;
|
|
2784
|
+
onSubmit: ({
|
|
2785
|
+
hotkeyDefinitions,
|
|
2786
|
+
language
|
|
2787
|
+
}) => {
|
|
2211
2788
|
if (language.value !== currentLanguage().value) {
|
|
2212
|
-
i18n_src
|
|
2789
|
+
i18n_src/* default */.A.changeLanguage(language.value);
|
|
2213
2790
|
}
|
|
2214
2791
|
hotkeysManager.setHotkeys(hotkeyDefinitions);
|
|
2215
2792
|
hide();
|
|
2216
2793
|
},
|
|
2217
2794
|
onReset: () => hotkeysManager.restoreDefaultBindings(),
|
|
2218
|
-
hotkeysModule: src/* hotkeys */.
|
|
2795
|
+
hotkeysModule: src/* hotkeys */.ot
|
|
2219
2796
|
}
|
|
2220
2797
|
})
|
|
2221
2798
|
}];
|
|
@@ -2228,61 +2805,93 @@ function ViewerHeader(_ref) {
|
|
|
2228
2805
|
}
|
|
2229
2806
|
});
|
|
2230
2807
|
}
|
|
2231
|
-
return /*#__PURE__*/react.createElement(ui_src/* Header */.
|
|
2808
|
+
return /*#__PURE__*/react.createElement(ui_src/* Header */.Y9, {
|
|
2232
2809
|
menuOptions: menuOptions,
|
|
2233
2810
|
isReturnEnabled: !!appConfig.showStudyList,
|
|
2234
2811
|
onClickReturnButton: onClickReturnButton,
|
|
2235
|
-
WhiteLabeling: appConfig.whiteLabeling
|
|
2236
|
-
|
|
2812
|
+
WhiteLabeling: appConfig.whiteLabeling,
|
|
2813
|
+
showPatientInfo: appConfig.showPatientInfo,
|
|
2814
|
+
servicesManager: servicesManager,
|
|
2815
|
+
Secondary: /*#__PURE__*/react.createElement(Toolbar, {
|
|
2816
|
+
servicesManager: servicesManager,
|
|
2817
|
+
buttonSection: "secondary"
|
|
2818
|
+
}),
|
|
2819
|
+
appConfig: appConfig
|
|
2820
|
+
}, /*#__PURE__*/react.createElement(ui_src/* ErrorBoundary */.tH, {
|
|
2237
2821
|
context: "Primary Toolbar"
|
|
2238
2822
|
}, /*#__PURE__*/react.createElement("div", {
|
|
2239
|
-
className: "relative flex justify-center"
|
|
2823
|
+
className: "relative flex justify-center gap-[4px]"
|
|
2240
2824
|
}, /*#__PURE__*/react.createElement(Toolbar, {
|
|
2241
2825
|
servicesManager: servicesManager
|
|
2242
2826
|
}))));
|
|
2243
2827
|
}
|
|
2244
2828
|
/* harmony default export */ const ViewerLayout_ViewerHeader = (ViewerHeader);
|
|
2245
2829
|
;// CONCATENATED MODULE: ../../../extensions/default/src/Components/SidePanelWithServices.tsx
|
|
2830
|
+
function SidePanelWithServices_extends() { SidePanelWithServices_extends = Object.assign ? Object.assign.bind() : function (target) { for (var i = 1; i < arguments.length; i++) { var source = arguments[i]; for (var key in source) { if (Object.prototype.hasOwnProperty.call(source, key)) { target[key] = source[key]; } } } return target; }; return SidePanelWithServices_extends.apply(this, arguments); }
|
|
2246
2831
|
|
|
2247
2832
|
|
|
2248
|
-
const SidePanelWithServices =
|
|
2249
|
-
|
|
2250
|
-
|
|
2251
|
-
|
|
2252
|
-
|
|
2253
|
-
|
|
2254
|
-
|
|
2255
|
-
|
|
2833
|
+
const SidePanelWithServices = ({
|
|
2834
|
+
servicesManager,
|
|
2835
|
+
side,
|
|
2836
|
+
activeTabIndex: activeTabIndexProp,
|
|
2837
|
+
tabs: tabsProp,
|
|
2838
|
+
expandedWidth,
|
|
2839
|
+
...props
|
|
2840
|
+
}) => {
|
|
2256
2841
|
const panelService = servicesManager?.services?.panelService;
|
|
2257
2842
|
|
|
2258
2843
|
// Tracks whether this SidePanel has been opened at least once since this SidePanel was inserted into the DOM.
|
|
2259
2844
|
// Thus going to the Study List page and back to the viewer resets this flag for a SidePanel.
|
|
2260
2845
|
const [hasBeenOpened, setHasBeenOpened] = (0,react.useState)(false);
|
|
2261
2846
|
const [activeTabIndex, setActiveTabIndex] = (0,react.useState)(activeTabIndexProp);
|
|
2847
|
+
const [tabs, setTabs] = (0,react.useState)(tabsProp ?? panelService.getPanels(side));
|
|
2848
|
+
const handleSidePanelOpen = (0,react.useCallback)(() => {
|
|
2849
|
+
setHasBeenOpened(true);
|
|
2850
|
+
}, []);
|
|
2851
|
+
const handleActiveTabIndexChange = (0,react.useCallback)(({
|
|
2852
|
+
activeTabIndex
|
|
2853
|
+
}) => {
|
|
2854
|
+
setActiveTabIndex(activeTabIndex);
|
|
2855
|
+
}, []);
|
|
2856
|
+
|
|
2857
|
+
/** update the active tab index from outside */
|
|
2262
2858
|
(0,react.useEffect)(() => {
|
|
2263
|
-
|
|
2264
|
-
|
|
2265
|
-
|
|
2266
|
-
|
|
2267
|
-
|
|
2268
|
-
|
|
2269
|
-
|
|
2859
|
+
setActiveTabIndex(activeTabIndexProp);
|
|
2860
|
+
}, [activeTabIndexProp]);
|
|
2861
|
+
(0,react.useEffect)(() => {
|
|
2862
|
+
const {
|
|
2863
|
+
unsubscribe
|
|
2864
|
+
} = panelService.subscribe(panelService.EVENTS.PANELS_CHANGED, panelChangedEvent => {
|
|
2865
|
+
if (panelChangedEvent.position !== side) {
|
|
2866
|
+
return;
|
|
2867
|
+
}
|
|
2868
|
+
setTabs(panelService.getPanels(side));
|
|
2869
|
+
});
|
|
2870
|
+
return () => {
|
|
2871
|
+
unsubscribe();
|
|
2872
|
+
};
|
|
2873
|
+
}, [panelService, side]);
|
|
2874
|
+
(0,react.useEffect)(() => {
|
|
2875
|
+
const activatePanelSubscription = panelService.subscribe(panelService.EVENTS.ACTIVATE_PANEL, activatePanelEvent => {
|
|
2876
|
+
if (!hasBeenOpened || activatePanelEvent.forceActive) {
|
|
2877
|
+
const tabIndex = tabs.findIndex(tab => tab.id === activatePanelEvent.panelId);
|
|
2878
|
+
if (tabIndex !== -1) {
|
|
2879
|
+
setActiveTabIndex(tabIndex);
|
|
2270
2880
|
}
|
|
2271
|
-
}
|
|
2272
|
-
|
|
2273
|
-
|
|
2274
|
-
|
|
2275
|
-
}
|
|
2881
|
+
}
|
|
2882
|
+
});
|
|
2883
|
+
return () => {
|
|
2884
|
+
activatePanelSubscription.unsubscribe();
|
|
2885
|
+
};
|
|
2276
2886
|
}, [tabs, hasBeenOpened, panelService]);
|
|
2277
|
-
return /*#__PURE__*/react.createElement(ui_src/* SidePanel */.
|
|
2887
|
+
return /*#__PURE__*/react.createElement(ui_src/* SidePanel */.wv, SidePanelWithServices_extends({}, props, {
|
|
2278
2888
|
side: side,
|
|
2279
|
-
className: className,
|
|
2280
|
-
activeTabIndex: activeTabIndex,
|
|
2281
2889
|
tabs: tabs,
|
|
2282
|
-
|
|
2283
|
-
|
|
2284
|
-
|
|
2285
|
-
|
|
2890
|
+
activeTabIndex: activeTabIndex,
|
|
2891
|
+
onOpen: handleSidePanelOpen,
|
|
2892
|
+
onActiveTabIndexChange: handleActiveTabIndexChange,
|
|
2893
|
+
expandedWidth: expandedWidth
|
|
2894
|
+
}));
|
|
2286
2895
|
};
|
|
2287
2896
|
/* harmony default export */ const Components_SidePanelWithServices = (SidePanelWithServices);
|
|
2288
2897
|
;// CONCATENATED MODULE: ../../../extensions/default/src/ViewerLayout/index.tsx
|
|
@@ -2293,26 +2902,29 @@ const SidePanelWithServices = _ref => {
|
|
|
2293
2902
|
|
|
2294
2903
|
|
|
2295
2904
|
|
|
2296
|
-
function ViewerLayout(
|
|
2297
|
-
|
|
2298
|
-
|
|
2299
|
-
|
|
2300
|
-
|
|
2301
|
-
|
|
2302
|
-
|
|
2303
|
-
|
|
2304
|
-
|
|
2305
|
-
|
|
2306
|
-
|
|
2307
|
-
|
|
2308
|
-
|
|
2309
|
-
rightPanelDefaultClosed = false
|
|
2310
|
-
} = _ref;
|
|
2311
|
-
const [appConfig] = (0,state/* useAppConfig */.M)();
|
|
2905
|
+
function ViewerLayout({
|
|
2906
|
+
// From Extension Module Params
|
|
2907
|
+
extensionManager,
|
|
2908
|
+
servicesManager,
|
|
2909
|
+
hotkeysManager,
|
|
2910
|
+
commandsManager,
|
|
2911
|
+
// From Modes
|
|
2912
|
+
viewports,
|
|
2913
|
+
ViewportGridComp,
|
|
2914
|
+
leftPanelClosed = false,
|
|
2915
|
+
rightPanelClosed = false
|
|
2916
|
+
}) {
|
|
2917
|
+
const [appConfig] = (0,state/* useAppConfig */.r)();
|
|
2312
2918
|
const {
|
|
2919
|
+
panelService,
|
|
2313
2920
|
hangingProtocolService
|
|
2314
2921
|
} = servicesManager.services;
|
|
2315
2922
|
const [showLoadingIndicator, setShowLoadingIndicator] = (0,react.useState)(appConfig.showLoadingIndicator);
|
|
2923
|
+
const hasPanels = (0,react.useCallback)(side => !!panelService.getPanels(side).length, [panelService]);
|
|
2924
|
+
const [hasRightPanels, setHasRightPanels] = (0,react.useState)(hasPanels('right'));
|
|
2925
|
+
const [hasLeftPanels, setHasLeftPanels] = (0,react.useState)(hasPanels('left'));
|
|
2926
|
+
const [leftPanelClosedState, setLeftPanelClosed] = (0,react.useState)(leftPanelClosed);
|
|
2927
|
+
const [rightPanelClosedState, setRightPanelClosed] = (0,react.useState)(rightPanelClosed);
|
|
2316
2928
|
|
|
2317
2929
|
/**
|
|
2318
2930
|
* Set body classes (tailwindcss) that don't allow vertical
|
|
@@ -2329,38 +2941,18 @@ function ViewerLayout(_ref) {
|
|
|
2329
2941
|
}, []);
|
|
2330
2942
|
const getComponent = id => {
|
|
2331
2943
|
const entry = extensionManager.getModuleEntry(id);
|
|
2332
|
-
if (!entry) {
|
|
2333
|
-
throw new Error(`${id} is not valid for an extension module. Please verify your configuration or ensure that the extension is properly registered. It's also possible that your mode is utilizing a module from an extension that hasn't been included in its dependencies (add the extension to the "extensionDependencies" array in your mode's index.js file)`);
|
|
2334
|
-
}
|
|
2335
|
-
let content;
|
|
2336
|
-
if (entry && entry.component) {
|
|
2337
|
-
content = entry.component;
|
|
2338
|
-
} else {
|
|
2339
|
-
throw new Error(`No component found from extension ${id}. Check the reference string to the extension in your Mode configuration`);
|
|
2944
|
+
if (!entry || !entry.component) {
|
|
2945
|
+
throw new Error(`${id} is not valid for an extension module or no component found from extension ${id}. Please verify your configuration or ensure that the extension is properly registered. It's also possible that your mode is utilizing a module from an extension that hasn't been included in its dependencies (add the extension to the "extensionDependencies" array in your mode's index.js file). Check the reference string to the extension in your Mode configuration`);
|
|
2340
2946
|
}
|
|
2341
2947
|
return {
|
|
2342
2948
|
entry,
|
|
2343
|
-
content
|
|
2344
|
-
};
|
|
2345
|
-
};
|
|
2346
|
-
const getPanelData = id => {
|
|
2347
|
-
const {
|
|
2348
|
-
content,
|
|
2349
|
-
entry
|
|
2350
|
-
} = getComponent(id);
|
|
2351
|
-
return {
|
|
2352
|
-
id: entry.id,
|
|
2353
|
-
iconName: entry.iconName,
|
|
2354
|
-
iconLabel: entry.iconLabel,
|
|
2355
|
-
label: entry.label,
|
|
2356
|
-
name: entry.name,
|
|
2357
|
-
content
|
|
2949
|
+
content: entry.component
|
|
2358
2950
|
};
|
|
2359
2951
|
};
|
|
2360
2952
|
(0,react.useEffect)(() => {
|
|
2361
2953
|
const {
|
|
2362
2954
|
unsubscribe
|
|
2363
|
-
} = hangingProtocolService.subscribe(src/* HangingProtocolService */.
|
|
2955
|
+
} = hangingProtocolService.subscribe(src/* HangingProtocolService */.Qe.EVENTS.PROTOCOL_CHANGED,
|
|
2364
2956
|
// Todo: right now to set the loading indicator to false, we need to wait for the
|
|
2365
2957
|
// hangingProtocolService to finish applying the viewport matching to each viewport,
|
|
2366
2958
|
// however, this might not be the only approach to set the loading indicator to false. we need to explore this further.
|
|
@@ -2380,58 +2972,76 @@ function ViewerLayout(_ref) {
|
|
|
2380
2972
|
displaySetsToDisplay: viewportComponent.displaySetsToDisplay
|
|
2381
2973
|
};
|
|
2382
2974
|
};
|
|
2383
|
-
|
|
2384
|
-
|
|
2975
|
+
(0,react.useEffect)(() => {
|
|
2976
|
+
const {
|
|
2977
|
+
unsubscribe
|
|
2978
|
+
} = panelService.subscribe(panelService.EVENTS.PANELS_CHANGED, ({
|
|
2979
|
+
options
|
|
2980
|
+
}) => {
|
|
2981
|
+
setHasLeftPanels(hasPanels('left'));
|
|
2982
|
+
setHasRightPanels(hasPanels('right'));
|
|
2983
|
+
if (options?.leftPanelClosed !== undefined) {
|
|
2984
|
+
setLeftPanelClosed(options.leftPanelClosed);
|
|
2985
|
+
}
|
|
2986
|
+
if (options?.rightPanelClosed !== undefined) {
|
|
2987
|
+
setRightPanelClosed(options.rightPanelClosed);
|
|
2988
|
+
}
|
|
2989
|
+
});
|
|
2990
|
+
return () => {
|
|
2991
|
+
unsubscribe();
|
|
2992
|
+
};
|
|
2993
|
+
}, [panelService, hasPanels]);
|
|
2385
2994
|
const viewportComponents = viewports.map(getViewportComponentData);
|
|
2386
2995
|
return /*#__PURE__*/react.createElement("div", null, /*#__PURE__*/react.createElement(ViewerLayout_ViewerHeader, {
|
|
2387
2996
|
hotkeysManager: hotkeysManager,
|
|
2388
2997
|
extensionManager: extensionManager,
|
|
2389
|
-
servicesManager: servicesManager
|
|
2998
|
+
servicesManager: servicesManager,
|
|
2999
|
+
appConfig: appConfig
|
|
2390
3000
|
}), /*#__PURE__*/react.createElement("div", {
|
|
2391
3001
|
className: "relative flex w-full flex-row flex-nowrap items-stretch overflow-hidden bg-black",
|
|
2392
3002
|
style: {
|
|
2393
3003
|
height: 'calc(100vh - 52px'
|
|
2394
3004
|
}
|
|
2395
|
-
}, /*#__PURE__*/react.createElement(react.Fragment, null, showLoadingIndicator && /*#__PURE__*/react.createElement(ui_src/* LoadingIndicatorProgress */.
|
|
3005
|
+
}, /*#__PURE__*/react.createElement(react.Fragment, null, showLoadingIndicator && /*#__PURE__*/react.createElement(ui_src/* LoadingIndicatorProgress */.Jx, {
|
|
2396
3006
|
className: "h-full w-full bg-black"
|
|
2397
|
-
}),
|
|
3007
|
+
}), hasLeftPanels ? /*#__PURE__*/react.createElement(ui_src/* ErrorBoundary */.tH, {
|
|
2398
3008
|
context: "Left Panel"
|
|
2399
3009
|
}, /*#__PURE__*/react.createElement(Components_SidePanelWithServices, {
|
|
2400
3010
|
side: "left",
|
|
2401
|
-
activeTabIndex:
|
|
2402
|
-
tabs: leftPanelComponents,
|
|
3011
|
+
activeTabIndex: leftPanelClosedState ? null : 0,
|
|
2403
3012
|
servicesManager: servicesManager
|
|
2404
3013
|
})) : null, /*#__PURE__*/react.createElement("div", {
|
|
2405
3014
|
className: "flex h-full flex-1 flex-col"
|
|
2406
3015
|
}, /*#__PURE__*/react.createElement("div", {
|
|
2407
3016
|
className: "relative flex h-full flex-1 items-center justify-center overflow-hidden bg-black"
|
|
2408
|
-
}, /*#__PURE__*/react.createElement(ui_src/* ErrorBoundary */.
|
|
3017
|
+
}, /*#__PURE__*/react.createElement(ui_src/* ErrorBoundary */.tH, {
|
|
2409
3018
|
context: "Grid"
|
|
2410
3019
|
}, /*#__PURE__*/react.createElement(ViewportGridComp, {
|
|
2411
3020
|
servicesManager: servicesManager,
|
|
2412
3021
|
viewportComponents: viewportComponents,
|
|
2413
3022
|
commandsManager: commandsManager
|
|
2414
|
-
})))),
|
|
3023
|
+
})))), hasRightPanels ? /*#__PURE__*/react.createElement(ui_src/* ErrorBoundary */.tH, {
|
|
2415
3024
|
context: "Right Panel"
|
|
2416
3025
|
}, /*#__PURE__*/react.createElement(Components_SidePanelWithServices, {
|
|
2417
3026
|
side: "right",
|
|
2418
|
-
activeTabIndex:
|
|
2419
|
-
tabs: rightPanelComponents,
|
|
3027
|
+
activeTabIndex: rightPanelClosedState ? null : 0,
|
|
2420
3028
|
servicesManager: servicesManager
|
|
2421
|
-
})) : null))
|
|
3029
|
+
})) : null)), /*#__PURE__*/react.createElement(ui_src/* InvestigationalUseDialog */.j, {
|
|
3030
|
+
dialogConfiguration: appConfig?.investigationalUseDialog
|
|
3031
|
+
}));
|
|
2422
3032
|
}
|
|
2423
3033
|
ViewerLayout.propTypes = {
|
|
2424
3034
|
// From extension module params
|
|
2425
3035
|
extensionManager: prop_types_default().shape({
|
|
2426
3036
|
getModuleEntry: (prop_types_default()).func.isRequired
|
|
2427
3037
|
}).isRequired,
|
|
2428
|
-
commandsManager: prop_types_default().instanceOf(src/* CommandsManager */.
|
|
2429
|
-
servicesManager: prop_types_default().instanceOf(src/* ServicesManager */.
|
|
3038
|
+
commandsManager: prop_types_default().instanceOf(src/* CommandsManager */.Sp),
|
|
3039
|
+
servicesManager: prop_types_default().instanceOf(src/* ServicesManager */.CS),
|
|
2430
3040
|
// From modes
|
|
2431
3041
|
leftPanels: (prop_types_default()).array,
|
|
2432
3042
|
rightPanels: (prop_types_default()).array,
|
|
2433
|
-
|
|
2434
|
-
|
|
3043
|
+
leftPanelClosed: (prop_types_default()).bool.isRequired,
|
|
3044
|
+
rightPanelClosed: (prop_types_default()).bool.isRequired,
|
|
2435
3045
|
/** Responsible for rendering our grid of viewports; provided by consuming application */
|
|
2436
3046
|
children: prop_types_default().oneOfType([(prop_types_default()).node, (prop_types_default()).func]).isRequired,
|
|
2437
3047
|
viewports: (prop_types_default()).array
|
|
@@ -2445,13 +3055,12 @@ ViewerLayout.propTypes = {
|
|
|
2445
3055
|
- Init layout based on the displaySets and the objects.
|
|
2446
3056
|
*/
|
|
2447
3057
|
|
|
2448
|
-
/* harmony default export */ function getLayoutTemplateModule(
|
|
2449
|
-
|
|
2450
|
-
|
|
2451
|
-
|
|
2452
|
-
|
|
2453
|
-
|
|
2454
|
-
} = _ref;
|
|
3058
|
+
/* harmony default export */ function getLayoutTemplateModule({
|
|
3059
|
+
servicesManager,
|
|
3060
|
+
extensionManager,
|
|
3061
|
+
commandsManager,
|
|
3062
|
+
hotkeysManager
|
|
3063
|
+
}) {
|
|
2455
3064
|
function ViewerLayoutWithServices(props) {
|
|
2456
3065
|
return src_ViewerLayout({
|
|
2457
3066
|
servicesManager,
|
|
@@ -2485,31 +3094,30 @@ const {
|
|
|
2485
3094
|
*
|
|
2486
3095
|
* @param {*} param0
|
|
2487
3096
|
*/
|
|
2488
|
-
function PanelStudyBrowser(
|
|
2489
|
-
|
|
2490
|
-
|
|
2491
|
-
|
|
2492
|
-
|
|
2493
|
-
|
|
2494
|
-
|
|
2495
|
-
} = _ref;
|
|
3097
|
+
function PanelStudyBrowser({
|
|
3098
|
+
servicesManager,
|
|
3099
|
+
getImageSrc,
|
|
3100
|
+
getStudiesForPatientByMRN,
|
|
3101
|
+
requestDisplaySetCreationForStudy,
|
|
3102
|
+
dataSource
|
|
3103
|
+
}) {
|
|
2496
3104
|
const {
|
|
2497
3105
|
hangingProtocolService,
|
|
2498
3106
|
displaySetService,
|
|
2499
3107
|
uiNotificationService
|
|
2500
3108
|
} = servicesManager.services;
|
|
2501
|
-
const navigate = (0,dist/* useNavigate */.
|
|
3109
|
+
const navigate = (0,dist/* useNavigate */.Zp)();
|
|
2502
3110
|
|
|
2503
3111
|
// Normally you nest the components so the tree isn't so deep, and the data
|
|
2504
3112
|
// doesn't have to have such an intense shape. This works well enough for now.
|
|
2505
3113
|
// Tabs --> Studies --> DisplaySets --> Thumbnails
|
|
2506
3114
|
const {
|
|
2507
3115
|
StudyInstanceUIDs
|
|
2508
|
-
} = (0,ui_src/* useImageViewer */.
|
|
3116
|
+
} = (0,ui_src/* useImageViewer */.Bz)();
|
|
2509
3117
|
const [{
|
|
2510
3118
|
activeViewportId,
|
|
2511
3119
|
viewports
|
|
2512
|
-
}, viewportGridService] = (0,ui_src/* useViewportGrid */.
|
|
3120
|
+
}, viewportGridService] = (0,ui_src/* useViewportGrid */.ih)();
|
|
2513
3121
|
const [activeTabName, setActiveTabName] = (0,react.useState)('primary');
|
|
2514
3122
|
const [expandedStudyInstanceUIDs, setExpandedStudyInstanceUIDs] = (0,react.useState)([...StudyInstanceUIDs]);
|
|
2515
3123
|
const [studyDisplayList, setStudyDisplayList] = (0,react.useState)([]);
|
|
@@ -2675,7 +3283,7 @@ function PanelStudyBrowser(_ref) {
|
|
|
2675
3283
|
}
|
|
2676
3284
|
}
|
|
2677
3285
|
const activeDisplaySetInstanceUIDs = viewports.get(activeViewportId)?.displaySetInstanceUIDs;
|
|
2678
|
-
return /*#__PURE__*/react.createElement(ui_src/* StudyBrowser */.
|
|
3286
|
+
return /*#__PURE__*/react.createElement(ui_src/* StudyBrowser */.M4, {
|
|
2679
3287
|
tabs: tabs,
|
|
2680
3288
|
servicesManager: servicesManager,
|
|
2681
3289
|
activeTabName: activeTabName,
|
|
@@ -2745,7 +3353,6 @@ function _mapDisplaySets(displaySets, thumbnailImageSrcMap) {
|
|
|
2745
3353
|
displaySetInstanceUID: ds.displaySetInstanceUID
|
|
2746
3354
|
// .. Any other data to pass
|
|
2747
3355
|
},
|
|
2748
|
-
|
|
2749
3356
|
isHydratedForDerivedDisplaySet: ds.isHydrated
|
|
2750
3357
|
});
|
|
2751
3358
|
});
|
|
@@ -2812,6 +3419,11 @@ function _createStudyBrowserTabs(primaryStudyInstanceUIDs, studyDisplayList, dis
|
|
|
2812
3419
|
function getImageSrcFromImageId(cornerstone, imageId) {
|
|
2813
3420
|
return new Promise((resolve, reject) => {
|
|
2814
3421
|
const canvas = document.createElement('canvas');
|
|
3422
|
+
// Note: the default width and height of the canvas is 300x150
|
|
3423
|
+
// but we need to set the width and height to the same number since
|
|
3424
|
+
// the thumbnails are usually square and we want to maintain the aspect ratio
|
|
3425
|
+
canvas.width = 128 / window.devicePixelRatio;
|
|
3426
|
+
canvas.height = 128 / window.devicePixelRatio;
|
|
2815
3427
|
cornerstone.utilities.loadImageToCanvas({
|
|
2816
3428
|
canvas,
|
|
2817
3429
|
imageId
|
|
@@ -2860,17 +3472,16 @@ function requestDisplaySetCreationForStudy(dataSource, displaySetService, StudyI
|
|
|
2860
3472
|
* @param {object} commandsManager
|
|
2861
3473
|
* @param {object} extensionManager
|
|
2862
3474
|
*/
|
|
2863
|
-
function WrappedPanelStudyBrowser(
|
|
2864
|
-
|
|
2865
|
-
|
|
2866
|
-
|
|
2867
|
-
|
|
2868
|
-
} = _ref;
|
|
3475
|
+
function WrappedPanelStudyBrowser({
|
|
3476
|
+
commandsManager,
|
|
3477
|
+
extensionManager,
|
|
3478
|
+
servicesManager
|
|
3479
|
+
}) {
|
|
2869
3480
|
// TODO: This should be made available a different way; route should have
|
|
2870
3481
|
// already determined our datasource
|
|
2871
3482
|
const dataSource = extensionManager.getDataSources()[0];
|
|
2872
3483
|
const _getStudiesForPatientByMRN = Panels_getStudiesForPatientByMRN.bind(null, dataSource);
|
|
2873
|
-
const _getImageSrcFromImageId = _createGetImageSrcFromImageIdFn(extensionManager);
|
|
3484
|
+
const _getImageSrcFromImageId = (0,react.useCallback)(_createGetImageSrcFromImageIdFn(extensionManager), []);
|
|
2874
3485
|
const _requestDisplaySetCreationForStudy = Panels_requestDisplaySetCreationForStudy.bind(null, dataSource);
|
|
2875
3486
|
return /*#__PURE__*/react.createElement(Panels_PanelStudyBrowser, {
|
|
2876
3487
|
servicesManager: servicesManager,
|
|
@@ -2907,41 +3518,8 @@ WrappedPanelStudyBrowser.propTypes = {
|
|
|
2907
3518
|
servicesManager: (prop_types_default()).object.isRequired
|
|
2908
3519
|
};
|
|
2909
3520
|
/* harmony default export */ const Panels_WrappedPanelStudyBrowser = (WrappedPanelStudyBrowser);
|
|
2910
|
-
;// CONCATENATED MODULE: ../../../extensions/default/src/Panels/ActionButtons.tsx
|
|
2911
|
-
|
|
2912
|
-
|
|
2913
|
-
|
|
2914
|
-
|
|
2915
|
-
function ActionButtons(_ref) {
|
|
2916
|
-
let {
|
|
2917
|
-
onExportClick,
|
|
2918
|
-
onCreateReportClick
|
|
2919
|
-
} = _ref;
|
|
2920
|
-
const {
|
|
2921
|
-
t
|
|
2922
|
-
} = (0,es/* useTranslation */.$G)('MeasurementTable');
|
|
2923
|
-
return /*#__PURE__*/react.createElement(react.Fragment, null, /*#__PURE__*/react.createElement(ui_src/* LegacyButtonGroup */.HO, {
|
|
2924
|
-
color: "black",
|
|
2925
|
-
size: "inherit"
|
|
2926
|
-
}, /*#__PURE__*/react.createElement(ui_src/* LegacyButton */.mN, {
|
|
2927
|
-
className: "px-2 py-2 text-base",
|
|
2928
|
-
onClick: onExportClick
|
|
2929
|
-
}, t('Export CSV')), /*#__PURE__*/react.createElement(ui_src/* LegacyButton */.mN, {
|
|
2930
|
-
className: "px-2 py-2 text-base",
|
|
2931
|
-
onClick: onCreateReportClick
|
|
2932
|
-
}, t('Create Report'))));
|
|
2933
|
-
}
|
|
2934
|
-
ActionButtons.propTypes = {
|
|
2935
|
-
onExportClick: (prop_types_default()).func,
|
|
2936
|
-
onCreateReportClick: (prop_types_default()).func
|
|
2937
|
-
};
|
|
2938
|
-
ActionButtons.defaultProps = {
|
|
2939
|
-
onExportClick: () => alert('Export'),
|
|
2940
|
-
onCreateReportClick: () => alert('Create Report')
|
|
2941
|
-
};
|
|
2942
|
-
/* harmony default export */ const Panels_ActionButtons = (ActionButtons);
|
|
2943
3521
|
// EXTERNAL MODULE: ../../../node_modules/lodash.debounce/index.js
|
|
2944
|
-
var lodash_debounce = __webpack_require__(
|
|
3522
|
+
var lodash_debounce = __webpack_require__(14771);
|
|
2945
3523
|
var lodash_debounce_default = /*#__PURE__*/__webpack_require__.n(lodash_debounce);
|
|
2946
3524
|
;// CONCATENATED MODULE: ../../../extensions/default/src/Panels/createReportDialogPrompt.tsx
|
|
2947
3525
|
|
|
@@ -2950,10 +3528,9 @@ const CREATE_REPORT_DIALOG_RESPONSE = {
|
|
|
2950
3528
|
CANCEL: 0,
|
|
2951
3529
|
CREATE_REPORT: 1
|
|
2952
3530
|
};
|
|
2953
|
-
function CreateReportDialogPrompt(uiDialogService,
|
|
2954
|
-
|
|
2955
|
-
|
|
2956
|
-
} = _ref;
|
|
3531
|
+
function CreateReportDialogPrompt(uiDialogService, {
|
|
3532
|
+
extensionManager
|
|
3533
|
+
}) {
|
|
2957
3534
|
return new Promise(function (resolve, reject) {
|
|
2958
3535
|
let dialogId = undefined;
|
|
2959
3536
|
const _handleClose = () => {
|
|
@@ -2974,11 +3551,10 @@ function CreateReportDialogPrompt(uiDialogService, _ref) {
|
|
|
2974
3551
|
* @param {string} param0.action - value of action performed
|
|
2975
3552
|
* @param {string} param0.value - value from input field
|
|
2976
3553
|
*/
|
|
2977
|
-
const _handleFormSubmit =
|
|
2978
|
-
|
|
2979
|
-
|
|
2980
|
-
|
|
2981
|
-
} = _ref2;
|
|
3554
|
+
const _handleFormSubmit = ({
|
|
3555
|
+
action,
|
|
3556
|
+
value
|
|
3557
|
+
}) => {
|
|
2982
3558
|
uiDialogService.dismiss({
|
|
2983
3559
|
id: dialogId
|
|
2984
3560
|
});
|
|
@@ -3013,7 +3589,7 @@ function CreateReportDialogPrompt(uiDialogService, _ref) {
|
|
|
3013
3589
|
dialogId = uiDialogService.create({
|
|
3014
3590
|
centralize: true,
|
|
3015
3591
|
isDraggable: false,
|
|
3016
|
-
content: ui_src/* Dialog */.
|
|
3592
|
+
content: ui_src/* Dialog */.lG,
|
|
3017
3593
|
useLastPosition: false,
|
|
3018
3594
|
showOverlay: true,
|
|
3019
3595
|
contentProps: {
|
|
@@ -3027,19 +3603,18 @@ function CreateReportDialogPrompt(uiDialogService, _ref) {
|
|
|
3027
3603
|
actions: [{
|
|
3028
3604
|
id: 'cancel',
|
|
3029
3605
|
text: 'Cancel',
|
|
3030
|
-
type: ui_src/* ButtonEnums.type */.
|
|
3606
|
+
type: ui_src/* ButtonEnums.type */.Ny.NW.secondary
|
|
3031
3607
|
}, {
|
|
3032
3608
|
id: 'save',
|
|
3033
3609
|
text: 'Save',
|
|
3034
|
-
type: ui_src/* ButtonEnums.type */.
|
|
3610
|
+
type: ui_src/* ButtonEnums.type */.Ny.NW.primary
|
|
3035
3611
|
}],
|
|
3036
3612
|
// TODO: Should be on button press...
|
|
3037
3613
|
onSubmit: _handleFormSubmit,
|
|
3038
|
-
body:
|
|
3039
|
-
|
|
3040
|
-
|
|
3041
|
-
|
|
3042
|
-
} = _ref3;
|
|
3614
|
+
body: ({
|
|
3615
|
+
value,
|
|
3616
|
+
setValue
|
|
3617
|
+
}) => {
|
|
3043
3618
|
const onChangeHandler = event => {
|
|
3044
3619
|
event.persist();
|
|
3045
3620
|
setValue(value => ({
|
|
@@ -3060,7 +3635,7 @@ function CreateReportDialogPrompt(uiDialogService, _ref) {
|
|
|
3060
3635
|
};
|
|
3061
3636
|
return /*#__PURE__*/react.createElement(react.Fragment, null, dataSourcesOpts.length > 1 && window.config?.allowMultiSelectExport && /*#__PURE__*/react.createElement("div", null, /*#__PURE__*/react.createElement("label", {
|
|
3062
3637
|
className: "text-[14px] leading-[1.2] text-white"
|
|
3063
|
-
}, "Data Source"), /*#__PURE__*/react.createElement(ui_src/* Select */.
|
|
3638
|
+
}, "Data Source"), /*#__PURE__*/react.createElement(ui_src/* Select */.l6, {
|
|
3064
3639
|
closeMenuOnSelect: true,
|
|
3065
3640
|
className: "border-primary-main mt-2 bg-black",
|
|
3066
3641
|
options: dataSourcesOpts,
|
|
@@ -3075,7 +3650,7 @@ function CreateReportDialogPrompt(uiDialogService, _ref) {
|
|
|
3075
3650
|
isClearable: false
|
|
3076
3651
|
})), /*#__PURE__*/react.createElement("div", {
|
|
3077
3652
|
className: "mt-3"
|
|
3078
|
-
}, /*#__PURE__*/react.createElement(ui_src/* Input */.
|
|
3653
|
+
}, /*#__PURE__*/react.createElement(ui_src/* Input */.pd, {
|
|
3079
3654
|
autoFocus: true,
|
|
3080
3655
|
label: "Enter the report name",
|
|
3081
3656
|
labelClassName: "text-white text-[14px] leading-[1.2]",
|
|
@@ -3099,12 +3674,11 @@ function CreateReportDialogPrompt(uiDialogService, _ref) {
|
|
|
3099
3674
|
*
|
|
3100
3675
|
* @param {*} servicesManager
|
|
3101
3676
|
*/
|
|
3102
|
-
async function createReportAsync(
|
|
3103
|
-
|
|
3104
|
-
|
|
3105
|
-
|
|
3106
|
-
|
|
3107
|
-
} = _ref;
|
|
3677
|
+
async function createReportAsync({
|
|
3678
|
+
servicesManager,
|
|
3679
|
+
getReport,
|
|
3680
|
+
reportType = 'measurement'
|
|
3681
|
+
}) {
|
|
3108
3682
|
const {
|
|
3109
3683
|
displaySetService,
|
|
3110
3684
|
uiNotificationService,
|
|
@@ -3218,13 +3792,15 @@ function findSRWithSameSeriesDescription(SeriesDescription, displaySetService) {
|
|
|
3218
3792
|
const {
|
|
3219
3793
|
downloadCSVReport
|
|
3220
3794
|
} = src.utils;
|
|
3221
|
-
function PanelMeasurementTable(
|
|
3222
|
-
|
|
3223
|
-
|
|
3224
|
-
|
|
3225
|
-
|
|
3226
|
-
|
|
3227
|
-
|
|
3795
|
+
function PanelMeasurementTable({
|
|
3796
|
+
servicesManager,
|
|
3797
|
+
commandsManager,
|
|
3798
|
+
extensionManager
|
|
3799
|
+
}) {
|
|
3800
|
+
const {
|
|
3801
|
+
t
|
|
3802
|
+
} = (0,es/* useTranslation */.Bd)('MeasurementTable');
|
|
3803
|
+
const [viewportGrid, viewportGridService] = (0,ui_src/* useViewportGrid */.ih)();
|
|
3228
3804
|
const {
|
|
3229
3805
|
activeViewportId,
|
|
3230
3806
|
viewports
|
|
@@ -3310,31 +3886,28 @@ function PanelMeasurementTable(_ref) {
|
|
|
3310
3886
|
});
|
|
3311
3887
|
}
|
|
3312
3888
|
}
|
|
3313
|
-
const jumpToImage =
|
|
3314
|
-
|
|
3315
|
-
|
|
3316
|
-
|
|
3317
|
-
} = _ref2;
|
|
3889
|
+
const jumpToImage = ({
|
|
3890
|
+
uid,
|
|
3891
|
+
isActive
|
|
3892
|
+
}) => {
|
|
3318
3893
|
measurementService.jumpToMeasurement(viewportGrid.activeViewportId, uid);
|
|
3319
3894
|
onMeasurementItemClickHandler({
|
|
3320
3895
|
uid,
|
|
3321
3896
|
isActive
|
|
3322
3897
|
});
|
|
3323
3898
|
};
|
|
3324
|
-
const onMeasurementItemEditHandler =
|
|
3325
|
-
|
|
3326
|
-
|
|
3327
|
-
|
|
3328
|
-
} = _ref3;
|
|
3899
|
+
const onMeasurementItemEditHandler = ({
|
|
3900
|
+
uid,
|
|
3901
|
+
isActive
|
|
3902
|
+
}) => {
|
|
3329
3903
|
const measurement = measurementService.getMeasurement(uid);
|
|
3330
3904
|
//Todo: why we are jumping to image?
|
|
3331
3905
|
// jumpToImage({ id, isActive });
|
|
3332
3906
|
|
|
3333
|
-
const onSubmitHandler =
|
|
3334
|
-
|
|
3335
|
-
|
|
3336
|
-
|
|
3337
|
-
} = _ref4;
|
|
3907
|
+
const onSubmitHandler = ({
|
|
3908
|
+
action,
|
|
3909
|
+
value
|
|
3910
|
+
}) => {
|
|
3338
3911
|
switch (action.id) {
|
|
3339
3912
|
case 'save':
|
|
3340
3913
|
{
|
|
@@ -3353,18 +3926,17 @@ function PanelMeasurementTable(_ref) {
|
|
|
3353
3926
|
centralize: true,
|
|
3354
3927
|
isDraggable: false,
|
|
3355
3928
|
showOverlay: true,
|
|
3356
|
-
content: ui_src/* Dialog */.
|
|
3929
|
+
content: ui_src/* Dialog */.lG,
|
|
3357
3930
|
contentProps: {
|
|
3358
3931
|
title: 'Annotation',
|
|
3359
3932
|
noCloseButton: true,
|
|
3360
3933
|
value: {
|
|
3361
3934
|
label: measurement.label || ''
|
|
3362
3935
|
},
|
|
3363
|
-
body:
|
|
3364
|
-
|
|
3365
|
-
|
|
3366
|
-
|
|
3367
|
-
} = _ref5;
|
|
3936
|
+
body: ({
|
|
3937
|
+
value,
|
|
3938
|
+
setValue
|
|
3939
|
+
}) => {
|
|
3368
3940
|
const onChangeHandler = event => {
|
|
3369
3941
|
event.persist();
|
|
3370
3942
|
setValue(value => ({
|
|
@@ -3382,7 +3954,7 @@ function PanelMeasurementTable(_ref) {
|
|
|
3382
3954
|
});
|
|
3383
3955
|
}
|
|
3384
3956
|
};
|
|
3385
|
-
return /*#__PURE__*/react.createElement(ui_src/* Input */.
|
|
3957
|
+
return /*#__PURE__*/react.createElement(ui_src/* Input */.pd, {
|
|
3386
3958
|
label: "Enter your annotation",
|
|
3387
3959
|
labelClassName: "text-white text-[14px] leading-[1.2]",
|
|
3388
3960
|
autoFocus: true,
|
|
@@ -3397,21 +3969,20 @@ function PanelMeasurementTable(_ref) {
|
|
|
3397
3969
|
actions: [{
|
|
3398
3970
|
id: 'cancel',
|
|
3399
3971
|
text: 'Cancel',
|
|
3400
|
-
type: ui_src/* ButtonEnums.type */.
|
|
3972
|
+
type: ui_src/* ButtonEnums.type */.Ny.NW.secondary
|
|
3401
3973
|
}, {
|
|
3402
3974
|
id: 'save',
|
|
3403
3975
|
text: 'Save',
|
|
3404
|
-
type: ui_src/* ButtonEnums.type */.
|
|
3976
|
+
type: ui_src/* ButtonEnums.type */.Ny.NW.primary
|
|
3405
3977
|
}],
|
|
3406
3978
|
onSubmit: onSubmitHandler
|
|
3407
3979
|
}
|
|
3408
3980
|
});
|
|
3409
3981
|
};
|
|
3410
|
-
const onMeasurementItemClickHandler =
|
|
3411
|
-
|
|
3412
|
-
|
|
3413
|
-
|
|
3414
|
-
} = _ref6;
|
|
3982
|
+
const onMeasurementItemClickHandler = ({
|
|
3983
|
+
uid,
|
|
3984
|
+
isActive
|
|
3985
|
+
}) => {
|
|
3415
3986
|
if (!isActive) {
|
|
3416
3987
|
const measurements = [...displayMeasurements];
|
|
3417
3988
|
const measurement = measurements.find(m => m.uid === uid);
|
|
@@ -3423,22 +3994,27 @@ function PanelMeasurementTable(_ref) {
|
|
|
3423
3994
|
return /*#__PURE__*/react.createElement(react.Fragment, null, /*#__PURE__*/react.createElement("div", {
|
|
3424
3995
|
className: "ohif-scrollbar overflow-y-auto overflow-x-hidden",
|
|
3425
3996
|
"data-cy": 'measurements-panel'
|
|
3426
|
-
}, /*#__PURE__*/react.createElement(ui_src/* MeasurementTable */.
|
|
3427
|
-
title:
|
|
3997
|
+
}, /*#__PURE__*/react.createElement(ui_src/* MeasurementTable */.V, {
|
|
3998
|
+
title: t('Measurements'),
|
|
3428
3999
|
servicesManager: servicesManager,
|
|
3429
4000
|
data: displayMeasurements,
|
|
3430
4001
|
onClick: jumpToImage,
|
|
3431
4002
|
onEdit: onMeasurementItemEditHandler
|
|
3432
4003
|
})), /*#__PURE__*/react.createElement("div", {
|
|
3433
4004
|
className: "flex justify-center p-4"
|
|
3434
|
-
}, /*#__PURE__*/react.createElement(
|
|
3435
|
-
|
|
3436
|
-
|
|
3437
|
-
|
|
4005
|
+
}, /*#__PURE__*/react.createElement(ui_src/* ActionButtons */.wr, {
|
|
4006
|
+
t: t('MeasurementTable'),
|
|
4007
|
+
actions: [{
|
|
4008
|
+
label: 'Export',
|
|
4009
|
+
onClick: exportReport
|
|
4010
|
+
}, {
|
|
4011
|
+
label: 'Create Report',
|
|
4012
|
+
onClick: createReport
|
|
4013
|
+
}]
|
|
3438
4014
|
})));
|
|
3439
4015
|
}
|
|
3440
4016
|
PanelMeasurementTable.propTypes = {
|
|
3441
|
-
servicesManager: prop_types_default().instanceOf(src/* ServicesManager */.
|
|
4017
|
+
servicesManager: prop_types_default().instanceOf(src/* ServicesManager */.CS).isRequired
|
|
3442
4018
|
};
|
|
3443
4019
|
function _getMappedMeasurements(measurementService) {
|
|
3444
4020
|
const measurements = measurementService.getMeasurements();
|
|
@@ -3495,21 +4071,23 @@ function _mapMeasurementToDisplay(measurement, index, types) {
|
|
|
3495
4071
|
|
|
3496
4072
|
|
|
3497
4073
|
|
|
4074
|
+
// EXTERNAL MODULE: ../../../node_modules/i18next/dist/esm/i18next.js
|
|
4075
|
+
var i18next = __webpack_require__(92344);
|
|
3498
4076
|
;// CONCATENATED MODULE: ../../../extensions/default/src/getPanelModule.tsx
|
|
3499
4077
|
|
|
3500
4078
|
|
|
3501
4079
|
|
|
4080
|
+
|
|
3502
4081
|
// TODO:
|
|
3503
4082
|
// - No loading UI exists yet
|
|
3504
4083
|
// - cancel promises when component is destroyed
|
|
3505
4084
|
// - show errors in UI for thumbnails if promise fails
|
|
3506
4085
|
|
|
3507
|
-
function getPanelModule(
|
|
3508
|
-
|
|
3509
|
-
|
|
3510
|
-
|
|
3511
|
-
|
|
3512
|
-
} = _ref;
|
|
4086
|
+
function getPanelModule({
|
|
4087
|
+
commandsManager,
|
|
4088
|
+
extensionManager,
|
|
4089
|
+
servicesManager
|
|
4090
|
+
}) {
|
|
3513
4091
|
const wrappedMeasurementPanel = () => {
|
|
3514
4092
|
return /*#__PURE__*/react.createElement(PanelMeasurementTable, {
|
|
3515
4093
|
commandsManager: commandsManager,
|
|
@@ -3521,7 +4099,7 @@ function getPanelModule(_ref) {
|
|
|
3521
4099
|
name: 'seriesList',
|
|
3522
4100
|
iconName: 'tab-studies',
|
|
3523
4101
|
iconLabel: 'Studies',
|
|
3524
|
-
label: 'Studies',
|
|
4102
|
+
label: i18next/* default */.A.t('SidePanel:Studies'),
|
|
3525
4103
|
component: Panels_WrappedPanelStudyBrowser.bind(null, {
|
|
3526
4104
|
commandsManager,
|
|
3527
4105
|
extensionManager,
|
|
@@ -3531,28 +4109,28 @@ function getPanelModule(_ref) {
|
|
|
3531
4109
|
name: 'measure',
|
|
3532
4110
|
iconName: 'tab-linear',
|
|
3533
4111
|
iconLabel: 'Measure',
|
|
3534
|
-
label: 'Measurements',
|
|
3535
|
-
secondaryLabel: 'Measurements',
|
|
4112
|
+
label: i18next/* default */.A.t('SidePanel:Measurements'),
|
|
4113
|
+
secondaryLabel: i18next/* default */.A.t('SidePanel:Measurements'),
|
|
3536
4114
|
component: wrappedMeasurementPanel
|
|
3537
4115
|
}];
|
|
3538
4116
|
}
|
|
3539
4117
|
/* harmony default export */ const src_getPanelModule = (getPanelModule);
|
|
3540
4118
|
// EXTERNAL MODULE: ../../core/src/utils/isImage.js
|
|
3541
|
-
var isImage = __webpack_require__(
|
|
4119
|
+
var isImage = __webpack_require__(8094);
|
|
3542
4120
|
// EXTERNAL MODULE: ../../core/src/utils/sopClassDictionary.js
|
|
3543
|
-
var sopClassDictionary = __webpack_require__(
|
|
4121
|
+
var sopClassDictionary = __webpack_require__(48085);
|
|
3544
4122
|
// EXTERNAL MODULE: ../../core/src/classes/ImageSet.ts
|
|
3545
|
-
var ImageSet = __webpack_require__(
|
|
4123
|
+
var ImageSet = __webpack_require__(14169);
|
|
3546
4124
|
// EXTERNAL MODULE: ../../core/src/utils/isDisplaySetReconstructable.js
|
|
3547
|
-
var isDisplaySetReconstructable = __webpack_require__(
|
|
4125
|
+
var isDisplaySetReconstructable = __webpack_require__(13835);
|
|
3548
4126
|
;// CONCATENATED MODULE: ../../../extensions/default/package.json
|
|
3549
|
-
const package_namespaceObject = JSON.parse('{"
|
|
4127
|
+
const package_namespaceObject = /*#__PURE__*/JSON.parse('{"UU":"@ohif/extension-default"}');
|
|
3550
4128
|
;// CONCATENATED MODULE: ../../../extensions/default/src/id.js
|
|
3551
4129
|
|
|
3552
|
-
const id = package_namespaceObject.
|
|
4130
|
+
const id = package_namespaceObject.UU;
|
|
3553
4131
|
|
|
3554
4132
|
// EXTERNAL MODULE: ../../core/src/utils/sortInstancesByPosition.ts
|
|
3555
|
-
var sortInstancesByPosition = __webpack_require__(
|
|
4133
|
+
var sortInstancesByPosition = __webpack_require__(44563);
|
|
3556
4134
|
;// CONCATENATED MODULE: ../../../extensions/default/src/utils/validations/checkMultiframe.ts
|
|
3557
4135
|
|
|
3558
4136
|
|
|
@@ -3563,18 +4141,18 @@ var sortInstancesByPosition = __webpack_require__(87425);
|
|
|
3563
4141
|
* @param {*} warnings
|
|
3564
4142
|
*/
|
|
3565
4143
|
function checkMultiFrame(multiFrameInstance, messages) {
|
|
3566
|
-
if (!(0,isDisplaySetReconstructable/* hasPixelMeasurements */.
|
|
3567
|
-
messages.addMessage(src/* DisplaySetMessage */.
|
|
4144
|
+
if (!(0,isDisplaySetReconstructable/* hasPixelMeasurements */.Yt)(multiFrameInstance)) {
|
|
4145
|
+
messages.addMessage(src/* DisplaySetMessage */.Ob.CODES.MULTIFRAME_NO_PIXEL_MEASUREMENTS);
|
|
3568
4146
|
}
|
|
3569
|
-
if (!(0,isDisplaySetReconstructable/* hasOrientation */.
|
|
3570
|
-
messages.addMessage(src/* DisplaySetMessage */.
|
|
4147
|
+
if (!(0,isDisplaySetReconstructable/* hasOrientation */.VX)(multiFrameInstance)) {
|
|
4148
|
+
messages.addMessage(src/* DisplaySetMessage */.Ob.CODES.MULTIFRAME_NO_ORIENTATION);
|
|
3571
4149
|
}
|
|
3572
|
-
if (!(0,isDisplaySetReconstructable/* hasPosition */.
|
|
3573
|
-
messages.addMessage(src/* DisplaySetMessage */.
|
|
4150
|
+
if (!(0,isDisplaySetReconstructable/* hasPosition */.sL)(multiFrameInstance)) {
|
|
4151
|
+
messages.addMessage(src/* DisplaySetMessage */.Ob.CODES.MULTIFRAME_NO_POSITION_INFORMATION);
|
|
3574
4152
|
}
|
|
3575
4153
|
}
|
|
3576
4154
|
// EXTERNAL MODULE: ../../core/src/utils/toNumber.js
|
|
3577
|
-
var toNumber = __webpack_require__(
|
|
4155
|
+
var toNumber = __webpack_require__(58099);
|
|
3578
4156
|
;// CONCATENATED MODULE: ../../../extensions/default/src/utils/validations/areAllImageDimensionsEqual.ts
|
|
3579
4157
|
|
|
3580
4158
|
|
|
@@ -3588,8 +4166,8 @@ function areAllImageDimensionsEqual(instances) {
|
|
|
3588
4166
|
return false;
|
|
3589
4167
|
}
|
|
3590
4168
|
const firstImage = instances[0];
|
|
3591
|
-
const firstImageRows = (0,toNumber/* default */.
|
|
3592
|
-
const firstImageColumns = (0,toNumber/* default */.
|
|
4169
|
+
const firstImageRows = (0,toNumber/* default */.A)(firstImage.Rows);
|
|
4170
|
+
const firstImageColumns = (0,toNumber/* default */.A)(firstImage.Columns);
|
|
3593
4171
|
for (let i = 1; i < instances.length; i++) {
|
|
3594
4172
|
const instance = instances[i];
|
|
3595
4173
|
const {
|
|
@@ -3615,7 +4193,7 @@ function areAllImageComponentsEqual(instances) {
|
|
|
3615
4193
|
return false;
|
|
3616
4194
|
}
|
|
3617
4195
|
const firstImage = instances[0];
|
|
3618
|
-
const firstImageSamplesPerPixel = (0,toNumber/* default */.
|
|
4196
|
+
const firstImageSamplesPerPixel = (0,toNumber/* default */.A)(firstImage.SamplesPerPixel);
|
|
3619
4197
|
for (let i = 1; i < instances.length; i++) {
|
|
3620
4198
|
const instance = instances[i];
|
|
3621
4199
|
const {
|
|
@@ -3641,18 +4219,18 @@ function areAllImageOrientationsEqual(instances) {
|
|
|
3641
4219
|
return false;
|
|
3642
4220
|
}
|
|
3643
4221
|
const firstImage = instances[0];
|
|
3644
|
-
const firstImageOrientationPatient = (0,toNumber/* default */.
|
|
4222
|
+
const firstImageOrientationPatient = (0,toNumber/* default */.A)(firstImage.ImageOrientationPatient);
|
|
3645
4223
|
for (let i = 1; i < instances.length; i++) {
|
|
3646
4224
|
const instance = instances[i];
|
|
3647
|
-
const imageOrientationPatient = (0,toNumber/* default */.
|
|
3648
|
-
if (!(0,isDisplaySetReconstructable/* _isSameOrientation */.
|
|
4225
|
+
const imageOrientationPatient = (0,toNumber/* default */.A)(instance.ImageOrientationPatient);
|
|
4226
|
+
if (!(0,isDisplaySetReconstructable/* _isSameOrientation */.sW)(imageOrientationPatient, firstImageOrientationPatient)) {
|
|
3649
4227
|
return false;
|
|
3650
4228
|
}
|
|
3651
4229
|
}
|
|
3652
4230
|
return true;
|
|
3653
4231
|
}
|
|
3654
|
-
// EXTERNAL MODULE: ../../../node_modules/gl-matrix/esm/index.js +
|
|
3655
|
-
var esm = __webpack_require__(
|
|
4232
|
+
// EXTERNAL MODULE: ../../../node_modules/gl-matrix/esm/index.js + 1 modules
|
|
4233
|
+
var esm = __webpack_require__(44753);
|
|
3656
4234
|
;// CONCATENATED MODULE: ../../../extensions/default/src/utils/calculateScanAxisNormal.ts
|
|
3657
4235
|
|
|
3658
4236
|
|
|
@@ -3662,9 +4240,9 @@ var esm = __webpack_require__(45451);
|
|
|
3662
4240
|
* @returns
|
|
3663
4241
|
*/
|
|
3664
4242
|
function calculateScanAxisNormal(imageOrientation) {
|
|
3665
|
-
const rowCosineVec = esm/* vec3.fromValues */.
|
|
3666
|
-
const colCosineVec = esm/* vec3.fromValues */.
|
|
3667
|
-
return esm/* vec3.cross */.
|
|
4243
|
+
const rowCosineVec = esm/* vec3.fromValues */.eR.fromValues(imageOrientation[0], imageOrientation[1], imageOrientation[2]);
|
|
4244
|
+
const colCosineVec = esm/* vec3.fromValues */.eR.fromValues(imageOrientation[3], imageOrientation[4], imageOrientation[5]);
|
|
4245
|
+
return esm/* vec3.cross */.eR.cross(esm/* vec3.create */.eR.create(), rowCosineVec, colCosineVec);
|
|
3668
4246
|
}
|
|
3669
4247
|
;// CONCATENATED MODULE: ../../../extensions/default/src/utils/validations/areAllImagePositionsEqual.ts
|
|
3670
4248
|
|
|
@@ -3683,8 +4261,8 @@ function calculateScanAxisNormal(imageOrientation) {
|
|
|
3683
4261
|
function _checkSeriesPositionShift(previousPosition, actualPosition, scanAxisNormal, averageSpacingBetweenFrames) {
|
|
3684
4262
|
// predicted position should be the previous position added by the multiplication
|
|
3685
4263
|
// of the scanAxisNormal and the average spacing between frames
|
|
3686
|
-
const predictedPosition = esm/* vec3.scaleAndAdd */.
|
|
3687
|
-
return esm/* vec3.distance */.
|
|
4264
|
+
const predictedPosition = esm/* vec3.scaleAndAdd */.eR.scaleAndAdd(esm/* vec3.create */.eR.create(), previousPosition, scanAxisNormal, averageSpacingBetweenFrames);
|
|
4265
|
+
return esm/* vec3.distance */.eR.distance(actualPosition, predictedPosition) > averageSpacingBetweenFrames;
|
|
3688
4266
|
}
|
|
3689
4267
|
|
|
3690
4268
|
/**
|
|
@@ -3696,18 +4274,18 @@ function areAllImagePositionsEqual(instances) {
|
|
|
3696
4274
|
if (!instances?.length) {
|
|
3697
4275
|
return false;
|
|
3698
4276
|
}
|
|
3699
|
-
const firstImageOrientationPatient = (0,toNumber/* default */.
|
|
4277
|
+
const firstImageOrientationPatient = (0,toNumber/* default */.A)(instances[0].ImageOrientationPatient);
|
|
3700
4278
|
if (!firstImageOrientationPatient) {
|
|
3701
4279
|
return false;
|
|
3702
4280
|
}
|
|
3703
4281
|
const scanAxisNormal = calculateScanAxisNormal(firstImageOrientationPatient);
|
|
3704
|
-
const firstImagePositionPatient = (0,toNumber/* default */.
|
|
3705
|
-
const lastIpp = (0,toNumber/* default */.
|
|
3706
|
-
const averageSpacingBetweenFrames = (0,isDisplaySetReconstructable/* _getPerpendicularDistance */.
|
|
4282
|
+
const firstImagePositionPatient = (0,toNumber/* default */.A)(instances[0].ImagePositionPatient);
|
|
4283
|
+
const lastIpp = (0,toNumber/* default */.A)(instances[instances.length - 1].ImagePositionPatient);
|
|
4284
|
+
const averageSpacingBetweenFrames = (0,isDisplaySetReconstructable/* _getPerpendicularDistance */.jj)(firstImagePositionPatient, lastIpp) / (instances.length - 1);
|
|
3707
4285
|
let previousImagePositionPatient = firstImagePositionPatient;
|
|
3708
4286
|
for (let i = 1; i < instances.length; i++) {
|
|
3709
4287
|
const instance = instances[i];
|
|
3710
|
-
const imagePositionPatient = (0,toNumber/* default */.
|
|
4288
|
+
const imagePositionPatient = (0,toNumber/* default */.A)(instance.ImagePositionPatient);
|
|
3711
4289
|
if (_checkSeriesPositionShift(previousImagePositionPatient, imagePositionPatient, scanAxisNormal, averageSpacingBetweenFrames)) {
|
|
3712
4290
|
return false;
|
|
3713
4291
|
}
|
|
@@ -3728,29 +4306,29 @@ function areAllImageSpacingEqual(instances, messages) {
|
|
|
3728
4306
|
if (!instances?.length) {
|
|
3729
4307
|
return;
|
|
3730
4308
|
}
|
|
3731
|
-
const firstImagePositionPatient = (0,toNumber/* default */.
|
|
4309
|
+
const firstImagePositionPatient = (0,toNumber/* default */.A)(instances[0].ImagePositionPatient);
|
|
3732
4310
|
if (!firstImagePositionPatient) {
|
|
3733
4311
|
return;
|
|
3734
4312
|
}
|
|
3735
|
-
const lastIpp = (0,toNumber/* default */.
|
|
3736
|
-
const averageSpacingBetweenFrames = (0,isDisplaySetReconstructable/* _getPerpendicularDistance */.
|
|
4313
|
+
const lastIpp = (0,toNumber/* default */.A)(instances[instances.length - 1].ImagePositionPatient);
|
|
4314
|
+
const averageSpacingBetweenFrames = (0,isDisplaySetReconstructable/* _getPerpendicularDistance */.jj)(firstImagePositionPatient, lastIpp) / (instances.length - 1);
|
|
3737
4315
|
let previousImagePositionPatient = firstImagePositionPatient;
|
|
3738
4316
|
const issuesFound = [];
|
|
3739
4317
|
for (let i = 1; i < instances.length; i++) {
|
|
3740
4318
|
const instance = instances[i];
|
|
3741
|
-
const imagePositionPatient = (0,toNumber/* default */.
|
|
3742
|
-
const spacingBetweenFrames = (0,isDisplaySetReconstructable/* _getPerpendicularDistance */.
|
|
3743
|
-
const spacingIssue = (0,isDisplaySetReconstructable/* _getSpacingIssue */.
|
|
4319
|
+
const imagePositionPatient = (0,toNumber/* default */.A)(instance.ImagePositionPatient);
|
|
4320
|
+
const spacingBetweenFrames = (0,isDisplaySetReconstructable/* _getPerpendicularDistance */.jj)(imagePositionPatient, previousImagePositionPatient);
|
|
4321
|
+
const spacingIssue = (0,isDisplaySetReconstructable/* _getSpacingIssue */.Op)(spacingBetweenFrames, averageSpacingBetweenFrames);
|
|
3744
4322
|
if (spacingIssue) {
|
|
3745
4323
|
const issue = spacingIssue.issue;
|
|
3746
4324
|
|
|
3747
4325
|
// avoid multiple warning of the same thing
|
|
3748
4326
|
if (!issuesFound.includes(issue)) {
|
|
3749
4327
|
issuesFound.push(issue);
|
|
3750
|
-
if (issue === isDisplaySetReconstructable/* reconstructionIssues */.
|
|
3751
|
-
messages.addMessage(src/* DisplaySetMessage */.
|
|
3752
|
-
} else if (issue === isDisplaySetReconstructable/* reconstructionIssues */.
|
|
3753
|
-
messages.addMessage(src/* DisplaySetMessage */.
|
|
4328
|
+
if (issue === isDisplaySetReconstructable/* reconstructionIssues */.JG.MISSING_FRAMES) {
|
|
4329
|
+
messages.addMessage(src/* DisplaySetMessage */.Ob.CODES.MISSING_FRAMES);
|
|
4330
|
+
} else if (issue === isDisplaySetReconstructable/* reconstructionIssues */.JG.IRREGULAR_SPACING) {
|
|
4331
|
+
messages.addMessage(src/* DisplaySetMessage */.Ob.CODES.IRREGULAR_SPACING);
|
|
3754
4332
|
}
|
|
3755
4333
|
}
|
|
3756
4334
|
// we just want to find issues not how many
|
|
@@ -3777,16 +4355,16 @@ function areAllImageSpacingEqual(instances, messages) {
|
|
|
3777
4355
|
function checkSingleFrames(instances, messages) {
|
|
3778
4356
|
if (instances.length > 2) {
|
|
3779
4357
|
if (!areAllImageDimensionsEqual(instances)) {
|
|
3780
|
-
messages.addMessage(src/* DisplaySetMessage */.
|
|
4358
|
+
messages.addMessage(src/* DisplaySetMessage */.Ob.CODES.INCONSISTENT_DIMENSIONS);
|
|
3781
4359
|
}
|
|
3782
4360
|
if (!areAllImageComponentsEqual(instances)) {
|
|
3783
|
-
messages.addMessage(src/* DisplaySetMessage */.
|
|
4361
|
+
messages.addMessage(src/* DisplaySetMessage */.Ob.CODES.INCONSISTENT_COMPONENTS);
|
|
3784
4362
|
}
|
|
3785
4363
|
if (!areAllImageOrientationsEqual(instances)) {
|
|
3786
|
-
messages.addMessage(src/* DisplaySetMessage */.
|
|
4364
|
+
messages.addMessage(src/* DisplaySetMessage */.Ob.CODES.INCONSISTENT_ORIENTATIONS);
|
|
3787
4365
|
}
|
|
3788
4366
|
if (!areAllImagePositionsEqual(instances)) {
|
|
3789
|
-
messages.addMessage(src/* DisplaySetMessage */.
|
|
4367
|
+
messages.addMessage(src/* DisplaySetMessage */.Ob.CODES.INCONSISTENT_POSITION_INFORMATION);
|
|
3790
4368
|
}
|
|
3791
4369
|
areAllImageSpacingEqual(instances, messages);
|
|
3792
4370
|
}
|
|
@@ -3802,10 +4380,13 @@ function checkSingleFrames(instances, messages) {
|
|
|
3802
4380
|
*
|
|
3803
4381
|
* @param {Object[]} instances An array of `OHIFInstanceMetadata` objects.
|
|
3804
4382
|
*/
|
|
3805
|
-
function getDisplaySetMessages(instances, isReconstructable) {
|
|
3806
|
-
const messages = new src/* DisplaySetMessageList */.
|
|
4383
|
+
function getDisplaySetMessages(instances, isReconstructable, isDynamicVolume) {
|
|
4384
|
+
const messages = new src/* DisplaySetMessageList */.WZ();
|
|
4385
|
+
if (isDynamicVolume) {
|
|
4386
|
+
return messages;
|
|
4387
|
+
}
|
|
3807
4388
|
if (!instances.length) {
|
|
3808
|
-
messages.addMessage(src/* DisplaySetMessage */.
|
|
4389
|
+
messages.addMessage(src/* DisplaySetMessage */.Ob.CODES.NO_VALID_INSTANCES);
|
|
3809
4390
|
return;
|
|
3810
4391
|
}
|
|
3811
4392
|
const firstInstance = instances[0];
|
|
@@ -3818,18 +4399,18 @@ function getDisplaySetMessages(instances, isReconstructable) {
|
|
|
3818
4399
|
if (ImageType?.includes('LOCALIZER')) {
|
|
3819
4400
|
return messages;
|
|
3820
4401
|
}
|
|
3821
|
-
if (!isDisplaySetReconstructable/* constructableModalities */.
|
|
4402
|
+
if (!isDisplaySetReconstructable/* constructableModalities */.Hf.includes(Modality)) {
|
|
3822
4403
|
return messages;
|
|
3823
4404
|
}
|
|
3824
4405
|
const isMultiframe = NumberOfFrames > 1;
|
|
3825
4406
|
// Can't reconstruct if all instances don't have the ImagePositionPatient.
|
|
3826
4407
|
if (!isMultiframe && !instances.every(instance => instance.ImagePositionPatient)) {
|
|
3827
|
-
messages.addMessage(src/* DisplaySetMessage */.
|
|
4408
|
+
messages.addMessage(src/* DisplaySetMessage */.Ob.CODES.NO_POSITION_INFORMATION);
|
|
3828
4409
|
}
|
|
3829
|
-
const sortedInstances = (0,sortInstancesByPosition/* default */.
|
|
4410
|
+
const sortedInstances = (0,sortInstancesByPosition/* default */.A)(instances);
|
|
3830
4411
|
isMultiframe ? checkMultiFrame(sortedInstances[0], messages) : checkSingleFrames(sortedInstances, messages);
|
|
3831
4412
|
if (!isReconstructable) {
|
|
3832
|
-
messages.addMessage(src/* DisplaySetMessage */.
|
|
4413
|
+
messages.addMessage(src/* DisplaySetMessage */.Ob.CODES.NOT_RECONSTRUCTABLE);
|
|
3833
4414
|
}
|
|
3834
4415
|
return messages;
|
|
3835
4416
|
}
|
|
@@ -3840,9 +4421,9 @@ function getDisplaySetMessages(instances, isReconstructable) {
|
|
|
3840
4421
|
* Default handler for a instance list with an unsupported sopClassUID
|
|
3841
4422
|
*/
|
|
3842
4423
|
function getDisplaySetsFromUnsupportedSeries(instances) {
|
|
3843
|
-
const imageSet = new ImageSet/* default */.
|
|
3844
|
-
const messages = new src/* DisplaySetMessageList */.
|
|
3845
|
-
messages.addMessage(src/* DisplaySetMessage */.
|
|
4424
|
+
const imageSet = new ImageSet/* default */.A(instances);
|
|
4425
|
+
const messages = new src/* DisplaySetMessageList */.WZ();
|
|
4426
|
+
messages.addMessage(src/* DisplaySetMessage */.Ob.CODES.UNSUPPORTED_DISPLAYSET);
|
|
3846
4427
|
const instance = instances[0];
|
|
3847
4428
|
imageSet.setAttributes({
|
|
3848
4429
|
displaySetInstanceUID: imageSet.uid,
|
|
@@ -3864,6 +4445,86 @@ function getDisplaySetsFromUnsupportedSeries(instances) {
|
|
|
3864
4445
|
});
|
|
3865
4446
|
return [imageSet];
|
|
3866
4447
|
}
|
|
4448
|
+
;// CONCATENATED MODULE: ../../../extensions/default/src/SOPClassHandlers/chartSOPClassHandler.ts
|
|
4449
|
+
|
|
4450
|
+
|
|
4451
|
+
const SOPClassHandlerName = 'chart';
|
|
4452
|
+
const CHART_MODALITY = 'CHT';
|
|
4453
|
+
|
|
4454
|
+
// Private SOPClassUid for chart data
|
|
4455
|
+
const ChartDataSOPClassUid = '1.9.451.13215.7.3.2.7.6.1';
|
|
4456
|
+
const sopClassUids = [ChartDataSOPClassUid];
|
|
4457
|
+
const makeChartDataDisplaySet = (instance, sopClassUids) => {
|
|
4458
|
+
const {
|
|
4459
|
+
StudyInstanceUID,
|
|
4460
|
+
SeriesInstanceUID,
|
|
4461
|
+
SOPInstanceUID,
|
|
4462
|
+
SeriesDescription,
|
|
4463
|
+
SeriesNumber,
|
|
4464
|
+
SeriesDate,
|
|
4465
|
+
SOPClassUID
|
|
4466
|
+
} = instance;
|
|
4467
|
+
return {
|
|
4468
|
+
Modality: CHART_MODALITY,
|
|
4469
|
+
loading: false,
|
|
4470
|
+
isReconstructable: false,
|
|
4471
|
+
displaySetInstanceUID: src.utils.guid(),
|
|
4472
|
+
SeriesDescription,
|
|
4473
|
+
SeriesNumber,
|
|
4474
|
+
SeriesDate,
|
|
4475
|
+
SOPInstanceUID,
|
|
4476
|
+
SeriesInstanceUID,
|
|
4477
|
+
StudyInstanceUID,
|
|
4478
|
+
SOPClassHandlerId: `${id}.sopClassHandlerModule.${SOPClassHandlerName}`,
|
|
4479
|
+
SOPClassUID,
|
|
4480
|
+
isDerivedDisplaySet: true,
|
|
4481
|
+
isLoaded: true,
|
|
4482
|
+
sopClassUids,
|
|
4483
|
+
instance,
|
|
4484
|
+
instances: [instance],
|
|
4485
|
+
/**
|
|
4486
|
+
* Adds instances to the chart displaySet, rather than creating a new one
|
|
4487
|
+
* when user moves to a different workflow step and gets back to a step that
|
|
4488
|
+
* recreates the chart
|
|
4489
|
+
*/
|
|
4490
|
+
addInstances: function (instances, _displaySetService) {
|
|
4491
|
+
this.instances.push(...instances);
|
|
4492
|
+
this.instance = this.instances[this.instances.length - 1];
|
|
4493
|
+
return this;
|
|
4494
|
+
}
|
|
4495
|
+
};
|
|
4496
|
+
};
|
|
4497
|
+
function getSopClassUids(instances) {
|
|
4498
|
+
const uniqueSopClassUidsInSeries = new Set();
|
|
4499
|
+
instances.forEach(instance => {
|
|
4500
|
+
uniqueSopClassUidsInSeries.add(instance.SOPClassUID);
|
|
4501
|
+
});
|
|
4502
|
+
const sopClassUids = Array.from(uniqueSopClassUidsInSeries);
|
|
4503
|
+
return sopClassUids;
|
|
4504
|
+
}
|
|
4505
|
+
function _getDisplaySetsFromSeries(instances) {
|
|
4506
|
+
debugger;
|
|
4507
|
+
// If the series has no instances, stop here
|
|
4508
|
+
if (!instances || !instances.length) {
|
|
4509
|
+
throw new Error('No instances were provided');
|
|
4510
|
+
}
|
|
4511
|
+
const sopClassUids = getSopClassUids(instances);
|
|
4512
|
+
const displaySets = instances.map(instance => {
|
|
4513
|
+
if (instance.Modality === CHART_MODALITY) {
|
|
4514
|
+
return makeChartDataDisplaySet(instance, sopClassUids);
|
|
4515
|
+
}
|
|
4516
|
+
throw new Error('Unsupported modality');
|
|
4517
|
+
});
|
|
4518
|
+
return displaySets;
|
|
4519
|
+
}
|
|
4520
|
+
const chartHandler = {
|
|
4521
|
+
name: SOPClassHandlerName,
|
|
4522
|
+
sopClassUids,
|
|
4523
|
+
getDisplaySetsFromSeries: instances => {
|
|
4524
|
+
return _getDisplaySetsFromSeries(instances);
|
|
4525
|
+
}
|
|
4526
|
+
};
|
|
4527
|
+
|
|
3867
4528
|
;// CONCATENATED MODULE: ../../../extensions/default/src/getSopClassHandlerModule.js
|
|
3868
4529
|
|
|
3869
4530
|
|
|
@@ -3872,20 +4533,69 @@ function getDisplaySetsFromUnsupportedSeries(instances) {
|
|
|
3872
4533
|
|
|
3873
4534
|
|
|
3874
4535
|
|
|
4536
|
+
|
|
4537
|
+
const DEFAULT_VOLUME_LOADER_SCHEME = 'cornerstoneStreamingImageVolume';
|
|
4538
|
+
const DYNAMIC_VOLUME_LOADER_SCHEME = 'cornerstoneStreamingDynamicImageVolume';
|
|
3875
4539
|
const sopClassHandlerName = 'stack';
|
|
4540
|
+
let appContext = {};
|
|
4541
|
+
const getDynamicVolumeInfo = instances => {
|
|
4542
|
+
const {
|
|
4543
|
+
extensionManager
|
|
4544
|
+
} = appContext;
|
|
4545
|
+
if (!extensionManager) {
|
|
4546
|
+
throw new Error('extensionManager is not available');
|
|
4547
|
+
}
|
|
4548
|
+
const imageIds = instances.map(({
|
|
4549
|
+
imageId
|
|
4550
|
+
}) => imageId);
|
|
4551
|
+
const volumeLoaderUtility = extensionManager.getModuleEntry('@ohif/extension-cornerstone.utilityModule.volumeLoader');
|
|
4552
|
+
const {
|
|
4553
|
+
getDynamicVolumeInfo: csGetDynamicVolumeInfo
|
|
4554
|
+
} = volumeLoaderUtility.exports;
|
|
4555
|
+
return csGetDynamicVolumeInfo(imageIds);
|
|
4556
|
+
};
|
|
3876
4557
|
const isMultiFrame = instance => {
|
|
3877
4558
|
return instance.NumberOfFrames > 1;
|
|
3878
4559
|
};
|
|
4560
|
+
function getDisplaySetInfo(instances) {
|
|
4561
|
+
const dynamicVolumeInfo = getDynamicVolumeInfo(instances);
|
|
4562
|
+
const {
|
|
4563
|
+
isDynamicVolume,
|
|
4564
|
+
timePoints
|
|
4565
|
+
} = dynamicVolumeInfo;
|
|
4566
|
+
let displaySetInfo;
|
|
4567
|
+
if (isDynamicVolume) {
|
|
4568
|
+
const timePoint = timePoints[0];
|
|
4569
|
+
const instancesMap = new Map();
|
|
4570
|
+
|
|
4571
|
+
// O(n) to convert it into a map and O(1) to find each instance
|
|
4572
|
+
instances.forEach(instance => instancesMap.set(instance.imageId, instance));
|
|
4573
|
+
const firstTimePointInstances = timePoint.map(imageId => instancesMap.get(imageId));
|
|
4574
|
+
displaySetInfo = (0,isDisplaySetReconstructable/* default */.Ay)(firstTimePointInstances);
|
|
4575
|
+
} else {
|
|
4576
|
+
displaySetInfo = (0,isDisplaySetReconstructable/* default */.Ay)(instances);
|
|
4577
|
+
}
|
|
4578
|
+
return {
|
|
4579
|
+
isDynamicVolume,
|
|
4580
|
+
...displaySetInfo,
|
|
4581
|
+
dynamicVolumeInfo
|
|
4582
|
+
};
|
|
4583
|
+
}
|
|
3879
4584
|
const makeDisplaySet = instances => {
|
|
3880
4585
|
const instance = instances[0];
|
|
3881
|
-
const imageSet = new ImageSet/* default */.
|
|
4586
|
+
const imageSet = new ImageSet/* default */.A(instances);
|
|
3882
4587
|
const {
|
|
4588
|
+
isDynamicVolume,
|
|
3883
4589
|
value: isReconstructable,
|
|
3884
|
-
averageSpacingBetweenFrames
|
|
3885
|
-
|
|
4590
|
+
averageSpacingBetweenFrames,
|
|
4591
|
+
dynamicVolumeInfo
|
|
4592
|
+
} = getDisplaySetInfo(instances);
|
|
4593
|
+
const volumeLoaderSchema = isDynamicVolume ? DYNAMIC_VOLUME_LOADER_SCHEME : DEFAULT_VOLUME_LOADER_SCHEME;
|
|
4594
|
+
|
|
3886
4595
|
// set appropriate attributes to image set...
|
|
3887
|
-
const messages = getDisplaySetMessages(instances, isReconstructable);
|
|
4596
|
+
const messages = getDisplaySetMessages(instances, isReconstructable, isDynamicVolume);
|
|
3888
4597
|
imageSet.setAttributes({
|
|
4598
|
+
volumeLoaderSchema,
|
|
3889
4599
|
displaySetInstanceUID: imageSet.uid,
|
|
3890
4600
|
// create a local alias for the imageSet UID
|
|
3891
4601
|
SeriesDate: instance.SeriesDate,
|
|
@@ -3903,7 +4613,9 @@ const makeDisplaySet = instances => {
|
|
|
3903
4613
|
SOPClassHandlerId: `${id}.sopClassHandlerModule.${sopClassHandlerName}`,
|
|
3904
4614
|
isReconstructable,
|
|
3905
4615
|
messages,
|
|
3906
|
-
averageSpacingBetweenFrames: averageSpacingBetweenFrames || null
|
|
4616
|
+
averageSpacingBetweenFrames: averageSpacingBetweenFrames || null,
|
|
4617
|
+
isDynamicVolume,
|
|
4618
|
+
dynamicVolumeInfo
|
|
3907
4619
|
});
|
|
3908
4620
|
|
|
3909
4621
|
// Sort the images in this series if needed
|
|
@@ -3934,7 +4646,7 @@ const makeDisplaySet = instances => {
|
|
|
3934
4646
|
const isSingleImageModality = modality => {
|
|
3935
4647
|
return modality === 'CR' || modality === 'MG' || modality === 'DX';
|
|
3936
4648
|
};
|
|
3937
|
-
function
|
|
4649
|
+
function getSopClassHandlerModule_getSopClassUids(instances) {
|
|
3938
4650
|
const uniqueSopClassUidsInSeries = new Set();
|
|
3939
4651
|
instances.forEach(instance => {
|
|
3940
4652
|
uniqueSopClassUidsInSeries.add(instance.SOPClassUID);
|
|
@@ -3948,7 +4660,6 @@ function getSopClassUids(instances) {
|
|
|
3948
4660
|
* - For all Image types that are stackable, create
|
|
3949
4661
|
* a displaySet with a stack of images
|
|
3950
4662
|
*
|
|
3951
|
-
* @param {Array} sopClassHandlerModules List of SOP Class Modules
|
|
3952
4663
|
* @param {SeriesMetadata} series The series metadata object from which the display sets will be created
|
|
3953
4664
|
* @returns {Array} The list of display sets created for the given series object
|
|
3954
4665
|
*/
|
|
@@ -3958,7 +4669,7 @@ function getDisplaySetsFromSeries(instances) {
|
|
|
3958
4669
|
throw new Error('No instances were provided');
|
|
3959
4670
|
}
|
|
3960
4671
|
const displaySets = [];
|
|
3961
|
-
const sopClassUids =
|
|
4672
|
+
const sopClassUids = getSopClassHandlerModule_getSopClassUids(instances);
|
|
3962
4673
|
|
|
3963
4674
|
// Search through the instances (InstanceMetadata object) of this series
|
|
3964
4675
|
// Split Multi-frame instances and Single-image modalities
|
|
@@ -3967,7 +4678,7 @@ function getDisplaySetsFromSeries(instances) {
|
|
|
3967
4678
|
const stackableInstances = [];
|
|
3968
4679
|
instances.forEach(instance => {
|
|
3969
4680
|
// All imaging modalities must have a valid value for sopClassUid (x00080016) or rows (x00280010)
|
|
3970
|
-
if (!(0,isImage/* isImage */.
|
|
4681
|
+
if (!(0,isImage/* isImage */.w)(instance.SOPClassUID) && !instance.Rows) {
|
|
3971
4682
|
return;
|
|
3972
4683
|
}
|
|
3973
4684
|
let displaySet;
|
|
@@ -4003,16 +4714,21 @@ function getDisplaySetsFromSeries(instances) {
|
|
|
4003
4714
|
}
|
|
4004
4715
|
return displaySets;
|
|
4005
4716
|
}
|
|
4006
|
-
const
|
|
4007
|
-
function getSopClassHandlerModule() {
|
|
4717
|
+
const getSopClassHandlerModule_sopClassUids = [sopClassDictionary/* default */.A.ComputedRadiographyImageStorage, sopClassDictionary/* default */.A.DigitalXRayImageStorageForPresentation, sopClassDictionary/* default */.A.DigitalXRayImageStorageForProcessing, sopClassDictionary/* default */.A.DigitalMammographyXRayImageStorageForPresentation, sopClassDictionary/* default */.A.DigitalMammographyXRayImageStorageForProcessing, sopClassDictionary/* default */.A.DigitalIntraOralXRayImageStorageForPresentation, sopClassDictionary/* default */.A.DigitalIntraOralXRayImageStorageForProcessing, sopClassDictionary/* default */.A.CTImageStorage, sopClassDictionary/* default */.A.EnhancedCTImageStorage, sopClassDictionary/* default */.A.LegacyConvertedEnhancedCTImageStorage, sopClassDictionary/* default */.A.UltrasoundMultiframeImageStorage, sopClassDictionary/* default */.A.MRImageStorage, sopClassDictionary/* default */.A.EnhancedMRImageStorage, sopClassDictionary/* default */.A.EnhancedMRColorImageStorage, sopClassDictionary/* default */.A.LegacyConvertedEnhancedMRImageStorage, sopClassDictionary/* default */.A.UltrasoundImageStorage, sopClassDictionary/* default */.A.UltrasoundImageStorageRET, sopClassDictionary/* default */.A.SecondaryCaptureImageStorage, sopClassDictionary/* default */.A.MultiframeSingleBitSecondaryCaptureImageStorage, sopClassDictionary/* default */.A.MultiframeGrayscaleByteSecondaryCaptureImageStorage, sopClassDictionary/* default */.A.MultiframeGrayscaleWordSecondaryCaptureImageStorage, sopClassDictionary/* default */.A.MultiframeTrueColorSecondaryCaptureImageStorage, sopClassDictionary/* default */.A.XRayAngiographicImageStorage, sopClassDictionary/* default */.A.EnhancedXAImageStorage, sopClassDictionary/* default */.A.XRayRadiofluoroscopicImageStorage, sopClassDictionary/* default */.A.EnhancedXRFImageStorage, sopClassDictionary/* default */.A.XRay3DAngiographicImageStorage, sopClassDictionary/* default */.A.XRay3DCraniofacialImageStorage, sopClassDictionary/* default */.A.BreastTomosynthesisImageStorage, sopClassDictionary/* default */.A.BreastProjectionXRayImageStorageForPresentation, sopClassDictionary/* default */.A.BreastProjectionXRayImageStorageForProcessing, sopClassDictionary/* default */.A.IntravascularOpticalCoherenceTomographyImageStorageForPresentation, sopClassDictionary/* default */.A.IntravascularOpticalCoherenceTomographyImageStorageForProcessing, sopClassDictionary/* default */.A.NuclearMedicineImageStorage, sopClassDictionary/* default */.A.VLEndoscopicImageStorage, sopClassDictionary/* default */.A.VideoEndoscopicImageStorage, sopClassDictionary/* default */.A.VLMicroscopicImageStorage, sopClassDictionary/* default */.A.VideoMicroscopicImageStorage, sopClassDictionary/* default */.A.VLSlideCoordinatesMicroscopicImageStorage, sopClassDictionary/* default */.A.VLPhotographicImageStorage, sopClassDictionary/* default */.A.VideoPhotographicImageStorage, sopClassDictionary/* default */.A.OphthalmicPhotography8BitImageStorage, sopClassDictionary/* default */.A.OphthalmicPhotography16BitImageStorage, sopClassDictionary/* default */.A.OphthalmicTomographyImageStorage, sopClassDictionary/* default */.A.VLWholeSlideMicroscopyImageStorage, sopClassDictionary/* default */.A.PositronEmissionTomographyImageStorage, sopClassDictionary/* default */.A.EnhancedPETImageStorage, sopClassDictionary/* default */.A.LegacyConvertedEnhancedPETImageStorage, sopClassDictionary/* default */.A.RTImageStorage, sopClassDictionary/* default */.A.EnhancedUSVolumeStorage];
|
|
4718
|
+
function getSopClassHandlerModule(appContextParam) {
|
|
4719
|
+
appContext = appContextParam;
|
|
4008
4720
|
return [{
|
|
4009
4721
|
name: sopClassHandlerName,
|
|
4010
|
-
sopClassUids,
|
|
4722
|
+
sopClassUids: getSopClassHandlerModule_sopClassUids,
|
|
4011
4723
|
getDisplaySetsFromSeries
|
|
4012
4724
|
}, {
|
|
4013
4725
|
name: 'not-supported-display-sets-handler',
|
|
4014
4726
|
sopClassUids: [],
|
|
4015
4727
|
getDisplaySetsFromSeries: getDisplaySetsFromUnsupportedSeries
|
|
4728
|
+
}, {
|
|
4729
|
+
name: chartHandler.name,
|
|
4730
|
+
sopClassUids: chartHandler.sopClassUids,
|
|
4731
|
+
getDisplaySetsFromSeries: chartHandler.getDisplaySetsFromSeries
|
|
4016
4732
|
}];
|
|
4017
4733
|
}
|
|
4018
4734
|
/* harmony default export */ const src_getSopClassHandlerModule = (getSopClassHandlerModule);
|
|
@@ -4029,39 +4745,99 @@ function ToolbarLayoutSelector_extends() { ToolbarLayoutSelector_extends = Objec
|
|
|
4029
4745
|
|
|
4030
4746
|
|
|
4031
4747
|
|
|
4032
|
-
|
|
4033
|
-
|
|
4034
|
-
|
|
4035
|
-
|
|
4036
|
-
|
|
4037
|
-
|
|
4038
|
-
|
|
4039
|
-
|
|
4748
|
+
const defaultCommonPresets = [{
|
|
4749
|
+
icon: 'layout-common-1x1',
|
|
4750
|
+
commandOptions: {
|
|
4751
|
+
numRows: 1,
|
|
4752
|
+
numCols: 1
|
|
4753
|
+
}
|
|
4754
|
+
}, {
|
|
4755
|
+
icon: 'layout-common-1x2',
|
|
4756
|
+
commandOptions: {
|
|
4757
|
+
numRows: 1,
|
|
4758
|
+
numCols: 2
|
|
4759
|
+
}
|
|
4760
|
+
}, {
|
|
4761
|
+
icon: 'layout-common-2x2',
|
|
4762
|
+
commandOptions: {
|
|
4763
|
+
numRows: 2,
|
|
4764
|
+
numCols: 2
|
|
4765
|
+
}
|
|
4766
|
+
}, {
|
|
4767
|
+
icon: 'layout-common-2x3',
|
|
4768
|
+
commandOptions: {
|
|
4769
|
+
numRows: 2,
|
|
4770
|
+
numCols: 3
|
|
4771
|
+
}
|
|
4772
|
+
}];
|
|
4773
|
+
const generateAdvancedPresets = hangingProtocolService => {
|
|
4774
|
+
const hangingProtocols = Array.from(hangingProtocolService.protocols.values());
|
|
4775
|
+
return hangingProtocols.map(hp => {
|
|
4776
|
+
if (!hp.isPreset) {
|
|
4777
|
+
return null;
|
|
4778
|
+
}
|
|
4779
|
+
return {
|
|
4780
|
+
icon: hp.icon,
|
|
4781
|
+
title: hp.name,
|
|
4782
|
+
commandOptions: {
|
|
4783
|
+
protocolId: hp.id
|
|
4784
|
+
}
|
|
4785
|
+
};
|
|
4786
|
+
}).filter(preset => preset !== null);
|
|
4787
|
+
};
|
|
4788
|
+
function ToolbarLayoutSelectorWithServices({
|
|
4789
|
+
commandsManager,
|
|
4790
|
+
servicesManager,
|
|
4791
|
+
...props
|
|
4792
|
+
}) {
|
|
4793
|
+
const [isDisabled, setIsDisabled] = (0,react.useState)(false);
|
|
4794
|
+
const handleMouseEnter = () => {
|
|
4795
|
+
setIsDisabled(false);
|
|
4796
|
+
};
|
|
4040
4797
|
const onSelection = (0,react.useCallback)(props => {
|
|
4041
|
-
|
|
4042
|
-
|
|
4043
|
-
|
|
4044
|
-
|
|
4045
|
-
|
|
4046
|
-
...props
|
|
4047
|
-
},
|
|
4048
|
-
context: 'DEFAULT'
|
|
4049
|
-
}]
|
|
4798
|
+
commandsManager.run({
|
|
4799
|
+
commandName: 'setViewportGridLayout',
|
|
4800
|
+
commandOptions: {
|
|
4801
|
+
...props
|
|
4802
|
+
}
|
|
4050
4803
|
});
|
|
4051
|
-
|
|
4052
|
-
|
|
4053
|
-
|
|
4054
|
-
|
|
4804
|
+
setIsDisabled(true);
|
|
4805
|
+
}, []);
|
|
4806
|
+
const onSelectionPreset = (0,react.useCallback)(props => {
|
|
4807
|
+
commandsManager.run({
|
|
4808
|
+
commandName: 'setHangingProtocol',
|
|
4809
|
+
commandOptions: {
|
|
4810
|
+
...props
|
|
4811
|
+
}
|
|
4812
|
+
});
|
|
4813
|
+
setIsDisabled(true);
|
|
4814
|
+
}, []);
|
|
4815
|
+
return /*#__PURE__*/react.createElement("div", {
|
|
4816
|
+
onMouseEnter: handleMouseEnter
|
|
4817
|
+
}, /*#__PURE__*/react.createElement(LayoutSelector, ToolbarLayoutSelector_extends({}, props, {
|
|
4818
|
+
onSelection: onSelection,
|
|
4819
|
+
onSelectionPreset: onSelectionPreset,
|
|
4820
|
+
servicesManager: servicesManager,
|
|
4821
|
+
tooltipDisabled: isDisabled
|
|
4822
|
+
})));
|
|
4055
4823
|
}
|
|
4056
|
-
function LayoutSelector(
|
|
4057
|
-
|
|
4058
|
-
|
|
4059
|
-
|
|
4060
|
-
|
|
4061
|
-
|
|
4062
|
-
|
|
4063
|
-
|
|
4824
|
+
function LayoutSelector({
|
|
4825
|
+
rows,
|
|
4826
|
+
columns,
|
|
4827
|
+
className,
|
|
4828
|
+
onSelection,
|
|
4829
|
+
onSelectionPreset,
|
|
4830
|
+
servicesManager,
|
|
4831
|
+
tooltipDisabled,
|
|
4832
|
+
...rest
|
|
4833
|
+
}) {
|
|
4064
4834
|
const [isOpen, setIsOpen] = (0,react.useState)(false);
|
|
4835
|
+
const {
|
|
4836
|
+
customizationService,
|
|
4837
|
+
hangingProtocolService
|
|
4838
|
+
} = servicesManager.services;
|
|
4839
|
+
const commonPresets = customizationService.get('commonPresets') || defaultCommonPresets;
|
|
4840
|
+
const advancedPresets = customizationService.get('advancedPresets') || generateAdvancedPresets(hangingProtocolService);
|
|
4065
4841
|
const closeOnOutsideClick = () => {
|
|
4066
4842
|
if (isOpen) {
|
|
4067
4843
|
setIsOpen(false);
|
|
@@ -4073,20 +4849,56 @@ function LayoutSelector(_ref2) {
|
|
|
4073
4849
|
window.removeEventListener('click', closeOnOutsideClick);
|
|
4074
4850
|
};
|
|
4075
4851
|
}, [isOpen]);
|
|
4076
|
-
const onInteractionHandler = () =>
|
|
4077
|
-
|
|
4078
|
-
|
|
4852
|
+
const onInteractionHandler = () => {
|
|
4853
|
+
setIsOpen(!isOpen);
|
|
4854
|
+
};
|
|
4855
|
+
const DropdownContent = isOpen ? ui_src/* LayoutSelector */.sG : null;
|
|
4856
|
+
return /*#__PURE__*/react.createElement(ui_src/* ToolbarButton */.IB, {
|
|
4079
4857
|
id: "Layout",
|
|
4080
|
-
label: "
|
|
4858
|
+
label: "Layout",
|
|
4081
4859
|
icon: "tool-layout",
|
|
4082
4860
|
onInteraction: onInteractionHandler,
|
|
4083
4861
|
className: className,
|
|
4084
4862
|
rounded: rest.rounded,
|
|
4085
|
-
|
|
4863
|
+
disableToolTip: tooltipDisabled,
|
|
4864
|
+
dropdownContent: DropdownContent !== null && /*#__PURE__*/react.createElement("div", {
|
|
4865
|
+
className: "flex "
|
|
4866
|
+
}, /*#__PURE__*/react.createElement("div", {
|
|
4867
|
+
className: "bg-secondary-dark flex flex-col gap-2.5 p-2"
|
|
4868
|
+
}, /*#__PURE__*/react.createElement("div", {
|
|
4869
|
+
className: "text-aqua-pale text-xs"
|
|
4870
|
+
}, "Common"), /*#__PURE__*/react.createElement("div", {
|
|
4871
|
+
className: "flex gap-4"
|
|
4872
|
+
}, commonPresets.map((preset, index) => /*#__PURE__*/react.createElement(ui_src/* LayoutPreset */.qu, {
|
|
4873
|
+
key: index,
|
|
4874
|
+
classNames: "hover:bg-primary-dark group p-1 cursor-pointer",
|
|
4875
|
+
icon: preset.icon,
|
|
4876
|
+
commandOptions: preset.commandOptions,
|
|
4877
|
+
onSelection: onSelection
|
|
4878
|
+
}))), /*#__PURE__*/react.createElement("div", {
|
|
4879
|
+
className: "h-[2px] bg-black"
|
|
4880
|
+
}), /*#__PURE__*/react.createElement("div", {
|
|
4881
|
+
className: "text-aqua-pale text-xs"
|
|
4882
|
+
}, "Advanced"), /*#__PURE__*/react.createElement("div", {
|
|
4883
|
+
className: "flex flex-col gap-2.5"
|
|
4884
|
+
}, advancedPresets.map((preset, index) => /*#__PURE__*/react.createElement(ui_src/* LayoutPreset */.qu, {
|
|
4885
|
+
key: index + commonPresets.length,
|
|
4886
|
+
classNames: "hover:bg-primary-dark group flex gap-2 p-1 cursor-pointer",
|
|
4887
|
+
icon: preset.icon,
|
|
4888
|
+
title: preset.title,
|
|
4889
|
+
commandOptions: preset.commandOptions,
|
|
4890
|
+
onSelection: onSelectionPreset
|
|
4891
|
+
})))), /*#__PURE__*/react.createElement("div", {
|
|
4892
|
+
className: "bg-primary-dark flex flex-col gap-2.5 border-l-2 border-solid border-black p-2"
|
|
4893
|
+
}, /*#__PURE__*/react.createElement("div", {
|
|
4894
|
+
className: "text-aqua-pale text-xs"
|
|
4895
|
+
}, "Custom"), /*#__PURE__*/react.createElement(DropdownContent, {
|
|
4086
4896
|
rows: rows,
|
|
4087
4897
|
columns: columns,
|
|
4088
4898
|
onSelection: onSelection
|
|
4089
|
-
}),
|
|
4899
|
+
}), /*#__PURE__*/react.createElement("p", {
|
|
4900
|
+
className: "text-aqua-pale text-xs leading-tight"
|
|
4901
|
+
}, "Hover to select ", /*#__PURE__*/react.createElement("br", null), "rows and columns ", /*#__PURE__*/react.createElement("br", null), " Click to apply"))),
|
|
4090
4902
|
isActive: isOpen,
|
|
4091
4903
|
type: "toggle"
|
|
4092
4904
|
});
|
|
@@ -4095,11 +4907,11 @@ LayoutSelector.propTypes = {
|
|
|
4095
4907
|
rows: (prop_types_default()).number,
|
|
4096
4908
|
columns: (prop_types_default()).number,
|
|
4097
4909
|
onLayoutChange: (prop_types_default()).func,
|
|
4098
|
-
servicesManager: prop_types_default().instanceOf(src/* ServicesManager */.
|
|
4910
|
+
servicesManager: prop_types_default().instanceOf(src/* ServicesManager */.CS)
|
|
4099
4911
|
};
|
|
4100
4912
|
LayoutSelector.defaultProps = {
|
|
4913
|
+
columns: 4,
|
|
4101
4914
|
rows: 3,
|
|
4102
|
-
columns: 3,
|
|
4103
4915
|
onLayoutChange: () => {}
|
|
4104
4916
|
};
|
|
4105
4917
|
/* harmony default export */ const ToolbarLayoutSelector = (ToolbarLayoutSelectorWithServices);
|
|
@@ -4108,122 +4920,39 @@ function ToolbarSplitButtonWithServices_extends() { ToolbarSplitButtonWithServic
|
|
|
4108
4920
|
|
|
4109
4921
|
|
|
4110
4922
|
|
|
4111
|
-
|
|
4112
|
-
|
|
4113
|
-
|
|
4114
|
-
|
|
4115
|
-
|
|
4116
|
-
|
|
4117
|
-
|
|
4118
|
-
|
|
4119
|
-
|
|
4120
|
-
renderer,
|
|
4121
|
-
onInteraction,
|
|
4122
|
-
servicesManager
|
|
4123
|
-
} = _ref;
|
|
4923
|
+
function ToolbarSplitButtonWithServices({
|
|
4924
|
+
groupId,
|
|
4925
|
+
primary,
|
|
4926
|
+
secondary,
|
|
4927
|
+
items,
|
|
4928
|
+
renderer,
|
|
4929
|
+
onInteraction,
|
|
4930
|
+
servicesManager
|
|
4931
|
+
}) {
|
|
4124
4932
|
const {
|
|
4125
4933
|
toolbarService
|
|
4126
4934
|
} = servicesManager?.services;
|
|
4127
|
-
const handleItemClick = (item, index) => {
|
|
4128
|
-
const {
|
|
4129
|
-
id,
|
|
4130
|
-
type,
|
|
4131
|
-
commands
|
|
4132
|
-
} = item;
|
|
4133
|
-
onInteraction({
|
|
4134
|
-
groupId,
|
|
4135
|
-
itemId: id,
|
|
4136
|
-
interactionType: type,
|
|
4137
|
-
commands
|
|
4138
|
-
});
|
|
4139
|
-
setState(state => ({
|
|
4140
|
-
...state,
|
|
4141
|
-
primary: !isAction && isRadio ? {
|
|
4142
|
-
...item,
|
|
4143
|
-
index
|
|
4144
|
-
} : state.primary,
|
|
4145
|
-
isExpanded: false,
|
|
4146
|
-
items: getSplitButtonItems(items).filter(item => isRadio && !isAction ? item.index !== index : true)
|
|
4147
|
-
}));
|
|
4148
|
-
};
|
|
4149
4935
|
|
|
4150
4936
|
/* Bubbles up individual item clicks */
|
|
4151
|
-
const getSplitButtonItems = items => items.map((item, index) => ({
|
|
4937
|
+
const getSplitButtonItems = (0,react.useCallback)(items => items.map((item, index) => ({
|
|
4152
4938
|
...item,
|
|
4153
4939
|
index,
|
|
4154
|
-
onClick: () =>
|
|
4155
|
-
|
|
4156
|
-
|
|
4157
|
-
|
|
4158
|
-
|
|
4159
|
-
groups: {}
|
|
4160
|
-
});
|
|
4161
|
-
const [state, setState] = (0,react.useState)({
|
|
4162
|
-
primary,
|
|
4163
|
-
items: getSplitButtonItems(items).filter(item => isRadio && !isAction ? item.id !== primary.id : true)
|
|
4164
|
-
});
|
|
4165
|
-
const {
|
|
4166
|
-
primaryToolId,
|
|
4167
|
-
toggles
|
|
4168
|
-
} = buttonsState;
|
|
4169
|
-
const isPrimaryToggle = state.primary.type === 'toggle';
|
|
4170
|
-
const isPrimaryActive = state.primary.type === 'tool' && primaryToolId === state.primary.id || isPrimaryToggle && toggles[state.primary.id] === true;
|
|
4171
|
-
const PrimaryButtonComponent = toolbarService?.getButtonComponentForUIType(state.primary.uiType) ?? ui_src/* ToolbarButton */.hA;
|
|
4172
|
-
(0,react.useEffect)(() => {
|
|
4173
|
-
const {
|
|
4174
|
-
unsubscribe
|
|
4175
|
-
} = toolbarService.subscribe(toolbarService.EVENTS.TOOL_BAR_STATE_MODIFIED, state => {
|
|
4176
|
-
setButtonState({
|
|
4177
|
-
...state
|
|
4940
|
+
onClick: () => {
|
|
4941
|
+
onInteraction({
|
|
4942
|
+
groupId,
|
|
4943
|
+
itemId: item.id,
|
|
4944
|
+
commands: item.commands
|
|
4178
4945
|
});
|
|
4179
|
-
}
|
|
4180
|
-
|
|
4181
|
-
|
|
4182
|
-
|
|
4183
|
-
|
|
4184
|
-
|
|
4185
|
-
const isActive = item.type === 'tool' && primaryToolId === item.id;
|
|
4186
|
-
|
|
4187
|
-
// We could have added the
|
|
4188
|
-
// item.type === 'toggle' && toggles[item.id] === true
|
|
4189
|
-
// too but that makes the button active when the toggle is active under it
|
|
4190
|
-
// which feels weird
|
|
4191
|
-
return {
|
|
4192
|
-
...item,
|
|
4193
|
-
isActive
|
|
4194
|
-
};
|
|
4195
|
-
});
|
|
4196
|
-
const DefaultListItemRenderer = _ref2 => {
|
|
4197
|
-
let {
|
|
4198
|
-
type,
|
|
4199
|
-
icon,
|
|
4200
|
-
label,
|
|
4201
|
-
t,
|
|
4202
|
-
id
|
|
4203
|
-
} = _ref2;
|
|
4204
|
-
const isActive = type === 'toggle' && toggles[id] === true;
|
|
4205
|
-
return /*#__PURE__*/react.createElement("div", {
|
|
4206
|
-
className: classnames_default()('hover:bg-primary-dark flex h-8 w-full flex-row items-center p-3', 'whitespace-pre text-base', isActive && 'bg-primary-dark', isActive ? 'text-[#348CFD]' : 'text-common-bright hover:bg-primary-dark hover:text-primary-light')
|
|
4207
|
-
}, icon && /*#__PURE__*/react.createElement("span", {
|
|
4208
|
-
className: "mr-4"
|
|
4209
|
-
}, /*#__PURE__*/react.createElement(ui_src/* Icon */.JO, {
|
|
4210
|
-
name: icon,
|
|
4211
|
-
className: "h-5 w-5"
|
|
4212
|
-
})), /*#__PURE__*/react.createElement("span", {
|
|
4213
|
-
className: "mr-5"
|
|
4214
|
-
}, t(label)));
|
|
4215
|
-
};
|
|
4216
|
-
const listItemRenderer = renderer || DefaultListItemRenderer;
|
|
4217
|
-
return /*#__PURE__*/react.createElement(ui_src/* SplitButton */.aW, {
|
|
4218
|
-
isRadio: isRadio,
|
|
4219
|
-
isAction: isAction,
|
|
4220
|
-
primary: state.primary,
|
|
4946
|
+
}
|
|
4947
|
+
})), []);
|
|
4948
|
+
const PrimaryButtonComponent = toolbarService?.getButtonComponentForUIType(primary.uiType) ?? ui_src/* ToolbarButton */.IB;
|
|
4949
|
+
const listItemRenderer = renderer;
|
|
4950
|
+
return /*#__PURE__*/react.createElement(ui_src/* SplitButton */.fk, {
|
|
4951
|
+
primary: primary,
|
|
4221
4952
|
secondary: secondary,
|
|
4222
|
-
items:
|
|
4953
|
+
items: getSplitButtonItems(items),
|
|
4223
4954
|
groupId: groupId,
|
|
4224
4955
|
renderer: listItemRenderer,
|
|
4225
|
-
isActive: isPrimaryActive || updatedItems.some(item => item.isActive),
|
|
4226
|
-
isToggle: isPrimaryToggle,
|
|
4227
4956
|
onInteraction: onInteraction,
|
|
4228
4957
|
Component: props => /*#__PURE__*/react.createElement(PrimaryButtonComponent, ToolbarSplitButtonWithServices_extends({}, props, {
|
|
4229
4958
|
servicesManager: servicesManager
|
|
@@ -4232,11 +4961,9 @@ function ToolbarSplitButtonWithServices(_ref) {
|
|
|
4232
4961
|
}
|
|
4233
4962
|
ToolbarSplitButtonWithServices.propTypes = {
|
|
4234
4963
|
isRadio: (prop_types_default()).bool,
|
|
4235
|
-
isAction: (prop_types_default()).bool,
|
|
4236
4964
|
groupId: (prop_types_default()).string,
|
|
4237
4965
|
primary: prop_types_default().shape({
|
|
4238
4966
|
id: (prop_types_default()).string.isRequired,
|
|
4239
|
-
type: prop_types_default().oneOf(['tool', 'action', 'toggle']).isRequired,
|
|
4240
4967
|
uiType: (prop_types_default()).string
|
|
4241
4968
|
}),
|
|
4242
4969
|
secondary: prop_types_default().shape({
|
|
@@ -4244,14 +4971,16 @@ ToolbarSplitButtonWithServices.propTypes = {
|
|
|
4244
4971
|
icon: (prop_types_default()).string.isRequired,
|
|
4245
4972
|
label: (prop_types_default()).string,
|
|
4246
4973
|
tooltip: (prop_types_default()).string.isRequired,
|
|
4247
|
-
|
|
4974
|
+
disabled: (prop_types_default()).bool,
|
|
4975
|
+
className: (prop_types_default()).string
|
|
4248
4976
|
}),
|
|
4249
4977
|
items: prop_types_default().arrayOf(prop_types_default().shape({
|
|
4250
4978
|
id: (prop_types_default()).string.isRequired,
|
|
4251
|
-
type: prop_types_default().oneOf(['tool', 'action', 'toggle']).isRequired,
|
|
4252
4979
|
icon: (prop_types_default()).string,
|
|
4253
4980
|
label: (prop_types_default()).string,
|
|
4254
|
-
tooltip: (prop_types_default()).string
|
|
4981
|
+
tooltip: (prop_types_default()).string,
|
|
4982
|
+
disabled: (prop_types_default()).bool,
|
|
4983
|
+
className: (prop_types_default()).string
|
|
4255
4984
|
})),
|
|
4256
4985
|
renderer: (prop_types_default()).func,
|
|
4257
4986
|
onInteraction: (prop_types_default()).func.isRequired,
|
|
@@ -4266,108 +4995,194 @@ ToolbarSplitButtonWithServices.defaultProps = {
|
|
|
4266
4995
|
isAction: false
|
|
4267
4996
|
};
|
|
4268
4997
|
/* harmony default export */ const Toolbar_ToolbarSplitButtonWithServices = (ToolbarSplitButtonWithServices);
|
|
4269
|
-
;// CONCATENATED MODULE: ../../../extensions/default/src/Toolbar/
|
|
4270
|
-
|
|
4271
|
-
|
|
4272
|
-
|
|
4273
|
-
|
|
4274
|
-
|
|
4275
|
-
|
|
4276
|
-
|
|
4277
|
-
|
|
4278
|
-
|
|
4279
|
-
|
|
4280
|
-
|
|
4281
|
-
|
|
4282
|
-
|
|
4283
|
-
|
|
4284
|
-
|
|
4285
|
-
|
|
4286
|
-
|
|
4287
|
-
|
|
4288
|
-
|
|
4289
|
-
|
|
4290
|
-
|
|
4998
|
+
;// CONCATENATED MODULE: ../../../extensions/default/src/Toolbar/ToolbarButtonGroupWithServices.tsx
|
|
4999
|
+
|
|
5000
|
+
|
|
5001
|
+
function ToolbarButtonGroupWithServices({
|
|
5002
|
+
groupId,
|
|
5003
|
+
items,
|
|
5004
|
+
onInteraction,
|
|
5005
|
+
size
|
|
5006
|
+
}) {
|
|
5007
|
+
const getSplitButtonItems = (0,react.useCallback)(items => items.map((item, index) => /*#__PURE__*/react.createElement(ui_src/* ToolbarButton */.IB, {
|
|
5008
|
+
key: item.id,
|
|
5009
|
+
icon: item.icon,
|
|
5010
|
+
label: item.label,
|
|
5011
|
+
disabled: item.disabled,
|
|
5012
|
+
className: item.className,
|
|
5013
|
+
id: item.id,
|
|
5014
|
+
size: size,
|
|
5015
|
+
onClick: () => {
|
|
5016
|
+
onInteraction({
|
|
5017
|
+
groupId,
|
|
5018
|
+
itemId: item.id,
|
|
5019
|
+
commands: item.commands
|
|
5020
|
+
});
|
|
5021
|
+
}
|
|
5022
|
+
// Note: this is necessary since tooltip will add
|
|
5023
|
+
// default styles to the tooltip container which
|
|
5024
|
+
// we don't want for groups
|
|
5025
|
+
,
|
|
5026
|
+
toolTipClassName: ""
|
|
5027
|
+
})), [onInteraction, groupId]);
|
|
5028
|
+
return /*#__PURE__*/react.createElement(ui_src/* ButtonGroup */.e2, null, getSplitButtonItems(items));
|
|
5029
|
+
}
|
|
5030
|
+
/* harmony default export */ const Toolbar_ToolbarButtonGroupWithServices = (ToolbarButtonGroupWithServices);
|
|
5031
|
+
;// CONCATENATED MODULE: ../../../extensions/default/src/components/ProgressDropdownWithService/ProgressDropdownWithService.tsx
|
|
5032
|
+
|
|
5033
|
+
|
|
5034
|
+
const workflowStepsToDropdownOptions = (steps = []) => steps.map(step => ({
|
|
5035
|
+
label: step.name,
|
|
5036
|
+
value: step.id,
|
|
5037
|
+
info: step.info,
|
|
5038
|
+
activated: false,
|
|
5039
|
+
completed: false
|
|
5040
|
+
}));
|
|
5041
|
+
function ProgressDropdownWithService({
|
|
5042
|
+
servicesManager
|
|
5043
|
+
}) {
|
|
4291
5044
|
const {
|
|
4292
|
-
|
|
4293
|
-
} =
|
|
4294
|
-
const
|
|
5045
|
+
workflowStepsService
|
|
5046
|
+
} = servicesManager.services;
|
|
5047
|
+
const [activeStepId, setActiveStepId] = (0,react.useState)(workflowStepsService.activeWorkflowStep?.id);
|
|
5048
|
+
const [dropdownOptions, setDropdownOptions] = (0,react.useState)(workflowStepsToDropdownOptions(workflowStepsService.workflowSteps));
|
|
5049
|
+
const setCurrentAndPreviousOptionsAsCompleted = (0,react.useCallback)(currentOption => {
|
|
5050
|
+
if (currentOption.completed) {
|
|
5051
|
+
return;
|
|
5052
|
+
}
|
|
5053
|
+
setDropdownOptions(prevOptions => {
|
|
5054
|
+
const newOptionsState = [...prevOptions];
|
|
5055
|
+
const startIndex = newOptionsState.findIndex(option => option.value === currentOption.value);
|
|
5056
|
+
for (let i = startIndex; i >= 0; i--) {
|
|
5057
|
+
const option = newOptionsState[i];
|
|
5058
|
+
if (option.completed) {
|
|
5059
|
+
break;
|
|
5060
|
+
}
|
|
5061
|
+
newOptionsState[i] = {
|
|
5062
|
+
...option,
|
|
5063
|
+
completed: true
|
|
5064
|
+
};
|
|
5065
|
+
}
|
|
5066
|
+
return newOptionsState;
|
|
5067
|
+
});
|
|
5068
|
+
}, []);
|
|
5069
|
+
const handleDropdownChange = (0,react.useCallback)(({
|
|
5070
|
+
selectedOption
|
|
5071
|
+
}) => {
|
|
5072
|
+
if (!selectedOption) {
|
|
5073
|
+
return;
|
|
5074
|
+
}
|
|
5075
|
+
|
|
5076
|
+
// TODO: Steps should be marked as completed after user has
|
|
5077
|
+
// completed some action when required (not implemented)
|
|
5078
|
+
setCurrentAndPreviousOptionsAsCompleted(selectedOption);
|
|
5079
|
+
setActiveStepId(selectedOption.value);
|
|
5080
|
+
}, [setCurrentAndPreviousOptionsAsCompleted]);
|
|
5081
|
+
(0,react.useEffect)(() => {
|
|
5082
|
+
let timeoutId;
|
|
5083
|
+
if (activeStepId) {
|
|
5084
|
+
// We've used setTimeout to give it more time to update the UI since
|
|
5085
|
+
// create3DFilterableFromDataArray from Texture.js may take 600+ ms to run
|
|
5086
|
+
// when there is a new series to load in the next step but that resulted
|
|
5087
|
+
// in the followed React error when updating the content from left/right panels
|
|
5088
|
+
// and all component states were being lost:
|
|
5089
|
+
// Error: Can't perform a React state update on an unmounted component
|
|
5090
|
+
workflowStepsService.setActiveWorkflowStep(activeStepId);
|
|
5091
|
+
}
|
|
5092
|
+
return () => clearTimeout(timeoutId);
|
|
5093
|
+
}, [activeStepId, workflowStepsService]);
|
|
4295
5094
|
(0,react.useEffect)(() => {
|
|
4296
5095
|
const {
|
|
4297
|
-
unsubscribe
|
|
4298
|
-
} =
|
|
4299
|
-
|
|
4300
|
-
|
|
4301
|
-
|
|
4302
|
-
});
|
|
5096
|
+
unsubscribe: unsubStepsChanged
|
|
5097
|
+
} = workflowStepsService.subscribe(workflowStepsService.EVENTS.STEPS_CHANGED, () => setDropdownOptions(workflowStepsToDropdownOptions(workflowStepsService.workflowSteps)));
|
|
5098
|
+
const {
|
|
5099
|
+
unsubscribe: unsubActiveStepChanged
|
|
5100
|
+
} = workflowStepsService.subscribe(workflowStepsService.EVENTS.ACTIVE_STEP_CHANGED, () => setActiveStepId(workflowStepsService.activeWorkflowStep.id));
|
|
4303
5101
|
return () => {
|
|
4304
|
-
|
|
5102
|
+
unsubStepsChanged();
|
|
5103
|
+
unsubActiveStepChanged();
|
|
4305
5104
|
};
|
|
4306
|
-
}, [
|
|
4307
|
-
return /*#__PURE__*/react.createElement(ui_src/*
|
|
4308
|
-
|
|
4309
|
-
|
|
4310
|
-
|
|
4311
|
-
|
|
4312
|
-
onInteraction: onInteraction
|
|
4313
|
-
}, props));
|
|
5105
|
+
}, [servicesManager, workflowStepsService]);
|
|
5106
|
+
return /*#__PURE__*/react.createElement(ui_src/* ProgressDropdown */.LW, {
|
|
5107
|
+
options: dropdownOptions,
|
|
5108
|
+
value: activeStepId,
|
|
5109
|
+
onChange: handleDropdownChange
|
|
5110
|
+
});
|
|
4314
5111
|
}
|
|
4315
|
-
|
|
4316
|
-
|
|
4317
|
-
|
|
4318
|
-
commands: prop_types_default().arrayOf(prop_types_default().shape({
|
|
4319
|
-
commandName: (prop_types_default()).string.isRequired,
|
|
4320
|
-
context: (prop_types_default()).string
|
|
4321
|
-
})),
|
|
4322
|
-
onInteraction: (prop_types_default()).func.isRequired,
|
|
4323
|
-
servicesManager: prop_types_default().shape({
|
|
4324
|
-
services: prop_types_default().shape({
|
|
4325
|
-
toolbarService: prop_types_default().shape({
|
|
4326
|
-
subscribe: (prop_types_default()).func.isRequired,
|
|
4327
|
-
state: prop_types_default().shape({
|
|
4328
|
-
primaryToolId: (prop_types_default()).string,
|
|
4329
|
-
toggles: prop_types_default().objectOf((prop_types_default()).bool),
|
|
4330
|
-
groups: prop_types_default().objectOf((prop_types_default()).any)
|
|
4331
|
-
}).isRequired
|
|
4332
|
-
}).isRequired
|
|
4333
|
-
}).isRequired
|
|
4334
|
-
}).isRequired
|
|
4335
|
-
};
|
|
4336
|
-
/* harmony default export */ const Toolbar_ToolbarButtonWithServices = (ToolbarButtonWithServices);
|
|
5112
|
+
/* harmony default export */ const ProgressDropdownWithService_ProgressDropdownWithService = (ProgressDropdownWithService);
|
|
5113
|
+
;// CONCATENATED MODULE: ../../../extensions/default/src/components/ProgressDropdownWithService/index.js
|
|
5114
|
+
|
|
4337
5115
|
;// CONCATENATED MODULE: ../../../extensions/default/src/getToolbarModule.tsx
|
|
4338
5116
|
|
|
4339
5117
|
|
|
4340
5118
|
|
|
4341
5119
|
|
|
4342
|
-
|
|
4343
|
-
|
|
4344
|
-
|
|
4345
|
-
|
|
4346
|
-
|
|
5120
|
+
|
|
5121
|
+
|
|
5122
|
+
const getClassName = isToggled => {
|
|
5123
|
+
return {
|
|
5124
|
+
className: isToggled ? '!text-primary-active' : '!text-common-bright hover:!bg-primary-dark hover:text-primary-light'
|
|
5125
|
+
};
|
|
5126
|
+
};
|
|
5127
|
+
function getToolbarModule({
|
|
5128
|
+
commandsManager,
|
|
5129
|
+
servicesManager
|
|
5130
|
+
}) {
|
|
5131
|
+
const {
|
|
5132
|
+
cineService
|
|
5133
|
+
} = servicesManager.services;
|
|
4347
5134
|
return [{
|
|
4348
|
-
name: 'ohif.divider',
|
|
4349
|
-
defaultComponent: ToolbarDivider,
|
|
4350
|
-
clickHandler: () => {}
|
|
4351
|
-
}, {
|
|
4352
|
-
name: 'ohif.action',
|
|
4353
|
-
defaultComponent: Toolbar_ToolbarButtonWithServices,
|
|
4354
|
-
clickHandler: () => {}
|
|
4355
|
-
}, {
|
|
4356
5135
|
name: 'ohif.radioGroup',
|
|
4357
|
-
defaultComponent:
|
|
4358
|
-
|
|
5136
|
+
defaultComponent: ui_src/* ToolbarButton */.IB
|
|
5137
|
+
}, {
|
|
5138
|
+
name: 'ohif.divider',
|
|
5139
|
+
defaultComponent: ToolbarDivider
|
|
4359
5140
|
}, {
|
|
4360
5141
|
name: 'ohif.splitButton',
|
|
4361
|
-
defaultComponent: Toolbar_ToolbarSplitButtonWithServices
|
|
4362
|
-
clickHandler: () => {}
|
|
5142
|
+
defaultComponent: Toolbar_ToolbarSplitButtonWithServices
|
|
4363
5143
|
}, {
|
|
4364
5144
|
name: 'ohif.layoutSelector',
|
|
4365
|
-
defaultComponent: ToolbarLayoutSelector
|
|
4366
|
-
|
|
5145
|
+
defaultComponent: props => ToolbarLayoutSelector({
|
|
5146
|
+
...props,
|
|
5147
|
+
commandsManager,
|
|
5148
|
+
servicesManager
|
|
5149
|
+
})
|
|
5150
|
+
}, {
|
|
5151
|
+
name: 'ohif.buttonGroup',
|
|
5152
|
+
defaultComponent: Toolbar_ToolbarButtonGroupWithServices
|
|
5153
|
+
}, {
|
|
5154
|
+
name: 'ohif.progressDropdown',
|
|
5155
|
+
defaultComponent: ProgressDropdownWithService_ProgressDropdownWithService
|
|
4367
5156
|
}, {
|
|
4368
|
-
name: '
|
|
4369
|
-
|
|
4370
|
-
|
|
5157
|
+
name: 'evaluate.group.promoteToPrimary',
|
|
5158
|
+
evaluate: ({
|
|
5159
|
+
viewportId,
|
|
5160
|
+
button,
|
|
5161
|
+
itemId
|
|
5162
|
+
}) => {
|
|
5163
|
+
const {
|
|
5164
|
+
items
|
|
5165
|
+
} = button.props;
|
|
5166
|
+
if (!itemId) {
|
|
5167
|
+
return {
|
|
5168
|
+
primary: button.props.primary,
|
|
5169
|
+
items
|
|
5170
|
+
};
|
|
5171
|
+
}
|
|
5172
|
+
|
|
5173
|
+
// other wise we can move the clicked tool to the primary button
|
|
5174
|
+
const clickedItemProps = items.find(item => item.id === itemId || item.itemId === itemId);
|
|
5175
|
+
return {
|
|
5176
|
+
primary: clickedItemProps,
|
|
5177
|
+
items
|
|
5178
|
+
};
|
|
5179
|
+
}
|
|
5180
|
+
}, {
|
|
5181
|
+
name: 'evaluate.cine',
|
|
5182
|
+
evaluate: () => {
|
|
5183
|
+
const isToggled = cineService.getState().isCineEnabled;
|
|
5184
|
+
return getClassName(isToggled);
|
|
5185
|
+
}
|
|
4371
5186
|
}];
|
|
4372
5187
|
}
|
|
4373
5188
|
;// CONCATENATED MODULE: ../../../extensions/default/src/CustomizableContextMenu/ContextMenuItemsBuilder.ts
|
|
@@ -4433,7 +5248,6 @@ function findMenu(menus, props, menuIdFilter) {
|
|
|
4433
5248
|
}
|
|
4434
5249
|
current = findIt.next();
|
|
4435
5250
|
}
|
|
4436
|
-
console.log('Menu chosen', menu?.id || 'NONE');
|
|
4437
5251
|
return menu;
|
|
4438
5252
|
}
|
|
4439
5253
|
|
|
@@ -4536,8 +5350,12 @@ function adaptItem(item, subProps) {
|
|
|
4536
5350
|
return newItem;
|
|
4537
5351
|
}
|
|
4538
5352
|
// EXTERNAL MODULE: ../../ui/src/components/ContextMenu/ContextMenu.tsx
|
|
4539
|
-
var ContextMenu = __webpack_require__(
|
|
5353
|
+
var ContextMenu = __webpack_require__(59852);
|
|
5354
|
+
// EXTERNAL MODULE: ../../../node_modules/@cornerstonejs/tools/dist/esm/index.js + 18 modules
|
|
5355
|
+
var dist_esm = __webpack_require__(24542);
|
|
4540
5356
|
;// CONCATENATED MODULE: ../../../extensions/default/src/CustomizableContextMenu/ContextMenuController.tsx
|
|
5357
|
+
var _ContextMenuController;
|
|
5358
|
+
|
|
4541
5359
|
|
|
4542
5360
|
|
|
4543
5361
|
/**
|
|
@@ -4584,7 +5402,16 @@ class ContextMenuController {
|
|
|
4584
5402
|
menus,
|
|
4585
5403
|
selectorProps
|
|
4586
5404
|
} = contextMenuProps;
|
|
4587
|
-
|
|
5405
|
+
const annotationManager = dist_esm.annotation.state.getAnnotationManager();
|
|
5406
|
+
const {
|
|
5407
|
+
locking
|
|
5408
|
+
} = dist_esm.annotation;
|
|
5409
|
+
const targetAnnotationId = selectorProps?.nearbyToolData?.annotationUID;
|
|
5410
|
+
const isLocked = locking.isAnnotationLocked(annotationManager.getAnnotation(targetAnnotationId));
|
|
5411
|
+
if (isLocked) {
|
|
5412
|
+
console.warn('Annotation is locked.');
|
|
5413
|
+
return;
|
|
5414
|
+
}
|
|
4588
5415
|
const items = getMenuItems(selectorProps || contextMenuProps, event, menus, menuId);
|
|
4589
5416
|
this.services.uiDialogService.dismiss({
|
|
4590
5417
|
id: 'context-menu'
|
|
@@ -4596,7 +5423,7 @@ class ContextMenuController {
|
|
|
4596
5423
|
preventCutOf: true,
|
|
4597
5424
|
defaultPosition: ContextMenuController._getDefaultPosition(defaultPointsPosition, event?.detail, viewportElement),
|
|
4598
5425
|
event,
|
|
4599
|
-
content: ContextMenu/* default */.
|
|
5426
|
+
content: ContextMenu/* default */.A,
|
|
4600
5427
|
// This naming is part of the uiDialogService convention
|
|
4601
5428
|
// Clicking outside simply closes the dialog box.
|
|
4602
5429
|
onClickOutside: () => this.services.uiDialogService.dismiss({
|
|
@@ -4642,6 +5469,7 @@ class ContextMenuController {
|
|
|
4642
5469
|
});
|
|
4643
5470
|
}
|
|
4644
5471
|
}
|
|
5472
|
+
_ContextMenuController = ContextMenuController;
|
|
4645
5473
|
ContextMenuController.getDefaultPosition = () => {
|
|
4646
5474
|
return {
|
|
4647
5475
|
x: 0,
|
|
@@ -4665,16 +5493,14 @@ ContextMenuController._getElementDefaultPosition = element => {
|
|
|
4665
5493
|
y: undefined
|
|
4666
5494
|
};
|
|
4667
5495
|
};
|
|
4668
|
-
ContextMenuController._getCanvasPointsPosition =
|
|
4669
|
-
|
|
4670
|
-
let element = arguments.length > 1 ? arguments[1] : undefined;
|
|
4671
|
-
const viewerPos = ContextMenuController._getElementDefaultPosition(element);
|
|
5496
|
+
ContextMenuController._getCanvasPointsPosition = (points = [], element) => {
|
|
5497
|
+
const viewerPos = _ContextMenuController._getElementDefaultPosition(element);
|
|
4672
5498
|
for (let pointIndex = 0; pointIndex < points.length; pointIndex++) {
|
|
4673
5499
|
const point = {
|
|
4674
5500
|
x: points[pointIndex][0] || points[pointIndex]['x'],
|
|
4675
5501
|
y: points[pointIndex][1] || points[pointIndex]['y']
|
|
4676
5502
|
};
|
|
4677
|
-
if (
|
|
5503
|
+
if (_ContextMenuController._isValidPosition(point) && _ContextMenuController._isValidPosition(viewerPos)) {
|
|
4678
5504
|
return {
|
|
4679
5505
|
x: point.x + viewerPos.x,
|
|
4680
5506
|
y: point.y + viewerPos.y
|
|
@@ -4690,17 +5516,17 @@ ContextMenuController._isValidPosition = source => {
|
|
|
4690
5516
|
*/
|
|
4691
5517
|
ContextMenuController._getDefaultPosition = (canvasPoints, eventDetail, viewerElement) => {
|
|
4692
5518
|
function* getPositionIterator() {
|
|
4693
|
-
yield
|
|
4694
|
-
yield
|
|
4695
|
-
yield
|
|
4696
|
-
yield
|
|
5519
|
+
yield _ContextMenuController._getCanvasPointsPosition(canvasPoints, viewerElement);
|
|
5520
|
+
yield _ContextMenuController._getEventDefaultPosition(eventDetail);
|
|
5521
|
+
yield _ContextMenuController._getElementDefaultPosition(viewerElement);
|
|
5522
|
+
yield _ContextMenuController.getDefaultPosition();
|
|
4697
5523
|
}
|
|
4698
5524
|
const positionIterator = getPositionIterator();
|
|
4699
5525
|
let current = positionIterator.next();
|
|
4700
5526
|
let position = current.value;
|
|
4701
5527
|
while (!current.done) {
|
|
4702
5528
|
position = current.value;
|
|
4703
|
-
if (
|
|
5529
|
+
if (_ContextMenuController._isValidPosition(position)) {
|
|
4704
5530
|
positionIterator.return();
|
|
4705
5531
|
}
|
|
4706
5532
|
current = positionIterator.next();
|
|
@@ -4715,12 +5541,9 @@ const defaultContextMenu = {
|
|
|
4715
5541
|
// Get the items from the UI Customization for the menu name (and have a custom name)
|
|
4716
5542
|
{
|
|
4717
5543
|
id: 'forExistingMeasurement',
|
|
4718
|
-
selector:
|
|
4719
|
-
|
|
4720
|
-
|
|
4721
|
-
} = _ref;
|
|
4722
|
-
return !!nearbyToolData;
|
|
4723
|
-
},
|
|
5544
|
+
selector: ({
|
|
5545
|
+
nearbyToolData
|
|
5546
|
+
}) => !!nearbyToolData,
|
|
4724
5547
|
items: [{
|
|
4725
5548
|
label: 'Delete measurement',
|
|
4726
5549
|
commands: [{
|
|
@@ -4745,10 +5568,13 @@ const defaultContextMenu = {
|
|
|
4745
5568
|
|
|
4746
5569
|
|
|
4747
5570
|
// EXTERNAL MODULE: ../../../node_modules/moment/moment.js
|
|
4748
|
-
var moment = __webpack_require__(
|
|
5571
|
+
var moment = __webpack_require__(8291);
|
|
4749
5572
|
var moment_default = /*#__PURE__*/__webpack_require__.n(moment);
|
|
4750
5573
|
// EXTERNAL MODULE: ../../../node_modules/react-window/dist/index.esm.js
|
|
4751
|
-
var index_esm = __webpack_require__(
|
|
5574
|
+
var index_esm = __webpack_require__(6943);
|
|
5575
|
+
// EXTERNAL MODULE: ../../../node_modules/classnames/index.js
|
|
5576
|
+
var classnames = __webpack_require__(61466);
|
|
5577
|
+
var classnames_default = /*#__PURE__*/__webpack_require__.n(classnames);
|
|
4752
5578
|
;// CONCATENATED MODULE: ../../../extensions/default/src/DicomTagBrowser/DicomTagTable.tsx
|
|
4753
5579
|
|
|
4754
5580
|
|
|
@@ -4765,13 +5591,12 @@ const rowStyle = {
|
|
|
4765
5591
|
borderBottomWidth: `${rowBottomBorderPx}px`,
|
|
4766
5592
|
...rowVerticalPaddingStyle
|
|
4767
5593
|
};
|
|
4768
|
-
function ColumnHeaders(
|
|
4769
|
-
|
|
4770
|
-
|
|
4771
|
-
|
|
4772
|
-
|
|
4773
|
-
|
|
4774
|
-
} = _ref;
|
|
5594
|
+
function ColumnHeaders({
|
|
5595
|
+
tagRef,
|
|
5596
|
+
vrRef,
|
|
5597
|
+
keywordRef,
|
|
5598
|
+
valueRef
|
|
5599
|
+
}) {
|
|
4775
5600
|
return /*#__PURE__*/react.createElement("div", {
|
|
4776
5601
|
className: classnames_default()('bg-secondary-dark ohif-scrollbar flex w-full flex-row overflow-y-scroll'),
|
|
4777
5602
|
style: rowVerticalPaddingStyle
|
|
@@ -4805,10 +5630,9 @@ function ColumnHeaders(_ref) {
|
|
|
4805
5630
|
className: "flex flex-row items-center focus:outline-none"
|
|
4806
5631
|
}, "Value"))));
|
|
4807
5632
|
}
|
|
4808
|
-
function DicomTagTable(
|
|
4809
|
-
|
|
4810
|
-
|
|
4811
|
-
} = _ref2;
|
|
5633
|
+
function DicomTagTable({
|
|
5634
|
+
rows
|
|
5635
|
+
}) {
|
|
4812
5636
|
const listRef = (0,react.useRef)();
|
|
4813
5637
|
const canvasRef = (0,react.useRef)();
|
|
4814
5638
|
const [tagHeaderElem, setTagHeaderElem] = (0,react.useState)(null);
|
|
@@ -4862,11 +5686,10 @@ function DicomTagTable(_ref2) {
|
|
|
4862
5686
|
window.removeEventListener('resize', debouncedResize);
|
|
4863
5687
|
};
|
|
4864
5688
|
}, []);
|
|
4865
|
-
const Row = (0,react.useCallback)(
|
|
4866
|
-
|
|
4867
|
-
|
|
4868
|
-
|
|
4869
|
-
} = _ref3;
|
|
5689
|
+
const Row = (0,react.useCallback)(({
|
|
5690
|
+
index,
|
|
5691
|
+
style
|
|
5692
|
+
}) => {
|
|
4870
5693
|
const row = rows[index];
|
|
4871
5694
|
return /*#__PURE__*/react.createElement("div", {
|
|
4872
5695
|
style: {
|
|
@@ -4924,7 +5747,7 @@ function DicomTagTable(_ref2) {
|
|
|
4924
5747
|
style: {
|
|
4925
5748
|
height: '32rem'
|
|
4926
5749
|
}
|
|
4927
|
-
}, isHeaderRendered() && /*#__PURE__*/react.createElement(index_esm/* VariableSizeList */.
|
|
5750
|
+
}, isHeaderRendered() && /*#__PURE__*/react.createElement(index_esm/* VariableSizeList */._m, {
|
|
4928
5751
|
ref: listRef,
|
|
4929
5752
|
height: 500,
|
|
4930
5753
|
itemCount: rows.length,
|
|
@@ -4951,15 +5774,14 @@ const {
|
|
|
4951
5774
|
} = src.classes;
|
|
4952
5775
|
const {
|
|
4953
5776
|
DicomMetaDictionary: DicomTagBrowser_DicomMetaDictionary
|
|
4954
|
-
} = dcmjs_es
|
|
5777
|
+
} = dcmjs_es/* default.data */.Ay.data;
|
|
4955
5778
|
const {
|
|
4956
5779
|
nameMap
|
|
4957
5780
|
} = DicomTagBrowser_DicomMetaDictionary;
|
|
4958
|
-
const DicomTagBrowser =
|
|
4959
|
-
|
|
4960
|
-
|
|
4961
|
-
|
|
4962
|
-
} = _ref;
|
|
5781
|
+
const DicomTagBrowser = ({
|
|
5782
|
+
displaySets,
|
|
5783
|
+
displaySetInstanceUID
|
|
5784
|
+
}) => {
|
|
4963
5785
|
// The column indices that are to be excluded during a filter of the table.
|
|
4964
5786
|
// At present the column indices are:
|
|
4965
5787
|
// 0: DICOM tag
|
|
@@ -5042,12 +5864,12 @@ const DicomTagBrowser = _ref => {
|
|
|
5042
5864
|
className: "mb-6 flex flex-row items-center pl-1"
|
|
5043
5865
|
}, /*#__PURE__*/react.createElement("div", {
|
|
5044
5866
|
className: "flex w-1/2 flex-row items-center"
|
|
5045
|
-
}, /*#__PURE__*/react.createElement(ui_src/* Typography */.
|
|
5867
|
+
}, /*#__PURE__*/react.createElement(ui_src/* Typography */.o5, {
|
|
5046
5868
|
variant: "subtitle",
|
|
5047
5869
|
className: "mr-4"
|
|
5048
5870
|
}, "Series"), /*#__PURE__*/react.createElement("div", {
|
|
5049
5871
|
className: "mr-8 grow"
|
|
5050
|
-
}, /*#__PURE__*/react.createElement(ui_src/* Select */.
|
|
5872
|
+
}, /*#__PURE__*/react.createElement(ui_src/* Select */.l6, {
|
|
5051
5873
|
id: "display-set-selector",
|
|
5052
5874
|
isClearable: false,
|
|
5053
5875
|
onChange: onSelectChange,
|
|
@@ -5056,12 +5878,12 @@ const DicomTagBrowser = _ref => {
|
|
|
5056
5878
|
className: "text-white"
|
|
5057
5879
|
}))), /*#__PURE__*/react.createElement("div", {
|
|
5058
5880
|
className: "flex w-1/2 flex-row items-center"
|
|
5059
|
-
}, showInstanceList && /*#__PURE__*/react.createElement(ui_src/* Typography */.
|
|
5881
|
+
}, showInstanceList && /*#__PURE__*/react.createElement(ui_src/* Typography */.o5, {
|
|
5060
5882
|
variant: "subtitle",
|
|
5061
5883
|
className: "mr-4"
|
|
5062
5884
|
}, "Instance Number"), showInstanceList && /*#__PURE__*/react.createElement("div", {
|
|
5063
5885
|
className: "grow"
|
|
5064
|
-
}, /*#__PURE__*/react.createElement(ui_src/* InputRange */.
|
|
5886
|
+
}, /*#__PURE__*/react.createElement(ui_src/* InputRange */.Qr, {
|
|
5065
5887
|
value: instanceNumber,
|
|
5066
5888
|
key: selectedDisplaySetInstanceUID,
|
|
5067
5889
|
onChange: value => {
|
|
@@ -5077,7 +5899,7 @@ const DicomTagBrowser = _ref => {
|
|
|
5077
5899
|
className: "h-1 w-full bg-black"
|
|
5078
5900
|
}), /*#__PURE__*/react.createElement("div", {
|
|
5079
5901
|
className: "my-3 flex w-1/2 flex-row"
|
|
5080
|
-
}, /*#__PURE__*/react.createElement(ui_src/* InputFilterText */.
|
|
5902
|
+
}, /*#__PURE__*/react.createElement(ui_src/* InputFilterText */.Cv, {
|
|
5081
5903
|
className: "mr-8 block w-full",
|
|
5082
5904
|
placeholder: "Search metadata...",
|
|
5083
5905
|
onDebounceChange: setFilterValue
|
|
@@ -5101,7 +5923,7 @@ function getFormattedRowsFromTags(tags, metadata) {
|
|
|
5101
5923
|
} else {
|
|
5102
5924
|
if (tagInfo.vr === 'xs') {
|
|
5103
5925
|
try {
|
|
5104
|
-
const tag = dcmjs_es
|
|
5926
|
+
const tag = dcmjs_es/* default.data */.Ay.data.Tag.fromPString(tagInfo.tag).toCleanString();
|
|
5105
5927
|
const originalTagInfo = metadata[tag];
|
|
5106
5928
|
tagInfo.vr = originalTagInfo.vr;
|
|
5107
5929
|
} catch (error) {
|
|
@@ -5120,8 +5942,7 @@ function getSortedTags(metadata) {
|
|
|
5120
5942
|
_sortTagList(tagList);
|
|
5121
5943
|
return tagList;
|
|
5122
5944
|
}
|
|
5123
|
-
function getRows(metadata) {
|
|
5124
|
-
let depth = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : 0;
|
|
5945
|
+
function getRows(metadata, depth = 0) {
|
|
5125
5946
|
// Tag, Type, Value, Keyword
|
|
5126
5947
|
|
|
5127
5948
|
const keywords = Object.keys(metadata);
|
|
@@ -5132,7 +5953,6 @@ function getRows(metadata) {
|
|
|
5132
5953
|
if (depth > 0) {
|
|
5133
5954
|
tagIndent += ' '; // If indented, add a space after the indents.
|
|
5134
5955
|
}
|
|
5135
|
-
|
|
5136
5956
|
const rows = [];
|
|
5137
5957
|
for (let i = 0; i < keywords.length; i++) {
|
|
5138
5958
|
let keyword = keywords[i];
|
|
@@ -5259,6 +6079,9 @@ const reuseCachedLayout = (state, hangingProtocolService, syncService) => {
|
|
|
5259
6079
|
const {
|
|
5260
6080
|
protocol
|
|
5261
6081
|
} = hangingProtocolService.getActiveProtocol();
|
|
6082
|
+
if (!protocol) {
|
|
6083
|
+
return;
|
|
6084
|
+
}
|
|
5262
6085
|
const hpInfo = hangingProtocolService.getState();
|
|
5263
6086
|
const {
|
|
5264
6087
|
protocolId,
|
|
@@ -5361,6 +6184,13 @@ const findViewportsByPosition_findOrCreateViewport = (hangingProtocolService, vi
|
|
|
5361
6184
|
}
|
|
5362
6185
|
};
|
|
5363
6186
|
}
|
|
6187
|
+
|
|
6188
|
+
// and lastly if there is no default viewport, then we see if we can grab the
|
|
6189
|
+
// viewportsByPosition at the position index and use that
|
|
6190
|
+
// const candidate = Object.values(viewportsByPosition)[position];
|
|
6191
|
+
|
|
6192
|
+
// // if it has something to display, then we can use it
|
|
6193
|
+
// return candidate?.displaySetInstanceUIDs ? candidate : {};
|
|
5364
6194
|
return {};
|
|
5365
6195
|
};
|
|
5366
6196
|
|
|
@@ -5373,11 +6203,10 @@ const findViewportsByPosition_findOrCreateViewport = (hangingProtocolService, vi
|
|
|
5373
6203
|
* @returns Set of states that can be applied to the state sync to remember
|
|
5374
6204
|
* the current view state.
|
|
5375
6205
|
*/
|
|
5376
|
-
const findViewportsByPosition = (state,
|
|
5377
|
-
|
|
5378
|
-
|
|
5379
|
-
|
|
5380
|
-
} = _ref;
|
|
6206
|
+
const findViewportsByPosition = (state, {
|
|
6207
|
+
numRows,
|
|
6208
|
+
numCols
|
|
6209
|
+
}, syncService) => {
|
|
5381
6210
|
const {
|
|
5382
6211
|
viewports
|
|
5383
6212
|
} = state;
|
|
@@ -5414,8 +6243,8 @@ const findViewportsByPosition = (state, _ref, syncService) => {
|
|
|
5414
6243
|
};
|
|
5415
6244
|
};
|
|
5416
6245
|
/* harmony default export */ const src_findViewportsByPosition = (findViewportsByPosition);
|
|
5417
|
-
// EXTERNAL MODULE: ./index.js +
|
|
5418
|
-
var index = __webpack_require__(
|
|
6246
|
+
// EXTERNAL MODULE: ./index.js + 35 modules
|
|
6247
|
+
var index = __webpack_require__(68870);
|
|
5419
6248
|
;// CONCATENATED MODULE: ../../../extensions/default/src/commandsModule.ts
|
|
5420
6249
|
|
|
5421
6250
|
|
|
@@ -5426,17 +6255,10 @@ var index = __webpack_require__(59754);
|
|
|
5426
6255
|
const {
|
|
5427
6256
|
subscribeToNextViewportGridChange
|
|
5428
6257
|
} = src.utils;
|
|
5429
|
-
|
|
5430
|
-
|
|
5431
|
-
|
|
5432
|
-
|
|
5433
|
-
*/
|
|
5434
|
-
const isHangingProtocolCommand = command => command && (command.commandName === 'setHangingProtocol' || command.commandName === 'toggleHangingProtocol');
|
|
5435
|
-
const commandsModule = _ref => {
|
|
5436
|
-
let {
|
|
5437
|
-
servicesManager,
|
|
5438
|
-
commandsManager
|
|
5439
|
-
} = _ref;
|
|
6258
|
+
const commandsModule = ({
|
|
6259
|
+
servicesManager,
|
|
6260
|
+
commandsManager
|
|
6261
|
+
}) => {
|
|
5440
6262
|
const {
|
|
5441
6263
|
customizationService,
|
|
5442
6264
|
measurementService,
|
|
@@ -5444,8 +6266,7 @@ const commandsModule = _ref => {
|
|
|
5444
6266
|
uiNotificationService,
|
|
5445
6267
|
viewportGridService,
|
|
5446
6268
|
displaySetService,
|
|
5447
|
-
stateSyncService
|
|
5448
|
-
toolbarService
|
|
6269
|
+
stateSyncService
|
|
5449
6270
|
} = servicesManager.services;
|
|
5450
6271
|
|
|
5451
6272
|
// Define a context menu controller for use with any context menus
|
|
@@ -5491,12 +6312,11 @@ const commandsModule = _ref => {
|
|
|
5491
6312
|
closeContextMenu: () => {
|
|
5492
6313
|
contextMenuController.closeContextMenu();
|
|
5493
6314
|
},
|
|
5494
|
-
displayNotification:
|
|
5495
|
-
|
|
5496
|
-
|
|
5497
|
-
|
|
5498
|
-
|
|
5499
|
-
} = _ref2;
|
|
6315
|
+
displayNotification: ({
|
|
6316
|
+
text,
|
|
6317
|
+
title,
|
|
6318
|
+
type
|
|
6319
|
+
}) => {
|
|
5500
6320
|
uiNotificationService.show({
|
|
5501
6321
|
title: title,
|
|
5502
6322
|
message: text,
|
|
@@ -5506,41 +6326,6 @@ const commandsModule = _ref => {
|
|
|
5506
6326
|
clearMeasurements: () => {
|
|
5507
6327
|
measurementService.clear();
|
|
5508
6328
|
},
|
|
5509
|
-
/**
|
|
5510
|
-
* Toggles off all tools which contain a commandName of setHangingProtocol
|
|
5511
|
-
* or toggleHangingProtocol, and which match/don't match the protocol id/stage
|
|
5512
|
-
*/
|
|
5513
|
-
toggleHpTools: () => {
|
|
5514
|
-
const {
|
|
5515
|
-
protocol,
|
|
5516
|
-
stageIndex: toggleStageIndex,
|
|
5517
|
-
stage
|
|
5518
|
-
} = hangingProtocolService.getActiveProtocol();
|
|
5519
|
-
const enableListener = button => {
|
|
5520
|
-
if (!button.id) {
|
|
5521
|
-
return;
|
|
5522
|
-
}
|
|
5523
|
-
const {
|
|
5524
|
-
commands,
|
|
5525
|
-
items
|
|
5526
|
-
} = button.props || button;
|
|
5527
|
-
if (items) {
|
|
5528
|
-
items.forEach(enableListener);
|
|
5529
|
-
}
|
|
5530
|
-
const hpCommand = commands?.find?.(isHangingProtocolCommand);
|
|
5531
|
-
if (!hpCommand) {
|
|
5532
|
-
return;
|
|
5533
|
-
}
|
|
5534
|
-
const {
|
|
5535
|
-
protocolId,
|
|
5536
|
-
stageIndex,
|
|
5537
|
-
stageId
|
|
5538
|
-
} = hpCommand.commandOptions;
|
|
5539
|
-
const isActive = (!protocolId || protocolId === protocol.id) && (stageIndex === undefined || stageIndex === toggleStageIndex) && (!stageId || stageId === stage.id);
|
|
5540
|
-
toolbarService.setToggled(button.id, isActive);
|
|
5541
|
-
};
|
|
5542
|
-
Object.values(toolbarService.getButtons()).forEach(enableListener);
|
|
5543
|
-
},
|
|
5544
6329
|
/**
|
|
5545
6330
|
* Sets the specified protocol
|
|
5546
6331
|
* 1. Records any existing state using the viewport grid service
|
|
@@ -5565,24 +6350,19 @@ const commandsModule = _ref => {
|
|
|
5565
6350
|
* @param options.stageIndex - the index of the stage to go to.
|
|
5566
6351
|
* @param options.reset - flag to indicate if the HP should be reset to its original and not restored to a previous state
|
|
5567
6352
|
*/
|
|
5568
|
-
setHangingProtocol:
|
|
5569
|
-
|
|
5570
|
-
|
|
5571
|
-
|
|
5572
|
-
|
|
5573
|
-
|
|
5574
|
-
|
|
5575
|
-
} = _ref3;
|
|
5576
|
-
const primaryToolBeforeHPChange = toolbarService.getActivePrimaryTool();
|
|
6353
|
+
setHangingProtocol: ({
|
|
6354
|
+
activeStudyUID = '',
|
|
6355
|
+
protocolId,
|
|
6356
|
+
stageId,
|
|
6357
|
+
stageIndex,
|
|
6358
|
+
reset = false
|
|
6359
|
+
}) => {
|
|
5577
6360
|
try {
|
|
5578
6361
|
// Stores in the state the display set selector id to displaySetUID mapping
|
|
5579
6362
|
// Pass in viewportId for the active viewport. This item will get set as
|
|
5580
6363
|
// the activeViewportId
|
|
5581
6364
|
const state = viewportGridService.getState();
|
|
5582
6365
|
const hpInfo = hangingProtocolService.getState();
|
|
5583
|
-
const {
|
|
5584
|
-
protocol: oldProtocol
|
|
5585
|
-
} = hangingProtocolService.getActiveProtocol();
|
|
5586
6366
|
const stateSyncReduce = reuseCachedLayouts(state, hangingProtocolService, stateSyncService);
|
|
5587
6367
|
const {
|
|
5588
6368
|
hangingProtocolStageIndexMap,
|
|
@@ -5632,45 +6412,9 @@ const commandsModule = _ref => {
|
|
|
5632
6412
|
// multi-study display.
|
|
5633
6413
|
delete displaySetSelectorMap[`${activeStudyUID || hpInfo.activeStudyUID}:activeDisplaySet:0`];
|
|
5634
6414
|
stateSyncService.store(stateSyncReduce);
|
|
5635
|
-
// This is a default action applied
|
|
5636
|
-
const {
|
|
5637
|
-
protocol
|
|
5638
|
-
} = hangingProtocolService.getActiveProtocol();
|
|
5639
|
-
actions.toggleHpTools();
|
|
5640
|
-
|
|
5641
|
-
// try to use the same tool in the new hanging protocol stage
|
|
5642
|
-
const primaryButton = toolbarService.getButton(primaryToolBeforeHPChange);
|
|
5643
|
-
if (primaryButton) {
|
|
5644
|
-
// is there any type of interaction on this button, if not it might be in the
|
|
5645
|
-
// items. This is a bit of a hack, but it works for now.
|
|
5646
|
-
|
|
5647
|
-
let interactionType = primaryButton.props?.interactionType;
|
|
5648
|
-
if (!interactionType && primaryButton.props?.items) {
|
|
5649
|
-
const firstItem = primaryButton.props.items[0];
|
|
5650
|
-
interactionType = firstItem.props?.interactionType || firstItem.props?.type;
|
|
5651
|
-
}
|
|
5652
|
-
if (interactionType) {
|
|
5653
|
-
toolbarService.recordInteraction({
|
|
5654
|
-
interactionType,
|
|
5655
|
-
...primaryButton.props
|
|
5656
|
-
});
|
|
5657
|
-
}
|
|
5658
|
-
}
|
|
5659
|
-
|
|
5660
|
-
// Send the notification about updating the state
|
|
5661
|
-
if (protocolId !== hpInfo.protocolId) {
|
|
5662
|
-
// The old protocol callbacks are used for turning off things
|
|
5663
|
-
// like crosshairs when moving to the new HP
|
|
5664
|
-
commandsManager.run(oldProtocol.callbacks?.onProtocolExit);
|
|
5665
|
-
// The new protocol callback is used for things like
|
|
5666
|
-
// activating modes etc.
|
|
5667
|
-
}
|
|
5668
|
-
|
|
5669
|
-
commandsManager.run(protocol.callbacks?.onProtocolEnter);
|
|
5670
6415
|
return true;
|
|
5671
6416
|
} catch (e) {
|
|
5672
6417
|
console.error(e);
|
|
5673
|
-
actions.toggleHpTools();
|
|
5674
6418
|
uiNotificationService.show({
|
|
5675
6419
|
title: 'Apply Hanging Protocol',
|
|
5676
6420
|
message: 'The hanging protocol could not be applied.',
|
|
@@ -5680,11 +6424,10 @@ const commandsModule = _ref => {
|
|
|
5680
6424
|
return false;
|
|
5681
6425
|
}
|
|
5682
6426
|
},
|
|
5683
|
-
toggleHangingProtocol:
|
|
5684
|
-
|
|
5685
|
-
|
|
5686
|
-
|
|
5687
|
-
} = _ref4;
|
|
6427
|
+
toggleHangingProtocol: ({
|
|
6428
|
+
protocolId,
|
|
6429
|
+
stageIndex
|
|
6430
|
+
}) => {
|
|
5688
6431
|
const {
|
|
5689
6432
|
protocol,
|
|
5690
6433
|
stageIndex: desiredStageIndex,
|
|
@@ -5717,10 +6460,9 @@ const commandsModule = _ref => {
|
|
|
5717
6460
|
});
|
|
5718
6461
|
}
|
|
5719
6462
|
},
|
|
5720
|
-
deltaStage:
|
|
5721
|
-
|
|
5722
|
-
|
|
5723
|
-
} = _ref5;
|
|
6463
|
+
deltaStage: ({
|
|
6464
|
+
direction
|
|
6465
|
+
}) => {
|
|
5724
6466
|
const {
|
|
5725
6467
|
protocolId,
|
|
5726
6468
|
stageIndex: oldStageIndex
|
|
@@ -5746,11 +6488,10 @@ const commandsModule = _ref => {
|
|
|
5746
6488
|
/**
|
|
5747
6489
|
* Changes the viewport grid layout in terms of the MxN layout.
|
|
5748
6490
|
*/
|
|
5749
|
-
setViewportGridLayout:
|
|
5750
|
-
|
|
5751
|
-
|
|
5752
|
-
|
|
5753
|
-
} = _ref6;
|
|
6491
|
+
setViewportGridLayout: ({
|
|
6492
|
+
numRows,
|
|
6493
|
+
numCols
|
|
6494
|
+
}) => {
|
|
5754
6495
|
const {
|
|
5755
6496
|
protocol
|
|
5756
6497
|
} = hangingProtocolService.getActiveProtocol();
|
|
@@ -5897,7 +6638,7 @@ const commandsModule = _ref => {
|
|
|
5897
6638
|
* for `replace` is false
|
|
5898
6639
|
*/
|
|
5899
6640
|
navigateHistory(historyArgs) {
|
|
5900
|
-
index/* history */.
|
|
6641
|
+
index/* history */.b.navigate(historyArgs.to, historyArgs.options);
|
|
5901
6642
|
},
|
|
5902
6643
|
openDICOMTagViewer() {
|
|
5903
6644
|
const {
|
|
@@ -5920,6 +6661,7 @@ const commandsModule = _ref => {
|
|
|
5920
6661
|
displaySetInstanceUID,
|
|
5921
6662
|
onClose: UIModalService.hide
|
|
5922
6663
|
},
|
|
6664
|
+
containerDimensions: 'max-w-4xl max-h-4xl',
|
|
5923
6665
|
title: 'DICOM Tag Browser'
|
|
5924
6666
|
});
|
|
5925
6667
|
},
|
|
@@ -5960,11 +6702,10 @@ const commandsModule = _ref => {
|
|
|
5960
6702
|
behavior: 'smooth'
|
|
5961
6703
|
});
|
|
5962
6704
|
},
|
|
5963
|
-
updateViewportDisplaySet:
|
|
5964
|
-
|
|
5965
|
-
|
|
5966
|
-
|
|
5967
|
-
} = _ref7;
|
|
6705
|
+
updateViewportDisplaySet: ({
|
|
6706
|
+
direction,
|
|
6707
|
+
excludeNonImageModalities
|
|
6708
|
+
}) => {
|
|
5968
6709
|
const nonImageModalities = ['SR', 'SEG', 'SM', 'RTSTRUCT', 'RTPLAN', 'RTDOSE'];
|
|
5969
6710
|
|
|
5970
6711
|
// Sort the display sets as per the hanging protocol service viewport/display set scoring system.
|
|
@@ -6016,61 +6757,43 @@ const commandsModule = _ref => {
|
|
|
6016
6757
|
commandFn: actions.closeContextMenu
|
|
6017
6758
|
},
|
|
6018
6759
|
clearMeasurements: {
|
|
6019
|
-
commandFn: actions.clearMeasurements
|
|
6020
|
-
storeContexts: [],
|
|
6021
|
-
options: {}
|
|
6760
|
+
commandFn: actions.clearMeasurements
|
|
6022
6761
|
},
|
|
6023
6762
|
displayNotification: {
|
|
6024
|
-
commandFn: actions.displayNotification
|
|
6025
|
-
storeContexts: [],
|
|
6026
|
-
options: {}
|
|
6763
|
+
commandFn: actions.displayNotification
|
|
6027
6764
|
},
|
|
6028
6765
|
setHangingProtocol: {
|
|
6029
|
-
commandFn: actions.setHangingProtocol
|
|
6030
|
-
storeContexts: [],
|
|
6031
|
-
options: {}
|
|
6766
|
+
commandFn: actions.setHangingProtocol
|
|
6032
6767
|
},
|
|
6033
6768
|
toggleHangingProtocol: {
|
|
6034
|
-
commandFn: actions.toggleHangingProtocol
|
|
6035
|
-
storeContexts: [],
|
|
6036
|
-
options: {}
|
|
6769
|
+
commandFn: actions.toggleHangingProtocol
|
|
6037
6770
|
},
|
|
6038
6771
|
navigateHistory: {
|
|
6039
|
-
commandFn: actions.navigateHistory
|
|
6040
|
-
storeContexts: [],
|
|
6041
|
-
options: {}
|
|
6772
|
+
commandFn: actions.navigateHistory
|
|
6042
6773
|
},
|
|
6043
6774
|
nextStage: {
|
|
6044
6775
|
commandFn: actions.deltaStage,
|
|
6045
|
-
storeContexts: [],
|
|
6046
6776
|
options: {
|
|
6047
6777
|
direction: 1
|
|
6048
6778
|
}
|
|
6049
6779
|
},
|
|
6050
6780
|
previousStage: {
|
|
6051
6781
|
commandFn: actions.deltaStage,
|
|
6052
|
-
storeContexts: [],
|
|
6053
6782
|
options: {
|
|
6054
6783
|
direction: -1
|
|
6055
6784
|
}
|
|
6056
6785
|
},
|
|
6057
6786
|
setViewportGridLayout: {
|
|
6058
|
-
commandFn: actions.setViewportGridLayout
|
|
6059
|
-
storeContexts: [],
|
|
6060
|
-
options: {}
|
|
6787
|
+
commandFn: actions.setViewportGridLayout
|
|
6061
6788
|
},
|
|
6062
6789
|
toggleOneUp: {
|
|
6063
|
-
commandFn: actions.toggleOneUp
|
|
6064
|
-
storeContexts: [],
|
|
6065
|
-
options: {}
|
|
6790
|
+
commandFn: actions.toggleOneUp
|
|
6066
6791
|
},
|
|
6067
6792
|
openDICOMTagViewer: {
|
|
6068
6793
|
commandFn: actions.openDICOMTagViewer
|
|
6069
6794
|
},
|
|
6070
6795
|
updateViewportDisplaySet: {
|
|
6071
|
-
commandFn: actions.updateViewportDisplaySet
|
|
6072
|
-
storeContexts: [],
|
|
6073
|
-
options: {}
|
|
6796
|
+
commandFn: actions.updateViewportDisplaySet
|
|
6074
6797
|
}
|
|
6075
6798
|
};
|
|
6076
6799
|
return {
|
|
@@ -6480,6 +7203,9 @@ const defaultProtocol = {
|
|
|
6480
7203
|
editableBy: {},
|
|
6481
7204
|
protocolMatchingRules: [],
|
|
6482
7205
|
toolGroupIds: ['default'],
|
|
7206
|
+
hpInitiationCriteria: {
|
|
7207
|
+
minSeriesLoaded: 1
|
|
7208
|
+
},
|
|
6483
7209
|
// -1 would be used to indicate active only, whereas other values are
|
|
6484
7210
|
// the number of required priors referenced - so 0 means active with
|
|
6485
7211
|
// 0 or more priors.
|
|
@@ -6524,7 +7250,6 @@ const defaultProtocol = {
|
|
|
6524
7250
|
// studyMatchingRules: [],
|
|
6525
7251
|
}
|
|
6526
7252
|
},
|
|
6527
|
-
|
|
6528
7253
|
stages: [{
|
|
6529
7254
|
name: 'default',
|
|
6530
7255
|
viewportStructure: {
|
|
@@ -6550,7 +7275,6 @@ const defaultProtocol = {
|
|
|
6550
7275
|
// preset: 'middle', // 'first', 'last', 'middle'
|
|
6551
7276
|
// },
|
|
6552
7277
|
},
|
|
6553
|
-
|
|
6554
7278
|
displaySets: [{
|
|
6555
7279
|
id: 'defaultDisplaySetId'
|
|
6556
7280
|
}]
|
|
@@ -6582,8 +7306,8 @@ function getHangingProtocolModule() {
|
|
|
6582
7306
|
|
|
6583
7307
|
|
|
6584
7308
|
function DataSourceSelector() {
|
|
6585
|
-
const [appConfig] = (0,state/* useAppConfig */.
|
|
6586
|
-
const navigate = (0,dist/* useNavigate */.
|
|
7309
|
+
const [appConfig] = (0,state/* useAppConfig */.r)();
|
|
7310
|
+
const navigate = (0,dist/* useNavigate */.Zp)();
|
|
6587
7311
|
|
|
6588
7312
|
// This is frowned upon, but the raw config is needed here to provide
|
|
6589
7313
|
// the selector
|
|
@@ -6607,8 +7331,8 @@ function DataSourceSelector() {
|
|
|
6607
7331
|
key: ds.sourceName
|
|
6608
7332
|
}, /*#__PURE__*/react.createElement("h1", {
|
|
6609
7333
|
className: "text-white"
|
|
6610
|
-
}, ds.configuration?.friendlyName || ds.friendlyName), /*#__PURE__*/react.createElement(ui_src/* Button
|
|
6611
|
-
type: ui_src/* ButtonEnums.type */.
|
|
7334
|
+
}, ds.configuration?.friendlyName || ds.friendlyName), /*#__PURE__*/react.createElement(ui_src/* Button */.$n, {
|
|
7335
|
+
type: ui_src/* ButtonEnums.type */.Ny.NW.primary,
|
|
6612
7336
|
className: classnames_default()('ml-2'),
|
|
6613
7337
|
onClick: () => {
|
|
6614
7338
|
navigate({
|
|
@@ -6624,15 +7348,14 @@ function DataSourceSelector() {
|
|
|
6624
7348
|
|
|
6625
7349
|
|
|
6626
7350
|
|
|
6627
|
-
function ItemListComponent(
|
|
6628
|
-
|
|
6629
|
-
|
|
6630
|
-
|
|
6631
|
-
|
|
6632
|
-
} = _ref;
|
|
7351
|
+
function ItemListComponent({
|
|
7352
|
+
itemLabel,
|
|
7353
|
+
itemList,
|
|
7354
|
+
onItemClicked
|
|
7355
|
+
}) {
|
|
6633
7356
|
const {
|
|
6634
7357
|
t
|
|
6635
|
-
} = (0,es/* useTranslation
|
|
7358
|
+
} = (0,es/* useTranslation */.Bd)('DataSourceConfiguration');
|
|
6636
7359
|
const [filterValue, setFilterValue] = (0,react.useState)('');
|
|
6637
7360
|
(0,react.useEffect)(() => {
|
|
6638
7361
|
setFilterValue('');
|
|
@@ -6643,18 +7366,18 @@ function ItemListComponent(_ref) {
|
|
|
6643
7366
|
className: "flex items-center justify-between"
|
|
6644
7367
|
}, /*#__PURE__*/react.createElement("div", {
|
|
6645
7368
|
className: "text-primary-light text-[20px]"
|
|
6646
|
-
}, t(`Select ${itemLabel}`)), /*#__PURE__*/react.createElement(ui_src/* InputFilterText */.
|
|
7369
|
+
}, t(`Select ${itemLabel}`)), /*#__PURE__*/react.createElement(ui_src/* InputFilterText */.Cv, {
|
|
6647
7370
|
className: "max-w-[40%] grow",
|
|
6648
7371
|
value: filterValue,
|
|
6649
7372
|
onDebounceChange: setFilterValue,
|
|
6650
7373
|
placeholder: t(`Search ${itemLabel} list`)
|
|
6651
7374
|
})), /*#__PURE__*/react.createElement("div", {
|
|
6652
7375
|
className: "relative flex min-h-[1px] grow flex-col bg-black text-[14px]"
|
|
6653
|
-
}, itemList == null ? /*#__PURE__*/react.createElement(ui_src/* LoadingIndicatorProgress */.
|
|
7376
|
+
}, itemList == null ? /*#__PURE__*/react.createElement(ui_src/* LoadingIndicatorProgress */.Jx, {
|
|
6654
7377
|
className: 'h-full w-full'
|
|
6655
7378
|
}) : itemList.length === 0 ? /*#__PURE__*/react.createElement("div", {
|
|
6656
7379
|
className: "text-primary-light flex h-full flex-col items-center justify-center px-6 py-4"
|
|
6657
|
-
}, /*#__PURE__*/react.createElement(ui_src/* Icon */.
|
|
7380
|
+
}, /*#__PURE__*/react.createElement(ui_src/* Icon */.In, {
|
|
6658
7381
|
name: "magnifier",
|
|
6659
7382
|
className: "mb-4"
|
|
6660
7383
|
}), /*#__PURE__*/react.createElement("span", null, t(`No ${itemLabel} available`))) : /*#__PURE__*/react.createElement(react.Fragment, null, /*#__PURE__*/react.createElement("div", {
|
|
@@ -6666,10 +7389,10 @@ function ItemListComponent(_ref) {
|
|
|
6666
7389
|
return /*#__PURE__*/react.createElement("div", {
|
|
6667
7390
|
className: classnames_default()('hover:text-primary-light hover:bg-primary-dark group mx-2 flex items-center justify-between px-6 py-2', border),
|
|
6668
7391
|
key: item.id
|
|
6669
|
-
}, /*#__PURE__*/react.createElement("div", null, item.name), /*#__PURE__*/react.createElement(ui_src/* Button
|
|
7392
|
+
}, /*#__PURE__*/react.createElement("div", null, item.name), /*#__PURE__*/react.createElement(ui_src/* Button */.$n, {
|
|
6670
7393
|
onClick: () => onItemClicked(item),
|
|
6671
7394
|
className: "invisible group-hover:visible",
|
|
6672
|
-
endIcon: /*#__PURE__*/react.createElement(ui_src/* Icon */.
|
|
7395
|
+
endIcon: /*#__PURE__*/react.createElement(ui_src/* Icon */.In, {
|
|
6673
7396
|
name: "arrow-left"
|
|
6674
7397
|
})
|
|
6675
7398
|
}, t('Select')));
|
|
@@ -6683,15 +7406,14 @@ function ItemListComponent(_ref) {
|
|
|
6683
7406
|
|
|
6684
7407
|
|
|
6685
7408
|
const NO_WRAP_ELLIPSIS_CLASS_NAMES = 'text-ellipsis whitespace-nowrap overflow-hidden';
|
|
6686
|
-
function DataSourceConfigurationModalComponent(
|
|
6687
|
-
|
|
6688
|
-
|
|
6689
|
-
|
|
6690
|
-
|
|
6691
|
-
} = _ref;
|
|
7409
|
+
function DataSourceConfigurationModalComponent({
|
|
7410
|
+
configurationAPI,
|
|
7411
|
+
configuredItems,
|
|
7412
|
+
onHide
|
|
7413
|
+
}) {
|
|
6692
7414
|
const {
|
|
6693
7415
|
t
|
|
6694
|
-
} = (0,es/* useTranslation
|
|
7416
|
+
} = (0,es/* useTranslation */.Bd)('DataSourceConfiguration');
|
|
6695
7417
|
const [itemList, setItemList] = (0,react.useState)();
|
|
6696
7418
|
const [selectedItems, setSelectedItems] = (0,react.useState)(configuredItems);
|
|
6697
7419
|
const [errorMessage, setErrorMessage] = (0,react.useState)();
|
|
@@ -6765,9 +7487,9 @@ function DataSourceConfigurationModalComponent(_ref) {
|
|
|
6765
7487
|
} : undefined
|
|
6766
7488
|
}, /*#__PURE__*/react.createElement("div", {
|
|
6767
7489
|
className: "text- flex items-center gap-2"
|
|
6768
|
-
}, itemLabelIndex < selectedItems.length ? /*#__PURE__*/react.createElement(ui_src/* Icon */.
|
|
7490
|
+
}, itemLabelIndex < selectedItems.length ? /*#__PURE__*/react.createElement(ui_src/* Icon */.In, {
|
|
6769
7491
|
name: "status-tracked"
|
|
6770
|
-
}) : /*#__PURE__*/react.createElement(ui_src/* Icon */.
|
|
7492
|
+
}) : /*#__PURE__*/react.createElement(ui_src/* Icon */.In, {
|
|
6771
7493
|
name: "status-untracked"
|
|
6772
7494
|
}), /*#__PURE__*/react.createElement("div", {
|
|
6773
7495
|
className: classnames_default()(NO_WRAP_ELLIPSIS_CLASS_NAMES)
|
|
@@ -6795,18 +7517,17 @@ function DataSourceConfigurationModalComponent(_ref) {
|
|
|
6795
7517
|
|
|
6796
7518
|
|
|
6797
7519
|
|
|
6798
|
-
function DataSourceConfigurationComponent(
|
|
6799
|
-
|
|
6800
|
-
|
|
6801
|
-
|
|
6802
|
-
} = _ref;
|
|
7520
|
+
function DataSourceConfigurationComponent({
|
|
7521
|
+
servicesManager,
|
|
7522
|
+
extensionManager
|
|
7523
|
+
}) {
|
|
6803
7524
|
const {
|
|
6804
7525
|
t
|
|
6805
|
-
} = (0,es/* useTranslation
|
|
7526
|
+
} = (0,es/* useTranslation */.Bd)('DataSourceConfiguration');
|
|
6806
7527
|
const {
|
|
6807
7528
|
show,
|
|
6808
7529
|
hide
|
|
6809
|
-
} = (0,ui_src/* useModal */.
|
|
7530
|
+
} = (0,ui_src/* useModal */.hS)();
|
|
6810
7531
|
const {
|
|
6811
7532
|
customizationService
|
|
6812
7533
|
} = servicesManager.services;
|
|
@@ -6865,7 +7586,7 @@ function DataSourceConfigurationComponent(_ref) {
|
|
|
6865
7586
|
}, [configurationAPI, configuredItems, showConfigurationModal]);
|
|
6866
7587
|
return configuredItems ? /*#__PURE__*/react.createElement("div", {
|
|
6867
7588
|
className: "text-aqua-pale flex items-center overflow-hidden"
|
|
6868
|
-
}, /*#__PURE__*/react.createElement(ui_src/* Icon */.
|
|
7589
|
+
}, /*#__PURE__*/react.createElement(ui_src/* Icon */.In, {
|
|
6869
7590
|
name: "settings",
|
|
6870
7591
|
className: "mr-2.5 h-3.5 w-3.5 shrink-0 cursor-pointer",
|
|
6871
7592
|
onClick: showConfigurationModal
|
|
@@ -7017,9 +7738,7 @@ class GoogleCloudDataSourceConfigurationAPI {
|
|
|
7017
7738
|
* @param fetchSearchParams any search query params; currently only used for paging results
|
|
7018
7739
|
* @returns an array of items of the specified type
|
|
7019
7740
|
*/
|
|
7020
|
-
static async _doFetch(urlStr, fetchItemType) {
|
|
7021
|
-
let fetchOptions = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : {};
|
|
7022
|
-
let fetchSearchParams = arguments.length > 3 && arguments[3] !== undefined ? arguments[3] : {};
|
|
7741
|
+
static async _doFetch(urlStr, fetchItemType, fetchOptions = {}, fetchSearchParams = {}) {
|
|
7023
7742
|
try {
|
|
7024
7743
|
const url = new URL(urlStr);
|
|
7025
7744
|
url.search = new URLSearchParams(fetchSearchParams).toString();
|
|
@@ -7055,6 +7774,7 @@ class GoogleCloudDataSourceConfigurationAPI {
|
|
|
7055
7774
|
|
|
7056
7775
|
|
|
7057
7776
|
|
|
7777
|
+
|
|
7058
7778
|
/**
|
|
7059
7779
|
*
|
|
7060
7780
|
* Note: this is an example of how the customization module can be used
|
|
@@ -7064,11 +7784,10 @@ class GoogleCloudDataSourceConfigurationAPI {
|
|
|
7064
7784
|
* custom page for the user to view their profile, or to add a custom
|
|
7065
7785
|
* page for login etc.
|
|
7066
7786
|
*/
|
|
7067
|
-
function getCustomizationModule(
|
|
7068
|
-
|
|
7069
|
-
|
|
7070
|
-
|
|
7071
|
-
} = _ref;
|
|
7787
|
+
function getCustomizationModule({
|
|
7788
|
+
servicesManager,
|
|
7789
|
+
extensionManager
|
|
7790
|
+
}) {
|
|
7072
7791
|
return [{
|
|
7073
7792
|
name: 'helloPage',
|
|
7074
7793
|
value: {
|
|
@@ -7193,14 +7912,65 @@ function getCustomizationModule(_ref) {
|
|
|
7193
7912
|
// The factory for creating an instance of a BaseDataSourceConfigurationAPI for Google Cloud Healthcare
|
|
7194
7913
|
id: 'ohif.dataSourceConfigurationAPI.google',
|
|
7195
7914
|
factory: dataSourceName => new GoogleCloudDataSourceConfigurationAPI(dataSourceName, servicesManager, extensionManager)
|
|
7915
|
+
}, {
|
|
7916
|
+
id: 'progressDropdownWithServiceComponent',
|
|
7917
|
+
component: ProgressDropdownWithService_ProgressDropdownWithService
|
|
7196
7918
|
}]
|
|
7197
7919
|
}];
|
|
7198
7920
|
}
|
|
7921
|
+
;// CONCATENATED MODULE: ../../../extensions/default/src/Components/LineChartViewport/LineChartViewport.tsx
|
|
7922
|
+
|
|
7923
|
+
|
|
7924
|
+
const LineChartViewport = ({
|
|
7925
|
+
displaySets
|
|
7926
|
+
}) => {
|
|
7927
|
+
const displaySet = displaySets[0];
|
|
7928
|
+
const {
|
|
7929
|
+
axis: chartAxis,
|
|
7930
|
+
series: chartSeries
|
|
7931
|
+
} = displaySet.instance.chartData;
|
|
7932
|
+
return /*#__PURE__*/react.createElement(ui_src/* LineChart */.bl, {
|
|
7933
|
+
showLegend: true,
|
|
7934
|
+
legendWidth: 150,
|
|
7935
|
+
axis: {
|
|
7936
|
+
x: {
|
|
7937
|
+
label: chartAxis.x.label,
|
|
7938
|
+
indexRef: 0,
|
|
7939
|
+
type: 'x',
|
|
7940
|
+
range: {
|
|
7941
|
+
min: 0
|
|
7942
|
+
}
|
|
7943
|
+
},
|
|
7944
|
+
y: {
|
|
7945
|
+
label: chartAxis.y.label,
|
|
7946
|
+
indexRef: 1,
|
|
7947
|
+
type: 'y'
|
|
7948
|
+
}
|
|
7949
|
+
},
|
|
7950
|
+
series: chartSeries
|
|
7951
|
+
});
|
|
7952
|
+
};
|
|
7953
|
+
|
|
7954
|
+
;// CONCATENATED MODULE: ../../../extensions/default/src/Components/LineChartViewport/index.ts
|
|
7955
|
+
|
|
7956
|
+
;// CONCATENATED MODULE: ../../../extensions/default/src/getViewportModule.tsx
|
|
7957
|
+
|
|
7958
|
+
const getViewportModule = ({
|
|
7959
|
+
servicesManager,
|
|
7960
|
+
commandsManager,
|
|
7961
|
+
extensionManager
|
|
7962
|
+
}) => {
|
|
7963
|
+
return [{
|
|
7964
|
+
name: 'chartViewport',
|
|
7965
|
+
component: LineChartViewport
|
|
7966
|
+
}];
|
|
7967
|
+
};
|
|
7968
|
+
|
|
7199
7969
|
// EXTERNAL MODULE: ../../../node_modules/@cornerstonejs/calculate-suv/dist/calculate-suv.esm.js
|
|
7200
|
-
var calculate_suv_esm = __webpack_require__(
|
|
7970
|
+
var calculate_suv_esm = __webpack_require__(79717);
|
|
7201
7971
|
;// CONCATENATED MODULE: ../../../extensions/default/src/getPTImageIdInstanceMetadata.ts
|
|
7202
7972
|
|
|
7203
|
-
const getPTImageIdInstanceMetadata_metadataProvider = src
|
|
7973
|
+
const getPTImageIdInstanceMetadata_metadataProvider = src/* default.classes */.Ay.classes.MetadataProvider;
|
|
7204
7974
|
function getPTImageIdInstanceMetadata(imageId) {
|
|
7205
7975
|
const dicomMetaData = getPTImageIdInstanceMetadata_metadataProvider.get('instance', imageId);
|
|
7206
7976
|
if (!dicomMetaData) {
|
|
@@ -7276,14 +8046,18 @@ const init_metadataProvider = src.classes.MetadataProvider;
|
|
|
7276
8046
|
* @param {Object} servicesManager
|
|
7277
8047
|
* @param {Object} configuration
|
|
7278
8048
|
*/
|
|
7279
|
-
function init(
|
|
7280
|
-
|
|
7281
|
-
|
|
7282
|
-
|
|
7283
|
-
|
|
8049
|
+
function init({
|
|
8050
|
+
servicesManager,
|
|
8051
|
+
configuration = {},
|
|
8052
|
+
commandsManager
|
|
8053
|
+
}) {
|
|
7284
8054
|
const {
|
|
7285
|
-
stateSyncService
|
|
8055
|
+
stateSyncService,
|
|
8056
|
+
toolbarService,
|
|
8057
|
+
cineService,
|
|
8058
|
+
viewportGridService
|
|
7286
8059
|
} = servicesManager.services;
|
|
8060
|
+
toolbarService.registerEventForToolbarUpdate(cineService, [cineService.EVENTS.CINE_STATE_CHANGED]);
|
|
7287
8061
|
// Add
|
|
7288
8062
|
src.DicomMetadataStore.subscribe(src.DicomMetadataStore.EVENTS.INSTANCES_ADDED, handlePETImageMetadata);
|
|
7289
8063
|
|
|
@@ -7298,6 +8072,12 @@ function init(_ref) {
|
|
|
7298
8072
|
clearOnModeExit: true
|
|
7299
8073
|
});
|
|
7300
8074
|
|
|
8075
|
+
// uiStateStore is a sync state which stores the relevant
|
|
8076
|
+
// UI state for the viewer
|
|
8077
|
+
stateSyncService.register('uiStateStore', {
|
|
8078
|
+
clearOnModeExit: true
|
|
8079
|
+
});
|
|
8080
|
+
|
|
7301
8081
|
// displaySetSelectorMap stores a map from
|
|
7302
8082
|
// `<activeStudyUID>:<displaySetSelectorId>:<matchOffset>` to
|
|
7303
8083
|
// a displaySetInstanceUID, used to display named display sets in
|
|
@@ -7314,7 +8094,7 @@ function init(_ref) {
|
|
|
7314
8094
|
});
|
|
7315
8095
|
|
|
7316
8096
|
// Stores a map from the to be applied hanging protocols `<activeStudyUID>:<protocolId>`
|
|
7317
|
-
// to the previously applied hanging
|
|
8097
|
+
// to the previously applied hanging protocolStageIndexMap key, in order to toggle
|
|
7318
8098
|
// off the applied protocol and remember the old state.
|
|
7319
8099
|
stateSyncService.register('toggleHangingProtocol', {
|
|
7320
8100
|
clearOnModeExit: true
|
|
@@ -7326,44 +8106,83 @@ function init(_ref) {
|
|
|
7326
8106
|
stateSyncService.register('viewportsByPosition', {
|
|
7327
8107
|
clearOnModeExit: true
|
|
7328
8108
|
});
|
|
8109
|
+
|
|
8110
|
+
// Function to process and subscribe to events for a given set of commands and listeners
|
|
8111
|
+
const subscribeToEvents = listeners => {
|
|
8112
|
+
Object.entries(listeners).forEach(([event, commands]) => {
|
|
8113
|
+
const supportedEvents = [viewportGridService.EVENTS.ACTIVE_VIEWPORT_ID_CHANGED, viewportGridService.EVENTS.VIEWPORTS_READY];
|
|
8114
|
+
if (supportedEvents.includes(event)) {
|
|
8115
|
+
viewportGridService.subscribe(event, eventData => {
|
|
8116
|
+
const viewportId = eventData?.viewportId ?? viewportGridService.getActiveViewportId();
|
|
8117
|
+
commandsManager.run(commands, {
|
|
8118
|
+
viewportId
|
|
8119
|
+
});
|
|
8120
|
+
});
|
|
8121
|
+
}
|
|
8122
|
+
});
|
|
8123
|
+
};
|
|
8124
|
+
toolbarService.subscribe(toolbarService.EVENTS.TOOL_BAR_MODIFIED, state => {
|
|
8125
|
+
const {
|
|
8126
|
+
buttons
|
|
8127
|
+
} = state;
|
|
8128
|
+
for (const [id, button] of Object.entries(buttons)) {
|
|
8129
|
+
const {
|
|
8130
|
+
groupId,
|
|
8131
|
+
items,
|
|
8132
|
+
listeners
|
|
8133
|
+
} = button.props || {};
|
|
8134
|
+
|
|
8135
|
+
// Handle group items' listeners
|
|
8136
|
+
if (groupId && items) {
|
|
8137
|
+
items.forEach(item => {
|
|
8138
|
+
if (item.listeners) {
|
|
8139
|
+
subscribeToEvents(item.listeners);
|
|
8140
|
+
}
|
|
8141
|
+
});
|
|
8142
|
+
}
|
|
8143
|
+
|
|
8144
|
+
// Handle button listeners
|
|
8145
|
+
if (listeners) {
|
|
8146
|
+
subscribeToEvents(listeners);
|
|
8147
|
+
}
|
|
8148
|
+
}
|
|
8149
|
+
});
|
|
7329
8150
|
}
|
|
7330
|
-
const handlePETImageMetadata =
|
|
7331
|
-
|
|
7332
|
-
|
|
7333
|
-
|
|
7334
|
-
} = _ref2;
|
|
8151
|
+
const handlePETImageMetadata = ({
|
|
8152
|
+
SeriesInstanceUID,
|
|
8153
|
+
StudyInstanceUID
|
|
8154
|
+
}) => {
|
|
7335
8155
|
const {
|
|
7336
8156
|
instances
|
|
7337
8157
|
} = src.DicomMetadataStore.getSeries(StudyInstanceUID, SeriesInstanceUID);
|
|
8158
|
+
if (!instances?.length) {
|
|
8159
|
+
return;
|
|
8160
|
+
}
|
|
7338
8161
|
const modality = instances[0].Modality;
|
|
7339
|
-
if (modality !== 'PT') {
|
|
8162
|
+
if (!modality || modality !== 'PT') {
|
|
7340
8163
|
return;
|
|
7341
8164
|
}
|
|
7342
8165
|
const imageIds = instances.map(instance => instance.imageId);
|
|
7343
8166
|
const instanceMetadataArray = [];
|
|
7344
|
-
imageIds.forEach(imageId => {
|
|
7345
|
-
const instanceMetadata = getPTImageIdInstanceMetadata(imageId);
|
|
7346
|
-
if (instanceMetadata) {
|
|
7347
|
-
instanceMetadataArray.push(instanceMetadata);
|
|
7348
|
-
}
|
|
7349
|
-
});
|
|
7350
|
-
if (!instanceMetadataArray.length) {
|
|
7351
|
-
return;
|
|
7352
|
-
}
|
|
7353
8167
|
|
|
7354
8168
|
// try except block to prevent errors when the metadata is not correct
|
|
7355
|
-
let suvScalingFactors;
|
|
7356
8169
|
try {
|
|
7357
|
-
|
|
8170
|
+
imageIds.forEach(imageId => {
|
|
8171
|
+
const instanceMetadata = getPTImageIdInstanceMetadata(imageId);
|
|
8172
|
+
if (instanceMetadata) {
|
|
8173
|
+
instanceMetadataArray.push(instanceMetadata);
|
|
8174
|
+
}
|
|
8175
|
+
});
|
|
8176
|
+
if (!instanceMetadataArray.length) {
|
|
8177
|
+
return;
|
|
8178
|
+
}
|
|
8179
|
+
const suvScalingFactors = (0,calculate_suv_esm/* calculateSUVScalingFactors */.C)(instanceMetadataArray);
|
|
8180
|
+
instanceMetadataArray.forEach((instanceMetadata, index) => {
|
|
8181
|
+
init_metadataProvider.addCustomMetadata(imageIds[index], 'scalingModule', suvScalingFactors[index]);
|
|
8182
|
+
});
|
|
7358
8183
|
} catch (error) {
|
|
7359
8184
|
console.log(error);
|
|
7360
8185
|
}
|
|
7361
|
-
if (!suvScalingFactors) {
|
|
7362
|
-
return;
|
|
7363
|
-
}
|
|
7364
|
-
instanceMetadataArray.forEach((instanceMetadata, index) => {
|
|
7365
|
-
init_metadataProvider.addCustomMetadata(imageIds[index], 'scalingModule', suvScalingFactors[index]);
|
|
7366
|
-
});
|
|
7367
8186
|
};
|
|
7368
8187
|
;// CONCATENATED MODULE: ../../../extensions/default/src/DicomWebDataSource/utils/index.ts
|
|
7369
8188
|
|
|
@@ -7384,6 +8203,8 @@ const handlePETImageMetadata = _ref2 => {
|
|
|
7384
8203
|
|
|
7385
8204
|
|
|
7386
8205
|
|
|
8206
|
+
|
|
8207
|
+
|
|
7387
8208
|
const defaultExtension = {
|
|
7388
8209
|
/**
|
|
7389
8210
|
* Only required property. Should be a unique value across all extensions.
|
|
@@ -7391,16 +8212,16 @@ const defaultExtension = {
|
|
|
7391
8212
|
id: id,
|
|
7392
8213
|
preRegistration: init,
|
|
7393
8214
|
getDataSourcesModule: src_getDataSourcesModule,
|
|
8215
|
+
getViewportModule: getViewportModule,
|
|
7394
8216
|
getLayoutTemplateModule: getLayoutTemplateModule,
|
|
7395
8217
|
getPanelModule: src_getPanelModule,
|
|
7396
8218
|
getHangingProtocolModule: src_getHangingProtocolModule,
|
|
7397
8219
|
getSopClassHandlerModule: src_getSopClassHandlerModule,
|
|
7398
8220
|
getToolbarModule: getToolbarModule,
|
|
7399
8221
|
getCommandsModule: src_commandsModule,
|
|
7400
|
-
getUtilityModule(
|
|
7401
|
-
|
|
7402
|
-
|
|
7403
|
-
} = _ref;
|
|
8222
|
+
getUtilityModule({
|
|
8223
|
+
servicesManager
|
|
8224
|
+
}) {
|
|
7404
8225
|
return [{
|
|
7405
8226
|
name: 'common',
|
|
7406
8227
|
exports: {
|