@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.
Files changed (99) hide show
  1. package/dist/{220.bundle.f7e1c96c94245e70f2be.js → 109.bundle.b4fee2a22b622839baf5.js} +4466 -3715
  2. package/dist/{471.bundle.49c8d281adbae4a2c4df.js → 121.bundle.787f5a848ed632a4d5fc.js} +90 -112
  3. package/dist/141.bundle.556b4c1e4cab770417ac.js +8620 -0
  4. package/dist/{687.bundle.9065db35c01823286f08.js → 164.bundle.d4598e491783753a8b6b.js} +22 -38
  5. package/dist/17dd54813d5acc10bf8f.wasm +0 -0
  6. package/dist/183.bundle.72bf18ad23ee6624986d.js +30394 -0
  7. package/dist/{506.bundle.5731bb4349e266491225.js → 188.bundle.b80554ec7df7dcd435a5.js} +23 -28
  8. package/dist/{342.bundle.e7c3d500f86fdfcc62b5.js → 206.bundle.f957e0d1cdff66dbac69.js} +1963 -1142
  9. package/dist/20fc4c659b85ccd2a9c0.wasm +0 -0
  10. package/dist/217.bundle.be1cc412f8e26be87d21.js +115079 -0
  11. package/dist/{451.bundle.57c21db5d003c75e9d61.js → 295.bundle.6f734abf8fa85b1a310d.js} +107 -127
  12. package/dist/{125.bundle.253395f320b72180da63.js → 297.bundle.194d8985ab974839b5b6.js} +7 -8
  13. package/dist/{19.bundle.f77c5787b6d8ac0b638b.js → 325.bundle.84909a08305556e9f924.js} +479 -371
  14. package/dist/335.bundle.c39d4aefe33aecab958f.js +2590 -0
  15. package/dist/{202.bundle.d3490836f71e001dd30f.js → 342.bundle.e6d0bba29351b5650a8c.js} +566 -868
  16. package/dist/{776.bundle.a2dedb405a12ffd7699b.js → 41.bundle.7c943bb857ed37831905.js} +7295 -3536
  17. package/dist/422.bundle.bd6529c536f59807fbee.js +881 -0
  18. package/dist/{957.bundle.9ea4506963ef8b2d84ba.js → 433.bundle.4c77c1fe8fc90ac14218.js} +14737 -27555
  19. package/dist/445.bundle.38c6d2af64e41cd7c614.js +7835 -0
  20. package/dist/{126.bundle.6e7111d58bcc937ffd80.js → 448.bundle.deedeff5744e77510734.js} +362 -430
  21. package/dist/487.bundle.7890ca42826941ebcd60.js +1875 -0
  22. package/dist/{886.bundle.c8dd3ecc42a4253de278.js → 530.bundle.7c94543955552475c56a.js} +98 -127
  23. package/dist/{663.bundle.d7be28450db14266cdd0.js → 540.bundle.079d43a6717e95c24392.js} +225 -188
  24. package/dist/{250.bundle.aea3335667054bdefe36.js → 544.bundle.1c1f57118560046649c1.js} +37 -62
  25. package/dist/574.bundle.be075ac52fb52b442a8b.js +2641 -0
  26. package/dist/{181.css → 574.css} +1 -1
  27. package/dist/{410.bundle.15c855b0ff4a1a674fb8.js → 594.bundle.0b1165661dd638820082.js} +183 -221
  28. package/dist/{221.bundle.aef554202c58483cb34e.js → 633.bundle.c1658e76f104cbd14cab.js} +349 -552
  29. package/dist/{774.bundle.4b2dc46a35012b898e1a.js → 644.bundle.1e77691d2eeb96a423b0.js} +1852 -8945
  30. package/dist/699.bundle.4f01772e7ce6637de339.js +768 -0
  31. package/dist/702.bundle.963481fbf871984b646f.js +8426 -0
  32. package/dist/722.bundle.afab1fe6bfcd569130ac.js +1083 -0
  33. package/dist/{359.bundle.45ecb3d28e8c22142606.js → 724.bundle.e5794460c391ee9cba2c.js} +164 -259
  34. package/dist/{757.bundle.ec8301d8e70d2b990f65.js → 726.bundle.0b3d9277d22fe7e15b89.js} +512 -879
  35. package/dist/{530.bundle.a03b6f942ace3e1baa1e.js → 835.bundle.15aff0b7433bb0dd6d6d.js} +37 -30
  36. package/dist/{822.bundle.82cdc418f8f56da6060b.js → 862.bundle.c0ee6e1d4d97e1353213.js} +77 -96
  37. package/dist/{236.bundle.4e9924934a747afac132.js → 889.bundle.7858e4b7ca1a2b12b64f.js} +207 -199
  38. package/dist/{281.bundle.deb7492d143e7768d8bf.js → 905.bundle.170908fe660fc6b40649.js} +157 -124
  39. package/dist/{814.bundle.c8c951d20039b63b865a.js → 907.bundle.dee4e30420caf07caea6.js} +16 -30
  40. package/dist/{417.bundle.af0a207c29b109f84159.js → 931.bundle.d270a1fda9a2836c3cc5.js} +26 -26
  41. package/dist/{686.bundle.dccef1f36e4bc79bcc48.js → 939.bundle.9d93b2e47c52338747a2.js} +7 -8
  42. package/dist/94.bundle.c452d9b0645277c2cf4e.js +784 -0
  43. package/dist/{12.bundle.b5ca13e5363f170ecb3b.js → 961.bundle.aaaaaba0ec015a3b85d8.js} +20 -33
  44. package/dist/app-config.js +1 -0
  45. package/dist/{app.bundle.a978edc59b9d82f2eb22.js → app.bundle.6c090a2d6d3ccc97a81d.js} +183240 -87650
  46. package/dist/app.bundle.css +16 -13
  47. package/dist/assets/images/CT-AAA.png +0 -0
  48. package/dist/assets/images/CT-AAA2.png +0 -0
  49. package/dist/assets/images/CT-Air.png +0 -0
  50. package/dist/assets/images/CT-Bone.png +0 -0
  51. package/dist/assets/images/CT-Bones.png +0 -0
  52. package/dist/assets/images/CT-Cardiac.png +0 -0
  53. package/dist/assets/images/CT-Cardiac2.png +0 -0
  54. package/dist/assets/images/CT-Cardiac3.png +0 -0
  55. package/dist/assets/images/CT-Chest-Contrast-Enhanced.png +0 -0
  56. package/dist/assets/images/CT-Chest-Vessels.png +0 -0
  57. package/dist/assets/images/CT-Coronary-Arteries-2.png +0 -0
  58. package/dist/assets/images/CT-Coronary-Arteries-3.png +0 -0
  59. package/dist/assets/images/CT-Coronary-Arteries.png +0 -0
  60. package/dist/assets/images/CT-Cropped-Volume-Bone.png +0 -0
  61. package/dist/assets/images/CT-Fat.png +0 -0
  62. package/dist/assets/images/CT-Liver-Vasculature.png +0 -0
  63. package/dist/assets/images/CT-Lung.png +0 -0
  64. package/dist/assets/images/CT-MIP.png +0 -0
  65. package/dist/assets/images/CT-Muscle.png +0 -0
  66. package/dist/assets/images/CT-Pulmonary-Arteries.png +0 -0
  67. package/dist/assets/images/CT-Soft-Tissue.png +0 -0
  68. package/dist/assets/images/DTI-FA-Brain.png +0 -0
  69. package/dist/assets/images/MR-Angio.png +0 -0
  70. package/dist/assets/images/MR-Default.png +0 -0
  71. package/dist/assets/images/MR-MIP.png +0 -0
  72. package/dist/assets/images/MR-T2-Brain.png +0 -0
  73. package/dist/assets/images/VolumeRendering.png +0 -0
  74. package/dist/cornerstoneDICOMImageLoader.min.js +1 -1
  75. package/dist/cornerstoneDICOMImageLoader.min.js.map +1 -1
  76. package/dist/{dicom-microscopy-viewer.bundle.2c146384eb9466d02ff8.js → dicom-microscopy-viewer.bundle.d3a56dc9f62df5e11019.js} +3 -3
  77. package/dist/histogram-worker.bundle.829e14ec12c2b41a4323.js +359 -0
  78. package/dist/index.html +1 -1
  79. package/dist/{index.worker.e62ecca63f1a2e124230.worker.js → index.worker.64c896c4316fcd506666.worker.js} +2 -2
  80. package/dist/index.worker.64c896c4316fcd506666.worker.js.map +1 -0
  81. package/dist/polySeg.bundle.63011312c3c79e717ea9.js +249 -0
  82. package/dist/serve.json +12 -0
  83. package/dist/sw.js +1 -1
  84. package/package.json +26 -22
  85. package/dist/181.bundle.a62b9f0ec692299acb35.js +0 -1527
  86. package/dist/23.bundle.e008ad788170f2ed5569.js +0 -900
  87. package/dist/604.bundle.a51f83e64004bca5f497.js +0 -1848
  88. package/dist/613.bundle.9e7072e5b575354fe51e.js +0 -532
  89. package/dist/743.bundle.489f7df3a089d4d374e1.js +0 -78007
  90. package/dist/75788f12450d4c5ed494.wasm +0 -0
  91. package/dist/775.bundle.2285e7e0e67878948c0d.js +0 -1009
  92. package/dist/788.bundle.207ac23c0dfa70cbe3fb.js +0 -2682
  93. package/dist/82.bundle.d6fdcca0f67540bb226a.js +0 -1049
  94. package/dist/index.worker.e62ecca63f1a2e124230.worker.js.map +0 -1
  95. /package/dist/{19.css → 325.css} +0 -0
  96. /package/dist/{776.css → 41.css} +0 -0
  97. /package/dist/{579.css → 481.css} +0 -0
  98. /package/dist/{250.css → 544.css} +0 -0
  99. /package/dist/{221.css → 633.css} +0 -0
@@ -1,7 +1,7 @@
1
1
  "use strict";
2
- (self["webpackChunk"] = self["webpackChunk"] || []).push([[342],{
2
+ (globalThis["webpackChunk"] = globalThis["webpackChunk"] || []).push([[206],{
3
3
 
4
- /***/ 56342:
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__(97604);
34
- // EXTERNAL MODULE: ../../core/src/index.ts + 65 modules
35
- var src = __webpack_require__(71771);
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__(62971);
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 */.IO)(series);
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(_ref) {
358
- let {
359
- instance,
360
- frame,
361
- config,
362
- thumbnail = false
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__(67540);
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} [filter.seriesInstanceUID] - series instance uid to filter results against
399
- * @param {Function} [sortSeries] - Custom sort function for series
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
- try {
426
- result = await loader();
427
- if (result && result.length) {
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
- async next() {
527
- const seriesInstanceUID = seriesInstanceUIDList.shift();
528
- return client.retrieveSeriesMetadata({
529
- studyInstanceUID,
530
- seriesInstanceUID
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
- const options = {
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["default"].data.DicomMetaDictionary;
634
+ } = dcmjs_es/* default.data */.Ay.data.DicomMetaDictionary;
578
635
  const naturalized = result.map(naturalizeDataset);
579
- return (0,sortStudy/* sortStudySeries */.IO)(naturalized, sortCriteria || sortStudy/* sortingCriteria */.S1.seriesSortCriteria.seriesInfoSortingCriteria, sortFunction);
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(s => s.SeriesInstanceUID);
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
- promises.push(seriesAsyncLoader.next());
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(_ref) {
598
- let {
599
- preLoadData,
600
- promises
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 {Object} dicomWebClient The dicomweb-client.
617
- * @param {string} studyInstanceUid The Study Instance UID of the study which needs to be loaded
618
- * @param {Object} [filters] - Object containing filters to be applied on retrieve metadata process
619
- * @param {string} [filter.seriesInstanceUID] - series instance uid to filter results against
620
- * @returns {Object} A study descriptor object
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, studyInstanceUid, enableStudyLazyLoad) {
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, studyInstanceUid, filters, sortCriteria, sortFunction);
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} server Object with server configuration parameters
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} enabledStudyLazyLoad Whether the study metadata should be loaded asynchronously.
644
- * @param {function} storeInstancesCallback A callback used to store the retrieved instance metadata.
645
- * @param {Object} [filters] - Object containing filters to be applied on retrieve metadata process
646
- * @param {string} [filter.seriesInstanceUID] - series instance uid to filter results against
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(StudyInstanceUID)) {
663
- return StudyMetaDataPromises.get(StudyInstanceUID);
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(StudyInstanceUID, promise);
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
- class StaticWadoClient extends dicomweb_client_es.api.DICOMwebClient {
701
- constructor(qidoConfig) {
702
- super(qidoConfig);
703
- this.staticWado = qidoConfig.staticWado;
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(_ref => {
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
- return value.retrieveBulkData().then(arr => {
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["default"].data;
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 {string} name - Data source name
1011
- * @param {string} wadoUriRoot - Legacy? (potentially unused/replaced)
1012
- * @param {string} qidoRoot - Base URL to use for QIDO requests
1013
- * @param {string} wadoRoot - Base URL to use for WADO requests
1014
- * @param {boolean} qidoSupportsIncludeField - Whether QIDO supports the "Include" option to request additional fields in response
1015
- * @param {string} imageRengering - wadors | ? (unsure of where/how this is used)
1016
- * @param {string} thumbnailRendering - wadors | ? (unsure of where/how this is used)
1017
- * @param {bool} supportsReject - Whether the server supports reject calls (i.e. DCM4CHEE)
1018
- * @param {bool} lazyLoadStudy - "enableStudyLazyLoad"; Request series meta async instead of blocking
1019
- * @param {string|bool} singlepart - indicates of the retrieves can fetch singlepart. Options are bulkdata, video, image or boolean true
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, userAuthenticationService) {
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: _ref => {
1025
- let {
1026
- params,
1027
- query
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 */.Po.getHTTPErrorHandler()
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 */.Po.getHTTPErrorHandler()
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.api.DICOMwebClient(qidoConfig);
1071
- wadoDicomWebClient = dicomWebConfig.staticWado ? new StaticWadoClient(wadoConfig) : new dicomweb_client_es.api.DICOMwebClient(wadoConfig);
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 _ref2 => {
1127
- let {
1128
- StudyInstanceUID,
1129
- BulkDataURI
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 function () {
1144
- let {
1145
- StudyInstanceUID,
1146
- filters,
1147
- sortCriteria,
1148
- sortFunction,
1149
- madeInClient = false
1150
- } = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : {};
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
- const meta = {
1172
- FileMetaInformationVersion: dataset._meta?.FileMetaInformationVersion?.Value,
1173
- MediaStorageSOPClassUID: dataset.SOPClassUID,
1174
- MediaStorageSOPInstanceUID: dataset.SOPInstanceUID,
1175
- TransferSyntaxUID: EXPLICIT_VR_LITTLE_ENDIAN,
1176
- ImplementationClassUID,
1177
- ImplementationVersionName
1178
- };
1179
- const denaturalized = denaturalizeDataset(meta);
1180
- const dicomDict = new DicomDict(denaturalized);
1181
- dicomDict.dict = denaturalizeDataset(dataset);
1182
- const part10Buffer = dicomDict.write();
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 function (StudyInstanceUID, filters, sortCriteria, sortFunction) {
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 options = {
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(options).then(val => {
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((instance, index) => {
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, madeInClient);
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 => promise.then(instances => {
1337
- storeInstances(instances);
1338
- }));
1339
- await Promise.all(seriesDeliveredPromises);
1340
- setSuccessFlag();
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(_ref3) {
1369
- let {
1370
- instance,
1371
- frame
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(_ref4) {
1384
- let {
1385
- params,
1386
- query
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 */.Is.create(implementation);
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["default"].classes.MetadataProvider;
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 _ref => {
1447
- let {
1448
- query,
1449
- url
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(wadoRoot, params);
1886
+ return utils_getDirectURL(dicomJsonConfig, params);
1549
1887
  },
1550
1888
  series: {
1551
- metadata: async function () {
1552
- let {
1553
- StudyInstanceUID,
1554
- madeInClient = false,
1555
- customSort
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
- ...instance.metadata,
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(_ref2) {
1640
- let {
1641
- instance,
1642
- frame
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: _ref3 => {
1651
- let {
1652
- params,
1653
- query
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 */.Is.create(implementation);
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["default"].classes.MetadataProvider;
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 = function (v1, v2) {
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: _ref => {
1709
- let {
1710
- params,
1711
- query
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 function () {
1793
- let {
1794
- StudyInstanceUID,
1795
- madeInClient = false
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["default"].data.datasetToBlob(naturalizedReport);
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(_ref2) {
1876
- let {
1877
- instance,
1878
- frame
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: _ref3 => {
1896
- let {
1897
- params,
1898
- query
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 */.Is.create(implementation);
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, UserAuthenticationService) {
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 _ref => {
1941
- let {
1942
- params,
1943
- query
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, UserAuthenticationService);
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: function () {
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: function () {
1976
- return dicomWebDelegate.retrieve.directURL(...arguments);
1977
- },
2306
+ directURL: (...args) => dicomWebDelegate.retrieve.directURL(...args),
1978
2307
  series: {
1979
- metadata: async function () {
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: function () {
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
- getImageIdsForInstance: function () {
1996
- return dicomWebDelegate.getImageIdsForInstance(...arguments);
1997
- },
1998
- getStudyInstanceUIDs(_ref2) {
1999
- let {
2000
- params,
2001
- query
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 */.Is.create(implementation);
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__(43001);
2645
+ var react = __webpack_require__(41766);
2052
2646
  // EXTERNAL MODULE: ../../../node_modules/prop-types/index.js
2053
- var prop_types = __webpack_require__(3827);
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 + 486 modules
2056
- var ui_src = __webpack_require__(22582);
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__(62657);
2652
+ var state = __webpack_require__(15575);
2059
2653
  // EXTERNAL MODULE: ../node_modules/react-router-dom/dist/index.js
2060
- var dist = __webpack_require__(62474);
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__(69190);
2656
+ var es = __webpack_require__(80619);
2063
2657
  // EXTERNAL MODULE: ../node_modules/react-router/dist/index.js
2064
- var react_router_dist = __webpack_require__(85066);
2065
- // EXTERNAL MODULE: ../../i18n/src/index.js + 132 modules
2066
- var i18n_src = __webpack_require__(45964);
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
- function Toolbar(_ref) {
2076
- let {
2077
- servicesManager
2078
- } = _ref;
2665
+ function Toolbar({
2666
+ servicesManager,
2667
+ buttonSection = 'primary'
2668
+ }) {
2079
2669
  const {
2080
- toolbarService
2081
- } = servicesManager.services;
2082
- const [viewportGrid, viewportGridService] = (0,ui_src/* useViewportGrid */.O_)();
2083
- const [toolbarButtons, setToolbarButtons] = (0,react.useState)([]);
2084
- (0,react.useEffect)(() => {
2085
- const updateToolbar = () => {
2086
- const toolGroupId = viewportGridService.getActiveViewportOptionByKey('toolGroupId') ?? 'default';
2087
- setToolbarButtons(toolbarService.getButtonSection(toolGroupId));
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
- return (
2105
- /*#__PURE__*/
2106
- // The margin for separating the tools on the toolbar should go here and NOT in each individual component (button) item.
2107
- // This allows for the individual items to be included in other UI components where perhaps alternative margins are desired.
2108
- react.createElement("div", {
2109
- key: id,
2110
- className: classnames_default()('mr-1')
2111
- }, /*#__PURE__*/react.createElement(Component, _extends({
2112
- id: id
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["default"];
2135
- function ViewerHeader(_ref) {
2136
- let {
2137
- hotkeysManager,
2138
- extensionManager,
2139
- servicesManager
2140
- } = _ref;
2141
- const [appConfig] = (0,state/* useAppConfig */.M)();
2142
- const navigate = (0,dist/* useNavigate */.s0)();
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 */.$G)();
2744
+ } = (0,es/* useTranslation */.Bd)();
2168
2745
  const {
2169
2746
  show,
2170
2747
  hide
2171
- } = (0,ui_src/* useModal */.dd)();
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.8";
2177
- const commitHash = "330e11c7ff0151e1096e19b8ffdae7d64cae280e";
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 */.tk,
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 */.i1,
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 */.dD.stopRecord();
2203
- src/* hotkeys */.dD.unpause();
2780
+ src/* hotkeys */.ot.stopRecord();
2781
+ src/* hotkeys */.ot.unpause();
2204
2782
  hide();
2205
2783
  },
2206
- onSubmit: _ref2 => {
2207
- let {
2208
- hotkeyDefinitions,
2209
- language
2210
- } = _ref2;
2784
+ onSubmit: ({
2785
+ hotkeyDefinitions,
2786
+ language
2787
+ }) => {
2211
2788
  if (language.value !== currentLanguage().value) {
2212
- i18n_src["default"].changeLanguage(language.value);
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 */.dD
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 */.h4, {
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
- }, /*#__PURE__*/react.createElement(ui_src/* ErrorBoundary */.SV, {
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 = _ref => {
2249
- let {
2250
- servicesManager,
2251
- side,
2252
- className,
2253
- activeTabIndex: activeTabIndexProp,
2254
- tabs
2255
- } = _ref;
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
- if (panelService) {
2264
- const activatePanelSubscription = panelService.subscribe(panelService.EVENTS.ACTIVATE_PANEL, activatePanelEvent => {
2265
- if (!hasBeenOpened || activatePanelEvent.forceActive) {
2266
- const tabIndex = tabs.findIndex(tab => tab.id === activatePanelEvent.panelId);
2267
- if (tabIndex !== -1) {
2268
- setActiveTabIndex(tabIndex);
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
- return () => {
2273
- activatePanelSubscription.unsubscribe();
2274
- };
2275
- }
2881
+ }
2882
+ });
2883
+ return () => {
2884
+ activatePanelSubscription.unsubscribe();
2885
+ };
2276
2886
  }, [tabs, hasBeenOpened, panelService]);
2277
- return /*#__PURE__*/react.createElement(ui_src/* SidePanel */.hs, {
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
- onOpen: () => {
2283
- setHasBeenOpened(true);
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(_ref) {
2297
- let {
2298
- // From Extension Module Params
2299
- extensionManager,
2300
- servicesManager,
2301
- hotkeysManager,
2302
- commandsManager,
2303
- // From Modes
2304
- viewports,
2305
- ViewportGridComp,
2306
- leftPanels = [],
2307
- rightPanels = [],
2308
- leftPanelDefaultClosed = false,
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 */.hy.EVENTS.PROTOCOL_CHANGED,
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
- const leftPanelComponents = leftPanels.map(getPanelData);
2384
- const rightPanelComponents = rightPanels.map(getPanelData);
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 */.LE, {
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
- }), leftPanelComponents.length ? /*#__PURE__*/react.createElement(ui_src/* ErrorBoundary */.SV, {
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: leftPanelDefaultClosed ? null : 0,
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 */.SV, {
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
- })))), rightPanelComponents.length ? /*#__PURE__*/react.createElement(ui_src/* ErrorBoundary */.SV, {
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: rightPanelDefaultClosed ? null : 0,
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 */.HQ),
2429
- servicesManager: prop_types_default().instanceOf(src/* ServicesManager */.Xw),
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
- leftPanelDefaultClosed: (prop_types_default()).bool.isRequired,
2434
- rightPanelDefaultClosed: (prop_types_default()).bool.isRequired,
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(_ref) {
2449
- let {
2450
- servicesManager,
2451
- extensionManager,
2452
- commandsManager,
2453
- hotkeysManager
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(_ref) {
2489
- let {
2490
- servicesManager,
2491
- getImageSrc,
2492
- getStudiesForPatientByMRN,
2493
- requestDisplaySetCreationForStudy,
2494
- dataSource
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 */.s0)();
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 */.zG)();
3116
+ } = (0,ui_src/* useImageViewer */.Bz)();
2509
3117
  const [{
2510
3118
  activeViewportId,
2511
3119
  viewports
2512
- }, viewportGridService] = (0,ui_src/* useViewportGrid */.O_)();
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 */.eX, {
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(_ref) {
2864
- let {
2865
- commandsManager,
2866
- extensionManager,
2867
- servicesManager
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__(8324);
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, _ref) {
2954
- let {
2955
- extensionManager
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 = _ref2 => {
2978
- let {
2979
- action,
2980
- value
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 */.Vq,
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 */.LZ.dt.secondary
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 */.LZ.dt.primary
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: _ref3 => {
3039
- let {
3040
- value,
3041
- setValue
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 */.Ph, {
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 */.II, {
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(_ref) {
3103
- let {
3104
- servicesManager,
3105
- getReport,
3106
- reportType = 'measurement'
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(_ref) {
3222
- let {
3223
- servicesManager,
3224
- commandsManager,
3225
- extensionManager
3226
- } = _ref;
3227
- const [viewportGrid, viewportGridService] = (0,ui_src/* useViewportGrid */.O_)();
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 = _ref2 => {
3314
- let {
3315
- uid,
3316
- isActive
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 = _ref3 => {
3325
- let {
3326
- uid,
3327
- isActive
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 = _ref4 => {
3334
- let {
3335
- action,
3336
- value
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 */.Vq,
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: _ref5 => {
3364
- let {
3365
- value,
3366
- setValue
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 */.II, {
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 */.LZ.dt.secondary
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 */.LZ.dt.primary
3976
+ type: ui_src/* ButtonEnums.type */.Ny.NW.primary
3405
3977
  }],
3406
3978
  onSubmit: onSubmitHandler
3407
3979
  }
3408
3980
  });
3409
3981
  };
3410
- const onMeasurementItemClickHandler = _ref6 => {
3411
- let {
3412
- uid,
3413
- isActive
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 */.wt, {
3427
- title: "Measurements",
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(Panels_ActionButtons, {
3435
- onExportClick: exportReport,
3436
- onClearMeasurementsClick: clearMeasurements,
3437
- onCreateReportClick: createReport
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 */.Xw).isRequired
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(_ref) {
3508
- let {
3509
- commandsManager,
3510
- extensionManager,
3511
- servicesManager
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__(11835);
4119
+ var isImage = __webpack_require__(8094);
3542
4120
  // EXTERNAL MODULE: ../../core/src/utils/sopClassDictionary.js
3543
- var sopClassDictionary = __webpack_require__(24369);
4121
+ var sopClassDictionary = __webpack_require__(48085);
3544
4122
  // EXTERNAL MODULE: ../../core/src/classes/ImageSet.ts
3545
- var ImageSet = __webpack_require__(13950);
4123
+ var ImageSet = __webpack_require__(14169);
3546
4124
  // EXTERNAL MODULE: ../../core/src/utils/isDisplaySetReconstructable.js
3547
- var isDisplaySetReconstructable = __webpack_require__(89359);
4125
+ var isDisplaySetReconstructable = __webpack_require__(13835);
3548
4126
  ;// CONCATENATED MODULE: ../../../extensions/default/package.json
3549
- const package_namespaceObject = JSON.parse('{"u2":"@ohif/extension-default"}');
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.u2;
4130
+ const id = package_namespaceObject.UU;
3553
4131
 
3554
4132
  // EXTERNAL MODULE: ../../core/src/utils/sortInstancesByPosition.ts
3555
- var sortInstancesByPosition = __webpack_require__(87425);
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 */.hu)(multiFrameInstance)) {
3567
- messages.addMessage(src/* DisplaySetMessage */.Lt.CODES.MULTIFRAME_NO_PIXEL_MEASUREMENTS);
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 */.sb)(multiFrameInstance)) {
3570
- messages.addMessage(src/* DisplaySetMessage */.Lt.CODES.MULTIFRAME_NO_ORIENTATION);
4147
+ if (!(0,isDisplaySetReconstructable/* hasOrientation */.VX)(multiFrameInstance)) {
4148
+ messages.addMessage(src/* DisplaySetMessage */.Ob.CODES.MULTIFRAME_NO_ORIENTATION);
3571
4149
  }
3572
- if (!(0,isDisplaySetReconstructable/* hasPosition */.kN)(multiFrameInstance)) {
3573
- messages.addMessage(src/* DisplaySetMessage */.Lt.CODES.MULTIFRAME_NO_POSITION_INFORMATION);
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__(94972);
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 */.Z)(firstImage.Rows);
3592
- const firstImageColumns = (0,toNumber/* default */.Z)(firstImage.Columns);
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 */.Z)(firstImage.SamplesPerPixel);
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 */.Z)(firstImage.ImageOrientationPatient);
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 */.Z)(instance.ImageOrientationPatient);
3648
- if (!(0,isDisplaySetReconstructable/* _isSameOrientation */.NB)(imageOrientationPatient, firstImageOrientationPatient)) {
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 + 10 modules
3655
- var esm = __webpack_require__(45451);
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 */.R3.fromValues(imageOrientation[0], imageOrientation[1], imageOrientation[2]);
3666
- const colCosineVec = esm/* vec3.fromValues */.R3.fromValues(imageOrientation[3], imageOrientation[4], imageOrientation[5]);
3667
- return esm/* vec3.cross */.R3.cross(esm/* vec3.create */.R3.create(), rowCosineVec, colCosineVec);
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 */.R3.scaleAndAdd(esm/* vec3.create */.R3.create(), previousPosition, scanAxisNormal, averageSpacingBetweenFrames);
3687
- return esm/* vec3.distance */.R3.distance(actualPosition, predictedPosition) > averageSpacingBetweenFrames;
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 */.Z)(instances[0].ImageOrientationPatient);
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 */.Z)(instances[0].ImagePositionPatient);
3705
- const lastIpp = (0,toNumber/* default */.Z)(instances[instances.length - 1].ImagePositionPatient);
3706
- const averageSpacingBetweenFrames = (0,isDisplaySetReconstructable/* _getPerpendicularDistance */.Xn)(firstImagePositionPatient, lastIpp) / (instances.length - 1);
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 */.Z)(instance.ImagePositionPatient);
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 */.Z)(instances[0].ImagePositionPatient);
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 */.Z)(instances[instances.length - 1].ImagePositionPatient);
3736
- const averageSpacingBetweenFrames = (0,isDisplaySetReconstructable/* _getPerpendicularDistance */.Xn)(firstImagePositionPatient, lastIpp) / (instances.length - 1);
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 */.Z)(instance.ImagePositionPatient);
3742
- const spacingBetweenFrames = (0,isDisplaySetReconstructable/* _getPerpendicularDistance */.Xn)(imagePositionPatient, previousImagePositionPatient);
3743
- const spacingIssue = (0,isDisplaySetReconstructable/* _getSpacingIssue */.bg)(spacingBetweenFrames, averageSpacingBetweenFrames);
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 */.e1.MISSING_FRAMES) {
3751
- messages.addMessage(src/* DisplaySetMessage */.Lt.CODES.MISSING_FRAMES);
3752
- } else if (issue === isDisplaySetReconstructable/* reconstructionIssues */.e1.IRREGULAR_SPACING) {
3753
- messages.addMessage(src/* DisplaySetMessage */.Lt.CODES.IRREGULAR_SPACING);
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 */.Lt.CODES.INCONSISTENT_DIMENSIONS);
4358
+ messages.addMessage(src/* DisplaySetMessage */.Ob.CODES.INCONSISTENT_DIMENSIONS);
3781
4359
  }
3782
4360
  if (!areAllImageComponentsEqual(instances)) {
3783
- messages.addMessage(src/* DisplaySetMessage */.Lt.CODES.INCONSISTENT_COMPONENTS);
4361
+ messages.addMessage(src/* DisplaySetMessage */.Ob.CODES.INCONSISTENT_COMPONENTS);
3784
4362
  }
3785
4363
  if (!areAllImageOrientationsEqual(instances)) {
3786
- messages.addMessage(src/* DisplaySetMessage */.Lt.CODES.INCONSISTENT_ORIENTATIONS);
4364
+ messages.addMessage(src/* DisplaySetMessage */.Ob.CODES.INCONSISTENT_ORIENTATIONS);
3787
4365
  }
3788
4366
  if (!areAllImagePositionsEqual(instances)) {
3789
- messages.addMessage(src/* DisplaySetMessage */.Lt.CODES.INCONSISTENT_POSITION_INFORMATION);
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 */.iK();
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 */.Lt.CODES.NO_VALID_INSTANCES);
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 */.M6.includes(Modality)) {
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 */.Lt.CODES.NO_POSITION_INFORMATION);
4408
+ messages.addMessage(src/* DisplaySetMessage */.Ob.CODES.NO_POSITION_INFORMATION);
3828
4409
  }
3829
- const sortedInstances = (0,sortInstancesByPosition/* default */.Z)(instances);
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 */.Lt.CODES.NOT_RECONSTRUCTABLE);
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 */.Z(instances);
3844
- const messages = new src/* DisplaySetMessageList */.iK();
3845
- messages.addMessage(src/* DisplaySetMessage */.Lt.CODES.UNSUPPORTED_DISPLAYSET);
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 */.Z(instances);
4586
+ const imageSet = new ImageSet/* default */.A(instances);
3882
4587
  const {
4588
+ isDynamicVolume,
3883
4589
  value: isReconstructable,
3884
- averageSpacingBetweenFrames
3885
- } = (0,isDisplaySetReconstructable/* default */.ZP)(instances);
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 getSopClassUids(instances) {
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 = getSopClassUids(instances);
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 */.O)(instance.SOPClassUID) && !instance.Rows) {
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 sopClassUids = [sopClassDictionary/* default */.Z.ComputedRadiographyImageStorage, sopClassDictionary/* default */.Z.DigitalXRayImageStorageForPresentation, sopClassDictionary/* default */.Z.DigitalXRayImageStorageForProcessing, sopClassDictionary/* default */.Z.DigitalMammographyXRayImageStorageForPresentation, sopClassDictionary/* default */.Z.DigitalMammographyXRayImageStorageForProcessing, sopClassDictionary/* default */.Z.DigitalIntraOralXRayImageStorageForPresentation, sopClassDictionary/* default */.Z.DigitalIntraOralXRayImageStorageForProcessing, sopClassDictionary/* default */.Z.CTImageStorage, sopClassDictionary/* default */.Z.EnhancedCTImageStorage, sopClassDictionary/* default */.Z.LegacyConvertedEnhancedCTImageStorage, sopClassDictionary/* default */.Z.UltrasoundMultiframeImageStorage, sopClassDictionary/* default */.Z.MRImageStorage, sopClassDictionary/* default */.Z.EnhancedMRImageStorage, sopClassDictionary/* default */.Z.EnhancedMRColorImageStorage, sopClassDictionary/* default */.Z.LegacyConvertedEnhancedMRImageStorage, sopClassDictionary/* default */.Z.UltrasoundImageStorage, sopClassDictionary/* default */.Z.UltrasoundImageStorageRET, sopClassDictionary/* default */.Z.SecondaryCaptureImageStorage, sopClassDictionary/* default */.Z.MultiframeSingleBitSecondaryCaptureImageStorage, sopClassDictionary/* default */.Z.MultiframeGrayscaleByteSecondaryCaptureImageStorage, sopClassDictionary/* default */.Z.MultiframeGrayscaleWordSecondaryCaptureImageStorage, sopClassDictionary/* default */.Z.MultiframeTrueColorSecondaryCaptureImageStorage, sopClassDictionary/* default */.Z.XRayAngiographicImageStorage, sopClassDictionary/* default */.Z.EnhancedXAImageStorage, sopClassDictionary/* default */.Z.XRayRadiofluoroscopicImageStorage, sopClassDictionary/* default */.Z.EnhancedXRFImageStorage, sopClassDictionary/* default */.Z.XRay3DAngiographicImageStorage, sopClassDictionary/* default */.Z.XRay3DCraniofacialImageStorage, sopClassDictionary/* default */.Z.BreastTomosynthesisImageStorage, sopClassDictionary/* default */.Z.BreastProjectionXRayImageStorageForPresentation, sopClassDictionary/* default */.Z.BreastProjectionXRayImageStorageForProcessing, sopClassDictionary/* default */.Z.IntravascularOpticalCoherenceTomographyImageStorageForPresentation, sopClassDictionary/* default */.Z.IntravascularOpticalCoherenceTomographyImageStorageForProcessing, sopClassDictionary/* default */.Z.NuclearMedicineImageStorage, sopClassDictionary/* default */.Z.VLEndoscopicImageStorage, sopClassDictionary/* default */.Z.VideoEndoscopicImageStorage, sopClassDictionary/* default */.Z.VLMicroscopicImageStorage, sopClassDictionary/* default */.Z.VideoMicroscopicImageStorage, sopClassDictionary/* default */.Z.VLSlideCoordinatesMicroscopicImageStorage, sopClassDictionary/* default */.Z.VLPhotographicImageStorage, sopClassDictionary/* default */.Z.VideoPhotographicImageStorage, sopClassDictionary/* default */.Z.OphthalmicPhotography8BitImageStorage, sopClassDictionary/* default */.Z.OphthalmicPhotography16BitImageStorage, sopClassDictionary/* default */.Z.OphthalmicTomographyImageStorage, sopClassDictionary/* default */.Z.VLWholeSlideMicroscopyImageStorage, sopClassDictionary/* default */.Z.PositronEmissionTomographyImageStorage, sopClassDictionary/* default */.Z.EnhancedPETImageStorage, sopClassDictionary/* default */.Z.LegacyConvertedEnhancedPETImageStorage, sopClassDictionary/* default */.Z.RTImageStorage, sopClassDictionary/* default */.Z.EnhancedUSVolumeStorage];
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
- function ToolbarLayoutSelectorWithServices(_ref) {
4033
- let {
4034
- servicesManager,
4035
- ...props
4036
- } = _ref;
4037
- const {
4038
- toolbarService
4039
- } = servicesManager.services;
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
- toolbarService.recordInteraction({
4042
- interactionType: 'action',
4043
- commands: [{
4044
- commandName: 'setViewportGridLayout',
4045
- commandOptions: {
4046
- ...props
4047
- },
4048
- context: 'DEFAULT'
4049
- }]
4798
+ commandsManager.run({
4799
+ commandName: 'setViewportGridLayout',
4800
+ commandOptions: {
4801
+ ...props
4802
+ }
4050
4803
  });
4051
- }, [toolbarService]);
4052
- return /*#__PURE__*/react.createElement(LayoutSelector, ToolbarLayoutSelector_extends({}, props, {
4053
- onSelection: onSelection
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(_ref2) {
4057
- let {
4058
- rows,
4059
- columns,
4060
- className,
4061
- onSelection,
4062
- ...rest
4063
- } = _ref2;
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 = () => setIsOpen(!isOpen);
4077
- const DropdownContent = isOpen ? ui_src/* LayoutSelector */.OF : null;
4078
- return /*#__PURE__*/react.createElement(ui_src/* ToolbarButton */.hA, {
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: "Grid Layout",
4858
+ label: "Layout",
4081
4859
  icon: "tool-layout",
4082
4860
  onInteraction: onInteractionHandler,
4083
4861
  className: className,
4084
4862
  rounded: rest.rounded,
4085
- dropdownContent: DropdownContent !== null && /*#__PURE__*/react.createElement(DropdownContent, {
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 */.Xw)
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
- function ToolbarSplitButtonWithServices(_ref) {
4113
- let {
4114
- isRadio,
4115
- isAction,
4116
- groupId,
4117
- primary,
4118
- secondary,
4119
- items,
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: () => handleItemClick(item, index)
4155
- }));
4156
- const [buttonsState, setButtonState] = (0,react.useState)({
4157
- primaryToolId: '',
4158
- toggles: {},
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
- return () => {
4181
- unsubscribe();
4182
- };
4183
- }, [toolbarService]);
4184
- const updatedItems = state.items.map(item => {
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: updatedItems,
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
- isActive: (prop_types_default()).bool
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/ToolbarButtonWithServices.tsx
4270
- function ToolbarButtonWithServices_extends() { ToolbarButtonWithServices_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 ToolbarButtonWithServices_extends.apply(this, arguments); }
4271
-
4272
-
4273
-
4274
- function ToolbarButtonWithServices(_ref) {
4275
- let {
4276
- id,
4277
- type,
4278
- commands,
4279
- onInteraction,
4280
- servicesManager,
4281
- ...props
4282
- } = _ref;
4283
- const {
4284
- toolbarService
4285
- } = servicesManager?.services || {};
4286
- const [buttonsState, setButtonState] = (0,react.useState)({
4287
- primaryToolId: '',
4288
- toggles: {},
4289
- groups: {}
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
- primaryToolId
4293
- } = buttonsState;
4294
- const isActive = type === 'tool' && id === primaryToolId || type === 'toggle' && buttonsState.toggles[id] === true;
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
- } = toolbarService.subscribe(toolbarService.EVENTS.TOOL_BAR_STATE_MODIFIED, state => {
4299
- setButtonState({
4300
- ...state
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
- unsubscribe();
5102
+ unsubStepsChanged();
5103
+ unsubActiveStepChanged();
4305
5104
  };
4306
- }, [toolbarService]);
4307
- return /*#__PURE__*/react.createElement(ui_src/* ToolbarButton */.hA, ToolbarButtonWithServices_extends({
4308
- commands: commands,
4309
- id: id,
4310
- type: type,
4311
- isActive: isActive,
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
- ToolbarButtonWithServices.propTypes = {
4316
- id: (prop_types_default()).string.isRequired,
4317
- type: prop_types_default().oneOf(['tool', 'action', 'toggle']).isRequired,
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
- function getToolbarModule(_ref) {
4343
- let {
4344
- commandsManager,
4345
- servicesManager
4346
- } = _ref;
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: Toolbar_ToolbarButtonWithServices,
4358
- clickHandler: () => {}
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
- clickHandler: (evt, clickedBtn, btnSectionName) => {}
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: 'ohif.toggle',
4369
- defaultComponent: Toolbar_ToolbarButtonWithServices,
4370
- clickHandler: () => {}
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__(5638);
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
- console.log('Getting items from', menus);
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 */.Z,
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 = function () {
4669
- let points = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : [];
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 (ContextMenuController._isValidPosition(point) && ContextMenuController._isValidPosition(viewerPos)) {
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 ContextMenuController._getCanvasPointsPosition(canvasPoints, viewerElement);
4694
- yield ContextMenuController._getEventDefaultPosition(eventDetail);
4695
- yield ContextMenuController._getElementDefaultPosition(viewerElement);
4696
- yield ContextMenuController.getDefaultPosition();
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 (ContextMenuController._isValidPosition(position)) {
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: _ref => {
4719
- let {
4720
- nearbyToolData
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__(71271);
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__(94614);
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(_ref) {
4769
- let {
4770
- tagRef,
4771
- vrRef,
4772
- keywordRef,
4773
- valueRef
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(_ref2) {
4809
- let {
4810
- rows
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)(_ref3 => {
4866
- let {
4867
- index,
4868
- style
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 */.S_, {
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["default"].data;
5777
+ } = dcmjs_es/* default.data */.Ay.data;
4955
5778
  const {
4956
5779
  nameMap
4957
5780
  } = DicomTagBrowser_DicomMetaDictionary;
4958
- const DicomTagBrowser = _ref => {
4959
- let {
4960
- displaySets,
4961
- displaySetInstanceUID
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 */.ZT, {
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 */.Ph, {
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 */.ZT, {
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 */.OX, {
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 */.Xe, {
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["default"].data.Tag.fromPString(tagInfo.tag).toCleanString();
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, _ref, syncService) => {
5377
- let {
5378
- numRows,
5379
- numCols
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 + 33 modules
5418
- var index = __webpack_require__(59754);
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
- * Determine if a command is a hanging protocol one.
5431
- * For now, just use the two hanging protocol commands that are in this
5432
- * commands module, but if others get added elsewhere this may need enhancing.
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: _ref2 => {
5495
- let {
5496
- text,
5497
- title,
5498
- type
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: _ref3 => {
5569
- let {
5570
- activeStudyUID = '',
5571
- protocolId,
5572
- stageId,
5573
- stageIndex,
5574
- reset = false
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: _ref4 => {
5684
- let {
5685
- protocolId,
5686
- stageIndex
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: _ref5 => {
5721
- let {
5722
- direction
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: _ref6 => {
5750
- let {
5751
- numRows,
5752
- numCols
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 */.m.navigate(historyArgs.to, historyArgs.options);
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: _ref7 => {
5964
- let {
5965
- direction,
5966
- excludeNonImageModalities
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 */.M)();
6586
- const navigate = (0,dist/* useNavigate */.s0)();
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 */.zx, {
6611
- type: ui_src/* ButtonEnums.type */.LZ.dt.primary,
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(_ref) {
6628
- let {
6629
- itemLabel,
6630
- itemList,
6631
- onItemClicked
6632
- } = _ref;
7351
+ function ItemListComponent({
7352
+ itemLabel,
7353
+ itemList,
7354
+ onItemClicked
7355
+ }) {
6633
7356
  const {
6634
7357
  t
6635
- } = (0,es/* useTranslation */.$G)('DataSourceConfiguration');
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 */.Xe, {
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 */.LE, {
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 */.JO, {
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 */.zx, {
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 */.JO, {
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(_ref) {
6687
- let {
6688
- configurationAPI,
6689
- configuredItems,
6690
- onHide
6691
- } = _ref;
7409
+ function DataSourceConfigurationModalComponent({
7410
+ configurationAPI,
7411
+ configuredItems,
7412
+ onHide
7413
+ }) {
6692
7414
  const {
6693
7415
  t
6694
- } = (0,es/* useTranslation */.$G)('DataSourceConfiguration');
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 */.JO, {
7490
+ }, itemLabelIndex < selectedItems.length ? /*#__PURE__*/react.createElement(ui_src/* Icon */.In, {
6769
7491
  name: "status-tracked"
6770
- }) : /*#__PURE__*/react.createElement(ui_src/* Icon */.JO, {
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(_ref) {
6799
- let {
6800
- servicesManager,
6801
- extensionManager
6802
- } = _ref;
7520
+ function DataSourceConfigurationComponent({
7521
+ servicesManager,
7522
+ extensionManager
7523
+ }) {
6803
7524
  const {
6804
7525
  t
6805
- } = (0,es/* useTranslation */.$G)('DataSourceConfiguration');
7526
+ } = (0,es/* useTranslation */.Bd)('DataSourceConfiguration');
6806
7527
  const {
6807
7528
  show,
6808
7529
  hide
6809
- } = (0,ui_src/* useModal */.dd)();
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 */.JO, {
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(_ref) {
7068
- let {
7069
- servicesManager,
7070
- extensionManager
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__(15747);
7970
+ var calculate_suv_esm = __webpack_require__(79717);
7201
7971
  ;// CONCATENATED MODULE: ../../../extensions/default/src/getPTImageIdInstanceMetadata.ts
7202
7972
 
7203
- const getPTImageIdInstanceMetadata_metadataProvider = src["default"].classes.MetadataProvider;
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(_ref) {
7280
- let {
7281
- servicesManager,
7282
- configuration = {}
7283
- } = _ref;
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 protolStageIndexMap key, in order to toggle
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 = _ref2 => {
7331
- let {
7332
- SeriesInstanceUID,
7333
- StudyInstanceUID
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
- suvScalingFactors = (0,calculate_suv_esm/* calculateSUVScalingFactors */.d)(instanceMetadataArray);
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(_ref) {
7401
- let {
7402
- servicesManager
7403
- } = _ref;
8222
+ getUtilityModule({
8223
+ servicesManager
8224
+ }) {
7404
8225
  return [{
7405
8226
  name: 'common',
7406
8227
  exports: {