@ohif/app 3.8.0-beta.8 → 3.8.0-beta.81

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.47f05840a5b3cdf75543.js} +94 -113
  3. package/dist/141.bundle.556b4c1e4cab770417ac.js +8620 -0
  4. package/dist/{687.bundle.9065db35c01823286f08.js → 164.bundle.fadc7c5d634402c73b5f.js} +22 -38
  5. package/dist/17dd54813d5acc10bf8f.wasm +0 -0
  6. package/dist/183.bundle.a3e238998be71c4b2af8.js +30410 -0
  7. package/dist/{506.bundle.5731bb4349e266491225.js → 188.bundle.51dc4b37920f45594393.js} +23 -28
  8. package/dist/{342.bundle.e7c3d500f86fdfcc62b5.js → 206.bundle.fcaa081a0d1f68095c31.js} +1991 -1145
  9. package/dist/20fc4c659b85ccd2a9c0.wasm +0 -0
  10. package/dist/217.bundle.d44bbaa50b6fa563fe15.js +115126 -0
  11. package/dist/{451.bundle.57c21db5d003c75e9d61.js → 295.bundle.5ace95771ced62bdcab8.js} +111 -128
  12. package/dist/{125.bundle.253395f320b72180da63.js → 297.bundle.194d8985ab974839b5b6.js} +7 -8
  13. package/dist/{19.bundle.f77c5787b6d8ac0b638b.js → 325.bundle.fd8e0c18db4708d03a91.js} +477 -373
  14. package/dist/335.bundle.8400aa5a88697a6b9d53.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.0905b258a90a7c6437bb.js} +7453 -3624
  17. package/dist/422.bundle.c6fd037b075dd54f1ba7.js +865 -0
  18. package/dist/{957.bundle.9ea4506963ef8b2d84ba.js → 433.bundle.e0018820758f5a86fa7f.js} +14797 -27561
  19. package/dist/445.bundle.38c6d2af64e41cd7c614.js +7835 -0
  20. package/dist/{126.bundle.6e7111d58bcc937ffd80.js → 448.bundle.5e6da31477887bf53016.js} +356 -430
  21. package/dist/487.bundle.89d973049defb3ba6cb7.js +1876 -0
  22. package/dist/{886.bundle.c8dd3ecc42a4253de278.js → 530.bundle.207b38c15c4c01e4db0e.js} +104 -121
  23. package/dist/{250.bundle.aea3335667054bdefe36.js → 544.bundle.1c1f57118560046649c1.js} +37 -62
  24. package/dist/574.bundle.d648fea691d6709bf2b4.js +2652 -0
  25. package/dist/{181.css → 574.css} +1 -1
  26. package/dist/{410.bundle.15c855b0ff4a1a674fb8.js → 594.bundle.84076375b127b9c7f673.js} +183 -221
  27. package/dist/{221.bundle.aef554202c58483cb34e.js → 633.bundle.acab89baaa06a299d679.js} +365 -553
  28. package/dist/{774.bundle.4b2dc46a35012b898e1a.js → 644.bundle.1e77691d2eeb96a423b0.js} +1852 -8945
  29. package/dist/{663.bundle.d7be28450db14266cdd0.js → 669.bundle.b17e8a621e38d92c653f.js} +310 -265
  30. package/dist/699.bundle.9367d7ef9f7615b2e733.js +772 -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.55f9f49816de931af91a.js} +165 -260
  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.d32ab08e64806b2e964d.js} +81 -97
  37. package/dist/{236.bundle.4e9924934a747afac132.js → 889.bundle.8ef8b723d0163d5d135c.js} +207 -199
  38. package/dist/{281.bundle.deb7492d143e7768d8bf.js → 905.bundle.8a96e1a75b7cfe5ec093.js} +157 -124
  39. package/dist/{814.bundle.c8c951d20039b63b865a.js → 907.bundle.5c88ed911bed18582da4.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.f5f2479c214180d05d42.js +778 -0
  43. package/dist/{12.bundle.b5ca13e5363f170ecb3b.js → 961.bundle.f4e52bc76d3044d05372.js} +20 -33
  44. package/dist/app-config.js +1 -0
  45. package/dist/app.bundle.css +16 -13
  46. package/dist/{app.bundle.a978edc59b9d82f2eb22.js → app.bundle.ed937512f7d19d61c411.js} +183396 -87682
  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.f1a6ece1396dc1385155.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);
2312
+ dicom: (...args) => dicomWebDelegate.store(...args)
1991
2313
  },
1992
- getImageIdsForDisplaySet: function () {
1993
- return dicomWebDelegate.getImageIdsForDisplaySet(...arguments);
1994
- },
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.81";
2754
+ const commitHash = "f99a0bfb31434aa137bbb3ed1f9eef1dfcc09025";
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
  });
@@ -2814,7 +3421,8 @@ function getImageSrcFromImageId(cornerstone, imageId) {
2814
3421
  const canvas = document.createElement('canvas');
2815
3422
  cornerstone.utilities.loadImageToCanvas({
2816
3423
  canvas,
2817
- imageId
3424
+ imageId,
3425
+ thumbnail: true
2818
3426
  }).then(imageId => {
2819
3427
  resolve(canvas.toDataURL());
2820
3428
  }).catch(reject);
@@ -2860,17 +3468,16 @@ function requestDisplaySetCreationForStudy(dataSource, displaySetService, StudyI
2860
3468
  * @param {object} commandsManager
2861
3469
  * @param {object} extensionManager
2862
3470
  */
2863
- function WrappedPanelStudyBrowser(_ref) {
2864
- let {
2865
- commandsManager,
2866
- extensionManager,
2867
- servicesManager
2868
- } = _ref;
3471
+ function WrappedPanelStudyBrowser({
3472
+ commandsManager,
3473
+ extensionManager,
3474
+ servicesManager
3475
+ }) {
2869
3476
  // TODO: This should be made available a different way; route should have
2870
3477
  // already determined our datasource
2871
3478
  const dataSource = extensionManager.getDataSources()[0];
2872
3479
  const _getStudiesForPatientByMRN = Panels_getStudiesForPatientByMRN.bind(null, dataSource);
2873
- const _getImageSrcFromImageId = _createGetImageSrcFromImageIdFn(extensionManager);
3480
+ const _getImageSrcFromImageId = (0,react.useCallback)(_createGetImageSrcFromImageIdFn(extensionManager), []);
2874
3481
  const _requestDisplaySetCreationForStudy = Panels_requestDisplaySetCreationForStudy.bind(null, dataSource);
2875
3482
  return /*#__PURE__*/react.createElement(Panels_PanelStudyBrowser, {
2876
3483
  servicesManager: servicesManager,
@@ -2907,41 +3514,8 @@ WrappedPanelStudyBrowser.propTypes = {
2907
3514
  servicesManager: (prop_types_default()).object.isRequired
2908
3515
  };
2909
3516
  /* 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
3517
  // EXTERNAL MODULE: ../../../node_modules/lodash.debounce/index.js
2944
- var lodash_debounce = __webpack_require__(8324);
3518
+ var lodash_debounce = __webpack_require__(14771);
2945
3519
  var lodash_debounce_default = /*#__PURE__*/__webpack_require__.n(lodash_debounce);
2946
3520
  ;// CONCATENATED MODULE: ../../../extensions/default/src/Panels/createReportDialogPrompt.tsx
2947
3521
 
@@ -2950,10 +3524,9 @@ const CREATE_REPORT_DIALOG_RESPONSE = {
2950
3524
  CANCEL: 0,
2951
3525
  CREATE_REPORT: 1
2952
3526
  };
2953
- function CreateReportDialogPrompt(uiDialogService, _ref) {
2954
- let {
2955
- extensionManager
2956
- } = _ref;
3527
+ function CreateReportDialogPrompt(uiDialogService, {
3528
+ extensionManager
3529
+ }) {
2957
3530
  return new Promise(function (resolve, reject) {
2958
3531
  let dialogId = undefined;
2959
3532
  const _handleClose = () => {
@@ -2974,11 +3547,10 @@ function CreateReportDialogPrompt(uiDialogService, _ref) {
2974
3547
  * @param {string} param0.action - value of action performed
2975
3548
  * @param {string} param0.value - value from input field
2976
3549
  */
2977
- const _handleFormSubmit = _ref2 => {
2978
- let {
2979
- action,
2980
- value
2981
- } = _ref2;
3550
+ const _handleFormSubmit = ({
3551
+ action,
3552
+ value
3553
+ }) => {
2982
3554
  uiDialogService.dismiss({
2983
3555
  id: dialogId
2984
3556
  });
@@ -3013,7 +3585,7 @@ function CreateReportDialogPrompt(uiDialogService, _ref) {
3013
3585
  dialogId = uiDialogService.create({
3014
3586
  centralize: true,
3015
3587
  isDraggable: false,
3016
- content: ui_src/* Dialog */.Vq,
3588
+ content: ui_src/* Dialog */.lG,
3017
3589
  useLastPosition: false,
3018
3590
  showOverlay: true,
3019
3591
  contentProps: {
@@ -3027,19 +3599,18 @@ function CreateReportDialogPrompt(uiDialogService, _ref) {
3027
3599
  actions: [{
3028
3600
  id: 'cancel',
3029
3601
  text: 'Cancel',
3030
- type: ui_src/* ButtonEnums.type */.LZ.dt.secondary
3602
+ type: ui_src/* ButtonEnums.type */.Ny.NW.secondary
3031
3603
  }, {
3032
3604
  id: 'save',
3033
3605
  text: 'Save',
3034
- type: ui_src/* ButtonEnums.type */.LZ.dt.primary
3606
+ type: ui_src/* ButtonEnums.type */.Ny.NW.primary
3035
3607
  }],
3036
3608
  // TODO: Should be on button press...
3037
3609
  onSubmit: _handleFormSubmit,
3038
- body: _ref3 => {
3039
- let {
3040
- value,
3041
- setValue
3042
- } = _ref3;
3610
+ body: ({
3611
+ value,
3612
+ setValue
3613
+ }) => {
3043
3614
  const onChangeHandler = event => {
3044
3615
  event.persist();
3045
3616
  setValue(value => ({
@@ -3060,7 +3631,7 @@ function CreateReportDialogPrompt(uiDialogService, _ref) {
3060
3631
  };
3061
3632
  return /*#__PURE__*/react.createElement(react.Fragment, null, dataSourcesOpts.length > 1 && window.config?.allowMultiSelectExport && /*#__PURE__*/react.createElement("div", null, /*#__PURE__*/react.createElement("label", {
3062
3633
  className: "text-[14px] leading-[1.2] text-white"
3063
- }, "Data Source"), /*#__PURE__*/react.createElement(ui_src/* Select */.Ph, {
3634
+ }, "Data Source"), /*#__PURE__*/react.createElement(ui_src/* Select */.l6, {
3064
3635
  closeMenuOnSelect: true,
3065
3636
  className: "border-primary-main mt-2 bg-black",
3066
3637
  options: dataSourcesOpts,
@@ -3075,7 +3646,7 @@ function CreateReportDialogPrompt(uiDialogService, _ref) {
3075
3646
  isClearable: false
3076
3647
  })), /*#__PURE__*/react.createElement("div", {
3077
3648
  className: "mt-3"
3078
- }, /*#__PURE__*/react.createElement(ui_src/* Input */.II, {
3649
+ }, /*#__PURE__*/react.createElement(ui_src/* Input */.pd, {
3079
3650
  autoFocus: true,
3080
3651
  label: "Enter the report name",
3081
3652
  labelClassName: "text-white text-[14px] leading-[1.2]",
@@ -3099,12 +3670,11 @@ function CreateReportDialogPrompt(uiDialogService, _ref) {
3099
3670
  *
3100
3671
  * @param {*} servicesManager
3101
3672
  */
3102
- async function createReportAsync(_ref) {
3103
- let {
3104
- servicesManager,
3105
- getReport,
3106
- reportType = 'measurement'
3107
- } = _ref;
3673
+ async function createReportAsync({
3674
+ servicesManager,
3675
+ getReport,
3676
+ reportType = 'measurement'
3677
+ }) {
3108
3678
  const {
3109
3679
  displaySetService,
3110
3680
  uiNotificationService,
@@ -3218,13 +3788,15 @@ function findSRWithSameSeriesDescription(SeriesDescription, displaySetService) {
3218
3788
  const {
3219
3789
  downloadCSVReport
3220
3790
  } = 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_)();
3791
+ function PanelMeasurementTable({
3792
+ servicesManager,
3793
+ commandsManager,
3794
+ extensionManager
3795
+ }) {
3796
+ const {
3797
+ t
3798
+ } = (0,es/* useTranslation */.Bd)('MeasurementTable');
3799
+ const [viewportGrid, viewportGridService] = (0,ui_src/* useViewportGrid */.ih)();
3228
3800
  const {
3229
3801
  activeViewportId,
3230
3802
  viewports
@@ -3310,31 +3882,28 @@ function PanelMeasurementTable(_ref) {
3310
3882
  });
3311
3883
  }
3312
3884
  }
3313
- const jumpToImage = _ref2 => {
3314
- let {
3315
- uid,
3316
- isActive
3317
- } = _ref2;
3885
+ const jumpToImage = ({
3886
+ uid,
3887
+ isActive
3888
+ }) => {
3318
3889
  measurementService.jumpToMeasurement(viewportGrid.activeViewportId, uid);
3319
3890
  onMeasurementItemClickHandler({
3320
3891
  uid,
3321
3892
  isActive
3322
3893
  });
3323
3894
  };
3324
- const onMeasurementItemEditHandler = _ref3 => {
3325
- let {
3326
- uid,
3327
- isActive
3328
- } = _ref3;
3895
+ const onMeasurementItemEditHandler = ({
3896
+ uid,
3897
+ isActive
3898
+ }) => {
3329
3899
  const measurement = measurementService.getMeasurement(uid);
3330
3900
  //Todo: why we are jumping to image?
3331
3901
  // jumpToImage({ id, isActive });
3332
3902
 
3333
- const onSubmitHandler = _ref4 => {
3334
- let {
3335
- action,
3336
- value
3337
- } = _ref4;
3903
+ const onSubmitHandler = ({
3904
+ action,
3905
+ value
3906
+ }) => {
3338
3907
  switch (action.id) {
3339
3908
  case 'save':
3340
3909
  {
@@ -3353,18 +3922,17 @@ function PanelMeasurementTable(_ref) {
3353
3922
  centralize: true,
3354
3923
  isDraggable: false,
3355
3924
  showOverlay: true,
3356
- content: ui_src/* Dialog */.Vq,
3925
+ content: ui_src/* Dialog */.lG,
3357
3926
  contentProps: {
3358
3927
  title: 'Annotation',
3359
3928
  noCloseButton: true,
3360
3929
  value: {
3361
3930
  label: measurement.label || ''
3362
3931
  },
3363
- body: _ref5 => {
3364
- let {
3365
- value,
3366
- setValue
3367
- } = _ref5;
3932
+ body: ({
3933
+ value,
3934
+ setValue
3935
+ }) => {
3368
3936
  const onChangeHandler = event => {
3369
3937
  event.persist();
3370
3938
  setValue(value => ({
@@ -3382,7 +3950,7 @@ function PanelMeasurementTable(_ref) {
3382
3950
  });
3383
3951
  }
3384
3952
  };
3385
- return /*#__PURE__*/react.createElement(ui_src/* Input */.II, {
3953
+ return /*#__PURE__*/react.createElement(ui_src/* Input */.pd, {
3386
3954
  label: "Enter your annotation",
3387
3955
  labelClassName: "text-white text-[14px] leading-[1.2]",
3388
3956
  autoFocus: true,
@@ -3397,21 +3965,20 @@ function PanelMeasurementTable(_ref) {
3397
3965
  actions: [{
3398
3966
  id: 'cancel',
3399
3967
  text: 'Cancel',
3400
- type: ui_src/* ButtonEnums.type */.LZ.dt.secondary
3968
+ type: ui_src/* ButtonEnums.type */.Ny.NW.secondary
3401
3969
  }, {
3402
3970
  id: 'save',
3403
3971
  text: 'Save',
3404
- type: ui_src/* ButtonEnums.type */.LZ.dt.primary
3972
+ type: ui_src/* ButtonEnums.type */.Ny.NW.primary
3405
3973
  }],
3406
3974
  onSubmit: onSubmitHandler
3407
3975
  }
3408
3976
  });
3409
3977
  };
3410
- const onMeasurementItemClickHandler = _ref6 => {
3411
- let {
3412
- uid,
3413
- isActive
3414
- } = _ref6;
3978
+ const onMeasurementItemClickHandler = ({
3979
+ uid,
3980
+ isActive
3981
+ }) => {
3415
3982
  if (!isActive) {
3416
3983
  const measurements = [...displayMeasurements];
3417
3984
  const measurement = measurements.find(m => m.uid === uid);
@@ -3423,22 +3990,27 @@ function PanelMeasurementTable(_ref) {
3423
3990
  return /*#__PURE__*/react.createElement(react.Fragment, null, /*#__PURE__*/react.createElement("div", {
3424
3991
  className: "ohif-scrollbar overflow-y-auto overflow-x-hidden",
3425
3992
  "data-cy": 'measurements-panel'
3426
- }, /*#__PURE__*/react.createElement(ui_src/* MeasurementTable */.wt, {
3427
- title: "Measurements",
3993
+ }, /*#__PURE__*/react.createElement(ui_src/* MeasurementTable */.V, {
3994
+ title: t('Measurements'),
3428
3995
  servicesManager: servicesManager,
3429
3996
  data: displayMeasurements,
3430
3997
  onClick: jumpToImage,
3431
3998
  onEdit: onMeasurementItemEditHandler
3432
3999
  })), /*#__PURE__*/react.createElement("div", {
3433
4000
  className: "flex justify-center p-4"
3434
- }, /*#__PURE__*/react.createElement(Panels_ActionButtons, {
3435
- onExportClick: exportReport,
3436
- onClearMeasurementsClick: clearMeasurements,
3437
- onCreateReportClick: createReport
4001
+ }, /*#__PURE__*/react.createElement(ui_src/* ActionButtons */.wr, {
4002
+ t: t,
4003
+ actions: [{
4004
+ label: 'Export',
4005
+ onClick: exportReport
4006
+ }, {
4007
+ label: 'Create Report',
4008
+ onClick: createReport
4009
+ }]
3438
4010
  })));
3439
4011
  }
3440
4012
  PanelMeasurementTable.propTypes = {
3441
- servicesManager: prop_types_default().instanceOf(src/* ServicesManager */.Xw).isRequired
4013
+ servicesManager: prop_types_default().instanceOf(src/* ServicesManager */.CS).isRequired
3442
4014
  };
3443
4015
  function _getMappedMeasurements(measurementService) {
3444
4016
  const measurements = measurementService.getMeasurements();
@@ -3495,21 +4067,23 @@ function _mapMeasurementToDisplay(measurement, index, types) {
3495
4067
 
3496
4068
 
3497
4069
 
4070
+ // EXTERNAL MODULE: ../../../node_modules/i18next/dist/esm/i18next.js
4071
+ var i18next = __webpack_require__(92344);
3498
4072
  ;// CONCATENATED MODULE: ../../../extensions/default/src/getPanelModule.tsx
3499
4073
 
3500
4074
 
3501
4075
 
4076
+
3502
4077
  // TODO:
3503
4078
  // - No loading UI exists yet
3504
4079
  // - cancel promises when component is destroyed
3505
4080
  // - show errors in UI for thumbnails if promise fails
3506
4081
 
3507
- function getPanelModule(_ref) {
3508
- let {
3509
- commandsManager,
3510
- extensionManager,
3511
- servicesManager
3512
- } = _ref;
4082
+ function getPanelModule({
4083
+ commandsManager,
4084
+ extensionManager,
4085
+ servicesManager
4086
+ }) {
3513
4087
  const wrappedMeasurementPanel = () => {
3514
4088
  return /*#__PURE__*/react.createElement(PanelMeasurementTable, {
3515
4089
  commandsManager: commandsManager,
@@ -3521,7 +4095,7 @@ function getPanelModule(_ref) {
3521
4095
  name: 'seriesList',
3522
4096
  iconName: 'tab-studies',
3523
4097
  iconLabel: 'Studies',
3524
- label: 'Studies',
4098
+ label: i18next/* default */.A.t('SidePanel:Studies'),
3525
4099
  component: Panels_WrappedPanelStudyBrowser.bind(null, {
3526
4100
  commandsManager,
3527
4101
  extensionManager,
@@ -3531,28 +4105,28 @@ function getPanelModule(_ref) {
3531
4105
  name: 'measure',
3532
4106
  iconName: 'tab-linear',
3533
4107
  iconLabel: 'Measure',
3534
- label: 'Measurements',
3535
- secondaryLabel: 'Measurements',
4108
+ label: i18next/* default */.A.t('SidePanel:Measurements'),
4109
+ secondaryLabel: i18next/* default */.A.t('SidePanel:Measurements'),
3536
4110
  component: wrappedMeasurementPanel
3537
4111
  }];
3538
4112
  }
3539
4113
  /* harmony default export */ const src_getPanelModule = (getPanelModule);
3540
4114
  // EXTERNAL MODULE: ../../core/src/utils/isImage.js
3541
- var isImage = __webpack_require__(11835);
4115
+ var isImage = __webpack_require__(8094);
3542
4116
  // EXTERNAL MODULE: ../../core/src/utils/sopClassDictionary.js
3543
- var sopClassDictionary = __webpack_require__(24369);
4117
+ var sopClassDictionary = __webpack_require__(48085);
3544
4118
  // EXTERNAL MODULE: ../../core/src/classes/ImageSet.ts
3545
- var ImageSet = __webpack_require__(13950);
4119
+ var ImageSet = __webpack_require__(14169);
3546
4120
  // EXTERNAL MODULE: ../../core/src/utils/isDisplaySetReconstructable.js
3547
- var isDisplaySetReconstructable = __webpack_require__(89359);
4121
+ var isDisplaySetReconstructable = __webpack_require__(13835);
3548
4122
  ;// CONCATENATED MODULE: ../../../extensions/default/package.json
3549
- const package_namespaceObject = JSON.parse('{"u2":"@ohif/extension-default"}');
4123
+ const package_namespaceObject = /*#__PURE__*/JSON.parse('{"UU":"@ohif/extension-default"}');
3550
4124
  ;// CONCATENATED MODULE: ../../../extensions/default/src/id.js
3551
4125
 
3552
- const id = package_namespaceObject.u2;
4126
+ const id = package_namespaceObject.UU;
3553
4127
 
3554
4128
  // EXTERNAL MODULE: ../../core/src/utils/sortInstancesByPosition.ts
3555
- var sortInstancesByPosition = __webpack_require__(87425);
4129
+ var sortInstancesByPosition = __webpack_require__(44563);
3556
4130
  ;// CONCATENATED MODULE: ../../../extensions/default/src/utils/validations/checkMultiframe.ts
3557
4131
 
3558
4132
 
@@ -3563,18 +4137,18 @@ var sortInstancesByPosition = __webpack_require__(87425);
3563
4137
  * @param {*} warnings
3564
4138
  */
3565
4139
  function checkMultiFrame(multiFrameInstance, messages) {
3566
- if (!(0,isDisplaySetReconstructable/* hasPixelMeasurements */.hu)(multiFrameInstance)) {
3567
- messages.addMessage(src/* DisplaySetMessage */.Lt.CODES.MULTIFRAME_NO_PIXEL_MEASUREMENTS);
4140
+ if (!(0,isDisplaySetReconstructable/* hasPixelMeasurements */.Yt)(multiFrameInstance)) {
4141
+ messages.addMessage(src/* DisplaySetMessage */.Ob.CODES.MULTIFRAME_NO_PIXEL_MEASUREMENTS);
3568
4142
  }
3569
- if (!(0,isDisplaySetReconstructable/* hasOrientation */.sb)(multiFrameInstance)) {
3570
- messages.addMessage(src/* DisplaySetMessage */.Lt.CODES.MULTIFRAME_NO_ORIENTATION);
4143
+ if (!(0,isDisplaySetReconstructable/* hasOrientation */.VX)(multiFrameInstance)) {
4144
+ messages.addMessage(src/* DisplaySetMessage */.Ob.CODES.MULTIFRAME_NO_ORIENTATION);
3571
4145
  }
3572
- if (!(0,isDisplaySetReconstructable/* hasPosition */.kN)(multiFrameInstance)) {
3573
- messages.addMessage(src/* DisplaySetMessage */.Lt.CODES.MULTIFRAME_NO_POSITION_INFORMATION);
4146
+ if (!(0,isDisplaySetReconstructable/* hasPosition */.sL)(multiFrameInstance)) {
4147
+ messages.addMessage(src/* DisplaySetMessage */.Ob.CODES.MULTIFRAME_NO_POSITION_INFORMATION);
3574
4148
  }
3575
4149
  }
3576
4150
  // EXTERNAL MODULE: ../../core/src/utils/toNumber.js
3577
- var toNumber = __webpack_require__(94972);
4151
+ var toNumber = __webpack_require__(58099);
3578
4152
  ;// CONCATENATED MODULE: ../../../extensions/default/src/utils/validations/areAllImageDimensionsEqual.ts
3579
4153
 
3580
4154
 
@@ -3588,8 +4162,8 @@ function areAllImageDimensionsEqual(instances) {
3588
4162
  return false;
3589
4163
  }
3590
4164
  const firstImage = instances[0];
3591
- const firstImageRows = (0,toNumber/* default */.Z)(firstImage.Rows);
3592
- const firstImageColumns = (0,toNumber/* default */.Z)(firstImage.Columns);
4165
+ const firstImageRows = (0,toNumber/* default */.A)(firstImage.Rows);
4166
+ const firstImageColumns = (0,toNumber/* default */.A)(firstImage.Columns);
3593
4167
  for (let i = 1; i < instances.length; i++) {
3594
4168
  const instance = instances[i];
3595
4169
  const {
@@ -3615,7 +4189,7 @@ function areAllImageComponentsEqual(instances) {
3615
4189
  return false;
3616
4190
  }
3617
4191
  const firstImage = instances[0];
3618
- const firstImageSamplesPerPixel = (0,toNumber/* default */.Z)(firstImage.SamplesPerPixel);
4192
+ const firstImageSamplesPerPixel = (0,toNumber/* default */.A)(firstImage.SamplesPerPixel);
3619
4193
  for (let i = 1; i < instances.length; i++) {
3620
4194
  const instance = instances[i];
3621
4195
  const {
@@ -3641,18 +4215,18 @@ function areAllImageOrientationsEqual(instances) {
3641
4215
  return false;
3642
4216
  }
3643
4217
  const firstImage = instances[0];
3644
- const firstImageOrientationPatient = (0,toNumber/* default */.Z)(firstImage.ImageOrientationPatient);
4218
+ const firstImageOrientationPatient = (0,toNumber/* default */.A)(firstImage.ImageOrientationPatient);
3645
4219
  for (let i = 1; i < instances.length; i++) {
3646
4220
  const instance = instances[i];
3647
- const imageOrientationPatient = (0,toNumber/* default */.Z)(instance.ImageOrientationPatient);
3648
- if (!(0,isDisplaySetReconstructable/* _isSameOrientation */.NB)(imageOrientationPatient, firstImageOrientationPatient)) {
4221
+ const imageOrientationPatient = (0,toNumber/* default */.A)(instance.ImageOrientationPatient);
4222
+ if (!(0,isDisplaySetReconstructable/* _isSameOrientation */.sW)(imageOrientationPatient, firstImageOrientationPatient)) {
3649
4223
  return false;
3650
4224
  }
3651
4225
  }
3652
4226
  return true;
3653
4227
  }
3654
- // EXTERNAL MODULE: ../../../node_modules/gl-matrix/esm/index.js + 10 modules
3655
- var esm = __webpack_require__(45451);
4228
+ // EXTERNAL MODULE: ../../../node_modules/gl-matrix/esm/index.js + 1 modules
4229
+ var esm = __webpack_require__(44753);
3656
4230
  ;// CONCATENATED MODULE: ../../../extensions/default/src/utils/calculateScanAxisNormal.ts
3657
4231
 
3658
4232
 
@@ -3662,9 +4236,9 @@ var esm = __webpack_require__(45451);
3662
4236
  * @returns
3663
4237
  */
3664
4238
  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);
4239
+ const rowCosineVec = esm/* vec3.fromValues */.eR.fromValues(imageOrientation[0], imageOrientation[1], imageOrientation[2]);
4240
+ const colCosineVec = esm/* vec3.fromValues */.eR.fromValues(imageOrientation[3], imageOrientation[4], imageOrientation[5]);
4241
+ return esm/* vec3.cross */.eR.cross(esm/* vec3.create */.eR.create(), rowCosineVec, colCosineVec);
3668
4242
  }
3669
4243
  ;// CONCATENATED MODULE: ../../../extensions/default/src/utils/validations/areAllImagePositionsEqual.ts
3670
4244
 
@@ -3683,8 +4257,8 @@ function calculateScanAxisNormal(imageOrientation) {
3683
4257
  function _checkSeriesPositionShift(previousPosition, actualPosition, scanAxisNormal, averageSpacingBetweenFrames) {
3684
4258
  // predicted position should be the previous position added by the multiplication
3685
4259
  // 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;
4260
+ const predictedPosition = esm/* vec3.scaleAndAdd */.eR.scaleAndAdd(esm/* vec3.create */.eR.create(), previousPosition, scanAxisNormal, averageSpacingBetweenFrames);
4261
+ return esm/* vec3.distance */.eR.distance(actualPosition, predictedPosition) > averageSpacingBetweenFrames;
3688
4262
  }
3689
4263
 
3690
4264
  /**
@@ -3696,18 +4270,18 @@ function areAllImagePositionsEqual(instances) {
3696
4270
  if (!instances?.length) {
3697
4271
  return false;
3698
4272
  }
3699
- const firstImageOrientationPatient = (0,toNumber/* default */.Z)(instances[0].ImageOrientationPatient);
4273
+ const firstImageOrientationPatient = (0,toNumber/* default */.A)(instances[0].ImageOrientationPatient);
3700
4274
  if (!firstImageOrientationPatient) {
3701
4275
  return false;
3702
4276
  }
3703
4277
  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);
4278
+ const firstImagePositionPatient = (0,toNumber/* default */.A)(instances[0].ImagePositionPatient);
4279
+ const lastIpp = (0,toNumber/* default */.A)(instances[instances.length - 1].ImagePositionPatient);
4280
+ const averageSpacingBetweenFrames = (0,isDisplaySetReconstructable/* _getPerpendicularDistance */.jj)(firstImagePositionPatient, lastIpp) / (instances.length - 1);
3707
4281
  let previousImagePositionPatient = firstImagePositionPatient;
3708
4282
  for (let i = 1; i < instances.length; i++) {
3709
4283
  const instance = instances[i];
3710
- const imagePositionPatient = (0,toNumber/* default */.Z)(instance.ImagePositionPatient);
4284
+ const imagePositionPatient = (0,toNumber/* default */.A)(instance.ImagePositionPatient);
3711
4285
  if (_checkSeriesPositionShift(previousImagePositionPatient, imagePositionPatient, scanAxisNormal, averageSpacingBetweenFrames)) {
3712
4286
  return false;
3713
4287
  }
@@ -3728,29 +4302,29 @@ function areAllImageSpacingEqual(instances, messages) {
3728
4302
  if (!instances?.length) {
3729
4303
  return;
3730
4304
  }
3731
- const firstImagePositionPatient = (0,toNumber/* default */.Z)(instances[0].ImagePositionPatient);
4305
+ const firstImagePositionPatient = (0,toNumber/* default */.A)(instances[0].ImagePositionPatient);
3732
4306
  if (!firstImagePositionPatient) {
3733
4307
  return;
3734
4308
  }
3735
- const lastIpp = (0,toNumber/* default */.Z)(instances[instances.length - 1].ImagePositionPatient);
3736
- const averageSpacingBetweenFrames = (0,isDisplaySetReconstructable/* _getPerpendicularDistance */.Xn)(firstImagePositionPatient, lastIpp) / (instances.length - 1);
4309
+ const lastIpp = (0,toNumber/* default */.A)(instances[instances.length - 1].ImagePositionPatient);
4310
+ const averageSpacingBetweenFrames = (0,isDisplaySetReconstructable/* _getPerpendicularDistance */.jj)(firstImagePositionPatient, lastIpp) / (instances.length - 1);
3737
4311
  let previousImagePositionPatient = firstImagePositionPatient;
3738
4312
  const issuesFound = [];
3739
4313
  for (let i = 1; i < instances.length; i++) {
3740
4314
  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);
4315
+ const imagePositionPatient = (0,toNumber/* default */.A)(instance.ImagePositionPatient);
4316
+ const spacingBetweenFrames = (0,isDisplaySetReconstructable/* _getPerpendicularDistance */.jj)(imagePositionPatient, previousImagePositionPatient);
4317
+ const spacingIssue = (0,isDisplaySetReconstructable/* _getSpacingIssue */.Op)(spacingBetweenFrames, averageSpacingBetweenFrames);
3744
4318
  if (spacingIssue) {
3745
4319
  const issue = spacingIssue.issue;
3746
4320
 
3747
4321
  // avoid multiple warning of the same thing
3748
4322
  if (!issuesFound.includes(issue)) {
3749
4323
  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);
4324
+ if (issue === isDisplaySetReconstructable/* reconstructionIssues */.JG.MISSING_FRAMES) {
4325
+ messages.addMessage(src/* DisplaySetMessage */.Ob.CODES.MISSING_FRAMES);
4326
+ } else if (issue === isDisplaySetReconstructable/* reconstructionIssues */.JG.IRREGULAR_SPACING) {
4327
+ messages.addMessage(src/* DisplaySetMessage */.Ob.CODES.IRREGULAR_SPACING);
3754
4328
  }
3755
4329
  }
3756
4330
  // we just want to find issues not how many
@@ -3777,16 +4351,16 @@ function areAllImageSpacingEqual(instances, messages) {
3777
4351
  function checkSingleFrames(instances, messages) {
3778
4352
  if (instances.length > 2) {
3779
4353
  if (!areAllImageDimensionsEqual(instances)) {
3780
- messages.addMessage(src/* DisplaySetMessage */.Lt.CODES.INCONSISTENT_DIMENSIONS);
4354
+ messages.addMessage(src/* DisplaySetMessage */.Ob.CODES.INCONSISTENT_DIMENSIONS);
3781
4355
  }
3782
4356
  if (!areAllImageComponentsEqual(instances)) {
3783
- messages.addMessage(src/* DisplaySetMessage */.Lt.CODES.INCONSISTENT_COMPONENTS);
4357
+ messages.addMessage(src/* DisplaySetMessage */.Ob.CODES.INCONSISTENT_COMPONENTS);
3784
4358
  }
3785
4359
  if (!areAllImageOrientationsEqual(instances)) {
3786
- messages.addMessage(src/* DisplaySetMessage */.Lt.CODES.INCONSISTENT_ORIENTATIONS);
4360
+ messages.addMessage(src/* DisplaySetMessage */.Ob.CODES.INCONSISTENT_ORIENTATIONS);
3787
4361
  }
3788
4362
  if (!areAllImagePositionsEqual(instances)) {
3789
- messages.addMessage(src/* DisplaySetMessage */.Lt.CODES.INCONSISTENT_POSITION_INFORMATION);
4363
+ messages.addMessage(src/* DisplaySetMessage */.Ob.CODES.INCONSISTENT_POSITION_INFORMATION);
3790
4364
  }
3791
4365
  areAllImageSpacingEqual(instances, messages);
3792
4366
  }
@@ -3802,10 +4376,13 @@ function checkSingleFrames(instances, messages) {
3802
4376
  *
3803
4377
  * @param {Object[]} instances An array of `OHIFInstanceMetadata` objects.
3804
4378
  */
3805
- function getDisplaySetMessages(instances, isReconstructable) {
3806
- const messages = new src/* DisplaySetMessageList */.iK();
4379
+ function getDisplaySetMessages(instances, isReconstructable, isDynamicVolume) {
4380
+ const messages = new src/* DisplaySetMessageList */.WZ();
4381
+ if (isDynamicVolume) {
4382
+ return messages;
4383
+ }
3807
4384
  if (!instances.length) {
3808
- messages.addMessage(src/* DisplaySetMessage */.Lt.CODES.NO_VALID_INSTANCES);
4385
+ messages.addMessage(src/* DisplaySetMessage */.Ob.CODES.NO_VALID_INSTANCES);
3809
4386
  return;
3810
4387
  }
3811
4388
  const firstInstance = instances[0];
@@ -3818,18 +4395,18 @@ function getDisplaySetMessages(instances, isReconstructable) {
3818
4395
  if (ImageType?.includes('LOCALIZER')) {
3819
4396
  return messages;
3820
4397
  }
3821
- if (!isDisplaySetReconstructable/* constructableModalities */.M6.includes(Modality)) {
4398
+ if (!isDisplaySetReconstructable/* constructableModalities */.Hf.includes(Modality)) {
3822
4399
  return messages;
3823
4400
  }
3824
4401
  const isMultiframe = NumberOfFrames > 1;
3825
4402
  // Can't reconstruct if all instances don't have the ImagePositionPatient.
3826
4403
  if (!isMultiframe && !instances.every(instance => instance.ImagePositionPatient)) {
3827
- messages.addMessage(src/* DisplaySetMessage */.Lt.CODES.NO_POSITION_INFORMATION);
4404
+ messages.addMessage(src/* DisplaySetMessage */.Ob.CODES.NO_POSITION_INFORMATION);
3828
4405
  }
3829
- const sortedInstances = (0,sortInstancesByPosition/* default */.Z)(instances);
4406
+ const sortedInstances = (0,sortInstancesByPosition/* default */.A)(instances);
3830
4407
  isMultiframe ? checkMultiFrame(sortedInstances[0], messages) : checkSingleFrames(sortedInstances, messages);
3831
4408
  if (!isReconstructable) {
3832
- messages.addMessage(src/* DisplaySetMessage */.Lt.CODES.NOT_RECONSTRUCTABLE);
4409
+ messages.addMessage(src/* DisplaySetMessage */.Ob.CODES.NOT_RECONSTRUCTABLE);
3833
4410
  }
3834
4411
  return messages;
3835
4412
  }
@@ -3840,9 +4417,9 @@ function getDisplaySetMessages(instances, isReconstructable) {
3840
4417
  * Default handler for a instance list with an unsupported sopClassUID
3841
4418
  */
3842
4419
  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);
4420
+ const imageSet = new ImageSet/* default */.A(instances);
4421
+ const messages = new src/* DisplaySetMessageList */.WZ();
4422
+ messages.addMessage(src/* DisplaySetMessage */.Ob.CODES.UNSUPPORTED_DISPLAYSET);
3846
4423
  const instance = instances[0];
3847
4424
  imageSet.setAttributes({
3848
4425
  displaySetInstanceUID: imageSet.uid,
@@ -3864,6 +4441,85 @@ function getDisplaySetsFromUnsupportedSeries(instances) {
3864
4441
  });
3865
4442
  return [imageSet];
3866
4443
  }
4444
+ ;// CONCATENATED MODULE: ../../../extensions/default/src/SOPClassHandlers/chartSOPClassHandler.ts
4445
+
4446
+
4447
+ const SOPClassHandlerName = 'chart';
4448
+ const CHART_MODALITY = 'CHT';
4449
+
4450
+ // Private SOPClassUid for chart data
4451
+ const ChartDataSOPClassUid = '1.9.451.13215.7.3.2.7.6.1';
4452
+ const sopClassUids = [ChartDataSOPClassUid];
4453
+ const makeChartDataDisplaySet = (instance, sopClassUids) => {
4454
+ const {
4455
+ StudyInstanceUID,
4456
+ SeriesInstanceUID,
4457
+ SOPInstanceUID,
4458
+ SeriesDescription,
4459
+ SeriesNumber,
4460
+ SeriesDate,
4461
+ SOPClassUID
4462
+ } = instance;
4463
+ return {
4464
+ Modality: CHART_MODALITY,
4465
+ loading: false,
4466
+ isReconstructable: false,
4467
+ displaySetInstanceUID: src.utils.guid(),
4468
+ SeriesDescription,
4469
+ SeriesNumber,
4470
+ SeriesDate,
4471
+ SOPInstanceUID,
4472
+ SeriesInstanceUID,
4473
+ StudyInstanceUID,
4474
+ SOPClassHandlerId: `${id}.sopClassHandlerModule.${SOPClassHandlerName}`,
4475
+ SOPClassUID,
4476
+ isDerivedDisplaySet: true,
4477
+ isLoaded: true,
4478
+ sopClassUids,
4479
+ instance,
4480
+ instances: [instance],
4481
+ /**
4482
+ * Adds instances to the chart displaySet, rather than creating a new one
4483
+ * when user moves to a different workflow step and gets back to a step that
4484
+ * recreates the chart
4485
+ */
4486
+ addInstances: function (instances, _displaySetService) {
4487
+ this.instances.push(...instances);
4488
+ this.instance = this.instances[this.instances.length - 1];
4489
+ return this;
4490
+ }
4491
+ };
4492
+ };
4493
+ function getSopClassUids(instances) {
4494
+ const uniqueSopClassUidsInSeries = new Set();
4495
+ instances.forEach(instance => {
4496
+ uniqueSopClassUidsInSeries.add(instance.SOPClassUID);
4497
+ });
4498
+ const sopClassUids = Array.from(uniqueSopClassUidsInSeries);
4499
+ return sopClassUids;
4500
+ }
4501
+ function _getDisplaySetsFromSeries(instances) {
4502
+ // If the series has no instances, stop here
4503
+ if (!instances || !instances.length) {
4504
+ throw new Error('No instances were provided');
4505
+ }
4506
+ const sopClassUids = getSopClassUids(instances);
4507
+ const displaySets = instances.map(instance => {
4508
+ if (instance.Modality === CHART_MODALITY) {
4509
+ return makeChartDataDisplaySet(instance, sopClassUids);
4510
+ }
4511
+ throw new Error('Unsupported modality');
4512
+ });
4513
+ return displaySets;
4514
+ }
4515
+ const chartHandler = {
4516
+ name: SOPClassHandlerName,
4517
+ sopClassUids,
4518
+ getDisplaySetsFromSeries: instances => {
4519
+ return _getDisplaySetsFromSeries(instances);
4520
+ }
4521
+ };
4522
+
3867
4523
  ;// CONCATENATED MODULE: ../../../extensions/default/src/getSopClassHandlerModule.js
3868
4524
 
3869
4525
 
@@ -3872,20 +4528,69 @@ function getDisplaySetsFromUnsupportedSeries(instances) {
3872
4528
 
3873
4529
 
3874
4530
 
4531
+
4532
+ const DEFAULT_VOLUME_LOADER_SCHEME = 'cornerstoneStreamingImageVolume';
4533
+ const DYNAMIC_VOLUME_LOADER_SCHEME = 'cornerstoneStreamingDynamicImageVolume';
3875
4534
  const sopClassHandlerName = 'stack';
4535
+ let appContext = {};
4536
+ const getDynamicVolumeInfo = instances => {
4537
+ const {
4538
+ extensionManager
4539
+ } = appContext;
4540
+ if (!extensionManager) {
4541
+ throw new Error('extensionManager is not available');
4542
+ }
4543
+ const imageIds = instances.map(({
4544
+ imageId
4545
+ }) => imageId);
4546
+ const volumeLoaderUtility = extensionManager.getModuleEntry('@ohif/extension-cornerstone.utilityModule.volumeLoader');
4547
+ const {
4548
+ getDynamicVolumeInfo: csGetDynamicVolumeInfo
4549
+ } = volumeLoaderUtility.exports;
4550
+ return csGetDynamicVolumeInfo(imageIds);
4551
+ };
3876
4552
  const isMultiFrame = instance => {
3877
4553
  return instance.NumberOfFrames > 1;
3878
4554
  };
4555
+ function getDisplaySetInfo(instances) {
4556
+ const dynamicVolumeInfo = getDynamicVolumeInfo(instances);
4557
+ const {
4558
+ isDynamicVolume,
4559
+ timePoints
4560
+ } = dynamicVolumeInfo;
4561
+ let displaySetInfo;
4562
+ if (isDynamicVolume) {
4563
+ const timePoint = timePoints[0];
4564
+ const instancesMap = new Map();
4565
+
4566
+ // O(n) to convert it into a map and O(1) to find each instance
4567
+ instances.forEach(instance => instancesMap.set(instance.imageId, instance));
4568
+ const firstTimePointInstances = timePoint.map(imageId => instancesMap.get(imageId));
4569
+ displaySetInfo = (0,isDisplaySetReconstructable/* default */.Ay)(firstTimePointInstances);
4570
+ } else {
4571
+ displaySetInfo = (0,isDisplaySetReconstructable/* default */.Ay)(instances);
4572
+ }
4573
+ return {
4574
+ isDynamicVolume,
4575
+ ...displaySetInfo,
4576
+ dynamicVolumeInfo
4577
+ };
4578
+ }
3879
4579
  const makeDisplaySet = instances => {
3880
4580
  const instance = instances[0];
3881
- const imageSet = new ImageSet/* default */.Z(instances);
4581
+ const imageSet = new ImageSet/* default */.A(instances);
3882
4582
  const {
4583
+ isDynamicVolume,
3883
4584
  value: isReconstructable,
3884
- averageSpacingBetweenFrames
3885
- } = (0,isDisplaySetReconstructable/* default */.ZP)(instances);
4585
+ averageSpacingBetweenFrames,
4586
+ dynamicVolumeInfo
4587
+ } = getDisplaySetInfo(instances);
4588
+ const volumeLoaderSchema = isDynamicVolume ? DYNAMIC_VOLUME_LOADER_SCHEME : DEFAULT_VOLUME_LOADER_SCHEME;
4589
+
3886
4590
  // set appropriate attributes to image set...
3887
- const messages = getDisplaySetMessages(instances, isReconstructable);
4591
+ const messages = getDisplaySetMessages(instances, isReconstructable, isDynamicVolume);
3888
4592
  imageSet.setAttributes({
4593
+ volumeLoaderSchema,
3889
4594
  displaySetInstanceUID: imageSet.uid,
3890
4595
  // create a local alias for the imageSet UID
3891
4596
  SeriesDate: instance.SeriesDate,
@@ -3903,7 +4608,9 @@ const makeDisplaySet = instances => {
3903
4608
  SOPClassHandlerId: `${id}.sopClassHandlerModule.${sopClassHandlerName}`,
3904
4609
  isReconstructable,
3905
4610
  messages,
3906
- averageSpacingBetweenFrames: averageSpacingBetweenFrames || null
4611
+ averageSpacingBetweenFrames: averageSpacingBetweenFrames || null,
4612
+ isDynamicVolume,
4613
+ dynamicVolumeInfo
3907
4614
  });
3908
4615
 
3909
4616
  // Sort the images in this series if needed
@@ -3934,7 +4641,7 @@ const makeDisplaySet = instances => {
3934
4641
  const isSingleImageModality = modality => {
3935
4642
  return modality === 'CR' || modality === 'MG' || modality === 'DX';
3936
4643
  };
3937
- function getSopClassUids(instances) {
4644
+ function getSopClassHandlerModule_getSopClassUids(instances) {
3938
4645
  const uniqueSopClassUidsInSeries = new Set();
3939
4646
  instances.forEach(instance => {
3940
4647
  uniqueSopClassUidsInSeries.add(instance.SOPClassUID);
@@ -3948,7 +4655,6 @@ function getSopClassUids(instances) {
3948
4655
  * - For all Image types that are stackable, create
3949
4656
  * a displaySet with a stack of images
3950
4657
  *
3951
- * @param {Array} sopClassHandlerModules List of SOP Class Modules
3952
4658
  * @param {SeriesMetadata} series The series metadata object from which the display sets will be created
3953
4659
  * @returns {Array} The list of display sets created for the given series object
3954
4660
  */
@@ -3958,7 +4664,7 @@ function getDisplaySetsFromSeries(instances) {
3958
4664
  throw new Error('No instances were provided');
3959
4665
  }
3960
4666
  const displaySets = [];
3961
- const sopClassUids = getSopClassUids(instances);
4667
+ const sopClassUids = getSopClassHandlerModule_getSopClassUids(instances);
3962
4668
 
3963
4669
  // Search through the instances (InstanceMetadata object) of this series
3964
4670
  // Split Multi-frame instances and Single-image modalities
@@ -3967,7 +4673,7 @@ function getDisplaySetsFromSeries(instances) {
3967
4673
  const stackableInstances = [];
3968
4674
  instances.forEach(instance => {
3969
4675
  // All imaging modalities must have a valid value for sopClassUid (x00080016) or rows (x00280010)
3970
- if (!(0,isImage/* isImage */.O)(instance.SOPClassUID) && !instance.Rows) {
4676
+ if (!(0,isImage/* isImage */.w)(instance.SOPClassUID) && !instance.Rows) {
3971
4677
  return;
3972
4678
  }
3973
4679
  let displaySet;
@@ -4003,16 +4709,21 @@ function getDisplaySetsFromSeries(instances) {
4003
4709
  }
4004
4710
  return displaySets;
4005
4711
  }
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() {
4712
+ 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];
4713
+ function getSopClassHandlerModule(appContextParam) {
4714
+ appContext = appContextParam;
4008
4715
  return [{
4009
4716
  name: sopClassHandlerName,
4010
- sopClassUids,
4717
+ sopClassUids: getSopClassHandlerModule_sopClassUids,
4011
4718
  getDisplaySetsFromSeries
4012
4719
  }, {
4013
4720
  name: 'not-supported-display-sets-handler',
4014
4721
  sopClassUids: [],
4015
4722
  getDisplaySetsFromSeries: getDisplaySetsFromUnsupportedSeries
4723
+ }, {
4724
+ name: chartHandler.name,
4725
+ sopClassUids: chartHandler.sopClassUids,
4726
+ getDisplaySetsFromSeries: chartHandler.getDisplaySetsFromSeries
4016
4727
  }];
4017
4728
  }
4018
4729
  /* harmony default export */ const src_getSopClassHandlerModule = (getSopClassHandlerModule);
@@ -4029,39 +4740,121 @@ function ToolbarLayoutSelector_extends() { ToolbarLayoutSelector_extends = Objec
4029
4740
 
4030
4741
 
4031
4742
 
4032
- function ToolbarLayoutSelectorWithServices(_ref) {
4033
- let {
4034
- servicesManager,
4035
- ...props
4036
- } = _ref;
4743
+ const defaultCommonPresets = [{
4744
+ icon: 'layout-common-1x1',
4745
+ commandOptions: {
4746
+ numRows: 1,
4747
+ numCols: 1
4748
+ }
4749
+ }, {
4750
+ icon: 'layout-common-1x2',
4751
+ commandOptions: {
4752
+ numRows: 1,
4753
+ numCols: 2
4754
+ }
4755
+ }, {
4756
+ icon: 'layout-common-2x2',
4757
+ commandOptions: {
4758
+ numRows: 2,
4759
+ numCols: 2
4760
+ }
4761
+ }, {
4762
+ icon: 'layout-common-2x3',
4763
+ commandOptions: {
4764
+ numRows: 2,
4765
+ numCols: 3
4766
+ }
4767
+ }];
4768
+ const _areSelectorsValid = (hp, displaySets, hangingProtocolService) => {
4769
+ if (!hp.displaySetSelectors || Object.values(hp.displaySetSelectors).length === 0) {
4770
+ return true;
4771
+ }
4772
+ return hangingProtocolService.areRequiredSelectorsValid(Object.values(hp.displaySetSelectors), displaySets[0]);
4773
+ };
4774
+ const generateAdvancedPresets = ({
4775
+ servicesManager
4776
+ }) => {
4037
4777
  const {
4038
- toolbarService
4778
+ hangingProtocolService,
4779
+ viewportGridService,
4780
+ displaySetService
4039
4781
  } = servicesManager.services;
4782
+ const hangingProtocols = Array.from(hangingProtocolService.protocols.values());
4783
+ const viewportId = viewportGridService.getActiveViewportId();
4784
+ if (!viewportId) {
4785
+ return [];
4786
+ }
4787
+ const displaySetInsaneUIDs = viewportGridService.getDisplaySetsUIDsForViewport(viewportId);
4788
+ const displaySets = displaySetInsaneUIDs.map(uid => displaySetService.getDisplaySetByUID(uid));
4789
+ return hangingProtocols.map(hp => {
4790
+ if (!hp.isPreset) {
4791
+ return null;
4792
+ }
4793
+ const areValid = _areSelectorsValid(hp, displaySets, hangingProtocolService);
4794
+ return {
4795
+ icon: hp.icon,
4796
+ title: hp.name,
4797
+ commandOptions: {
4798
+ protocolId: hp.id
4799
+ },
4800
+ disabled: !areValid
4801
+ };
4802
+ }).filter(preset => preset !== null);
4803
+ };
4804
+ function ToolbarLayoutSelectorWithServices({
4805
+ commandsManager,
4806
+ servicesManager,
4807
+ ...props
4808
+ }) {
4809
+ const [isDisabled, setIsDisabled] = (0,react.useState)(false);
4810
+ const handleMouseEnter = () => {
4811
+ setIsDisabled(false);
4812
+ };
4040
4813
  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
- }]
4814
+ commandsManager.run({
4815
+ commandName: 'setViewportGridLayout',
4816
+ commandOptions: {
4817
+ ...props
4818
+ }
4050
4819
  });
4051
- }, [toolbarService]);
4052
- return /*#__PURE__*/react.createElement(LayoutSelector, ToolbarLayoutSelector_extends({}, props, {
4053
- onSelection: onSelection
4054
- }));
4820
+ setIsDisabled(true);
4821
+ }, []);
4822
+ const onSelectionPreset = (0,react.useCallback)(props => {
4823
+ commandsManager.run({
4824
+ commandName: 'setHangingProtocol',
4825
+ commandOptions: {
4826
+ ...props
4827
+ }
4828
+ });
4829
+ setIsDisabled(true);
4830
+ }, []);
4831
+ return /*#__PURE__*/react.createElement("div", {
4832
+ onMouseEnter: handleMouseEnter
4833
+ }, /*#__PURE__*/react.createElement(LayoutSelector, ToolbarLayoutSelector_extends({}, props, {
4834
+ onSelection: onSelection,
4835
+ onSelectionPreset: onSelectionPreset,
4836
+ servicesManager: servicesManager,
4837
+ tooltipDisabled: isDisabled
4838
+ })));
4055
4839
  }
4056
- function LayoutSelector(_ref2) {
4057
- let {
4058
- rows,
4059
- columns,
4060
- className,
4061
- onSelection,
4062
- ...rest
4063
- } = _ref2;
4840
+ function LayoutSelector({
4841
+ rows,
4842
+ columns,
4843
+ className,
4844
+ onSelection,
4845
+ onSelectionPreset,
4846
+ servicesManager,
4847
+ tooltipDisabled,
4848
+ ...rest
4849
+ }) {
4064
4850
  const [isOpen, setIsOpen] = (0,react.useState)(false);
4851
+ const {
4852
+ customizationService
4853
+ } = servicesManager.services;
4854
+ const commonPresets = customizationService.get('commonPresets') || defaultCommonPresets;
4855
+ const advancedPresets = customizationService.get('advancedPresets') || generateAdvancedPresets({
4856
+ servicesManager
4857
+ });
4065
4858
  const closeOnOutsideClick = () => {
4066
4859
  if (isOpen) {
4067
4860
  setIsOpen(false);
@@ -4073,20 +4866,57 @@ function LayoutSelector(_ref2) {
4073
4866
  window.removeEventListener('click', closeOnOutsideClick);
4074
4867
  };
4075
4868
  }, [isOpen]);
4076
- const onInteractionHandler = () => setIsOpen(!isOpen);
4077
- const DropdownContent = isOpen ? ui_src/* LayoutSelector */.OF : null;
4078
- return /*#__PURE__*/react.createElement(ui_src/* ToolbarButton */.hA, {
4869
+ const onInteractionHandler = () => {
4870
+ setIsOpen(!isOpen);
4871
+ };
4872
+ const DropdownContent = isOpen ? ui_src/* LayoutSelector */.sG : null;
4873
+ return /*#__PURE__*/react.createElement(ui_src/* ToolbarButton */.IB, {
4079
4874
  id: "Layout",
4080
- label: "Grid Layout",
4875
+ label: "Layout",
4081
4876
  icon: "tool-layout",
4082
4877
  onInteraction: onInteractionHandler,
4083
4878
  className: className,
4084
4879
  rounded: rest.rounded,
4085
- dropdownContent: DropdownContent !== null && /*#__PURE__*/react.createElement(DropdownContent, {
4880
+ disableToolTip: tooltipDisabled,
4881
+ dropdownContent: DropdownContent !== null && /*#__PURE__*/react.createElement("div", {
4882
+ className: "flex "
4883
+ }, /*#__PURE__*/react.createElement("div", {
4884
+ className: "bg-secondary-dark flex flex-col gap-2.5 p-2"
4885
+ }, /*#__PURE__*/react.createElement("div", {
4886
+ className: "text-aqua-pale text-xs"
4887
+ }, "Common"), /*#__PURE__*/react.createElement("div", {
4888
+ className: "flex gap-4"
4889
+ }, commonPresets.map((preset, index) => /*#__PURE__*/react.createElement(ui_src/* LayoutPreset */.qu, {
4890
+ key: index,
4891
+ classNames: "hover:bg-primary-dark group p-1 cursor-pointer",
4892
+ icon: preset.icon,
4893
+ commandOptions: preset.commandOptions,
4894
+ onSelection: onSelection
4895
+ }))), /*#__PURE__*/react.createElement("div", {
4896
+ className: "h-[2px] bg-black"
4897
+ }), /*#__PURE__*/react.createElement("div", {
4898
+ className: "text-aqua-pale text-xs"
4899
+ }, "Advanced"), /*#__PURE__*/react.createElement("div", {
4900
+ className: "flex flex-col gap-2.5"
4901
+ }, advancedPresets.map((preset, index) => /*#__PURE__*/react.createElement(ui_src/* LayoutPreset */.qu, {
4902
+ key: index + commonPresets.length,
4903
+ classNames: "hover:bg-primary-dark group flex gap-2 p-1 cursor-pointer",
4904
+ icon: preset.icon,
4905
+ title: preset.title,
4906
+ disabled: preset.disabled,
4907
+ commandOptions: preset.commandOptions,
4908
+ onSelection: onSelectionPreset
4909
+ })))), /*#__PURE__*/react.createElement("div", {
4910
+ className: "bg-primary-dark flex flex-col gap-2.5 border-l-2 border-solid border-black p-2"
4911
+ }, /*#__PURE__*/react.createElement("div", {
4912
+ className: "text-aqua-pale text-xs"
4913
+ }, "Custom"), /*#__PURE__*/react.createElement(DropdownContent, {
4086
4914
  rows: rows,
4087
4915
  columns: columns,
4088
4916
  onSelection: onSelection
4089
- }),
4917
+ }), /*#__PURE__*/react.createElement("p", {
4918
+ className: "text-aqua-pale text-xs leading-tight"
4919
+ }, "Hover to select ", /*#__PURE__*/react.createElement("br", null), "rows and columns ", /*#__PURE__*/react.createElement("br", null), " Click to apply"))),
4090
4920
  isActive: isOpen,
4091
4921
  type: "toggle"
4092
4922
  });
@@ -4095,11 +4925,11 @@ LayoutSelector.propTypes = {
4095
4925
  rows: (prop_types_default()).number,
4096
4926
  columns: (prop_types_default()).number,
4097
4927
  onLayoutChange: (prop_types_default()).func,
4098
- servicesManager: prop_types_default().instanceOf(src/* ServicesManager */.Xw)
4928
+ servicesManager: prop_types_default().instanceOf(src/* ServicesManager */.CS)
4099
4929
  };
4100
4930
  LayoutSelector.defaultProps = {
4931
+ columns: 4,
4101
4932
  rows: 3,
4102
- columns: 3,
4103
4933
  onLayoutChange: () => {}
4104
4934
  };
4105
4935
  /* harmony default export */ const ToolbarLayoutSelector = (ToolbarLayoutSelectorWithServices);
@@ -4108,122 +4938,39 @@ function ToolbarSplitButtonWithServices_extends() { ToolbarSplitButtonWithServic
4108
4938
 
4109
4939
 
4110
4940
 
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;
4941
+ function ToolbarSplitButtonWithServices({
4942
+ groupId,
4943
+ primary,
4944
+ secondary,
4945
+ items,
4946
+ renderer,
4947
+ onInteraction,
4948
+ servicesManager
4949
+ }) {
4124
4950
  const {
4125
4951
  toolbarService
4126
4952
  } = 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
4953
 
4150
4954
  /* Bubbles up individual item clicks */
4151
- const getSplitButtonItems = items => items.map((item, index) => ({
4955
+ const getSplitButtonItems = (0,react.useCallback)(items => items.map((item, index) => ({
4152
4956
  ...item,
4153
4957
  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
4958
+ onClick: () => {
4959
+ onInteraction({
4960
+ groupId,
4961
+ itemId: item.id,
4962
+ commands: item.commands
4178
4963
  });
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,
4964
+ }
4965
+ })), []);
4966
+ const PrimaryButtonComponent = toolbarService?.getButtonComponentForUIType(primary.uiType) ?? ui_src/* ToolbarButton */.IB;
4967
+ const listItemRenderer = renderer;
4968
+ return /*#__PURE__*/react.createElement(ui_src/* SplitButton */.fk, {
4969
+ primary: primary,
4221
4970
  secondary: secondary,
4222
- items: updatedItems,
4971
+ items: getSplitButtonItems(items),
4223
4972
  groupId: groupId,
4224
4973
  renderer: listItemRenderer,
4225
- isActive: isPrimaryActive || updatedItems.some(item => item.isActive),
4226
- isToggle: isPrimaryToggle,
4227
4974
  onInteraction: onInteraction,
4228
4975
  Component: props => /*#__PURE__*/react.createElement(PrimaryButtonComponent, ToolbarSplitButtonWithServices_extends({}, props, {
4229
4976
  servicesManager: servicesManager
@@ -4232,11 +4979,9 @@ function ToolbarSplitButtonWithServices(_ref) {
4232
4979
  }
4233
4980
  ToolbarSplitButtonWithServices.propTypes = {
4234
4981
  isRadio: (prop_types_default()).bool,
4235
- isAction: (prop_types_default()).bool,
4236
4982
  groupId: (prop_types_default()).string,
4237
4983
  primary: prop_types_default().shape({
4238
4984
  id: (prop_types_default()).string.isRequired,
4239
- type: prop_types_default().oneOf(['tool', 'action', 'toggle']).isRequired,
4240
4985
  uiType: (prop_types_default()).string
4241
4986
  }),
4242
4987
  secondary: prop_types_default().shape({
@@ -4244,14 +4989,16 @@ ToolbarSplitButtonWithServices.propTypes = {
4244
4989
  icon: (prop_types_default()).string.isRequired,
4245
4990
  label: (prop_types_default()).string,
4246
4991
  tooltip: (prop_types_default()).string.isRequired,
4247
- isActive: (prop_types_default()).bool
4992
+ disabled: (prop_types_default()).bool,
4993
+ className: (prop_types_default()).string
4248
4994
  }),
4249
4995
  items: prop_types_default().arrayOf(prop_types_default().shape({
4250
4996
  id: (prop_types_default()).string.isRequired,
4251
- type: prop_types_default().oneOf(['tool', 'action', 'toggle']).isRequired,
4252
4997
  icon: (prop_types_default()).string,
4253
4998
  label: (prop_types_default()).string,
4254
- tooltip: (prop_types_default()).string
4999
+ tooltip: (prop_types_default()).string,
5000
+ disabled: (prop_types_default()).bool,
5001
+ className: (prop_types_default()).string
4255
5002
  })),
4256
5003
  renderer: (prop_types_default()).func,
4257
5004
  onInteraction: (prop_types_default()).func.isRequired,
@@ -4266,108 +5013,194 @@ ToolbarSplitButtonWithServices.defaultProps = {
4266
5013
  isAction: false
4267
5014
  };
4268
5015
  /* 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
- });
5016
+ ;// CONCATENATED MODULE: ../../../extensions/default/src/Toolbar/ToolbarButtonGroupWithServices.tsx
5017
+
5018
+
5019
+ function ToolbarButtonGroupWithServices({
5020
+ groupId,
5021
+ items,
5022
+ onInteraction,
5023
+ size
5024
+ }) {
5025
+ const getSplitButtonItems = (0,react.useCallback)(items => items.map((item, index) => /*#__PURE__*/react.createElement(ui_src/* ToolbarButton */.IB, {
5026
+ key: item.id,
5027
+ icon: item.icon,
5028
+ label: item.label,
5029
+ disabled: item.disabled,
5030
+ className: item.className,
5031
+ id: item.id,
5032
+ size: size,
5033
+ onClick: () => {
5034
+ onInteraction({
5035
+ groupId,
5036
+ itemId: item.id,
5037
+ commands: item.commands
5038
+ });
5039
+ }
5040
+ // Note: this is necessary since tooltip will add
5041
+ // default styles to the tooltip container which
5042
+ // we don't want for groups
5043
+ ,
5044
+ toolTipClassName: ""
5045
+ })), [onInteraction, groupId]);
5046
+ return /*#__PURE__*/react.createElement(ui_src/* ButtonGroup */.e2, null, getSplitButtonItems(items));
5047
+ }
5048
+ /* harmony default export */ const Toolbar_ToolbarButtonGroupWithServices = (ToolbarButtonGroupWithServices);
5049
+ ;// CONCATENATED MODULE: ../../../extensions/default/src/components/ProgressDropdownWithService/ProgressDropdownWithService.tsx
5050
+
5051
+
5052
+ const workflowStepsToDropdownOptions = (steps = []) => steps.map(step => ({
5053
+ label: step.name,
5054
+ value: step.id,
5055
+ info: step.info,
5056
+ activated: false,
5057
+ completed: false
5058
+ }));
5059
+ function ProgressDropdownWithService({
5060
+ servicesManager
5061
+ }) {
4291
5062
  const {
4292
- primaryToolId
4293
- } = buttonsState;
4294
- const isActive = type === 'tool' && id === primaryToolId || type === 'toggle' && buttonsState.toggles[id] === true;
5063
+ workflowStepsService
5064
+ } = servicesManager.services;
5065
+ const [activeStepId, setActiveStepId] = (0,react.useState)(workflowStepsService.activeWorkflowStep?.id);
5066
+ const [dropdownOptions, setDropdownOptions] = (0,react.useState)(workflowStepsToDropdownOptions(workflowStepsService.workflowSteps));
5067
+ const setCurrentAndPreviousOptionsAsCompleted = (0,react.useCallback)(currentOption => {
5068
+ if (currentOption.completed) {
5069
+ return;
5070
+ }
5071
+ setDropdownOptions(prevOptions => {
5072
+ const newOptionsState = [...prevOptions];
5073
+ const startIndex = newOptionsState.findIndex(option => option.value === currentOption.value);
5074
+ for (let i = startIndex; i >= 0; i--) {
5075
+ const option = newOptionsState[i];
5076
+ if (option.completed) {
5077
+ break;
5078
+ }
5079
+ newOptionsState[i] = {
5080
+ ...option,
5081
+ completed: true
5082
+ };
5083
+ }
5084
+ return newOptionsState;
5085
+ });
5086
+ }, []);
5087
+ const handleDropdownChange = (0,react.useCallback)(({
5088
+ selectedOption
5089
+ }) => {
5090
+ if (!selectedOption) {
5091
+ return;
5092
+ }
5093
+
5094
+ // TODO: Steps should be marked as completed after user has
5095
+ // completed some action when required (not implemented)
5096
+ setCurrentAndPreviousOptionsAsCompleted(selectedOption);
5097
+ setActiveStepId(selectedOption.value);
5098
+ }, [setCurrentAndPreviousOptionsAsCompleted]);
5099
+ (0,react.useEffect)(() => {
5100
+ let timeoutId;
5101
+ if (activeStepId) {
5102
+ // We've used setTimeout to give it more time to update the UI since
5103
+ // create3DFilterableFromDataArray from Texture.js may take 600+ ms to run
5104
+ // when there is a new series to load in the next step but that resulted
5105
+ // in the followed React error when updating the content from left/right panels
5106
+ // and all component states were being lost:
5107
+ // Error: Can't perform a React state update on an unmounted component
5108
+ workflowStepsService.setActiveWorkflowStep(activeStepId);
5109
+ }
5110
+ return () => clearTimeout(timeoutId);
5111
+ }, [activeStepId, workflowStepsService]);
4295
5112
  (0,react.useEffect)(() => {
4296
5113
  const {
4297
- unsubscribe
4298
- } = toolbarService.subscribe(toolbarService.EVENTS.TOOL_BAR_STATE_MODIFIED, state => {
4299
- setButtonState({
4300
- ...state
4301
- });
4302
- });
5114
+ unsubscribe: unsubStepsChanged
5115
+ } = workflowStepsService.subscribe(workflowStepsService.EVENTS.STEPS_CHANGED, () => setDropdownOptions(workflowStepsToDropdownOptions(workflowStepsService.workflowSteps)));
5116
+ const {
5117
+ unsubscribe: unsubActiveStepChanged
5118
+ } = workflowStepsService.subscribe(workflowStepsService.EVENTS.ACTIVE_STEP_CHANGED, () => setActiveStepId(workflowStepsService.activeWorkflowStep.id));
4303
5119
  return () => {
4304
- unsubscribe();
5120
+ unsubStepsChanged();
5121
+ unsubActiveStepChanged();
4305
5122
  };
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));
5123
+ }, [servicesManager, workflowStepsService]);
5124
+ return /*#__PURE__*/react.createElement(ui_src/* ProgressDropdown */.LW, {
5125
+ options: dropdownOptions,
5126
+ value: activeStepId,
5127
+ onChange: handleDropdownChange
5128
+ });
4314
5129
  }
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);
5130
+ /* harmony default export */ const ProgressDropdownWithService_ProgressDropdownWithService = (ProgressDropdownWithService);
5131
+ ;// CONCATENATED MODULE: ../../../extensions/default/src/components/ProgressDropdownWithService/index.js
5132
+
4337
5133
  ;// CONCATENATED MODULE: ../../../extensions/default/src/getToolbarModule.tsx
4338
5134
 
4339
5135
 
4340
5136
 
4341
5137
 
4342
- function getToolbarModule(_ref) {
4343
- let {
4344
- commandsManager,
4345
- servicesManager
4346
- } = _ref;
5138
+
5139
+
5140
+ const getClassName = isToggled => {
5141
+ return {
5142
+ className: isToggled ? '!text-primary-active' : '!text-common-bright hover:!bg-primary-dark hover:text-primary-light'
5143
+ };
5144
+ };
5145
+ function getToolbarModule({
5146
+ commandsManager,
5147
+ servicesManager
5148
+ }) {
5149
+ const {
5150
+ cineService
5151
+ } = servicesManager.services;
4347
5152
  return [{
4348
- name: 'ohif.divider',
4349
- defaultComponent: ToolbarDivider,
4350
- clickHandler: () => {}
4351
- }, {
4352
- name: 'ohif.action',
4353
- defaultComponent: Toolbar_ToolbarButtonWithServices,
4354
- clickHandler: () => {}
4355
- }, {
4356
5153
  name: 'ohif.radioGroup',
4357
- defaultComponent: Toolbar_ToolbarButtonWithServices,
4358
- clickHandler: () => {}
5154
+ defaultComponent: ui_src/* ToolbarButton */.IB
5155
+ }, {
5156
+ name: 'ohif.divider',
5157
+ defaultComponent: ToolbarDivider
4359
5158
  }, {
4360
5159
  name: 'ohif.splitButton',
4361
- defaultComponent: Toolbar_ToolbarSplitButtonWithServices,
4362
- clickHandler: () => {}
5160
+ defaultComponent: Toolbar_ToolbarSplitButtonWithServices
4363
5161
  }, {
4364
5162
  name: 'ohif.layoutSelector',
4365
- defaultComponent: ToolbarLayoutSelector,
4366
- clickHandler: (evt, clickedBtn, btnSectionName) => {}
5163
+ defaultComponent: props => ToolbarLayoutSelector({
5164
+ ...props,
5165
+ commandsManager,
5166
+ servicesManager
5167
+ })
5168
+ }, {
5169
+ name: 'ohif.buttonGroup',
5170
+ defaultComponent: Toolbar_ToolbarButtonGroupWithServices
5171
+ }, {
5172
+ name: 'ohif.progressDropdown',
5173
+ defaultComponent: ProgressDropdownWithService_ProgressDropdownWithService
4367
5174
  }, {
4368
- name: 'ohif.toggle',
4369
- defaultComponent: Toolbar_ToolbarButtonWithServices,
4370
- clickHandler: () => {}
5175
+ name: 'evaluate.group.promoteToPrimary',
5176
+ evaluate: ({
5177
+ viewportId,
5178
+ button,
5179
+ itemId
5180
+ }) => {
5181
+ const {
5182
+ items
5183
+ } = button.props;
5184
+ if (!itemId) {
5185
+ return {
5186
+ primary: button.props.primary,
5187
+ items
5188
+ };
5189
+ }
5190
+
5191
+ // other wise we can move the clicked tool to the primary button
5192
+ const clickedItemProps = items.find(item => item.id === itemId || item.itemId === itemId);
5193
+ return {
5194
+ primary: clickedItemProps,
5195
+ items
5196
+ };
5197
+ }
5198
+ }, {
5199
+ name: 'evaluate.cine',
5200
+ evaluate: () => {
5201
+ const isToggled = cineService.getState().isCineEnabled;
5202
+ return getClassName(isToggled);
5203
+ }
4371
5204
  }];
4372
5205
  }
4373
5206
  ;// CONCATENATED MODULE: ../../../extensions/default/src/CustomizableContextMenu/ContextMenuItemsBuilder.ts
@@ -4433,7 +5266,6 @@ function findMenu(menus, props, menuIdFilter) {
4433
5266
  }
4434
5267
  current = findIt.next();
4435
5268
  }
4436
- console.log('Menu chosen', menu?.id || 'NONE');
4437
5269
  return menu;
4438
5270
  }
4439
5271
 
@@ -4536,8 +5368,12 @@ function adaptItem(item, subProps) {
4536
5368
  return newItem;
4537
5369
  }
4538
5370
  // EXTERNAL MODULE: ../../ui/src/components/ContextMenu/ContextMenu.tsx
4539
- var ContextMenu = __webpack_require__(5638);
5371
+ var ContextMenu = __webpack_require__(59852);
5372
+ // EXTERNAL MODULE: ../../../node_modules/@cornerstonejs/tools/dist/esm/index.js + 18 modules
5373
+ var dist_esm = __webpack_require__(24542);
4540
5374
  ;// CONCATENATED MODULE: ../../../extensions/default/src/CustomizableContextMenu/ContextMenuController.tsx
5375
+ var _ContextMenuController;
5376
+
4541
5377
 
4542
5378
 
4543
5379
  /**
@@ -4584,7 +5420,16 @@ class ContextMenuController {
4584
5420
  menus,
4585
5421
  selectorProps
4586
5422
  } = contextMenuProps;
4587
- console.log('Getting items from', menus);
5423
+ const annotationManager = dist_esm.annotation.state.getAnnotationManager();
5424
+ const {
5425
+ locking
5426
+ } = dist_esm.annotation;
5427
+ const targetAnnotationId = selectorProps?.nearbyToolData?.annotationUID;
5428
+ const isLocked = locking.isAnnotationLocked(annotationManager.getAnnotation(targetAnnotationId));
5429
+ if (isLocked) {
5430
+ console.warn('Annotation is locked.');
5431
+ return;
5432
+ }
4588
5433
  const items = getMenuItems(selectorProps || contextMenuProps, event, menus, menuId);
4589
5434
  this.services.uiDialogService.dismiss({
4590
5435
  id: 'context-menu'
@@ -4596,7 +5441,7 @@ class ContextMenuController {
4596
5441
  preventCutOf: true,
4597
5442
  defaultPosition: ContextMenuController._getDefaultPosition(defaultPointsPosition, event?.detail, viewportElement),
4598
5443
  event,
4599
- content: ContextMenu/* default */.Z,
5444
+ content: ContextMenu/* default */.A,
4600
5445
  // This naming is part of the uiDialogService convention
4601
5446
  // Clicking outside simply closes the dialog box.
4602
5447
  onClickOutside: () => this.services.uiDialogService.dismiss({
@@ -4642,6 +5487,7 @@ class ContextMenuController {
4642
5487
  });
4643
5488
  }
4644
5489
  }
5490
+ _ContextMenuController = ContextMenuController;
4645
5491
  ContextMenuController.getDefaultPosition = () => {
4646
5492
  return {
4647
5493
  x: 0,
@@ -4665,16 +5511,14 @@ ContextMenuController._getElementDefaultPosition = element => {
4665
5511
  y: undefined
4666
5512
  };
4667
5513
  };
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);
5514
+ ContextMenuController._getCanvasPointsPosition = (points = [], element) => {
5515
+ const viewerPos = _ContextMenuController._getElementDefaultPosition(element);
4672
5516
  for (let pointIndex = 0; pointIndex < points.length; pointIndex++) {
4673
5517
  const point = {
4674
5518
  x: points[pointIndex][0] || points[pointIndex]['x'],
4675
5519
  y: points[pointIndex][1] || points[pointIndex]['y']
4676
5520
  };
4677
- if (ContextMenuController._isValidPosition(point) && ContextMenuController._isValidPosition(viewerPos)) {
5521
+ if (_ContextMenuController._isValidPosition(point) && _ContextMenuController._isValidPosition(viewerPos)) {
4678
5522
  return {
4679
5523
  x: point.x + viewerPos.x,
4680
5524
  y: point.y + viewerPos.y
@@ -4690,17 +5534,17 @@ ContextMenuController._isValidPosition = source => {
4690
5534
  */
4691
5535
  ContextMenuController._getDefaultPosition = (canvasPoints, eventDetail, viewerElement) => {
4692
5536
  function* getPositionIterator() {
4693
- yield ContextMenuController._getCanvasPointsPosition(canvasPoints, viewerElement);
4694
- yield ContextMenuController._getEventDefaultPosition(eventDetail);
4695
- yield ContextMenuController._getElementDefaultPosition(viewerElement);
4696
- yield ContextMenuController.getDefaultPosition();
5537
+ yield _ContextMenuController._getCanvasPointsPosition(canvasPoints, viewerElement);
5538
+ yield _ContextMenuController._getEventDefaultPosition(eventDetail);
5539
+ yield _ContextMenuController._getElementDefaultPosition(viewerElement);
5540
+ yield _ContextMenuController.getDefaultPosition();
4697
5541
  }
4698
5542
  const positionIterator = getPositionIterator();
4699
5543
  let current = positionIterator.next();
4700
5544
  let position = current.value;
4701
5545
  while (!current.done) {
4702
5546
  position = current.value;
4703
- if (ContextMenuController._isValidPosition(position)) {
5547
+ if (_ContextMenuController._isValidPosition(position)) {
4704
5548
  positionIterator.return();
4705
5549
  }
4706
5550
  current = positionIterator.next();
@@ -4715,16 +5559,16 @@ const defaultContextMenu = {
4715
5559
  // Get the items from the UI Customization for the menu name (and have a custom name)
4716
5560
  {
4717
5561
  id: 'forExistingMeasurement',
4718
- selector: _ref => {
4719
- let {
4720
- nearbyToolData
4721
- } = _ref;
4722
- return !!nearbyToolData;
4723
- },
5562
+ selector: ({
5563
+ nearbyToolData
5564
+ }) => !!nearbyToolData,
4724
5565
  items: [{
4725
5566
  label: 'Delete measurement',
4726
5567
  commands: [{
4727
- commandName: 'deleteMeasurement'
5568
+ commandName: 'deleteMeasurement',
5569
+ // we only have support for cornerstoneTools context menu since
5570
+ // they are svg based
5571
+ context: 'CORNERSTONE'
4728
5572
  }]
4729
5573
  }, {
4730
5574
  label: 'Add Label',
@@ -4745,10 +5589,13 @@ const defaultContextMenu = {
4745
5589
 
4746
5590
 
4747
5591
  // EXTERNAL MODULE: ../../../node_modules/moment/moment.js
4748
- var moment = __webpack_require__(71271);
5592
+ var moment = __webpack_require__(8291);
4749
5593
  var moment_default = /*#__PURE__*/__webpack_require__.n(moment);
4750
5594
  // EXTERNAL MODULE: ../../../node_modules/react-window/dist/index.esm.js
4751
- var index_esm = __webpack_require__(94614);
5595
+ var index_esm = __webpack_require__(6943);
5596
+ // EXTERNAL MODULE: ../../../node_modules/classnames/index.js
5597
+ var classnames = __webpack_require__(61466);
5598
+ var classnames_default = /*#__PURE__*/__webpack_require__.n(classnames);
4752
5599
  ;// CONCATENATED MODULE: ../../../extensions/default/src/DicomTagBrowser/DicomTagTable.tsx
4753
5600
 
4754
5601
 
@@ -4765,13 +5612,12 @@ const rowStyle = {
4765
5612
  borderBottomWidth: `${rowBottomBorderPx}px`,
4766
5613
  ...rowVerticalPaddingStyle
4767
5614
  };
4768
- function ColumnHeaders(_ref) {
4769
- let {
4770
- tagRef,
4771
- vrRef,
4772
- keywordRef,
4773
- valueRef
4774
- } = _ref;
5615
+ function ColumnHeaders({
5616
+ tagRef,
5617
+ vrRef,
5618
+ keywordRef,
5619
+ valueRef
5620
+ }) {
4775
5621
  return /*#__PURE__*/react.createElement("div", {
4776
5622
  className: classnames_default()('bg-secondary-dark ohif-scrollbar flex w-full flex-row overflow-y-scroll'),
4777
5623
  style: rowVerticalPaddingStyle
@@ -4805,10 +5651,9 @@ function ColumnHeaders(_ref) {
4805
5651
  className: "flex flex-row items-center focus:outline-none"
4806
5652
  }, "Value"))));
4807
5653
  }
4808
- function DicomTagTable(_ref2) {
4809
- let {
4810
- rows
4811
- } = _ref2;
5654
+ function DicomTagTable({
5655
+ rows
5656
+ }) {
4812
5657
  const listRef = (0,react.useRef)();
4813
5658
  const canvasRef = (0,react.useRef)();
4814
5659
  const [tagHeaderElem, setTagHeaderElem] = (0,react.useState)(null);
@@ -4862,11 +5707,10 @@ function DicomTagTable(_ref2) {
4862
5707
  window.removeEventListener('resize', debouncedResize);
4863
5708
  };
4864
5709
  }, []);
4865
- const Row = (0,react.useCallback)(_ref3 => {
4866
- let {
4867
- index,
4868
- style
4869
- } = _ref3;
5710
+ const Row = (0,react.useCallback)(({
5711
+ index,
5712
+ style
5713
+ }) => {
4870
5714
  const row = rows[index];
4871
5715
  return /*#__PURE__*/react.createElement("div", {
4872
5716
  style: {
@@ -4924,7 +5768,7 @@ function DicomTagTable(_ref2) {
4924
5768
  style: {
4925
5769
  height: '32rem'
4926
5770
  }
4927
- }, isHeaderRendered() && /*#__PURE__*/react.createElement(index_esm/* VariableSizeList */.S_, {
5771
+ }, isHeaderRendered() && /*#__PURE__*/react.createElement(index_esm/* VariableSizeList */._m, {
4928
5772
  ref: listRef,
4929
5773
  height: 500,
4930
5774
  itemCount: rows.length,
@@ -4951,15 +5795,14 @@ const {
4951
5795
  } = src.classes;
4952
5796
  const {
4953
5797
  DicomMetaDictionary: DicomTagBrowser_DicomMetaDictionary
4954
- } = dcmjs_es["default"].data;
5798
+ } = dcmjs_es/* default.data */.Ay.data;
4955
5799
  const {
4956
5800
  nameMap
4957
5801
  } = DicomTagBrowser_DicomMetaDictionary;
4958
- const DicomTagBrowser = _ref => {
4959
- let {
4960
- displaySets,
4961
- displaySetInstanceUID
4962
- } = _ref;
5802
+ const DicomTagBrowser = ({
5803
+ displaySets,
5804
+ displaySetInstanceUID
5805
+ }) => {
4963
5806
  // The column indices that are to be excluded during a filter of the table.
4964
5807
  // At present the column indices are:
4965
5808
  // 0: DICOM tag
@@ -5042,12 +5885,12 @@ const DicomTagBrowser = _ref => {
5042
5885
  className: "mb-6 flex flex-row items-center pl-1"
5043
5886
  }, /*#__PURE__*/react.createElement("div", {
5044
5887
  className: "flex w-1/2 flex-row items-center"
5045
- }, /*#__PURE__*/react.createElement(ui_src/* Typography */.ZT, {
5888
+ }, /*#__PURE__*/react.createElement(ui_src/* Typography */.o5, {
5046
5889
  variant: "subtitle",
5047
5890
  className: "mr-4"
5048
5891
  }, "Series"), /*#__PURE__*/react.createElement("div", {
5049
5892
  className: "mr-8 grow"
5050
- }, /*#__PURE__*/react.createElement(ui_src/* Select */.Ph, {
5893
+ }, /*#__PURE__*/react.createElement(ui_src/* Select */.l6, {
5051
5894
  id: "display-set-selector",
5052
5895
  isClearable: false,
5053
5896
  onChange: onSelectChange,
@@ -5056,12 +5899,12 @@ const DicomTagBrowser = _ref => {
5056
5899
  className: "text-white"
5057
5900
  }))), /*#__PURE__*/react.createElement("div", {
5058
5901
  className: "flex w-1/2 flex-row items-center"
5059
- }, showInstanceList && /*#__PURE__*/react.createElement(ui_src/* Typography */.ZT, {
5902
+ }, showInstanceList && /*#__PURE__*/react.createElement(ui_src/* Typography */.o5, {
5060
5903
  variant: "subtitle",
5061
5904
  className: "mr-4"
5062
5905
  }, "Instance Number"), showInstanceList && /*#__PURE__*/react.createElement("div", {
5063
5906
  className: "grow"
5064
- }, /*#__PURE__*/react.createElement(ui_src/* InputRange */.OX, {
5907
+ }, /*#__PURE__*/react.createElement(ui_src/* InputRange */.Qr, {
5065
5908
  value: instanceNumber,
5066
5909
  key: selectedDisplaySetInstanceUID,
5067
5910
  onChange: value => {
@@ -5077,7 +5920,7 @@ const DicomTagBrowser = _ref => {
5077
5920
  className: "h-1 w-full bg-black"
5078
5921
  }), /*#__PURE__*/react.createElement("div", {
5079
5922
  className: "my-3 flex w-1/2 flex-row"
5080
- }, /*#__PURE__*/react.createElement(ui_src/* InputFilterText */.Xe, {
5923
+ }, /*#__PURE__*/react.createElement(ui_src/* InputFilterText */.Cv, {
5081
5924
  className: "mr-8 block w-full",
5082
5925
  placeholder: "Search metadata...",
5083
5926
  onDebounceChange: setFilterValue
@@ -5101,7 +5944,7 @@ function getFormattedRowsFromTags(tags, metadata) {
5101
5944
  } else {
5102
5945
  if (tagInfo.vr === 'xs') {
5103
5946
  try {
5104
- const tag = dcmjs_es["default"].data.Tag.fromPString(tagInfo.tag).toCleanString();
5947
+ const tag = dcmjs_es/* default.data */.Ay.data.Tag.fromPString(tagInfo.tag).toCleanString();
5105
5948
  const originalTagInfo = metadata[tag];
5106
5949
  tagInfo.vr = originalTagInfo.vr;
5107
5950
  } catch (error) {
@@ -5120,8 +5963,7 @@ function getSortedTags(metadata) {
5120
5963
  _sortTagList(tagList);
5121
5964
  return tagList;
5122
5965
  }
5123
- function getRows(metadata) {
5124
- let depth = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : 0;
5966
+ function getRows(metadata, depth = 0) {
5125
5967
  // Tag, Type, Value, Keyword
5126
5968
 
5127
5969
  const keywords = Object.keys(metadata);
@@ -5132,7 +5974,6 @@ function getRows(metadata) {
5132
5974
  if (depth > 0) {
5133
5975
  tagIndent += ' '; // If indented, add a space after the indents.
5134
5976
  }
5135
-
5136
5977
  const rows = [];
5137
5978
  for (let i = 0; i < keywords.length; i++) {
5138
5979
  let keyword = keywords[i];
@@ -5259,6 +6100,9 @@ const reuseCachedLayout = (state, hangingProtocolService, syncService) => {
5259
6100
  const {
5260
6101
  protocol
5261
6102
  } = hangingProtocolService.getActiveProtocol();
6103
+ if (!protocol) {
6104
+ return;
6105
+ }
5262
6106
  const hpInfo = hangingProtocolService.getState();
5263
6107
  const {
5264
6108
  protocolId,
@@ -5361,6 +6205,13 @@ const findViewportsByPosition_findOrCreateViewport = (hangingProtocolService, vi
5361
6205
  }
5362
6206
  };
5363
6207
  }
6208
+
6209
+ // and lastly if there is no default viewport, then we see if we can grab the
6210
+ // viewportsByPosition at the position index and use that
6211
+ // const candidate = Object.values(viewportsByPosition)[position];
6212
+
6213
+ // // if it has something to display, then we can use it
6214
+ // return candidate?.displaySetInstanceUIDs ? candidate : {};
5364
6215
  return {};
5365
6216
  };
5366
6217
 
@@ -5373,11 +6224,10 @@ const findViewportsByPosition_findOrCreateViewport = (hangingProtocolService, vi
5373
6224
  * @returns Set of states that can be applied to the state sync to remember
5374
6225
  * the current view state.
5375
6226
  */
5376
- const findViewportsByPosition = (state, _ref, syncService) => {
5377
- let {
5378
- numRows,
5379
- numCols
5380
- } = _ref;
6227
+ const findViewportsByPosition = (state, {
6228
+ numRows,
6229
+ numCols
6230
+ }, syncService) => {
5381
6231
  const {
5382
6232
  viewports
5383
6233
  } = state;
@@ -5414,8 +6264,8 @@ const findViewportsByPosition = (state, _ref, syncService) => {
5414
6264
  };
5415
6265
  };
5416
6266
  /* harmony default export */ const src_findViewportsByPosition = (findViewportsByPosition);
5417
- // EXTERNAL MODULE: ./index.js + 33 modules
5418
- var index = __webpack_require__(59754);
6267
+ // EXTERNAL MODULE: ./index.js + 35 modules
6268
+ var index = __webpack_require__(68870);
5419
6269
  ;// CONCATENATED MODULE: ../../../extensions/default/src/commandsModule.ts
5420
6270
 
5421
6271
 
@@ -5426,17 +6276,10 @@ var index = __webpack_require__(59754);
5426
6276
  const {
5427
6277
  subscribeToNextViewportGridChange
5428
6278
  } = 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;
6279
+ const commandsModule = ({
6280
+ servicesManager,
6281
+ commandsManager
6282
+ }) => {
5440
6283
  const {
5441
6284
  customizationService,
5442
6285
  measurementService,
@@ -5444,8 +6287,7 @@ const commandsModule = _ref => {
5444
6287
  uiNotificationService,
5445
6288
  viewportGridService,
5446
6289
  displaySetService,
5447
- stateSyncService,
5448
- toolbarService
6290
+ stateSyncService
5449
6291
  } = servicesManager.services;
5450
6292
 
5451
6293
  // Define a context menu controller for use with any context menus
@@ -5491,12 +6333,11 @@ const commandsModule = _ref => {
5491
6333
  closeContextMenu: () => {
5492
6334
  contextMenuController.closeContextMenu();
5493
6335
  },
5494
- displayNotification: _ref2 => {
5495
- let {
5496
- text,
5497
- title,
5498
- type
5499
- } = _ref2;
6336
+ displayNotification: ({
6337
+ text,
6338
+ title,
6339
+ type
6340
+ }) => {
5500
6341
  uiNotificationService.show({
5501
6342
  title: title,
5502
6343
  message: text,
@@ -5506,41 +6347,6 @@ const commandsModule = _ref => {
5506
6347
  clearMeasurements: () => {
5507
6348
  measurementService.clear();
5508
6349
  },
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
6350
  /**
5545
6351
  * Sets the specified protocol
5546
6352
  * 1. Records any existing state using the viewport grid service
@@ -5565,24 +6371,19 @@ const commandsModule = _ref => {
5565
6371
  * @param options.stageIndex - the index of the stage to go to.
5566
6372
  * @param options.reset - flag to indicate if the HP should be reset to its original and not restored to a previous state
5567
6373
  */
5568
- setHangingProtocol: _ref3 => {
5569
- let {
5570
- activeStudyUID = '',
5571
- protocolId,
5572
- stageId,
5573
- stageIndex,
5574
- reset = false
5575
- } = _ref3;
5576
- const primaryToolBeforeHPChange = toolbarService.getActivePrimaryTool();
6374
+ setHangingProtocol: ({
6375
+ activeStudyUID = '',
6376
+ protocolId,
6377
+ stageId,
6378
+ stageIndex,
6379
+ reset = false
6380
+ }) => {
5577
6381
  try {
5578
6382
  // Stores in the state the display set selector id to displaySetUID mapping
5579
6383
  // Pass in viewportId for the active viewport. This item will get set as
5580
6384
  // the activeViewportId
5581
6385
  const state = viewportGridService.getState();
5582
6386
  const hpInfo = hangingProtocolService.getState();
5583
- const {
5584
- protocol: oldProtocol
5585
- } = hangingProtocolService.getActiveProtocol();
5586
6387
  const stateSyncReduce = reuseCachedLayouts(state, hangingProtocolService, stateSyncService);
5587
6388
  const {
5588
6389
  hangingProtocolStageIndexMap,
@@ -5632,45 +6433,9 @@ const commandsModule = _ref => {
5632
6433
  // multi-study display.
5633
6434
  delete displaySetSelectorMap[`${activeStudyUID || hpInfo.activeStudyUID}:activeDisplaySet:0`];
5634
6435
  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
6436
  return true;
5671
6437
  } catch (e) {
5672
6438
  console.error(e);
5673
- actions.toggleHpTools();
5674
6439
  uiNotificationService.show({
5675
6440
  title: 'Apply Hanging Protocol',
5676
6441
  message: 'The hanging protocol could not be applied.',
@@ -5680,11 +6445,10 @@ const commandsModule = _ref => {
5680
6445
  return false;
5681
6446
  }
5682
6447
  },
5683
- toggleHangingProtocol: _ref4 => {
5684
- let {
5685
- protocolId,
5686
- stageIndex
5687
- } = _ref4;
6448
+ toggleHangingProtocol: ({
6449
+ protocolId,
6450
+ stageIndex
6451
+ }) => {
5688
6452
  const {
5689
6453
  protocol,
5690
6454
  stageIndex: desiredStageIndex,
@@ -5717,10 +6481,9 @@ const commandsModule = _ref => {
5717
6481
  });
5718
6482
  }
5719
6483
  },
5720
- deltaStage: _ref5 => {
5721
- let {
5722
- direction
5723
- } = _ref5;
6484
+ deltaStage: ({
6485
+ direction
6486
+ }) => {
5724
6487
  const {
5725
6488
  protocolId,
5726
6489
  stageIndex: oldStageIndex
@@ -5746,11 +6509,11 @@ const commandsModule = _ref => {
5746
6509
  /**
5747
6510
  * Changes the viewport grid layout in terms of the MxN layout.
5748
6511
  */
5749
- setViewportGridLayout: _ref6 => {
5750
- let {
5751
- numRows,
5752
- numCols
5753
- } = _ref6;
6512
+ setViewportGridLayout: ({
6513
+ numRows,
6514
+ numCols,
6515
+ isHangingProtocolLayout = false
6516
+ }) => {
5754
6517
  const {
5755
6518
  protocol
5756
6519
  } = hangingProtocolService.getActiveProtocol();
@@ -5773,7 +6536,8 @@ const commandsModule = _ref => {
5773
6536
  viewportGridService.setLayout({
5774
6537
  numRows,
5775
6538
  numCols,
5776
- findOrCreateViewport
6539
+ findOrCreateViewport,
6540
+ isHangingProtocolLayout
5777
6541
  });
5778
6542
  stateSyncService.store(stateReduce);
5779
6543
  };
@@ -5838,7 +6602,8 @@ const commandsModule = _ref => {
5838
6602
  numCols: toggleOneUpViewportGridStore.layout.numCols,
5839
6603
  activeViewportId: viewportIdToUpdate,
5840
6604
  layoutOptions,
5841
- findOrCreateViewport
6605
+ findOrCreateViewport,
6606
+ isHangingProtocolLayout: true
5842
6607
  });
5843
6608
  } else {
5844
6609
  // We are not in one-up, so toggle to one up.
@@ -5862,7 +6627,8 @@ const commandsModule = _ref => {
5862
6627
  viewportGridService.setLayout({
5863
6628
  numRows: 1,
5864
6629
  numCols: 1,
5865
- findOrCreateViewport
6630
+ findOrCreateViewport,
6631
+ isHangingProtocolLayout: true
5866
6632
  });
5867
6633
 
5868
6634
  // Subscribe to ANY (i.e. manual and hanging protocol) layout changes so that
@@ -5897,7 +6663,7 @@ const commandsModule = _ref => {
5897
6663
  * for `replace` is false
5898
6664
  */
5899
6665
  navigateHistory(historyArgs) {
5900
- index/* history */.m.navigate(historyArgs.to, historyArgs.options);
6666
+ index/* history */.b.navigate(historyArgs.to, historyArgs.options);
5901
6667
  },
5902
6668
  openDICOMTagViewer() {
5903
6669
  const {
@@ -5920,6 +6686,7 @@ const commandsModule = _ref => {
5920
6686
  displaySetInstanceUID,
5921
6687
  onClose: UIModalService.hide
5922
6688
  },
6689
+ containerDimensions: 'max-w-4xl max-h-4xl',
5923
6690
  title: 'DICOM Tag Browser'
5924
6691
  });
5925
6692
  },
@@ -5960,11 +6727,10 @@ const commandsModule = _ref => {
5960
6727
  behavior: 'smooth'
5961
6728
  });
5962
6729
  },
5963
- updateViewportDisplaySet: _ref7 => {
5964
- let {
5965
- direction,
5966
- excludeNonImageModalities
5967
- } = _ref7;
6730
+ updateViewportDisplaySet: ({
6731
+ direction,
6732
+ excludeNonImageModalities
6733
+ }) => {
5968
6734
  const nonImageModalities = ['SR', 'SEG', 'SM', 'RTSTRUCT', 'RTPLAN', 'RTDOSE'];
5969
6735
 
5970
6736
  // Sort the display sets as per the hanging protocol service viewport/display set scoring system.
@@ -6016,61 +6782,43 @@ const commandsModule = _ref => {
6016
6782
  commandFn: actions.closeContextMenu
6017
6783
  },
6018
6784
  clearMeasurements: {
6019
- commandFn: actions.clearMeasurements,
6020
- storeContexts: [],
6021
- options: {}
6785
+ commandFn: actions.clearMeasurements
6022
6786
  },
6023
6787
  displayNotification: {
6024
- commandFn: actions.displayNotification,
6025
- storeContexts: [],
6026
- options: {}
6788
+ commandFn: actions.displayNotification
6027
6789
  },
6028
6790
  setHangingProtocol: {
6029
- commandFn: actions.setHangingProtocol,
6030
- storeContexts: [],
6031
- options: {}
6791
+ commandFn: actions.setHangingProtocol
6032
6792
  },
6033
6793
  toggleHangingProtocol: {
6034
- commandFn: actions.toggleHangingProtocol,
6035
- storeContexts: [],
6036
- options: {}
6794
+ commandFn: actions.toggleHangingProtocol
6037
6795
  },
6038
6796
  navigateHistory: {
6039
- commandFn: actions.navigateHistory,
6040
- storeContexts: [],
6041
- options: {}
6797
+ commandFn: actions.navigateHistory
6042
6798
  },
6043
6799
  nextStage: {
6044
6800
  commandFn: actions.deltaStage,
6045
- storeContexts: [],
6046
6801
  options: {
6047
6802
  direction: 1
6048
6803
  }
6049
6804
  },
6050
6805
  previousStage: {
6051
6806
  commandFn: actions.deltaStage,
6052
- storeContexts: [],
6053
6807
  options: {
6054
6808
  direction: -1
6055
6809
  }
6056
6810
  },
6057
6811
  setViewportGridLayout: {
6058
- commandFn: actions.setViewportGridLayout,
6059
- storeContexts: [],
6060
- options: {}
6812
+ commandFn: actions.setViewportGridLayout
6061
6813
  },
6062
6814
  toggleOneUp: {
6063
- commandFn: actions.toggleOneUp,
6064
- storeContexts: [],
6065
- options: {}
6815
+ commandFn: actions.toggleOneUp
6066
6816
  },
6067
6817
  openDICOMTagViewer: {
6068
6818
  commandFn: actions.openDICOMTagViewer
6069
6819
  },
6070
6820
  updateViewportDisplaySet: {
6071
- commandFn: actions.updateViewportDisplaySet,
6072
- storeContexts: [],
6073
- options: {}
6821
+ commandFn: actions.updateViewportDisplaySet
6074
6822
  }
6075
6823
  };
6076
6824
  return {
@@ -6480,6 +7228,9 @@ const defaultProtocol = {
6480
7228
  editableBy: {},
6481
7229
  protocolMatchingRules: [],
6482
7230
  toolGroupIds: ['default'],
7231
+ hpInitiationCriteria: {
7232
+ minSeriesLoaded: 1
7233
+ },
6483
7234
  // -1 would be used to indicate active only, whereas other values are
6484
7235
  // the number of required priors referenced - so 0 means active with
6485
7236
  // 0 or more priors.
@@ -6524,7 +7275,6 @@ const defaultProtocol = {
6524
7275
  // studyMatchingRules: [],
6525
7276
  }
6526
7277
  },
6527
-
6528
7278
  stages: [{
6529
7279
  name: 'default',
6530
7280
  viewportStructure: {
@@ -6550,7 +7300,6 @@ const defaultProtocol = {
6550
7300
  // preset: 'middle', // 'first', 'last', 'middle'
6551
7301
  // },
6552
7302
  },
6553
-
6554
7303
  displaySets: [{
6555
7304
  id: 'defaultDisplaySetId'
6556
7305
  }]
@@ -6582,8 +7331,8 @@ function getHangingProtocolModule() {
6582
7331
 
6583
7332
 
6584
7333
  function DataSourceSelector() {
6585
- const [appConfig] = (0,state/* useAppConfig */.M)();
6586
- const navigate = (0,dist/* useNavigate */.s0)();
7334
+ const [appConfig] = (0,state/* useAppConfig */.r)();
7335
+ const navigate = (0,dist/* useNavigate */.Zp)();
6587
7336
 
6588
7337
  // This is frowned upon, but the raw config is needed here to provide
6589
7338
  // the selector
@@ -6607,8 +7356,8 @@ function DataSourceSelector() {
6607
7356
  key: ds.sourceName
6608
7357
  }, /*#__PURE__*/react.createElement("h1", {
6609
7358
  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,
7359
+ }, ds.configuration?.friendlyName || ds.friendlyName), /*#__PURE__*/react.createElement(ui_src/* Button */.$n, {
7360
+ type: ui_src/* ButtonEnums.type */.Ny.NW.primary,
6612
7361
  className: classnames_default()('ml-2'),
6613
7362
  onClick: () => {
6614
7363
  navigate({
@@ -6624,15 +7373,14 @@ function DataSourceSelector() {
6624
7373
 
6625
7374
 
6626
7375
 
6627
- function ItemListComponent(_ref) {
6628
- let {
6629
- itemLabel,
6630
- itemList,
6631
- onItemClicked
6632
- } = _ref;
7376
+ function ItemListComponent({
7377
+ itemLabel,
7378
+ itemList,
7379
+ onItemClicked
7380
+ }) {
6633
7381
  const {
6634
7382
  t
6635
- } = (0,es/* useTranslation */.$G)('DataSourceConfiguration');
7383
+ } = (0,es/* useTranslation */.Bd)('DataSourceConfiguration');
6636
7384
  const [filterValue, setFilterValue] = (0,react.useState)('');
6637
7385
  (0,react.useEffect)(() => {
6638
7386
  setFilterValue('');
@@ -6643,18 +7391,18 @@ function ItemListComponent(_ref) {
6643
7391
  className: "flex items-center justify-between"
6644
7392
  }, /*#__PURE__*/react.createElement("div", {
6645
7393
  className: "text-primary-light text-[20px]"
6646
- }, t(`Select ${itemLabel}`)), /*#__PURE__*/react.createElement(ui_src/* InputFilterText */.Xe, {
7394
+ }, t(`Select ${itemLabel}`)), /*#__PURE__*/react.createElement(ui_src/* InputFilterText */.Cv, {
6647
7395
  className: "max-w-[40%] grow",
6648
7396
  value: filterValue,
6649
7397
  onDebounceChange: setFilterValue,
6650
7398
  placeholder: t(`Search ${itemLabel} list`)
6651
7399
  })), /*#__PURE__*/react.createElement("div", {
6652
7400
  className: "relative flex min-h-[1px] grow flex-col bg-black text-[14px]"
6653
- }, itemList == null ? /*#__PURE__*/react.createElement(ui_src/* LoadingIndicatorProgress */.LE, {
7401
+ }, itemList == null ? /*#__PURE__*/react.createElement(ui_src/* LoadingIndicatorProgress */.Jx, {
6654
7402
  className: 'h-full w-full'
6655
7403
  }) : itemList.length === 0 ? /*#__PURE__*/react.createElement("div", {
6656
7404
  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, {
7405
+ }, /*#__PURE__*/react.createElement(ui_src/* Icon */.In, {
6658
7406
  name: "magnifier",
6659
7407
  className: "mb-4"
6660
7408
  }), /*#__PURE__*/react.createElement("span", null, t(`No ${itemLabel} available`))) : /*#__PURE__*/react.createElement(react.Fragment, null, /*#__PURE__*/react.createElement("div", {
@@ -6666,10 +7414,10 @@ function ItemListComponent(_ref) {
6666
7414
  return /*#__PURE__*/react.createElement("div", {
6667
7415
  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
7416
  key: item.id
6669
- }, /*#__PURE__*/react.createElement("div", null, item.name), /*#__PURE__*/react.createElement(ui_src/* Button */.zx, {
7417
+ }, /*#__PURE__*/react.createElement("div", null, item.name), /*#__PURE__*/react.createElement(ui_src/* Button */.$n, {
6670
7418
  onClick: () => onItemClicked(item),
6671
7419
  className: "invisible group-hover:visible",
6672
- endIcon: /*#__PURE__*/react.createElement(ui_src/* Icon */.JO, {
7420
+ endIcon: /*#__PURE__*/react.createElement(ui_src/* Icon */.In, {
6673
7421
  name: "arrow-left"
6674
7422
  })
6675
7423
  }, t('Select')));
@@ -6683,15 +7431,14 @@ function ItemListComponent(_ref) {
6683
7431
 
6684
7432
 
6685
7433
  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;
7434
+ function DataSourceConfigurationModalComponent({
7435
+ configurationAPI,
7436
+ configuredItems,
7437
+ onHide
7438
+ }) {
6692
7439
  const {
6693
7440
  t
6694
- } = (0,es/* useTranslation */.$G)('DataSourceConfiguration');
7441
+ } = (0,es/* useTranslation */.Bd)('DataSourceConfiguration');
6695
7442
  const [itemList, setItemList] = (0,react.useState)();
6696
7443
  const [selectedItems, setSelectedItems] = (0,react.useState)(configuredItems);
6697
7444
  const [errorMessage, setErrorMessage] = (0,react.useState)();
@@ -6765,9 +7512,9 @@ function DataSourceConfigurationModalComponent(_ref) {
6765
7512
  } : undefined
6766
7513
  }, /*#__PURE__*/react.createElement("div", {
6767
7514
  className: "text- flex items-center gap-2"
6768
- }, itemLabelIndex < selectedItems.length ? /*#__PURE__*/react.createElement(ui_src/* Icon */.JO, {
7515
+ }, itemLabelIndex < selectedItems.length ? /*#__PURE__*/react.createElement(ui_src/* Icon */.In, {
6769
7516
  name: "status-tracked"
6770
- }) : /*#__PURE__*/react.createElement(ui_src/* Icon */.JO, {
7517
+ }) : /*#__PURE__*/react.createElement(ui_src/* Icon */.In, {
6771
7518
  name: "status-untracked"
6772
7519
  }), /*#__PURE__*/react.createElement("div", {
6773
7520
  className: classnames_default()(NO_WRAP_ELLIPSIS_CLASS_NAMES)
@@ -6795,18 +7542,17 @@ function DataSourceConfigurationModalComponent(_ref) {
6795
7542
 
6796
7543
 
6797
7544
 
6798
- function DataSourceConfigurationComponent(_ref) {
6799
- let {
6800
- servicesManager,
6801
- extensionManager
6802
- } = _ref;
7545
+ function DataSourceConfigurationComponent({
7546
+ servicesManager,
7547
+ extensionManager
7548
+ }) {
6803
7549
  const {
6804
7550
  t
6805
- } = (0,es/* useTranslation */.$G)('DataSourceConfiguration');
7551
+ } = (0,es/* useTranslation */.Bd)('DataSourceConfiguration');
6806
7552
  const {
6807
7553
  show,
6808
7554
  hide
6809
- } = (0,ui_src/* useModal */.dd)();
7555
+ } = (0,ui_src/* useModal */.hS)();
6810
7556
  const {
6811
7557
  customizationService
6812
7558
  } = servicesManager.services;
@@ -6865,7 +7611,7 @@ function DataSourceConfigurationComponent(_ref) {
6865
7611
  }, [configurationAPI, configuredItems, showConfigurationModal]);
6866
7612
  return configuredItems ? /*#__PURE__*/react.createElement("div", {
6867
7613
  className: "text-aqua-pale flex items-center overflow-hidden"
6868
- }, /*#__PURE__*/react.createElement(ui_src/* Icon */.JO, {
7614
+ }, /*#__PURE__*/react.createElement(ui_src/* Icon */.In, {
6869
7615
  name: "settings",
6870
7616
  className: "mr-2.5 h-3.5 w-3.5 shrink-0 cursor-pointer",
6871
7617
  onClick: showConfigurationModal
@@ -7017,9 +7763,7 @@ class GoogleCloudDataSourceConfigurationAPI {
7017
7763
  * @param fetchSearchParams any search query params; currently only used for paging results
7018
7764
  * @returns an array of items of the specified type
7019
7765
  */
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] : {};
7766
+ static async _doFetch(urlStr, fetchItemType, fetchOptions = {}, fetchSearchParams = {}) {
7023
7767
  try {
7024
7768
  const url = new URL(urlStr);
7025
7769
  url.search = new URLSearchParams(fetchSearchParams).toString();
@@ -7055,6 +7799,7 @@ class GoogleCloudDataSourceConfigurationAPI {
7055
7799
 
7056
7800
 
7057
7801
 
7802
+
7058
7803
  /**
7059
7804
  *
7060
7805
  * Note: this is an example of how the customization module can be used
@@ -7064,11 +7809,10 @@ class GoogleCloudDataSourceConfigurationAPI {
7064
7809
  * custom page for the user to view their profile, or to add a custom
7065
7810
  * page for login etc.
7066
7811
  */
7067
- function getCustomizationModule(_ref) {
7068
- let {
7069
- servicesManager,
7070
- extensionManager
7071
- } = _ref;
7812
+ function getCustomizationModule({
7813
+ servicesManager,
7814
+ extensionManager
7815
+ }) {
7072
7816
  return [{
7073
7817
  name: 'helloPage',
7074
7818
  value: {
@@ -7193,14 +7937,65 @@ function getCustomizationModule(_ref) {
7193
7937
  // The factory for creating an instance of a BaseDataSourceConfigurationAPI for Google Cloud Healthcare
7194
7938
  id: 'ohif.dataSourceConfigurationAPI.google',
7195
7939
  factory: dataSourceName => new GoogleCloudDataSourceConfigurationAPI(dataSourceName, servicesManager, extensionManager)
7940
+ }, {
7941
+ id: 'progressDropdownWithServiceComponent',
7942
+ component: ProgressDropdownWithService_ProgressDropdownWithService
7196
7943
  }]
7197
7944
  }];
7198
7945
  }
7946
+ ;// CONCATENATED MODULE: ../../../extensions/default/src/Components/LineChartViewport/LineChartViewport.tsx
7947
+
7948
+
7949
+ const LineChartViewport = ({
7950
+ displaySets
7951
+ }) => {
7952
+ const displaySet = displaySets[0];
7953
+ const {
7954
+ axis: chartAxis,
7955
+ series: chartSeries
7956
+ } = displaySet.instance.chartData;
7957
+ return /*#__PURE__*/react.createElement(ui_src/* LineChart */.bl, {
7958
+ showLegend: true,
7959
+ legendWidth: 150,
7960
+ axis: {
7961
+ x: {
7962
+ label: chartAxis.x.label,
7963
+ indexRef: 0,
7964
+ type: 'x',
7965
+ range: {
7966
+ min: 0
7967
+ }
7968
+ },
7969
+ y: {
7970
+ label: chartAxis.y.label,
7971
+ indexRef: 1,
7972
+ type: 'y'
7973
+ }
7974
+ },
7975
+ series: chartSeries
7976
+ });
7977
+ };
7978
+
7979
+ ;// CONCATENATED MODULE: ../../../extensions/default/src/Components/LineChartViewport/index.ts
7980
+
7981
+ ;// CONCATENATED MODULE: ../../../extensions/default/src/getViewportModule.tsx
7982
+
7983
+ const getViewportModule = ({
7984
+ servicesManager,
7985
+ commandsManager,
7986
+ extensionManager
7987
+ }) => {
7988
+ return [{
7989
+ name: 'chartViewport',
7990
+ component: LineChartViewport
7991
+ }];
7992
+ };
7993
+
7199
7994
  // EXTERNAL MODULE: ../../../node_modules/@cornerstonejs/calculate-suv/dist/calculate-suv.esm.js
7200
- var calculate_suv_esm = __webpack_require__(15747);
7995
+ var calculate_suv_esm = __webpack_require__(79717);
7201
7996
  ;// CONCATENATED MODULE: ../../../extensions/default/src/getPTImageIdInstanceMetadata.ts
7202
7997
 
7203
- const getPTImageIdInstanceMetadata_metadataProvider = src["default"].classes.MetadataProvider;
7998
+ const getPTImageIdInstanceMetadata_metadataProvider = src/* default.classes */.Ay.classes.MetadataProvider;
7204
7999
  function getPTImageIdInstanceMetadata(imageId) {
7205
8000
  const dicomMetaData = getPTImageIdInstanceMetadata_metadataProvider.get('instance', imageId);
7206
8001
  if (!dicomMetaData) {
@@ -7276,14 +8071,18 @@ const init_metadataProvider = src.classes.MetadataProvider;
7276
8071
  * @param {Object} servicesManager
7277
8072
  * @param {Object} configuration
7278
8073
  */
7279
- function init(_ref) {
7280
- let {
7281
- servicesManager,
7282
- configuration = {}
7283
- } = _ref;
8074
+ function init({
8075
+ servicesManager,
8076
+ configuration = {},
8077
+ commandsManager
8078
+ }) {
7284
8079
  const {
7285
- stateSyncService
8080
+ stateSyncService,
8081
+ toolbarService,
8082
+ cineService,
8083
+ viewportGridService
7286
8084
  } = servicesManager.services;
8085
+ toolbarService.registerEventForToolbarUpdate(cineService, [cineService.EVENTS.CINE_STATE_CHANGED]);
7287
8086
  // Add
7288
8087
  src.DicomMetadataStore.subscribe(src.DicomMetadataStore.EVENTS.INSTANCES_ADDED, handlePETImageMetadata);
7289
8088
 
@@ -7298,6 +8097,12 @@ function init(_ref) {
7298
8097
  clearOnModeExit: true
7299
8098
  });
7300
8099
 
8100
+ // uiStateStore is a sync state which stores the relevant
8101
+ // UI state for the viewer
8102
+ stateSyncService.register('uiStateStore', {
8103
+ clearOnModeExit: true
8104
+ });
8105
+
7301
8106
  // displaySetSelectorMap stores a map from
7302
8107
  // `<activeStudyUID>:<displaySetSelectorId>:<matchOffset>` to
7303
8108
  // a displaySetInstanceUID, used to display named display sets in
@@ -7314,7 +8119,7 @@ function init(_ref) {
7314
8119
  });
7315
8120
 
7316
8121
  // Stores a map from the to be applied hanging protocols `<activeStudyUID>:<protocolId>`
7317
- // to the previously applied hanging protolStageIndexMap key, in order to toggle
8122
+ // to the previously applied hanging protocolStageIndexMap key, in order to toggle
7318
8123
  // off the applied protocol and remember the old state.
7319
8124
  stateSyncService.register('toggleHangingProtocol', {
7320
8125
  clearOnModeExit: true
@@ -7326,44 +8131,83 @@ function init(_ref) {
7326
8131
  stateSyncService.register('viewportsByPosition', {
7327
8132
  clearOnModeExit: true
7328
8133
  });
8134
+
8135
+ // Function to process and subscribe to events for a given set of commands and listeners
8136
+ const subscribeToEvents = listeners => {
8137
+ Object.entries(listeners).forEach(([event, commands]) => {
8138
+ const supportedEvents = [viewportGridService.EVENTS.ACTIVE_VIEWPORT_ID_CHANGED, viewportGridService.EVENTS.VIEWPORTS_READY];
8139
+ if (supportedEvents.includes(event)) {
8140
+ viewportGridService.subscribe(event, eventData => {
8141
+ const viewportId = eventData?.viewportId ?? viewportGridService.getActiveViewportId();
8142
+ commandsManager.run(commands, {
8143
+ viewportId
8144
+ });
8145
+ });
8146
+ }
8147
+ });
8148
+ };
8149
+ toolbarService.subscribe(toolbarService.EVENTS.TOOL_BAR_MODIFIED, state => {
8150
+ const {
8151
+ buttons
8152
+ } = state;
8153
+ for (const [id, button] of Object.entries(buttons)) {
8154
+ const {
8155
+ groupId,
8156
+ items,
8157
+ listeners
8158
+ } = button.props || {};
8159
+
8160
+ // Handle group items' listeners
8161
+ if (groupId && items) {
8162
+ items.forEach(item => {
8163
+ if (item.listeners) {
8164
+ subscribeToEvents(item.listeners);
8165
+ }
8166
+ });
8167
+ }
8168
+
8169
+ // Handle button listeners
8170
+ if (listeners) {
8171
+ subscribeToEvents(listeners);
8172
+ }
8173
+ }
8174
+ });
7329
8175
  }
7330
- const handlePETImageMetadata = _ref2 => {
7331
- let {
7332
- SeriesInstanceUID,
7333
- StudyInstanceUID
7334
- } = _ref2;
8176
+ const handlePETImageMetadata = ({
8177
+ SeriesInstanceUID,
8178
+ StudyInstanceUID
8179
+ }) => {
7335
8180
  const {
7336
8181
  instances
7337
8182
  } = src.DicomMetadataStore.getSeries(StudyInstanceUID, SeriesInstanceUID);
8183
+ if (!instances?.length) {
8184
+ return;
8185
+ }
7338
8186
  const modality = instances[0].Modality;
7339
- if (modality !== 'PT') {
8187
+ if (!modality || modality !== 'PT') {
7340
8188
  return;
7341
8189
  }
7342
8190
  const imageIds = instances.map(instance => instance.imageId);
7343
8191
  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
8192
 
7354
8193
  // try except block to prevent errors when the metadata is not correct
7355
- let suvScalingFactors;
7356
8194
  try {
7357
- suvScalingFactors = (0,calculate_suv_esm/* calculateSUVScalingFactors */.d)(instanceMetadataArray);
8195
+ imageIds.forEach(imageId => {
8196
+ const instanceMetadata = getPTImageIdInstanceMetadata(imageId);
8197
+ if (instanceMetadata) {
8198
+ instanceMetadataArray.push(instanceMetadata);
8199
+ }
8200
+ });
8201
+ if (!instanceMetadataArray.length) {
8202
+ return;
8203
+ }
8204
+ const suvScalingFactors = (0,calculate_suv_esm/* calculateSUVScalingFactors */.C)(instanceMetadataArray);
8205
+ instanceMetadataArray.forEach((instanceMetadata, index) => {
8206
+ init_metadataProvider.addCustomMetadata(imageIds[index], 'scalingModule', suvScalingFactors[index]);
8207
+ });
7358
8208
  } catch (error) {
7359
8209
  console.log(error);
7360
8210
  }
7361
- if (!suvScalingFactors) {
7362
- return;
7363
- }
7364
- instanceMetadataArray.forEach((instanceMetadata, index) => {
7365
- init_metadataProvider.addCustomMetadata(imageIds[index], 'scalingModule', suvScalingFactors[index]);
7366
- });
7367
8211
  };
7368
8212
  ;// CONCATENATED MODULE: ../../../extensions/default/src/DicomWebDataSource/utils/index.ts
7369
8213
 
@@ -7384,6 +8228,8 @@ const handlePETImageMetadata = _ref2 => {
7384
8228
 
7385
8229
 
7386
8230
 
8231
+
8232
+
7387
8233
  const defaultExtension = {
7388
8234
  /**
7389
8235
  * Only required property. Should be a unique value across all extensions.
@@ -7391,16 +8237,16 @@ const defaultExtension = {
7391
8237
  id: id,
7392
8238
  preRegistration: init,
7393
8239
  getDataSourcesModule: src_getDataSourcesModule,
8240
+ getViewportModule: getViewportModule,
7394
8241
  getLayoutTemplateModule: getLayoutTemplateModule,
7395
8242
  getPanelModule: src_getPanelModule,
7396
8243
  getHangingProtocolModule: src_getHangingProtocolModule,
7397
8244
  getSopClassHandlerModule: src_getSopClassHandlerModule,
7398
8245
  getToolbarModule: getToolbarModule,
7399
8246
  getCommandsModule: src_commandsModule,
7400
- getUtilityModule(_ref) {
7401
- let {
7402
- servicesManager
7403
- } = _ref;
8247
+ getUtilityModule({
8248
+ servicesManager
8249
+ }) {
7404
8250
  return [{
7405
8251
  name: 'common',
7406
8252
  exports: {