@ohif/app 3.8.0-beta.73 → 3.8.0-beta.75

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 (46) hide show
  1. package/dist/{121.bundle.21827fec690c01ee9ab3.js → 121.bundle.bd8acf52b6a7047ae832.js} +2 -2
  2. package/dist/141.bundle.556b4c1e4cab770417ac.js +8620 -0
  3. package/dist/{191.bundle.c0ea2d031ffddeca32c9.js → 183.bundle.25293de927ef032a6695.js} +195 -122
  4. package/dist/{188.bundle.acfe3c0e6eb9cc90aef1.js → 188.bundle.e992f05e4e8166db89c4.js} +2 -2
  5. package/dist/{90.bundle.70f4752bb4ac79aef269.js → 206.bundle.88019f84ccd7fb9276e7.js} +580 -140
  6. package/dist/{987.bundle.e19408decfd59aadd118.js → 217.bundle.9631d914f170f8d7ef63.js} +31558 -39396
  7. package/dist/{295.bundle.3a0d5062d65296c4bf5d.js → 295.bundle.688b6bbff493cd904ae7.js} +2 -2
  8. package/dist/{155.bundle.64e00e96835d61e99c0e.js → 325.bundle.52287c47a07bb16869cb.js} +43 -58
  9. package/dist/{425.bundle.f796ed1020fbed0f1e71.js → 335.bundle.8ed90c9c715dafb05c77.js} +132 -518
  10. package/dist/{342.bundle.521c0217f82380c0c2ad.js → 342.bundle.c6165579c4ac3ef0d6a8.js} +2 -2
  11. package/dist/{41.bundle.8b3f6e6f4bd71b85ef14.js → 41.bundle.6a01588b0e9bf25372ea.js} +28 -29
  12. package/dist/{433.bundle.6f2308ab10593784778c.js → 433.bundle.1474591f213852cffcba.js} +188 -172
  13. package/dist/{290.bundle.952de53057f98e2c5ef0.js → 445.bundle.38c6d2af64e41cd7c614.js} +1 -1049
  14. package/dist/{448.bundle.19df2fef38bb0f6a272a.js → 448.bundle.eb2e38dfa7fd0d731109.js} +16 -22
  15. package/dist/487.bundle.c7a54a90b005e5b977df.js +1875 -0
  16. package/dist/{530.bundle.f4b7966fb33eafb8cd5d.js → 530.bundle.7c94543955552475c56a.js} +9 -9
  17. package/dist/{540.bundle.32224b29bfa11d1f1cec.js → 540.bundle.45a7a300cc09906b4acc.js} +15 -15
  18. package/dist/{544.bundle.1110b24e96863d719a95.js → 544.bundle.1c1f57118560046649c1.js} +9 -17
  19. package/dist/{574.bundle.2b3369042aad5d553463.js → 574.bundle.b4eb8773d7741868e84b.js} +166 -45
  20. package/dist/{594.bundle.61a9f0567260e9bb4480.js → 594.bundle.6a804bd412dbf955c5b9.js} +4 -4
  21. package/dist/{2.bundle.a849401e1fefc0898248.js → 633.bundle.65ed703c889005f8ffa8.js} +35 -43
  22. package/dist/{699.bundle.9f4eddf87548c0d0dca3.js → 699.bundle.d672e71097df9be1b2a7.js} +18 -35
  23. package/dist/702.bundle.963481fbf871984b646f.js +8426 -0
  24. package/dist/722.bundle.afab1fe6bfcd569130ac.js +1083 -0
  25. package/dist/{724.bundle.b57096deac9649aada4b.js → 724.bundle.73c3bd976d8a7f1d040c.js} +20 -11
  26. package/dist/{862.bundle.47305c27f0fb939c2f97.js → 862.bundle.f49a379497bb3b43a942.js} +3 -3
  27. package/dist/{889.bundle.3816444220909bd1fc78.js → 889.bundle.fa29b24385d14e4fa4fd.js} +8 -8
  28. package/dist/{595.bundle.e8ff2d0672cb195d4ab8.js → 896.bundle.2635ab03af0b472f6e39.js} +686 -57
  29. package/dist/{905.bundle.2dd7f62cb6e49851926b.js → 905.bundle.9f0b28f4bf91fffdc90c.js} +4 -4
  30. package/dist/{907.bundle.d22edc6203167e985ab3.js → 907.bundle.7c64be49c9a44fbd1e61.js} +2 -2
  31. package/dist/94.bundle.e9ca76b8e5c4000c9742.js +784 -0
  32. package/dist/{961.bundle.f207f1ac54a174e67d82.js → 961.bundle.d1888c50a49e80380c69.js} +2 -2
  33. package/dist/{app.bundle.5e5ee16c43a68961e8c4.js → app.bundle.a6eb6707172f9eb6c8c2.js} +98584 -89435
  34. package/dist/app.bundle.css +5 -4
  35. package/dist/cornerstoneDICOMImageLoader.min.js +1 -1
  36. package/dist/cornerstoneDICOMImageLoader.min.js.map +1 -1
  37. package/dist/histogram-worker.bundle.829e14ec12c2b41a4323.js +359 -0
  38. package/dist/index.html +1 -1
  39. package/dist/{polySeg.bundle.fe47718e6a8414f175b1.js → polySeg.bundle.c503e9460cef894737cd.js} +3 -6
  40. package/dist/sw.js +1 -1
  41. package/package.json +20 -19
  42. package/dist/425.css +0 -2
  43. /package/dist/{164.bundle.6b98e9caf53620fbd6ca.js → 164.bundle.2fd64799a0bae7596af8.js} +0 -0
  44. /package/dist/{155.css → 325.css} +0 -0
  45. /package/dist/{2.css → 633.css} +0 -0
  46. /package/dist/{595.css → 896.css} +0 -0
@@ -1,7 +1,7 @@
1
1
  "use strict";
2
- (globalThis["webpackChunk"] = globalThis["webpackChunk"] || []).push([[90],{
2
+ (globalThis["webpackChunk"] = globalThis["webpackChunk"] || []).push([[206],{
3
3
 
4
- /***/ 54090:
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),
@@ -31,8 +32,8 @@ __webpack_require__.d(utils_namespaceObject, {
31
32
 
32
33
  // EXTERNAL MODULE: ../../../node_modules/dicomweb-client/build/dicomweb-client.es.js
33
34
  var dicomweb_client_es = __webpack_require__(36922);
34
- // EXTERNAL MODULE: ../../core/src/index.ts + 68 modules
35
- var src = __webpack_require__(85073);
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
38
  var sortStudy = __webpack_require__(45476);
38
39
  ;// CONCATENATED MODULE: ../../../extensions/default/src/DicomWebDataSource/qido.js
@@ -803,9 +804,123 @@ function deleteStudyMetadataPromise(StudyInstanceUID) {
803
804
  StudyMetaDataPromises.delete(StudyInstanceUID);
804
805
  }
805
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
+ }
806
904
  ;// CONCATENATED MODULE: ../../../extensions/default/src/DicomWebDataSource/utils/StaticWadoClient.ts
807
905
 
808
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
+
809
924
  /**
810
925
  * An implementation of the static wado client, that fetches data from
811
926
  * a static response rather than actually doing real queries. This allows
@@ -815,9 +930,51 @@ function deleteStudyMetadataPromise(StudyInstanceUID) {
815
930
  */
816
931
 
817
932
  class StaticWadoClient extends dicomweb_client_es/* api */.FH.DICOMwebClient {
818
- constructor(qidoConfig) {
819
- super(qidoConfig);
820
- this.staticWado = qidoConfig.staticWado;
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
+ }
821
978
  }
822
979
 
823
980
  /**
@@ -2484,8 +2641,8 @@ var react = __webpack_require__(41766);
2484
2641
  // EXTERNAL MODULE: ../../../node_modules/prop-types/index.js
2485
2642
  var prop_types = __webpack_require__(11374);
2486
2643
  var prop_types_default = /*#__PURE__*/__webpack_require__.n(prop_types);
2487
- // EXTERNAL MODULE: ../../ui/src/index.js + 542 modules
2488
- var ui_src = __webpack_require__(48804);
2644
+ // EXTERNAL MODULE: ../../ui/src/index.js + 785 modules
2645
+ var ui_src = __webpack_require__(5085);
2489
2646
  // EXTERNAL MODULE: ./state/index.js + 1 modules
2490
2647
  var state = __webpack_require__(15575);
2491
2648
  // EXTERNAL MODULE: ../node_modules/react-router-dom/dist/index.js
@@ -2501,14 +2658,15 @@ function _extends() { _extends = Object.assign ? Object.assign.bind() : function
2501
2658
 
2502
2659
 
2503
2660
  function Toolbar({
2504
- servicesManager
2661
+ servicesManager,
2662
+ buttonSection = 'primary'
2505
2663
  }) {
2506
2664
  const {
2507
2665
  toolbarButtons,
2508
2666
  onInteraction
2509
2667
  } = (0,src/* useToolbar */.tR)({
2510
2668
  servicesManager,
2511
- buttonSection: 'primary'
2669
+ buttonSection
2512
2670
  });
2513
2671
  if (!toolbarButtons.length) {
2514
2672
  return null;
@@ -2542,7 +2700,6 @@ function Toolbar({
2542
2700
 
2543
2701
 
2544
2702
 
2545
-
2546
2703
  const {
2547
2704
  availableLanguages,
2548
2705
  defaultLanguage,
@@ -2551,9 +2708,9 @@ const {
2551
2708
  function ViewerHeader({
2552
2709
  hotkeysManager,
2553
2710
  extensionManager,
2554
- servicesManager
2711
+ servicesManager,
2712
+ appConfig
2555
2713
  }) {
2556
- const [appConfig] = (0,state/* useAppConfig */.r)();
2557
2714
  const navigate = (0,dist/* useNavigate */.Zp)();
2558
2715
  const location = (0,react_router_dist/* useLocation */.zy)();
2559
2716
  const onClickReturnButton = () => {
@@ -2588,8 +2745,8 @@ function ViewerHeader({
2588
2745
  hotkeyDefinitions,
2589
2746
  hotkeyDefaults
2590
2747
  } = hotkeysManager;
2591
- const versionNumber = "3.8.0-beta.73";
2592
- const commitHash = "dc37802ec1f739a6ed602363bdf231d6fe58827e";
2748
+ const versionNumber = "3.8.0-beta.75";
2749
+ const commitHash = "7fac49b4492b4bd5e9ece8e2e2b0fa2faa840d7f";
2593
2750
  const menuOptions = [{
2594
2751
  title: t('Header:About'),
2595
2752
  icon: 'info',
@@ -2648,7 +2805,12 @@ function ViewerHeader({
2648
2805
  onClickReturnButton: onClickReturnButton,
2649
2806
  WhiteLabeling: appConfig.whiteLabeling,
2650
2807
  showPatientInfo: appConfig.showPatientInfo,
2651
- servicesManager: servicesManager
2808
+ servicesManager: servicesManager,
2809
+ Secondary: /*#__PURE__*/react.createElement(Toolbar, {
2810
+ servicesManager: servicesManager,
2811
+ buttonSection: "secondary"
2812
+ }),
2813
+ appConfig: appConfig
2652
2814
  }, /*#__PURE__*/react.createElement(ui_src/* ErrorBoundary */.tH, {
2653
2815
  context: "Primary Toolbar"
2654
2816
  }, /*#__PURE__*/react.createElement("div", {
@@ -2659,15 +2821,16 @@ function ViewerHeader({
2659
2821
  }
2660
2822
  /* harmony default export */ const ViewerLayout_ViewerHeader = (ViewerHeader);
2661
2823
  ;// CONCATENATED MODULE: ../../../extensions/default/src/Components/SidePanelWithServices.tsx
2824
+ 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); }
2662
2825
 
2663
2826
 
2664
2827
  const SidePanelWithServices = ({
2665
2828
  servicesManager,
2666
2829
  side,
2667
- className,
2668
2830
  activeTabIndex: activeTabIndexProp,
2669
- tabs,
2670
- expandedWidth
2831
+ tabs: tabsProp,
2832
+ expandedWidth,
2833
+ ...props
2671
2834
  }) => {
2672
2835
  const panelService = servicesManager?.services?.panelService;
2673
2836
 
@@ -2675,31 +2838,54 @@ const SidePanelWithServices = ({
2675
2838
  // Thus going to the Study List page and back to the viewer resets this flag for a SidePanel.
2676
2839
  const [hasBeenOpened, setHasBeenOpened] = (0,react.useState)(false);
2677
2840
  const [activeTabIndex, setActiveTabIndex] = (0,react.useState)(activeTabIndexProp);
2841
+ const [tabs, setTabs] = (0,react.useState)(tabsProp ?? panelService.getPanels(side));
2842
+ const handleSidePanelOpen = (0,react.useCallback)(() => {
2843
+ setHasBeenOpened(true);
2844
+ }, []);
2845
+ const handleActiveTabIndexChange = (0,react.useCallback)(({
2846
+ activeTabIndex
2847
+ }) => {
2848
+ setActiveTabIndex(activeTabIndex);
2849
+ }, []);
2850
+
2851
+ /** update the active tab index from outside */
2678
2852
  (0,react.useEffect)(() => {
2679
- if (panelService) {
2680
- const activatePanelSubscription = panelService.subscribe(panelService.EVENTS.ACTIVATE_PANEL, activatePanelEvent => {
2681
- if (!hasBeenOpened || activatePanelEvent.forceActive) {
2682
- const tabIndex = tabs.findIndex(tab => tab.id === activatePanelEvent.panelId);
2683
- if (tabIndex !== -1) {
2684
- setActiveTabIndex(tabIndex);
2685
- }
2853
+ setActiveTabIndex(activeTabIndexProp);
2854
+ }, [activeTabIndexProp]);
2855
+ (0,react.useEffect)(() => {
2856
+ const {
2857
+ unsubscribe
2858
+ } = panelService.subscribe(panelService.EVENTS.PANELS_CHANGED, panelChangedEvent => {
2859
+ if (panelChangedEvent.position !== side) {
2860
+ return;
2861
+ }
2862
+ setTabs(panelService.getPanels(side));
2863
+ });
2864
+ return () => {
2865
+ unsubscribe();
2866
+ };
2867
+ }, [panelService, side]);
2868
+ (0,react.useEffect)(() => {
2869
+ const activatePanelSubscription = panelService.subscribe(panelService.EVENTS.ACTIVATE_PANEL, activatePanelEvent => {
2870
+ if (!hasBeenOpened || activatePanelEvent.forceActive) {
2871
+ const tabIndex = tabs.findIndex(tab => tab.id === activatePanelEvent.panelId);
2872
+ if (tabIndex !== -1) {
2873
+ setActiveTabIndex(tabIndex);
2686
2874
  }
2687
- });
2688
- return () => {
2689
- activatePanelSubscription.unsubscribe();
2690
- };
2691
- }
2875
+ }
2876
+ });
2877
+ return () => {
2878
+ activatePanelSubscription.unsubscribe();
2879
+ };
2692
2880
  }, [tabs, hasBeenOpened, panelService]);
2693
- return /*#__PURE__*/react.createElement(ui_src/* SidePanel */.wv, {
2881
+ return /*#__PURE__*/react.createElement(ui_src/* SidePanel */.wv, SidePanelWithServices_extends({}, props, {
2694
2882
  side: side,
2695
- className: className,
2696
- activeTabIndex: activeTabIndex,
2697
2883
  tabs: tabs,
2698
- onOpen: () => {
2699
- setHasBeenOpened(true);
2700
- },
2884
+ activeTabIndex: activeTabIndex,
2885
+ onOpen: handleSidePanelOpen,
2886
+ onActiveTabIndexChange: handleActiveTabIndexChange,
2701
2887
  expandedWidth: expandedWidth
2702
- });
2888
+ }));
2703
2889
  };
2704
2890
  /* harmony default export */ const Components_SidePanelWithServices = (SidePanelWithServices);
2705
2891
  ;// CONCATENATED MODULE: ../../../extensions/default/src/ViewerLayout/index.tsx
@@ -2719,16 +2905,20 @@ function ViewerLayout({
2719
2905
  // From Modes
2720
2906
  viewports,
2721
2907
  ViewportGridComp,
2722
- leftPanels = [],
2723
- rightPanels = [],
2724
- leftPanelDefaultClosed = false,
2725
- rightPanelDefaultClosed = false
2908
+ leftPanelClosed = false,
2909
+ rightPanelClosed = false
2726
2910
  }) {
2727
2911
  const [appConfig] = (0,state/* useAppConfig */.r)();
2728
2912
  const {
2913
+ panelService,
2729
2914
  hangingProtocolService
2730
2915
  } = servicesManager.services;
2731
2916
  const [showLoadingIndicator, setShowLoadingIndicator] = (0,react.useState)(appConfig.showLoadingIndicator);
2917
+ const hasPanels = (0,react.useCallback)(side => !!panelService.getPanels(side).length, [panelService]);
2918
+ const [hasRightPanels, setHasRightPanels] = (0,react.useState)(hasPanels('right'));
2919
+ const [hasLeftPanels, setHasLeftPanels] = (0,react.useState)(hasPanels('left'));
2920
+ const [leftPanelClosedState, setLeftPanelClosed] = (0,react.useState)(leftPanelClosed);
2921
+ const [rightPanelClosedState, setRightPanelClosed] = (0,react.useState)(rightPanelClosed);
2732
2922
 
2733
2923
  /**
2734
2924
  * Set body classes (tailwindcss) that don't allow vertical
@@ -2753,21 +2943,6 @@ function ViewerLayout({
2753
2943
  content: entry.component
2754
2944
  };
2755
2945
  };
2756
- const getPanelData = id => {
2757
- const {
2758
- content,
2759
- entry
2760
- } = getComponent(id);
2761
- return {
2762
- id: entry.id,
2763
- iconName: entry.iconName,
2764
- iconLabel: entry.iconLabel,
2765
- label: entry.label,
2766
- name: entry.name,
2767
- content,
2768
- contexts: entry.contexts
2769
- };
2770
- };
2771
2946
  (0,react.useEffect)(() => {
2772
2947
  const {
2773
2948
  unsubscribe
@@ -2791,13 +2966,31 @@ function ViewerLayout({
2791
2966
  displaySetsToDisplay: viewportComponent.displaySetsToDisplay
2792
2967
  };
2793
2968
  };
2794
- const leftPanelComponents = leftPanels.map(getPanelData);
2795
- const rightPanelComponents = rightPanels.map(getPanelData);
2969
+ (0,react.useEffect)(() => {
2970
+ const {
2971
+ unsubscribe
2972
+ } = panelService.subscribe(panelService.EVENTS.PANELS_CHANGED, ({
2973
+ options
2974
+ }) => {
2975
+ setHasLeftPanels(hasPanels('left'));
2976
+ setHasRightPanels(hasPanels('right'));
2977
+ if (options?.leftPanelClosed !== undefined) {
2978
+ setLeftPanelClosed(options.leftPanelClosed);
2979
+ }
2980
+ if (options?.rightPanelClosed !== undefined) {
2981
+ setRightPanelClosed(options.rightPanelClosed);
2982
+ }
2983
+ });
2984
+ return () => {
2985
+ unsubscribe();
2986
+ };
2987
+ }, [panelService, hasPanels]);
2796
2988
  const viewportComponents = viewports.map(getViewportComponentData);
2797
2989
  return /*#__PURE__*/react.createElement("div", null, /*#__PURE__*/react.createElement(ViewerLayout_ViewerHeader, {
2798
2990
  hotkeysManager: hotkeysManager,
2799
2991
  extensionManager: extensionManager,
2800
- servicesManager: servicesManager
2992
+ servicesManager: servicesManager,
2993
+ appConfig: appConfig
2801
2994
  }), /*#__PURE__*/react.createElement("div", {
2802
2995
  className: "relative flex w-full flex-row flex-nowrap items-stretch overflow-hidden bg-black",
2803
2996
  style: {
@@ -2805,12 +2998,11 @@ function ViewerLayout({
2805
2998
  }
2806
2999
  }, /*#__PURE__*/react.createElement(react.Fragment, null, showLoadingIndicator && /*#__PURE__*/react.createElement(ui_src/* LoadingIndicatorProgress */.Jx, {
2807
3000
  className: "h-full w-full bg-black"
2808
- }), leftPanelComponents.length ? /*#__PURE__*/react.createElement(ui_src/* ErrorBoundary */.tH, {
3001
+ }), hasLeftPanels ? /*#__PURE__*/react.createElement(ui_src/* ErrorBoundary */.tH, {
2809
3002
  context: "Left Panel"
2810
3003
  }, /*#__PURE__*/react.createElement(Components_SidePanelWithServices, {
2811
3004
  side: "left",
2812
- activeTabIndex: leftPanelDefaultClosed ? null : 0,
2813
- tabs: leftPanelComponents,
3005
+ activeTabIndex: leftPanelClosedState ? null : 0,
2814
3006
  servicesManager: servicesManager
2815
3007
  })) : null, /*#__PURE__*/react.createElement("div", {
2816
3008
  className: "flex h-full flex-1 flex-col"
@@ -2822,12 +3014,11 @@ function ViewerLayout({
2822
3014
  servicesManager: servicesManager,
2823
3015
  viewportComponents: viewportComponents,
2824
3016
  commandsManager: commandsManager
2825
- })))), rightPanelComponents.length ? /*#__PURE__*/react.createElement(ui_src/* ErrorBoundary */.tH, {
3017
+ })))), hasRightPanels ? /*#__PURE__*/react.createElement(ui_src/* ErrorBoundary */.tH, {
2826
3018
  context: "Right Panel"
2827
3019
  }, /*#__PURE__*/react.createElement(Components_SidePanelWithServices, {
2828
3020
  side: "right",
2829
- activeTabIndex: rightPanelDefaultClosed ? null : 0,
2830
- tabs: rightPanelComponents,
3021
+ activeTabIndex: rightPanelClosedState ? null : 0,
2831
3022
  servicesManager: servicesManager
2832
3023
  })) : null)), /*#__PURE__*/react.createElement(ui_src/* InvestigationalUseDialog */.j, {
2833
3024
  dialogConfiguration: appConfig?.investigationalUseDialog
@@ -2843,8 +3034,8 @@ ViewerLayout.propTypes = {
2843
3034
  // From modes
2844
3035
  leftPanels: (prop_types_default()).array,
2845
3036
  rightPanels: (prop_types_default()).array,
2846
- leftPanelDefaultClosed: (prop_types_default()).bool.isRequired,
2847
- rightPanelDefaultClosed: (prop_types_default()).bool.isRequired,
3037
+ leftPanelClosed: (prop_types_default()).bool.isRequired,
3038
+ rightPanelClosed: (prop_types_default()).bool.isRequired,
2848
3039
  /** Responsible for rendering our grid of viewports; provided by consuming application */
2849
3040
  children: prop_types_default().oneOfType([(prop_types_default()).node, (prop_types_default()).func]).isRequired,
2850
3041
  viewports: (prop_types_default()).array
@@ -3321,38 +3512,6 @@ WrappedPanelStudyBrowser.propTypes = {
3321
3512
  servicesManager: (prop_types_default()).object.isRequired
3322
3513
  };
3323
3514
  /* harmony default export */ const Panels_WrappedPanelStudyBrowser = (WrappedPanelStudyBrowser);
3324
- ;// CONCATENATED MODULE: ../../../extensions/default/src/Panels/ActionButtons.tsx
3325
-
3326
-
3327
-
3328
-
3329
- function ActionButtons({
3330
- onExportClick,
3331
- onCreateReportClick
3332
- }) {
3333
- const {
3334
- t
3335
- } = (0,es/* useTranslation */.Bd)('MeasurementTable');
3336
- return /*#__PURE__*/react.createElement(react.Fragment, null, /*#__PURE__*/react.createElement(ui_src/* LegacyButtonGroup */.xA, {
3337
- color: "black",
3338
- size: "inherit"
3339
- }, /*#__PURE__*/react.createElement(ui_src/* LegacyButton */._H, {
3340
- className: "px-2 py-2 text-base",
3341
- onClick: onExportClick
3342
- }, t('Export CSV')), /*#__PURE__*/react.createElement(ui_src/* LegacyButton */._H, {
3343
- className: "px-2 py-2 text-base",
3344
- onClick: onCreateReportClick
3345
- }, t('Create Report'))));
3346
- }
3347
- ActionButtons.propTypes = {
3348
- onExportClick: (prop_types_default()).func,
3349
- onCreateReportClick: (prop_types_default()).func
3350
- };
3351
- ActionButtons.defaultProps = {
3352
- onExportClick: () => alert('Export'),
3353
- onCreateReportClick: () => alert('Create Report')
3354
- };
3355
- /* harmony default export */ const Panels_ActionButtons = (ActionButtons);
3356
3515
  // EXTERNAL MODULE: ../../../node_modules/lodash.debounce/index.js
3357
3516
  var lodash_debounce = __webpack_require__(14771);
3358
3517
  var lodash_debounce_default = /*#__PURE__*/__webpack_require__.n(lodash_debounce);
@@ -3624,7 +3783,6 @@ function findSRWithSameSeriesDescription(SeriesDescription, displaySetService) {
3624
3783
 
3625
3784
 
3626
3785
 
3627
-
3628
3786
  const {
3629
3787
  downloadCSVReport
3630
3788
  } = src.utils;
@@ -3831,17 +3989,22 @@ function PanelMeasurementTable({
3831
3989
  className: "ohif-scrollbar overflow-y-auto overflow-x-hidden",
3832
3990
  "data-cy": 'measurements-panel'
3833
3991
  }, /*#__PURE__*/react.createElement(ui_src/* MeasurementTable */.V, {
3834
- title: t("Measurements"),
3992
+ title: t('Measurements'),
3835
3993
  servicesManager: servicesManager,
3836
3994
  data: displayMeasurements,
3837
3995
  onClick: jumpToImage,
3838
3996
  onEdit: onMeasurementItemEditHandler
3839
3997
  })), /*#__PURE__*/react.createElement("div", {
3840
3998
  className: "flex justify-center p-4"
3841
- }, /*#__PURE__*/react.createElement(Panels_ActionButtons, {
3842
- onExportClick: exportReport,
3843
- onClearMeasurementsClick: clearMeasurements,
3844
- onCreateReportClick: createReport
3999
+ }, /*#__PURE__*/react.createElement(ui_src/* ActionButtons */.wr, {
4000
+ t: t('MeasurementTable'),
4001
+ actions: [{
4002
+ label: 'Export',
4003
+ onClick: exportReport
4004
+ }, {
4005
+ label: 'Create Report',
4006
+ onClick: createReport
4007
+ }]
3845
4008
  })));
3846
4009
  }
3847
4010
  PanelMeasurementTable.propTypes = {
@@ -4060,8 +4223,8 @@ function areAllImageOrientationsEqual(instances) {
4060
4223
  }
4061
4224
  return true;
4062
4225
  }
4063
- // EXTERNAL MODULE: ../../../node_modules/gl-matrix/esm/index.js + 10 modules
4064
- var esm = __webpack_require__(83636);
4226
+ // EXTERNAL MODULE: ../../../node_modules/gl-matrix/esm/index.js + 1 modules
4227
+ var esm = __webpack_require__(44753);
4065
4228
  ;// CONCATENATED MODULE: ../../../extensions/default/src/utils/calculateScanAxisNormal.ts
4066
4229
 
4067
4230
 
@@ -4211,8 +4374,11 @@ function checkSingleFrames(instances, messages) {
4211
4374
  *
4212
4375
  * @param {Object[]} instances An array of `OHIFInstanceMetadata` objects.
4213
4376
  */
4214
- function getDisplaySetMessages(instances, isReconstructable) {
4377
+ function getDisplaySetMessages(instances, isReconstructable, isDynamicVolume) {
4215
4378
  const messages = new src/* DisplaySetMessageList */.WZ();
4379
+ if (isDynamicVolume) {
4380
+ return messages;
4381
+ }
4216
4382
  if (!instances.length) {
4217
4383
  messages.addMessage(src/* DisplaySetMessage */.Ob.CODES.NO_VALID_INSTANCES);
4218
4384
  return;
@@ -4273,6 +4439,86 @@ function getDisplaySetsFromUnsupportedSeries(instances) {
4273
4439
  });
4274
4440
  return [imageSet];
4275
4441
  }
4442
+ ;// CONCATENATED MODULE: ../../../extensions/default/src/SOPClassHandlers/chartSOPClassHandler.ts
4443
+
4444
+
4445
+ const SOPClassHandlerName = 'chart';
4446
+ const CHART_MODALITY = 'CHT';
4447
+
4448
+ // Private SOPClassUid for chart data
4449
+ const ChartDataSOPClassUid = '1.9.451.13215.7.3.2.7.6.1';
4450
+ const sopClassUids = [ChartDataSOPClassUid];
4451
+ const makeChartDataDisplaySet = (instance, sopClassUids) => {
4452
+ const {
4453
+ StudyInstanceUID,
4454
+ SeriesInstanceUID,
4455
+ SOPInstanceUID,
4456
+ SeriesDescription,
4457
+ SeriesNumber,
4458
+ SeriesDate,
4459
+ SOPClassUID
4460
+ } = instance;
4461
+ return {
4462
+ Modality: CHART_MODALITY,
4463
+ loading: false,
4464
+ isReconstructable: false,
4465
+ displaySetInstanceUID: src.utils.guid(),
4466
+ SeriesDescription,
4467
+ SeriesNumber,
4468
+ SeriesDate,
4469
+ SOPInstanceUID,
4470
+ SeriesInstanceUID,
4471
+ StudyInstanceUID,
4472
+ SOPClassHandlerId: `${id}.sopClassHandlerModule.${SOPClassHandlerName}`,
4473
+ SOPClassUID,
4474
+ isDerivedDisplaySet: true,
4475
+ isLoaded: true,
4476
+ sopClassUids,
4477
+ instance,
4478
+ instances: [instance],
4479
+ /**
4480
+ * Adds instances to the chart displaySet, rather than creating a new one
4481
+ * when user moves to a different workflow step and gets back to a step that
4482
+ * recreates the chart
4483
+ */
4484
+ addInstances: function (instances, _displaySetService) {
4485
+ this.instances.push(...instances);
4486
+ this.instance = this.instances[this.instances.length - 1];
4487
+ return this;
4488
+ }
4489
+ };
4490
+ };
4491
+ function getSopClassUids(instances) {
4492
+ const uniqueSopClassUidsInSeries = new Set();
4493
+ instances.forEach(instance => {
4494
+ uniqueSopClassUidsInSeries.add(instance.SOPClassUID);
4495
+ });
4496
+ const sopClassUids = Array.from(uniqueSopClassUidsInSeries);
4497
+ return sopClassUids;
4498
+ }
4499
+ function _getDisplaySetsFromSeries(instances) {
4500
+ debugger;
4501
+ // If the series has no instances, stop here
4502
+ if (!instances || !instances.length) {
4503
+ throw new Error('No instances were provided');
4504
+ }
4505
+ const sopClassUids = getSopClassUids(instances);
4506
+ const displaySets = instances.map(instance => {
4507
+ if (instance.Modality === CHART_MODALITY) {
4508
+ return makeChartDataDisplaySet(instance, sopClassUids);
4509
+ }
4510
+ throw new Error('Unsupported modality');
4511
+ });
4512
+ return displaySets;
4513
+ }
4514
+ const chartHandler = {
4515
+ name: SOPClassHandlerName,
4516
+ sopClassUids,
4517
+ getDisplaySetsFromSeries: instances => {
4518
+ return _getDisplaySetsFromSeries(instances);
4519
+ }
4520
+ };
4521
+
4276
4522
  ;// CONCATENATED MODULE: ../../../extensions/default/src/getSopClassHandlerModule.js
4277
4523
 
4278
4524
 
@@ -4281,20 +4527,69 @@ function getDisplaySetsFromUnsupportedSeries(instances) {
4281
4527
 
4282
4528
 
4283
4529
 
4530
+
4531
+ const DEFAULT_VOLUME_LOADER_SCHEME = 'cornerstoneStreamingImageVolume';
4532
+ const DYNAMIC_VOLUME_LOADER_SCHEME = 'cornerstoneStreamingDynamicImageVolume';
4284
4533
  const sopClassHandlerName = 'stack';
4534
+ let appContext = {};
4535
+ const getDynamicVolumeInfo = instances => {
4536
+ const {
4537
+ extensionManager
4538
+ } = appContext;
4539
+ if (!extensionManager) {
4540
+ throw new Error('extensionManager is not available');
4541
+ }
4542
+ const imageIds = instances.map(({
4543
+ imageId
4544
+ }) => imageId);
4545
+ const volumeLoaderUtility = extensionManager.getModuleEntry('@ohif/extension-cornerstone.utilityModule.volumeLoader');
4546
+ const {
4547
+ getDynamicVolumeInfo: csGetDynamicVolumeInfo
4548
+ } = volumeLoaderUtility.exports;
4549
+ return csGetDynamicVolumeInfo(imageIds);
4550
+ };
4285
4551
  const isMultiFrame = instance => {
4286
4552
  return instance.NumberOfFrames > 1;
4287
4553
  };
4554
+ function getDisplaySetInfo(instances) {
4555
+ const dynamicVolumeInfo = getDynamicVolumeInfo(instances);
4556
+ const {
4557
+ isDynamicVolume,
4558
+ timePoints
4559
+ } = dynamicVolumeInfo;
4560
+ let displaySetInfo;
4561
+ if (isDynamicVolume) {
4562
+ const timePoint = timePoints[0];
4563
+ const instancesMap = new Map();
4564
+
4565
+ // O(n) to convert it into a map and O(1) to find each instance
4566
+ instances.forEach(instance => instancesMap.set(instance.imageId, instance));
4567
+ const firstTimePointInstances = timePoint.map(imageId => instancesMap.get(imageId));
4568
+ displaySetInfo = (0,isDisplaySetReconstructable/* default */.Ay)(firstTimePointInstances);
4569
+ } else {
4570
+ displaySetInfo = (0,isDisplaySetReconstructable/* default */.Ay)(instances);
4571
+ }
4572
+ return {
4573
+ isDynamicVolume,
4574
+ ...displaySetInfo,
4575
+ dynamicVolumeInfo
4576
+ };
4577
+ }
4288
4578
  const makeDisplaySet = instances => {
4289
4579
  const instance = instances[0];
4290
4580
  const imageSet = new ImageSet/* default */.A(instances);
4291
4581
  const {
4582
+ isDynamicVolume,
4292
4583
  value: isReconstructable,
4293
- averageSpacingBetweenFrames
4294
- } = (0,isDisplaySetReconstructable/* default */.Ay)(instances);
4584
+ averageSpacingBetweenFrames,
4585
+ dynamicVolumeInfo
4586
+ } = getDisplaySetInfo(instances);
4587
+ const volumeLoaderSchema = isDynamicVolume ? DYNAMIC_VOLUME_LOADER_SCHEME : DEFAULT_VOLUME_LOADER_SCHEME;
4588
+
4295
4589
  // set appropriate attributes to image set...
4296
- const messages = getDisplaySetMessages(instances, isReconstructable);
4590
+ const messages = getDisplaySetMessages(instances, isReconstructable, isDynamicVolume);
4297
4591
  imageSet.setAttributes({
4592
+ volumeLoaderSchema,
4298
4593
  displaySetInstanceUID: imageSet.uid,
4299
4594
  // create a local alias for the imageSet UID
4300
4595
  SeriesDate: instance.SeriesDate,
@@ -4312,7 +4607,9 @@ const makeDisplaySet = instances => {
4312
4607
  SOPClassHandlerId: `${id}.sopClassHandlerModule.${sopClassHandlerName}`,
4313
4608
  isReconstructable,
4314
4609
  messages,
4315
- averageSpacingBetweenFrames: averageSpacingBetweenFrames || null
4610
+ averageSpacingBetweenFrames: averageSpacingBetweenFrames || null,
4611
+ isDynamicVolume,
4612
+ dynamicVolumeInfo
4316
4613
  });
4317
4614
 
4318
4615
  // Sort the images in this series if needed
@@ -4343,7 +4640,7 @@ const makeDisplaySet = instances => {
4343
4640
  const isSingleImageModality = modality => {
4344
4641
  return modality === 'CR' || modality === 'MG' || modality === 'DX';
4345
4642
  };
4346
- function getSopClassUids(instances) {
4643
+ function getSopClassHandlerModule_getSopClassUids(instances) {
4347
4644
  const uniqueSopClassUidsInSeries = new Set();
4348
4645
  instances.forEach(instance => {
4349
4646
  uniqueSopClassUidsInSeries.add(instance.SOPClassUID);
@@ -4357,7 +4654,6 @@ function getSopClassUids(instances) {
4357
4654
  * - For all Image types that are stackable, create
4358
4655
  * a displaySet with a stack of images
4359
4656
  *
4360
- * @param {Array} sopClassHandlerModules List of SOP Class Modules
4361
4657
  * @param {SeriesMetadata} series The series metadata object from which the display sets will be created
4362
4658
  * @returns {Array} The list of display sets created for the given series object
4363
4659
  */
@@ -4367,7 +4663,7 @@ function getDisplaySetsFromSeries(instances) {
4367
4663
  throw new Error('No instances were provided');
4368
4664
  }
4369
4665
  const displaySets = [];
4370
- const sopClassUids = getSopClassUids(instances);
4666
+ const sopClassUids = getSopClassHandlerModule_getSopClassUids(instances);
4371
4667
 
4372
4668
  // Search through the instances (InstanceMetadata object) of this series
4373
4669
  // Split Multi-frame instances and Single-image modalities
@@ -4412,16 +4708,21 @@ function getDisplaySetsFromSeries(instances) {
4412
4708
  }
4413
4709
  return displaySets;
4414
4710
  }
4415
- const 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];
4416
- function getSopClassHandlerModule() {
4711
+ 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];
4712
+ function getSopClassHandlerModule(appContextParam) {
4713
+ appContext = appContextParam;
4417
4714
  return [{
4418
4715
  name: sopClassHandlerName,
4419
- sopClassUids,
4716
+ sopClassUids: getSopClassHandlerModule_sopClassUids,
4420
4717
  getDisplaySetsFromSeries
4421
4718
  }, {
4422
4719
  name: 'not-supported-display-sets-handler',
4423
4720
  sopClassUids: [],
4424
4721
  getDisplaySetsFromSeries: getDisplaySetsFromUnsupportedSeries
4722
+ }, {
4723
+ name: chartHandler.name,
4724
+ sopClassUids: chartHandler.sopClassUids,
4725
+ getDisplaySetsFromSeries: chartHandler.getDisplaySetsFromSeries
4425
4726
  }];
4426
4727
  }
4427
4728
  /* harmony default export */ const src_getSopClassHandlerModule = (getSopClassHandlerModule);
@@ -4721,12 +5022,97 @@ function ToolbarButtonGroupWithServices({
4721
5022
  return /*#__PURE__*/react.createElement(ui_src/* ButtonGroup */.e2, null, getSplitButtonItems(items));
4722
5023
  }
4723
5024
  /* harmony default export */ const Toolbar_ToolbarButtonGroupWithServices = (ToolbarButtonGroupWithServices);
5025
+ ;// CONCATENATED MODULE: ../../../extensions/default/src/components/ProgressDropdownWithService/ProgressDropdownWithService.tsx
5026
+
5027
+
5028
+ const workflowStepsToDropdownOptions = (steps = []) => steps.map(step => ({
5029
+ label: step.name,
5030
+ value: step.id,
5031
+ info: step.info,
5032
+ activated: false,
5033
+ completed: false
5034
+ }));
5035
+ function ProgressDropdownWithService({
5036
+ servicesManager
5037
+ }) {
5038
+ const {
5039
+ workflowStepsService
5040
+ } = servicesManager.services;
5041
+ const [activeStepId, setActiveStepId] = (0,react.useState)(workflowStepsService.activeWorkflowStep?.id);
5042
+ const [dropdownOptions, setDropdownOptions] = (0,react.useState)(workflowStepsToDropdownOptions(workflowStepsService.workflowSteps));
5043
+ const setCurrentAndPreviousOptionsAsCompleted = (0,react.useCallback)(currentOption => {
5044
+ if (currentOption.completed) {
5045
+ return;
5046
+ }
5047
+ setDropdownOptions(prevOptions => {
5048
+ const newOptionsState = [...prevOptions];
5049
+ const startIndex = newOptionsState.findIndex(option => option.value === currentOption.value);
5050
+ for (let i = startIndex; i >= 0; i--) {
5051
+ const option = newOptionsState[i];
5052
+ if (option.completed) {
5053
+ break;
5054
+ }
5055
+ newOptionsState[i] = {
5056
+ ...option,
5057
+ completed: true
5058
+ };
5059
+ }
5060
+ return newOptionsState;
5061
+ });
5062
+ }, []);
5063
+ const handleDropdownChange = (0,react.useCallback)(({
5064
+ selectedOption
5065
+ }) => {
5066
+ if (!selectedOption) {
5067
+ return;
5068
+ }
5069
+
5070
+ // TODO: Steps should be marked as completed after user has
5071
+ // completed some action when required (not implemented)
5072
+ setCurrentAndPreviousOptionsAsCompleted(selectedOption);
5073
+ setActiveStepId(selectedOption.value);
5074
+ }, [setCurrentAndPreviousOptionsAsCompleted]);
5075
+ (0,react.useEffect)(() => {
5076
+ let timeoutId;
5077
+ if (activeStepId) {
5078
+ // We've used setTimeout to give it more time to update the UI since
5079
+ // create3DFilterableFromDataArray from Texture.js may take 600+ ms to run
5080
+ // when there is a new series to load in the next step but that resulted
5081
+ // in the followed React error when updating the content from left/right panels
5082
+ // and all component states were being lost:
5083
+ // Error: Can't perform a React state update on an unmounted component
5084
+ workflowStepsService.setActiveWorkflowStep(activeStepId);
5085
+ }
5086
+ return () => clearTimeout(timeoutId);
5087
+ }, [activeStepId, workflowStepsService]);
5088
+ (0,react.useEffect)(() => {
5089
+ const {
5090
+ unsubscribe: unsubStepsChanged
5091
+ } = workflowStepsService.subscribe(workflowStepsService.EVENTS.STEPS_CHANGED, () => setDropdownOptions(workflowStepsToDropdownOptions(workflowStepsService.workflowSteps)));
5092
+ const {
5093
+ unsubscribe: unsubActiveStepChanged
5094
+ } = workflowStepsService.subscribe(workflowStepsService.EVENTS.ACTIVE_STEP_CHANGED, () => setActiveStepId(workflowStepsService.activeWorkflowStep.id));
5095
+ return () => {
5096
+ unsubStepsChanged();
5097
+ unsubActiveStepChanged();
5098
+ };
5099
+ }, [servicesManager, workflowStepsService]);
5100
+ return /*#__PURE__*/react.createElement(ui_src/* ProgressDropdown */.LW, {
5101
+ options: dropdownOptions,
5102
+ value: activeStepId,
5103
+ onChange: handleDropdownChange
5104
+ });
5105
+ }
5106
+ /* harmony default export */ const ProgressDropdownWithService_ProgressDropdownWithService = (ProgressDropdownWithService);
5107
+ ;// CONCATENATED MODULE: ../../../extensions/default/src/components/ProgressDropdownWithService/index.js
5108
+
4724
5109
  ;// CONCATENATED MODULE: ../../../extensions/default/src/getToolbarModule.tsx
4725
5110
 
4726
5111
 
4727
5112
 
4728
5113
 
4729
5114
 
5115
+
4730
5116
  const getClassName = isToggled => {
4731
5117
  return {
4732
5118
  className: isToggled ? '!text-primary-active' : '!text-common-bright hover:!bg-primary-dark hover:text-primary-light'
@@ -4758,6 +5144,9 @@ function getToolbarModule({
4758
5144
  }, {
4759
5145
  name: 'ohif.buttonGroup',
4760
5146
  defaultComponent: Toolbar_ToolbarButtonGroupWithServices
5147
+ }, {
5148
+ name: 'ohif.progressDropdown',
5149
+ defaultComponent: ProgressDropdownWithService_ProgressDropdownWithService
4761
5150
  }, {
4762
5151
  name: 'evaluate.group.promoteToPrimary',
4763
5152
  evaluate: ({
@@ -4956,10 +5345,10 @@ function adaptItem(item, subProps) {
4956
5345
  }
4957
5346
  // EXTERNAL MODULE: ../../ui/src/components/ContextMenu/ContextMenu.tsx
4958
5347
  var ContextMenu = __webpack_require__(59852);
4959
- // EXTERNAL MODULE: ../../../node_modules/@cornerstonejs/tools/dist/esm/index.js + 16 modules
4960
- var dist_esm = __webpack_require__(20767);
5348
+ // EXTERNAL MODULE: ../../../node_modules/@cornerstonejs/tools/dist/esm/index.js + 18 modules
5349
+ var dist_esm = __webpack_require__(24542);
4961
5350
  ;// CONCATENATED MODULE: ../../../extensions/default/src/CustomizableContextMenu/ContextMenuController.tsx
4962
- var _class;
5351
+ var _ContextMenuController;
4963
5352
 
4964
5353
 
4965
5354
 
@@ -5074,7 +5463,7 @@ class ContextMenuController {
5074
5463
  });
5075
5464
  }
5076
5465
  }
5077
- _class = ContextMenuController;
5466
+ _ContextMenuController = ContextMenuController;
5078
5467
  ContextMenuController.getDefaultPosition = () => {
5079
5468
  return {
5080
5469
  x: 0,
@@ -5099,13 +5488,13 @@ ContextMenuController._getElementDefaultPosition = element => {
5099
5488
  };
5100
5489
  };
5101
5490
  ContextMenuController._getCanvasPointsPosition = (points = [], element) => {
5102
- const viewerPos = _class._getElementDefaultPosition(element);
5491
+ const viewerPos = _ContextMenuController._getElementDefaultPosition(element);
5103
5492
  for (let pointIndex = 0; pointIndex < points.length; pointIndex++) {
5104
5493
  const point = {
5105
5494
  x: points[pointIndex][0] || points[pointIndex]['x'],
5106
5495
  y: points[pointIndex][1] || points[pointIndex]['y']
5107
5496
  };
5108
- if (_class._isValidPosition(point) && _class._isValidPosition(viewerPos)) {
5497
+ if (_ContextMenuController._isValidPosition(point) && _ContextMenuController._isValidPosition(viewerPos)) {
5109
5498
  return {
5110
5499
  x: point.x + viewerPos.x,
5111
5500
  y: point.y + viewerPos.y
@@ -5121,17 +5510,17 @@ ContextMenuController._isValidPosition = source => {
5121
5510
  */
5122
5511
  ContextMenuController._getDefaultPosition = (canvasPoints, eventDetail, viewerElement) => {
5123
5512
  function* getPositionIterator() {
5124
- yield _class._getCanvasPointsPosition(canvasPoints, viewerElement);
5125
- yield _class._getEventDefaultPosition(eventDetail);
5126
- yield _class._getElementDefaultPosition(viewerElement);
5127
- yield _class.getDefaultPosition();
5513
+ yield _ContextMenuController._getCanvasPointsPosition(canvasPoints, viewerElement);
5514
+ yield _ContextMenuController._getEventDefaultPosition(eventDetail);
5515
+ yield _ContextMenuController._getElementDefaultPosition(viewerElement);
5516
+ yield _ContextMenuController.getDefaultPosition();
5128
5517
  }
5129
5518
  const positionIterator = getPositionIterator();
5130
5519
  let current = positionIterator.next();
5131
5520
  let position = current.value;
5132
5521
  while (!current.done) {
5133
5522
  position = current.value;
5134
- if (_class._isValidPosition(position)) {
5523
+ if (_ContextMenuController._isValidPosition(position)) {
5135
5524
  positionIterator.return();
5136
5525
  }
5137
5526
  current = positionIterator.next();
@@ -5684,6 +6073,9 @@ const reuseCachedLayout = (state, hangingProtocolService, syncService) => {
5684
6073
  const {
5685
6074
  protocol
5686
6075
  } = hangingProtocolService.getActiveProtocol();
6076
+ if (!protocol) {
6077
+ return;
6078
+ }
5687
6079
  const hpInfo = hangingProtocolService.getState();
5688
6080
  const {
5689
6081
  protocolId,
@@ -5857,12 +6249,6 @@ var index = __webpack_require__(68870);
5857
6249
  const {
5858
6250
  subscribeToNextViewportGridChange
5859
6251
  } = src.utils;
5860
- /**
5861
- * Determine if a command is a hanging protocol one.
5862
- * For now, just use the two hanging protocol commands that are in this
5863
- * commands module, but if others get added elsewhere this may need enhancing.
5864
- */
5865
- const isHangingProtocolCommand = command => command && (command.commandName === 'setHangingProtocol' || command.commandName === 'toggleHangingProtocol');
5866
6252
  const commandsModule = ({
5867
6253
  servicesManager,
5868
6254
  commandsManager
@@ -5874,8 +6260,7 @@ const commandsModule = ({
5874
6260
  uiNotificationService,
5875
6261
  viewportGridService,
5876
6262
  displaySetService,
5877
- stateSyncService,
5878
- toolbarService
6263
+ stateSyncService
5879
6264
  } = servicesManager.services;
5880
6265
 
5881
6266
  // Define a context menu controller for use with any context menus
@@ -7382,6 +7767,7 @@ class GoogleCloudDataSourceConfigurationAPI {
7382
7767
 
7383
7768
 
7384
7769
 
7770
+
7385
7771
  /**
7386
7772
  *
7387
7773
  * Note: this is an example of how the customization module can be used
@@ -7519,9 +7905,60 @@ function getCustomizationModule({
7519
7905
  // The factory for creating an instance of a BaseDataSourceConfigurationAPI for Google Cloud Healthcare
7520
7906
  id: 'ohif.dataSourceConfigurationAPI.google',
7521
7907
  factory: dataSourceName => new GoogleCloudDataSourceConfigurationAPI(dataSourceName, servicesManager, extensionManager)
7908
+ }, {
7909
+ id: 'progressDropdownWithServiceComponent',
7910
+ component: ProgressDropdownWithService_ProgressDropdownWithService
7522
7911
  }]
7523
7912
  }];
7524
7913
  }
7914
+ ;// CONCATENATED MODULE: ../../../extensions/default/src/Components/LineChartViewport/LineChartViewport.tsx
7915
+
7916
+
7917
+ const LineChartViewport = ({
7918
+ displaySets
7919
+ }) => {
7920
+ const displaySet = displaySets[0];
7921
+ const {
7922
+ axis: chartAxis,
7923
+ series: chartSeries
7924
+ } = displaySet.instance.chartData;
7925
+ return /*#__PURE__*/react.createElement(ui_src/* LineChart */.bl, {
7926
+ showLegend: true,
7927
+ legendWidth: 150,
7928
+ axis: {
7929
+ x: {
7930
+ label: chartAxis.x.label,
7931
+ indexRef: 0,
7932
+ type: 'x',
7933
+ range: {
7934
+ min: 0
7935
+ }
7936
+ },
7937
+ y: {
7938
+ label: chartAxis.y.label,
7939
+ indexRef: 1,
7940
+ type: 'y'
7941
+ }
7942
+ },
7943
+ series: chartSeries
7944
+ });
7945
+ };
7946
+
7947
+ ;// CONCATENATED MODULE: ../../../extensions/default/src/Components/LineChartViewport/index.ts
7948
+
7949
+ ;// CONCATENATED MODULE: ../../../extensions/default/src/getViewportModule.tsx
7950
+
7951
+ const getViewportModule = ({
7952
+ servicesManager,
7953
+ commandsManager,
7954
+ extensionManager
7955
+ }) => {
7956
+ return [{
7957
+ name: 'chartViewport',
7958
+ component: LineChartViewport
7959
+ }];
7960
+ };
7961
+
7525
7962
  // EXTERNAL MODULE: ../../../node_modules/@cornerstonejs/calculate-suv/dist/calculate-suv.esm.js
7526
7963
  var calculate_suv_esm = __webpack_require__(79717);
7527
7964
  ;// CONCATENATED MODULE: ../../../extensions/default/src/getPTImageIdInstanceMetadata.ts
@@ -7686,7 +8123,7 @@ function init({
7686
8123
  groupId,
7687
8124
  items,
7688
8125
  listeners
7689
- } = button.props;
8126
+ } = button.props || {};
7690
8127
 
7691
8128
  // Handle group items' listeners
7692
8129
  if (groupId && items) {
@@ -7759,6 +8196,8 @@ const handlePETImageMetadata = ({
7759
8196
 
7760
8197
 
7761
8198
 
8199
+
8200
+
7762
8201
  const defaultExtension = {
7763
8202
  /**
7764
8203
  * Only required property. Should be a unique value across all extensions.
@@ -7766,6 +8205,7 @@ const defaultExtension = {
7766
8205
  id: id,
7767
8206
  preRegistration: init,
7768
8207
  getDataSourcesModule: src_getDataSourcesModule,
8208
+ getViewportModule: getViewportModule,
7769
8209
  getLayoutTemplateModule: getLayoutTemplateModule,
7770
8210
  getPanelModule: src_getPanelModule,
7771
8211
  getHangingProtocolModule: src_getHangingProtocolModule,