@ohif/app 3.7.0-beta.61 → 3.7.0-beta.63

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 (38) hide show
  1. package/dist/{12.bundle.c54b94d07d31f5716eb1.js → 12.bundle.c80ff2e8651297d7aec8.js} +2 -2
  2. package/dist/{125.bundle.1ae4c6313c31cd0502cc.js → 125.bundle.aeaad798561853bf6939.js} +2 -2
  3. package/dist/{128.bundle.b0a7aa9ae66c094c40b5.js → 128.bundle.8d7db97e0d90ba8be751.js} +3 -3
  4. package/dist/{150.bundle.2075342642eddc35e924.js → 150.bundle.0ed8ccb7f15a603151b6.js} +17 -11
  5. package/dist/{181.bundle.70c4340cbe29bd14aafc.js → 181.bundle.1accc89eac7f1b4bc752.js} +96 -92
  6. package/dist/{236.bundle.4aab776fb3e7654f1f0c.js → 236.bundle.308648f0e447eaaeda67.js} +37 -62
  7. package/dist/{250.bundle.0d497b1b8afb0cbbe02f.js → 250.bundle.1543b1b8466d43f3465d.js} +17 -13
  8. package/dist/{281.bundle.c35a76364b385ee72bfd.js → 281.bundle.015cf8cb9625c7fb3dd5.js} +2 -2
  9. package/dist/{30.bundle.777231cf20f408db12f1.js → 30.bundle.4d8b67d4ed86238948ca.js} +64 -62
  10. package/dist/{348.bundle.be4810ac9ac67cd7d8c5.js → 348.bundle.81366dddd24e78113662.js} +3 -3
  11. package/dist/{359.bundle.d723d31672f7fe575501.js → 359.bundle.1c14405c9d974bb5a30f.js} +3 -3
  12. package/dist/{362.bundle.9d4d81eab3e31314a932.js → 362.bundle.11a6a0792b8042b5c81b.js} +160 -133
  13. package/dist/{410.bundle.f973e56e3a7d8165d87a.js → 410.bundle.c0ed86f4d3cbc0939903.js} +3 -3
  14. package/dist/{451.bundle.a573877dff7b43382138.js → 451.bundle.b3d9a67d4b2a962be96b.js} +26 -26
  15. package/dist/{471.bundle.e9ecd59867a19e323234.js → 471.bundle.87b1c57d4c04ae35cb88.js} +26 -26
  16. package/dist/{506.bundle.8b2c661a99271b31663c.js → 506.bundle.a9e9ceb9fc71cdf45d91.js} +14 -7
  17. package/dist/{663.bundle.80190c7364dd4095010b.js → 663.bundle.05e8cc381eadc38f9755.js} +4 -4
  18. package/dist/{678.bundle.adc83cac2fd0ea4f19f2.js → 678.bundle.784d7fb157d76611068d.js} +190 -246
  19. package/dist/{686.bundle.70565410179f1e7d22e6.js → 686.bundle.b3dbf84eefbef768843f.js} +2 -2
  20. package/dist/{378.bundle.3069476ee6501c83ad44.js → 687.bundle.3de11e7a373ee3588813.js} +210 -3
  21. package/dist/{754.bundle.1884c227b361aefa66b4.js → 754.bundle.7ae67c55a90a6a2d8494.js} +14 -5
  22. package/dist/{782.bundle.fc7e353f1dce39953254.js → 782.bundle.082672a46147b8402d4a.js} +58 -39
  23. package/dist/{814.bundle.9218ffc353490526c320.js → 814.bundle.35355762730e3b4ee89f.js} +2 -2
  24. package/dist/{822.bundle.99bf759483aa32086346.js → 822.bundle.00dacc09a7d028fca29b.js} +21 -23
  25. package/dist/{886.bundle.c5a6b96760ea43352375.js → 886.bundle.d0915318107cf24e8beb.js} +19 -20
  26. package/dist/{925.bundle.7b06521fc75e0d3f71c3.js → 925.bundle.5e929605d3235ebcdebf.js} +7 -4
  27. package/dist/app.bundle.css +1 -1
  28. package/dist/{app.bundle.2a91a8b9b9e61b42cc21.js → app.bundle.eeda76c463f838f592c1.js} +603 -600
  29. package/dist/assets/yandex-browser-manifest.json +1 -1
  30. package/dist/es6-shim.min.js +3569 -2
  31. package/dist/google.js +1 -2
  32. package/dist/index.html +1 -1
  33. package/dist/init-service-worker.js +3 -5
  34. package/dist/oidc-client.min.js +10857 -39
  35. package/dist/polyfill.min.js +184 -1
  36. package/dist/silent-refresh.html +18 -9
  37. package/dist/sw.js +1 -1
  38. package/package.json +19 -19
@@ -29,8 +29,8 @@ __webpack_require__.d(utils_namespaceObject, {
29
29
 
30
30
  // EXTERNAL MODULE: ../../../node_modules/dicomweb-client/build/dicomweb-client.es.js
31
31
  var dicomweb_client_es = __webpack_require__(97604);
32
- // EXTERNAL MODULE: ../../core/src/index.ts + 106 modules
33
- var src = __webpack_require__(38930);
32
+ // EXTERNAL MODULE: ../../core/src/index.ts + 107 modules
33
+ var src = __webpack_require__(3854);
34
34
  // EXTERNAL MODULE: ../../core/src/utils/sortStudy.ts
35
35
  var sortStudy = __webpack_require__(62971);
36
36
  ;// CONCATENATED MODULE: ../../../extensions/default/src/DicomWebDataSource/qido.js
@@ -2055,7 +2055,7 @@ var es = __webpack_require__(69190);
2055
2055
  // EXTERNAL MODULE: ../node_modules/react-router/dist/index.js
2056
2056
  var react_router_dist = __webpack_require__(85066);
2057
2057
  // EXTERNAL MODULE: ../../ui/src/index.js + 458 modules
2058
- var ui_src = __webpack_require__(33570);
2058
+ var ui_src = __webpack_require__(88344);
2059
2059
  // EXTERNAL MODULE: ../../i18n/src/index.js + 98 modules
2060
2060
  var i18n_src = __webpack_require__(43040);
2061
2061
  // EXTERNAL MODULE: ./state/index.js + 1 modules
@@ -2211,8 +2211,8 @@ function ViewerLayout(_ref) {
2211
2211
  hotkeyDefinitions,
2212
2212
  hotkeyDefaults
2213
2213
  } = hotkeysManager;
2214
- const versionNumber = "3.7.0-beta.61";
2215
- const commitHash = "35fc30c5359d8199cc38ffa670c08687d2672f11";
2214
+ const versionNumber = "3.7.0-beta.63";
2215
+ const commitHash = "9045ddaedca2eb852d8e0652dc6c403db12ce05b";
2216
2216
  const menuOptions = [{
2217
2217
  title: t('Header:About'),
2218
2218
  icon: 'info',
@@ -2346,7 +2346,7 @@ function ViewerLayout(_ref) {
2346
2346
  }, /*#__PURE__*/react.createElement(Toolbar, {
2347
2347
  servicesManager: servicesManager
2348
2348
  })))), /*#__PURE__*/react.createElement("div", {
2349
- className: "bg-black flex flex-row items-stretch w-full overflow-hidden flex-nowrap relative",
2349
+ className: "relative flex w-full flex-row flex-nowrap items-stretch overflow-hidden bg-black",
2350
2350
  style: {
2351
2351
  height: 'calc(100vh - 52px'
2352
2352
  }
@@ -2360,9 +2360,9 @@ function ViewerLayout(_ref) {
2360
2360
  tabs: leftPanelComponents,
2361
2361
  servicesManager: servicesManager
2362
2362
  })) : null, /*#__PURE__*/react.createElement("div", {
2363
- className: "flex flex-col flex-1 h-full"
2363
+ className: "flex h-full flex-1 flex-col"
2364
2364
  }, /*#__PURE__*/react.createElement("div", {
2365
- className: "flex items-center justify-center flex-1 h-full overflow-hidden bg-black relative"
2365
+ className: "relative flex h-full flex-1 items-center justify-center overflow-hidden bg-black"
2366
2366
  }, /*#__PURE__*/react.createElement(ui_src/* ErrorBoundary */.SV, {
2367
2367
  context: "Grid"
2368
2368
  }, /*#__PURE__*/react.createElement(ViewportGridComp, {
@@ -2464,7 +2464,7 @@ function PanelStudyBrowser(_ref) {
2464
2464
  StudyInstanceUIDs
2465
2465
  } = (0,ui_src/* useImageViewer */.zG)();
2466
2466
  const [{
2467
- activeViewportIndex,
2467
+ activeViewportId,
2468
2468
  viewports
2469
2469
  }, viewportGridService] = (0,ui_src/* useViewportGrid */.O_)();
2470
2470
  const [activeTabName, setActiveTabName] = (0,react.useState)('primary');
@@ -2475,9 +2475,9 @@ function PanelStudyBrowser(_ref) {
2475
2475
  const isMounted = (0,react.useRef)(true);
2476
2476
  const onDoubleClickThumbnailHandler = displaySetInstanceUID => {
2477
2477
  let updatedViewports = [];
2478
- const viewportIndex = activeViewportIndex;
2478
+ const viewportId = activeViewportId;
2479
2479
  try {
2480
- updatedViewports = hangingProtocolService.getViewportsRequireUpdate(viewportIndex, displaySetInstanceUID);
2480
+ updatedViewports = hangingProtocolService.getViewportsRequireUpdate(viewportId, displaySetInstanceUID);
2481
2481
  } catch (error) {
2482
2482
  console.warn(error);
2483
2483
  uiNotificationService.show({
@@ -2636,7 +2636,7 @@ function PanelStudyBrowser(_ref) {
2636
2636
  requestDisplaySetCreationForStudy(displaySetService, StudyInstanceUID, madeInClient);
2637
2637
  }
2638
2638
  }
2639
- const activeDisplaySetInstanceUIDs = viewports[activeViewportIndex]?.displaySetInstanceUIDs;
2639
+ const activeDisplaySetInstanceUIDs = viewports.get(activeViewportId)?.displaySetInstanceUIDs;
2640
2640
  return /*#__PURE__*/react.createElement(ui_src/* StudyBrowser */.eX, {
2641
2641
  tabs: tabs,
2642
2642
  servicesManager: servicesManager,
@@ -3023,7 +3023,7 @@ function createReportDialogPrompt(uiDialogService, _ref) {
3023
3023
  };
3024
3024
  return /*#__PURE__*/react.createElement(react.Fragment, null, dataSourcesOpts.length > 1 && /*#__PURE__*/react.createElement(ui_src/* Select */.Ph, {
3025
3025
  closeMenuOnSelect: true,
3026
- className: "mr-2 bg-black border-primary-main",
3026
+ className: "border-primary-main mr-2 bg-black",
3027
3027
  options: dataSourcesOpts,
3028
3028
  placeholder: dataSourcesOpts.find(option => option.value === value.dataSourceName).placeHolder,
3029
3029
  value: value.dataSourceName,
@@ -3038,7 +3038,7 @@ function createReportDialogPrompt(uiDialogService, _ref) {
3038
3038
  autoFocus: true,
3039
3039
  label: "Enter the report name",
3040
3040
  labelClassName: "text-white text-[14px] leading-[1.2]",
3041
- className: "bg-black border-primary-main",
3041
+ className: "border-primary-main bg-black",
3042
3042
  type: "text",
3043
3043
  value: value.label,
3044
3044
  onChange: onChangeHandler,
@@ -3189,7 +3189,7 @@ function PanelMeasurementTable(_ref) {
3189
3189
  } = _ref;
3190
3190
  const [viewportGrid, viewportGridService] = (0,ui_src/* useViewportGrid */.O_)();
3191
3191
  const {
3192
- activeViewportIndex,
3192
+ activeViewportId,
3193
3193
  viewports
3194
3194
  } = viewportGrid;
3195
3195
  const {
@@ -3232,7 +3232,7 @@ function PanelMeasurementTable(_ref) {
3232
3232
  }
3233
3233
  async function createReport() {
3234
3234
  // filter measurements that are added to the active study
3235
- const activeViewport = viewports[activeViewportIndex];
3235
+ const activeViewport = viewports.get(activeViewportId);
3236
3236
  const measurements = measurementService.getMeasurements();
3237
3237
  const displaySet = displaySetService.getDisplaySetByUID(activeViewport.displaySetInstanceUIDs[0]);
3238
3238
  const trackedMeasurements = measurements.filter(m => displaySet.StudyInstanceUID === m.referenceStudyUID);
@@ -3267,7 +3267,7 @@ function PanelMeasurementTable(_ref) {
3267
3267
  uid,
3268
3268
  isActive
3269
3269
  } = _ref2;
3270
- measurementService.jumpToMeasurement(viewportGrid.activeViewportIndex, uid);
3270
+ measurementService.jumpToMeasurement(viewportGrid.activeViewportId, uid);
3271
3271
  onMeasurementItemClickHandler({
3272
3272
  uid,
3273
3273
  isActive
@@ -3339,7 +3339,7 @@ function PanelMeasurementTable(_ref) {
3339
3339
  labelClassName: "text-white text-[14px] leading-[1.2]",
3340
3340
  autoFocus: true,
3341
3341
  id: "annotation",
3342
- className: "bg-black border-primary-main",
3342
+ className: "border-primary-main bg-black",
3343
3343
  type: "text",
3344
3344
  value: value.label,
3345
3345
  onChange: onChangeHandler,
@@ -3373,7 +3373,7 @@ function PanelMeasurementTable(_ref) {
3373
3373
  }
3374
3374
  };
3375
3375
  return /*#__PURE__*/react.createElement(react.Fragment, null, /*#__PURE__*/react.createElement("div", {
3376
- className: "overflow-x-hidden overflow-y-auto ohif-scrollbar",
3376
+ className: "ohif-scrollbar overflow-y-auto overflow-x-hidden",
3377
3377
  "data-cy": 'measurements-panel'
3378
3378
  }, /*#__PURE__*/react.createElement(ui_src/* MeasurementTable */.wt, {
3379
3379
  title: "Measurements",
@@ -3960,7 +3960,7 @@ function getSopClassHandlerModule() {
3960
3960
 
3961
3961
  function ToolbarDivider() {
3962
3962
  return /*#__PURE__*/react.createElement("span", {
3963
- className: "self-center w-4 h-8 mx-2 border-l border-common-dark"
3963
+ className: "border-common-dark mx-2 h-8 w-4 self-center border-l"
3964
3964
  });
3965
3965
  }
3966
3966
  ;// CONCATENATED MODULE: ../../../extensions/default/src/Toolbar/ToolbarLayoutSelector.tsx
@@ -4488,34 +4488,34 @@ function ColumnHeaders(_ref) {
4488
4488
  valueRef
4489
4489
  } = _ref;
4490
4490
  return /*#__PURE__*/react.createElement("div", {
4491
- className: classnames_default()('flex flex-row w-full bg-secondary-dark ohif-scrollbar overflow-y-scroll'),
4491
+ className: classnames_default()('bg-secondary-dark ohif-scrollbar flex w-full flex-row overflow-y-scroll'),
4492
4492
  style: rowVerticalPaddingStyle
4493
4493
  }, /*#__PURE__*/react.createElement("div", {
4494
- className: "px-3 w-4/24"
4494
+ className: "w-4/24 px-3"
4495
4495
  }, /*#__PURE__*/react.createElement("label", {
4496
4496
  ref: tagRef,
4497
- className: "flex flex-col flex-1 text-white text-lg pl-1 select-none"
4497
+ className: "flex flex-1 select-none flex-col pl-1 text-lg text-white"
4498
4498
  }, /*#__PURE__*/react.createElement("span", {
4499
4499
  className: "flex flex-row items-center focus:outline-none"
4500
4500
  }, "Tag"))), /*#__PURE__*/react.createElement("div", {
4501
- className: "px-3 w-2/24"
4501
+ className: "w-2/24 px-3"
4502
4502
  }, /*#__PURE__*/react.createElement("label", {
4503
4503
  ref: vrRef,
4504
- className: "flex flex-col flex-1 text-white text-lg pl-1 select-none"
4504
+ className: "flex flex-1 select-none flex-col pl-1 text-lg text-white"
4505
4505
  }, /*#__PURE__*/react.createElement("span", {
4506
4506
  className: "flex flex-row items-center focus:outline-none"
4507
4507
  }, "VR"))), /*#__PURE__*/react.createElement("div", {
4508
- className: "px-3 w-6/24"
4508
+ className: "w-6/24 px-3"
4509
4509
  }, /*#__PURE__*/react.createElement("label", {
4510
4510
  ref: keywordRef,
4511
- className: "flex flex-col flex-1 text-white text-lg pl-1 select-none"
4511
+ className: "flex flex-1 select-none flex-col pl-1 text-lg text-white"
4512
4512
  }, /*#__PURE__*/react.createElement("span", {
4513
4513
  className: "flex flex-row items-center focus:outline-none"
4514
4514
  }, "Keyword"))), /*#__PURE__*/react.createElement("div", {
4515
- className: "px-3 w-5/24 grow"
4515
+ className: "w-5/24 grow px-3"
4516
4516
  }, /*#__PURE__*/react.createElement("label", {
4517
4517
  ref: valueRef,
4518
- className: "flex flex-col flex-1 text-white text-lg pl-1 select-none"
4518
+ className: "flex flex-1 select-none flex-col pl-1 text-lg text-white"
4519
4519
  }, /*#__PURE__*/react.createElement("span", {
4520
4520
  className: "flex flex-row items-center focus:outline-none"
4521
4521
  }, "Value"))));
@@ -4588,16 +4588,16 @@ function DicomTagTable(_ref2) {
4588
4588
  ...style,
4589
4589
  ...rowStyle
4590
4590
  },
4591
- className: classnames_default()('hover:bg-secondary-main transition duration-300 bg-black flex flex-row w-full border-secondary-light items-center text-base break-all', lineHeightClassName),
4591
+ className: classnames_default()('hover:bg-secondary-main border-secondary-light flex w-full flex-row items-center break-all bg-black text-base transition duration-300', lineHeightClassName),
4592
4592
  key: `DICOMTagRow-${index}`
4593
4593
  }, /*#__PURE__*/react.createElement("div", {
4594
- className: "px-3 w-4/24"
4594
+ className: "w-4/24 px-3"
4595
4595
  }, row[0]), /*#__PURE__*/react.createElement("div", {
4596
- className: "px-3 w-2/24"
4596
+ className: "w-2/24 px-3"
4597
4597
  }, row[1]), /*#__PURE__*/react.createElement("div", {
4598
- className: "px-3 w-6/24"
4598
+ className: "w-6/24 px-3"
4599
4599
  }, row[2]), /*#__PURE__*/react.createElement("div", {
4600
- className: "px-3 w-5/24 grow"
4600
+ className: "w-5/24 grow px-3"
4601
4601
  }, row[3]));
4602
4602
  }, [rows]);
4603
4603
 
@@ -4635,7 +4635,7 @@ function DicomTagTable(_ref2) {
4635
4635
  keywordRef: keywordRef,
4636
4636
  valueRef: valueRef
4637
4637
  }), /*#__PURE__*/react.createElement("div", {
4638
- className: "m-auto relative border-2 border-black bg-black",
4638
+ className: "relative m-auto border-2 border-black bg-black",
4639
4639
  style: {
4640
4640
  height: '32rem'
4641
4641
  }
@@ -4754,14 +4754,14 @@ const DicomTagBrowser = _ref => {
4754
4754
  return /*#__PURE__*/react.createElement("div", {
4755
4755
  className: "dicom-tag-browser-content"
4756
4756
  }, /*#__PURE__*/react.createElement("div", {
4757
- className: "flex flex-row mb-6 items-center pl-1"
4757
+ className: "mb-6 flex flex-row items-center pl-1"
4758
4758
  }, /*#__PURE__*/react.createElement("div", {
4759
- className: "flex flex-row items-center w-1/2"
4759
+ className: "flex w-1/2 flex-row items-center"
4760
4760
  }, /*#__PURE__*/react.createElement(ui_src/* Typography */.ZT, {
4761
4761
  variant: "subtitle",
4762
4762
  className: "mr-4"
4763
4763
  }, "Series"), /*#__PURE__*/react.createElement("div", {
4764
- className: "grow mr-8"
4764
+ className: "mr-8 grow"
4765
4765
  }, /*#__PURE__*/react.createElement(ui_src/* Select */.Ph, {
4766
4766
  id: "display-set-selector",
4767
4767
  isClearable: false,
@@ -4770,7 +4770,7 @@ const DicomTagBrowser = _ref => {
4770
4770
  value: displaySetList.find(ds => ds.value === selectedDisplaySetInstanceUID),
4771
4771
  className: "text-white"
4772
4772
  }))), /*#__PURE__*/react.createElement("div", {
4773
- className: "flex flex-row items-center w-1/2"
4773
+ className: "flex w-1/2 flex-row items-center"
4774
4774
  }, showInstanceList && /*#__PURE__*/react.createElement(ui_src/* Typography */.ZT, {
4775
4775
  variant: "subtitle",
4776
4776
  className: "mr-4"
@@ -4789,11 +4789,11 @@ const DicomTagBrowser = _ref => {
4789
4789
  labelPosition: "left",
4790
4790
  trackColor: '#3a3f99'
4791
4791
  })))), /*#__PURE__*/react.createElement("div", {
4792
- className: "w-full h-1 bg-black"
4792
+ className: "h-1 w-full bg-black"
4793
4793
  }), /*#__PURE__*/react.createElement("div", {
4794
- className: "flex flex-row my-3 w-1/2"
4794
+ className: "my-3 flex w-1/2 flex-row"
4795
4795
  }, /*#__PURE__*/react.createElement(ui_src/* InputFilterText */.Xe, {
4796
- className: "block w-full mr-8",
4796
+ className: "mr-8 block w-full",
4797
4797
  placeholder: "Search metadata...",
4798
4798
  onDebounceChange: setFilterValue
4799
4799
  })), /*#__PURE__*/react.createElement(DicomTagBrowser_DicomTagTable, {
@@ -4969,65 +4969,62 @@ function _sortTagList(tagList) {
4969
4969
  */
4970
4970
  const reuseCachedLayout = (state, hangingProtocolService, syncService) => {
4971
4971
  const {
4972
- activeViewportIndex,
4973
- viewports,
4974
- layout
4972
+ activeViewportId
4975
4973
  } = state;
4974
+ const {
4975
+ protocol
4976
+ } = hangingProtocolService.getActiveProtocol();
4976
4977
  const hpInfo = hangingProtocolService.getState();
4977
4978
  const {
4978
4979
  protocolId,
4979
4980
  stageIndex,
4980
4981
  activeStudyUID
4981
4982
  } = hpInfo;
4982
- const {
4983
- protocol
4984
- } = hangingProtocolService.getActiveProtocol();
4985
- const stage = protocol.stages[stageIndex];
4986
- const storeId = `${activeStudyUID}:${protocolId}:${stageIndex}`;
4987
4983
  const syncState = syncService.getState();
4988
- const cacheId = `${activeStudyUID}:${protocolId}`;
4989
4984
  const viewportGridStore = {
4990
4985
  ...syncState.viewportGridStore
4991
4986
  };
4992
- const hangingProtocolStageIndexMap = {
4993
- ...syncState.hangingProtocolStageIndexMap
4994
- };
4995
4987
  const displaySetSelectorMap = {
4996
4988
  ...syncState.displaySetSelectorMap
4997
4989
  };
4990
+ const stage = protocol.stages[stageIndex];
4991
+ const storeId = `${activeStudyUID}:${protocolId}:${stageIndex}`;
4992
+ const cacheId = `${activeStudyUID}:${protocolId}`;
4993
+ const hangingProtocolStageIndexMap = {
4994
+ ...syncState.hangingProtocolStageIndexMap
4995
+ };
4998
4996
  const {
4999
4997
  rows,
5000
4998
  columns
5001
4999
  } = stage.viewportStructure.properties;
5002
- const custom = stage.viewports.length !== state.viewports.length || state.layout.numRows !== rows || state.layout.numCols !== columns;
5000
+ const custom = stage.viewports.length !== state.viewports.size || state.layout.numRows !== rows || state.layout.numCols !== columns;
5003
5001
  hangingProtocolStageIndexMap[cacheId] = hpInfo;
5004
5002
  if (storeId && custom) {
5005
5003
  viewportGridStore[storeId] = {
5006
5004
  ...state
5007
5005
  };
5008
5006
  }
5009
- for (let idx = 0; idx < state.viewports.length; idx++) {
5010
- const viewport = state.viewports[idx];
5007
+ state.viewports.forEach((viewport, viewportId) => {
5011
5008
  const {
5012
5009
  displaySetOptions,
5013
5010
  displaySetInstanceUIDs
5014
5011
  } = viewport;
5015
5012
  if (!displaySetOptions) {
5016
- continue;
5013
+ return;
5017
5014
  }
5018
5015
  for (let i = 0; i < displaySetOptions.length; i++) {
5019
5016
  const displaySetUID = displaySetInstanceUIDs[i];
5020
5017
  if (!displaySetUID) {
5021
5018
  continue;
5022
5019
  }
5023
- if (idx === activeViewportIndex && i === 0) {
5020
+ if (viewportId === activeViewportId && i === 0) {
5024
5021
  displaySetSelectorMap[`${activeStudyUID}:activeDisplaySet:0`] = displaySetUID;
5025
5022
  }
5026
5023
  if (displaySetOptions[i]?.id) {
5027
5024
  displaySetSelectorMap[`${activeStudyUID}:${displaySetOptions[i].id}:${displaySetOptions[i].matchedDisplaySetsIndex || 0}`] = displaySetUID;
5028
5025
  }
5029
5026
  }
5030
- }
5027
+ });
5031
5028
  return {
5032
5029
  hangingProtocolStageIndexMap,
5033
5030
  viewportGridStore,
@@ -5043,14 +5040,14 @@ const reuseCachedLayout = (state, hangingProtocolService, syncService) => {
5043
5040
  * then one can be re-used from the display set if it isn't going to be displayed.
5044
5041
  * @param hangingProtocolService - bound parameter supplied before using this
5045
5042
  * @param viewportsByPosition - bound parameter supplied before using this
5046
- * @param viewportIndex - the index to retrieve
5043
+ * @param position - the position in the grid to retrieve
5047
5044
  * @param positionId - the current position on screen to retrieve
5048
5045
  * @param options - the set of options used, so that subsequent calls can
5049
5046
  * store state that is reset by the setLayout.
5050
5047
  * This class uses the options to store the already viewed
5051
5048
  * display sets, filling it initially with the pre-existing viewports.
5052
5049
  */
5053
- const findViewportsByPosition_findOrCreateViewport = (hangingProtocolService, viewportsByPosition, viewportIndex, positionId, options) => {
5050
+ const findViewportsByPosition_findOrCreateViewport = (hangingProtocolService, viewportsByPosition, position, positionId, options) => {
5054
5051
  const byPositionViewport = viewportsByPosition?.[positionId];
5055
5052
  if (byPositionViewport) {
5056
5053
  return {
@@ -5104,7 +5101,7 @@ const findViewportsByPosition = (state, _ref, syncService) => {
5104
5101
  ...syncState.viewportsByPosition
5105
5102
  };
5106
5103
  const initialInDisplay = [];
5107
- for (const viewport of viewports) {
5104
+ viewports.forEach(viewport => {
5108
5105
  if (viewport.positionId) {
5109
5106
  const storedViewport = {
5110
5107
  ...viewport,
@@ -5113,16 +5110,11 @@ const findViewportsByPosition = (state, _ref, syncService) => {
5113
5110
  }
5114
5111
  };
5115
5112
  viewportsByPosition[viewport.positionId] = storedViewport;
5116
- // The cache doesn't store the viewport options - it is only useful
5117
- // for remembering the type of viewport and UIDs
5118
- delete storedViewport.viewportId;
5119
- delete storedViewport.viewportOptions.viewportId;
5120
5113
  }
5121
- }
5114
+ });
5122
5115
  for (let row = 0; row < numRows; row++) {
5123
5116
  for (let col = 0; col < numCols; col++) {
5124
- const pos = col + row * numCols;
5125
- const positionId = viewports?.[pos]?.positionId || `${col}-${row}`;
5117
+ const positionId = `${col}-${row}`;
5126
5118
  const viewport = viewportsByPosition[positionId];
5127
5119
  if (viewport?.displaySetInstanceUIDs) {
5128
5120
  initialInDisplay.push(...viewport.displaySetInstanceUIDs);
@@ -5355,19 +5347,20 @@ const commandsModule = _ref => {
5355
5347
  delete displaySetSelectorMap[`${activeStudyUID || hpInfo.activeStudyUID}:activeDisplaySet:0`];
5356
5348
  stateSyncService.store(stateSyncReduce);
5357
5349
  // This is a default action applied
5358
- actions.toggleHpTools(hangingProtocolService.getActiveProtocol());
5350
+ const {
5351
+ protocol
5352
+ } = hangingProtocolService.getActiveProtocol();
5353
+ actions.toggleHpTools(protocol);
5359
5354
  // Send the notification about updating the state
5360
5355
  if (protocolId !== hpInfo.protocolId) {
5361
- const {
5362
- protocol
5363
- } = hangingProtocolService.getActiveProtocol();
5364
5356
  // The old protocol callbacks are used for turning off things
5365
5357
  // like crosshairs when moving to the new HP
5366
5358
  commandsManager.run(oldProtocol.callbacks?.onProtocolExit);
5367
5359
  // The new protocol callback is used for things like
5368
5360
  // activating modes etc.
5369
- commandsManager.run(protocol.callbacks?.onProtocolEnter);
5370
5361
  }
5362
+
5363
+ commandsManager.run(protocol.callbacks?.onProtocolEnter);
5371
5364
  return true;
5372
5365
  } catch (e) {
5373
5366
  actions.toggleHpTools(hangingProtocolService.getActiveProtocol());
@@ -5483,7 +5476,7 @@ const commandsModule = _ref => {
5483
5476
  toggleOneUp() {
5484
5477
  const viewportGridState = viewportGridService.getState();
5485
5478
  const {
5486
- activeViewportIndex,
5479
+ activeViewportId,
5487
5480
  viewports,
5488
5481
  layout
5489
5482
  } = viewportGridState;
@@ -5491,7 +5484,7 @@ const commandsModule = _ref => {
5491
5484
  displaySetInstanceUIDs,
5492
5485
  displaySetOptions,
5493
5486
  viewportOptions
5494
- } = viewports[activeViewportIndex];
5487
+ } = viewports.get(activeViewportId);
5495
5488
  if (layout.numCols === 1 && layout.numRows === 1) {
5496
5489
  // The viewer is in one-up. Check if there is a state to restore/toggle back to.
5497
5490
  const {
@@ -5502,24 +5495,37 @@ const commandsModule = _ref => {
5502
5495
  }
5503
5496
  // There is a state to toggle back to. The viewport that was
5504
5497
  // originally toggled to one up was the former active viewport.
5505
- const viewportIndexToUpdate = toggleOneUpViewportGridStore.activeViewportIndex;
5506
-
5507
- // Determine which viewports need to be updated. This is particularly
5508
- // important when MPR is toggled to one up and a different reconstructable
5509
- // is swapped in. Note that currently HangingProtocolService.getViewportsRequireUpdate
5510
- // does not support viewport with multiple display sets.
5511
- const updatedViewports = displaySetInstanceUIDs.length > 1 ? [] : displaySetInstanceUIDs.map(displaySetInstanceUID => hangingProtocolService.getViewportsRequireUpdate(viewportIndexToUpdate, displaySetInstanceUID)).flat();
5498
+ const viewportIdToUpdate = toggleOneUpViewportGridStore.activeViewportId;
5499
+ const updatedViewportsViaHP = displaySetInstanceUIDs.length > 1 ? [] : displaySetInstanceUIDs.map(displaySetInstanceUID => hangingProtocolService.getViewportsRequireUpdate(viewportIdToUpdate, displaySetInstanceUID)).flat();
5512
5500
 
5513
5501
  // This findOrCreateViewport returns either one of the updatedViewports
5514
5502
  // returned from the HP service OR if there is not one from the HP service then
5515
5503
  // simply returns what was in the previous state.
5516
- const findOrCreateViewport = viewportIndex => {
5517
- const viewport = updatedViewports.find(viewport => viewport.viewportIndex === viewportIndex);
5518
- return viewport ? {
5504
+ const findOrCreateViewport = position => {
5505
+ // get the viewportId in the current state (since we are in the one-up layout)
5506
+ const currentOneUpViewport = Array.from(viewports.values())[0];
5507
+
5508
+ // we should restore the previous layout but take into the account the fact that
5509
+ // the current one up viewport might have a new displaySet dragged and dropped on it
5510
+ // so we should prioritize the current one in the old grid store layout viewports
5511
+
5512
+ const newViewports = Array.from(toggleOneUpViewportGridStore.viewports.values()).map(viewport => {
5513
+ if (viewport.viewportId === currentOneUpViewport.viewportId) {
5514
+ return {
5515
+ ...currentOneUpViewport
5516
+ };
5517
+ }
5518
+ return viewport;
5519
+ });
5520
+
5521
+ // However, we also need to take into account that the current one up viewport
5522
+ // might have been part of a bigger hanging protocol layout, so going back
5523
+ // from one up we should apply those viewports as well.
5524
+ return updatedViewportsViaHP.length > 1 && updatedViewportsViaHP[position] ? {
5519
5525
  viewportOptions,
5520
5526
  displaySetOptions,
5521
- ...viewport
5522
- } : toggleOneUpViewportGridStore.viewports[viewportIndex];
5527
+ ...updatedViewportsViaHP[position]
5528
+ } : newViewports[position];
5523
5529
  };
5524
5530
  const layoutOptions = viewportGridService.getLayoutOptionsFromState(toggleOneUpViewportGridStore);
5525
5531
 
@@ -5527,7 +5533,7 @@ const commandsModule = _ref => {
5527
5533
  viewportGridService.setLayout({
5528
5534
  numRows: toggleOneUpViewportGridStore.layout.numRows,
5529
5535
  numCols: toggleOneUpViewportGridStore.layout.numCols,
5530
- activeViewportIndex: viewportIndexToUpdate,
5536
+ activeViewportId: viewportIdToUpdate,
5531
5537
  layoutOptions,
5532
5538
  findOrCreateViewport
5533
5539
  });
@@ -5592,10 +5598,10 @@ const commandsModule = _ref => {
5592
5598
  },
5593
5599
  openDICOMTagViewer() {
5594
5600
  const {
5595
- activeViewportIndex,
5601
+ activeViewportId,
5596
5602
  viewports
5597
5603
  } = viewportGridService.getState();
5598
- const activeViewportSpecificData = viewports[activeViewportIndex];
5604
+ const activeViewportSpecificData = viewports.get(activeViewportId);
5599
5605
  const {
5600
5606
  displaySetInstanceUIDs
5601
5607
  } = activeViewportSpecificData;
@@ -5627,13 +5633,10 @@ const commandsModule = _ref => {
5627
5633
  },
5628
5634
  scrollActiveThumbnailIntoView: () => {
5629
5635
  const {
5630
- activeViewportIndex,
5636
+ activeViewportId,
5631
5637
  viewports
5632
5638
  } = viewportGridService.getState();
5633
- if (!viewports || activeViewportIndex < 0 || activeViewportIndex > viewports.length - 1) {
5634
- return;
5635
- }
5636
- const activeViewport = viewports[activeViewportIndex];
5639
+ const activeViewport = viewports.get(activeViewportId);
5637
5640
  const activeDisplaySetInstanceUID = activeViewport.displaySetInstanceUIDs[0];
5638
5641
  const thumbnailList = document.querySelector('#ohif-thumbnail-list');
5639
5642
  if (!thumbnailList) {
@@ -5667,12 +5670,12 @@ const commandsModule = _ref => {
5667
5670
  const currentDisplaySets = [...displaySetService.activeDisplaySets];
5668
5671
  currentDisplaySets.sort(dsSortFn);
5669
5672
  const {
5670
- activeViewportIndex,
5673
+ activeViewportId,
5671
5674
  viewports
5672
5675
  } = viewportGridService.getState();
5673
5676
  const {
5674
5677
  displaySetInstanceUIDs
5675
- } = viewports[activeViewportIndex];
5678
+ } = viewports.get(activeViewportId);
5676
5679
  const activeDisplaySetIndex = currentDisplaySets.findIndex(displaySet => displaySetInstanceUIDs.includes(displaySet.displaySetInstanceUID));
5677
5680
  let displaySetIndexToShow;
5678
5681
  for (displaySetIndexToShow = activeDisplaySetIndex + direction; displaySetIndexToShow > -1 && displaySetIndexToShow < currentDisplaySets.length; displaySetIndexToShow += direction) {
@@ -5688,7 +5691,7 @@ const commandsModule = _ref => {
5688
5691
  } = currentDisplaySets[displaySetIndexToShow];
5689
5692
  let updatedViewports = [];
5690
5693
  try {
5691
- updatedViewports = hangingProtocolService.getViewportsRequireUpdate(activeViewportIndex, displaySetInstanceUID);
5694
+ updatedViewports = hangingProtocolService.getViewportsRequireUpdate(activeViewportId, displaySetInstanceUID);
5692
5695
  } catch (error) {
5693
5696
  console.warn(error);
5694
5697
  uiNotificationService.show({
@@ -6230,6 +6233,7 @@ const defaultProtocol = {
6230
6233
  viewports: [{
6231
6234
  viewportOptions: {
6232
6235
  viewportType: 'stack',
6236
+ viewportId: 'default',
6233
6237
  toolGroupId: 'default',
6234
6238
  // This will specify the initial image options index if it matches in the URL
6235
6239
  // and will otherwise not specify anything.
@@ -6286,15 +6290,15 @@ function DataSourceSelector() {
6286
6290
  height: '100%'
6287
6291
  }
6288
6292
  }, /*#__PURE__*/react.createElement("div", {
6289
- className: "h-screen w-screen flex justify-center items-center "
6293
+ className: "flex h-screen w-screen items-center justify-center "
6290
6294
  }, /*#__PURE__*/react.createElement("div", {
6291
- className: "py-8 px-8 mx-auto bg-secondary-dark drop-shadow-md space-y-2 rounded-lg"
6295
+ className: "bg-secondary-dark mx-auto space-y-2 rounded-lg py-8 px-8 drop-shadow-md"
6292
6296
  }, /*#__PURE__*/react.createElement("img", {
6293
- className: "block mx-auto h-14",
6297
+ className: "mx-auto block h-14",
6294
6298
  src: "./ohif-logo.svg",
6295
6299
  alt: "OHIF"
6296
6300
  }), /*#__PURE__*/react.createElement("div", {
6297
- className: "text-center space-y-2 pt-4"
6301
+ className: "space-y-2 pt-4 text-center"
6298
6302
  }, dsConfigs.filter(it => it.sourceName !== 'dicomjson' && it.sourceName !== 'dicomlocal').map(ds => /*#__PURE__*/react.createElement("div", {
6299
6303
  key: ds.sourceName
6300
6304
  }, /*#__PURE__*/react.createElement("h1", {
@@ -6330,33 +6334,33 @@ function ItemListComponent(_ref) {
6330
6334
  setFilterValue('');
6331
6335
  }, [itemList]);
6332
6336
  return /*#__PURE__*/react.createElement("div", {
6333
- className: "flex flex-col gap-4 min-h-[1px] grow"
6337
+ className: "flex min-h-[1px] grow flex-col gap-4"
6334
6338
  }, /*#__PURE__*/react.createElement("div", {
6335
- className: "flex justify-between items-center"
6339
+ className: "flex items-center justify-between"
6336
6340
  }, /*#__PURE__*/react.createElement("div", {
6337
6341
  className: "text-primary-light text-[20px]"
6338
6342
  }, t(`Select ${itemLabel}`)), /*#__PURE__*/react.createElement(ui_src/* InputFilterText */.Xe, {
6339
- className: "grow max-w-[40%]",
6343
+ className: "max-w-[40%] grow",
6340
6344
  value: filterValue,
6341
6345
  onDebounceChange: setFilterValue,
6342
6346
  placeholder: t(`Search ${itemLabel} list`)
6343
6347
  })), /*#__PURE__*/react.createElement("div", {
6344
- className: "flex flex-col relative min-h-[1px] grow text-[14px] bg-black"
6348
+ className: "relative flex min-h-[1px] grow flex-col bg-black text-[14px]"
6345
6349
  }, itemList == null ? /*#__PURE__*/react.createElement(ui_src/* LoadingIndicatorProgress */.LE, {
6346
- className: 'w-full h-full'
6350
+ className: 'h-full w-full'
6347
6351
  }) : itemList.length === 0 ? /*#__PURE__*/react.createElement("div", {
6348
- className: "flex flex-col h-full px-6 py-4 items-center justify-center text-primary-light"
6352
+ className: "text-primary-light flex h-full flex-col items-center justify-center px-6 py-4"
6349
6353
  }, /*#__PURE__*/react.createElement(ui_src/* Icon */.JO, {
6350
6354
  name: "magnifier",
6351
6355
  className: "mb-4"
6352
6356
  }), /*#__PURE__*/react.createElement("span", null, t(`No ${itemLabel} available`))) : /*#__PURE__*/react.createElement(react.Fragment, null, /*#__PURE__*/react.createElement("div", {
6353
- className: "bg-secondary-dark text-white px-3 py-1.5"
6357
+ className: "bg-secondary-dark px-3 py-1.5 text-white"
6354
6358
  }, t(itemLabel)), /*#__PURE__*/react.createElement("div", {
6355
- className: "overflow-auto ohif-scrollbar"
6359
+ className: "ohif-scrollbar overflow-auto"
6356
6360
  }, itemList.filter(item => !filterValue || item.name.toLowerCase().includes(filterValue.toLowerCase())).map(item => {
6357
6361
  const border = 'rounded border-transparent border-b-secondary-light border-[1px] hover:border-primary-light';
6358
6362
  return /*#__PURE__*/react.createElement("div", {
6359
- className: classnames_default()('group mx-2 px-6 py-2 flex justify-between items-center hover:text-primary-light hover:bg-primary-dark', border),
6363
+ className: classnames_default()('hover:text-primary-light hover:bg-primary-dark group mx-2 flex items-center justify-between px-6 py-2', border),
6360
6364
  key: item.id
6361
6365
  }, /*#__PURE__*/react.createElement("div", null, item.name), /*#__PURE__*/react.createElement(ui_src/* Button */.zx, {
6362
6366
  onClick: () => onItemClicked(item),
@@ -6386,13 +6390,16 @@ function DataSourceConfigurationModalComponent(_ref) {
6386
6390
  } = (0,es/* useTranslation */.$G)('DataSourceConfiguration');
6387
6391
  const [itemList, setItemList] = (0,react.useState)();
6388
6392
  const [selectedItems, setSelectedItems] = (0,react.useState)(configuredItems);
6389
-
6390
- // Determines whether to show the full configuration for the data source.
6391
- // This typically occurs when the configuration component is first displayed.
6392
- const [showFullConfig, setShowFullConfig] = (0,react.useState)(true);
6393
6393
  const [errorMessage, setErrorMessage] = (0,react.useState)();
6394
6394
  const [itemLabels] = (0,react.useState)(configurationAPI.getItemLabels());
6395
6395
 
6396
+ // Determines whether to show the full/existing configuration for the data source.
6397
+ // A full or complete configuration is one where the data source (path) has the
6398
+ // maximum/required number of path items. Anything less is considered not complete and
6399
+ // the configuration starts from scratch (i.e. as if no items are configured at all).
6400
+ // TODO: consider configuration starting from a partial (i.e. non-empty) configuration
6401
+ const [showFullConfig, setShowFullConfig] = (0,react.useState)(itemLabels.length === configuredItems.length);
6402
+
6396
6403
  /**
6397
6404
  * The index of the selected item that is considered current and for which
6398
6405
  * its sub-items should be displayed in the items list component. When the
@@ -6434,11 +6441,11 @@ function DataSourceConfigurationModalComponent(_ref) {
6434
6441
  const getSelectedItemTextClasses = itemIndex => itemIndex <= selectedItems.length ? 'text-primary-light' : 'text-primary-active';
6435
6442
  const getErrorComponent = () => {
6436
6443
  return /*#__PURE__*/react.createElement("div", {
6437
- className: "flex flex-col gap-4 min-h-[1px] grow"
6444
+ className: "flex min-h-[1px] grow flex-col gap-4"
6438
6445
  }, /*#__PURE__*/react.createElement("div", {
6439
6446
  className: "text-primary-light text-[20px]"
6440
6447
  }, t(`Error fetching ${itemLabels[selectedItems.length]} list`)), /*#__PURE__*/react.createElement("div", {
6441
- className: "bg-black text-[14px] grow p-4"
6448
+ className: "grow bg-black p-4 text-[14px]"
6442
6449
  }, errorMessage));
6443
6450
  };
6444
6451
  const getSelectedItemsComponent = () => {
@@ -6447,13 +6454,13 @@ function DataSourceConfigurationModalComponent(_ref) {
6447
6454
  }, itemLabels.map((itemLabel, itemLabelIndex) => {
6448
6455
  return /*#__PURE__*/react.createElement("div", {
6449
6456
  key: itemLabel,
6450
- className: classnames_default()('rounded-md p-3.5 flex flex-col gap-1 shrink min-w-[1px] basis-[200px]', getSelectedItemCursorClasses(itemLabelIndex), getSelectedItemBackgroundClasses(itemLabelIndex), getSelectedItemBorderClasses(itemLabelIndex), getSelectedItemTextClasses(itemLabelIndex)),
6457
+ className: classnames_default()('flex min-w-[1px] shrink basis-[200px] flex-col gap-1 rounded-md p-3.5', getSelectedItemCursorClasses(itemLabelIndex), getSelectedItemBackgroundClasses(itemLabelIndex), getSelectedItemBorderClasses(itemLabelIndex), getSelectedItemTextClasses(itemLabelIndex)),
6451
6458
  onClick: showFullConfig && itemLabelIndex < currentSelectedItemIndex || itemLabelIndex <= currentSelectedItemIndex ? () => {
6452
6459
  setShowFullConfig(false);
6453
6460
  setSelectedItems(theList => theList.slice(0, itemLabelIndex));
6454
6461
  } : undefined
6455
6462
  }, /*#__PURE__*/react.createElement("div", {
6456
- className: "flex gap-2 items-center text-"
6463
+ className: "text- flex items-center gap-2"
6457
6464
  }, itemLabelIndex < selectedItems.length ? /*#__PURE__*/react.createElement(ui_src/* Icon */.JO, {
6458
6465
  name: "status-tracked"
6459
6466
  }) : /*#__PURE__*/react.createElement(ui_src/* Icon */.JO, {
@@ -6461,14 +6468,14 @@ function DataSourceConfigurationModalComponent(_ref) {
6461
6468
  }), /*#__PURE__*/react.createElement("div", {
6462
6469
  className: classnames_default()(NO_WRAP_ELLIPSIS_CLASS_NAMES)
6463
6470
  }, t(itemLabel))), itemLabelIndex < selectedItems.length ? /*#__PURE__*/react.createElement("div", {
6464
- className: classnames_default()('text-white text-[14px]', NO_WRAP_ELLIPSIS_CLASS_NAMES)
6471
+ className: classnames_default()('text-[14px] text-white', NO_WRAP_ELLIPSIS_CLASS_NAMES)
6465
6472
  }, selectedItems[itemLabelIndex].name) : /*#__PURE__*/react.createElement("br", null));
6466
6473
  }));
6467
6474
  };
6468
6475
  return /*#__PURE__*/react.createElement("div", {
6469
- className: "h-[calc(100vh-300px)] flex flex-col pt-0.5 gap-4 select-none"
6476
+ className: "flex h-[calc(100vh-300px)] select-none flex-col gap-4 pt-0.5"
6470
6477
  }, getSelectedItemsComponent(), /*#__PURE__*/react.createElement("div", {
6471
- className: "w-full h-0.5 shrink-0 bg-black"
6478
+ className: "h-0.5 w-full shrink-0 bg-black"
6472
6479
  }), errorMessage ? getErrorComponent() : /*#__PURE__*/react.createElement(Components_ItemListComponent, {
6473
6480
  itemLabel: itemLabels[currentSelectedItemIndex + 1],
6474
6481
  itemList: itemList,
@@ -6516,6 +6523,9 @@ function DataSourceConfigurationComponent(_ref) {
6516
6523
  }
6517
6524
  const configAPI = configurationAPIFactory(activeDataSourceDef.sourceName);
6518
6525
  setConfigurationAPI(configAPI);
6526
+
6527
+ // New configuration API means that the existing configured items must be cleared.
6528
+ setConfiguredItems(null);
6519
6529
  configAPI.getConfiguredItems().then(list => {
6520
6530
  if (shouldUpdate) {
6521
6531
  setConfiguredItems(list);
@@ -6529,12 +6539,8 @@ function DataSourceConfigurationComponent(_ref) {
6529
6539
  sub.unsubscribe();
6530
6540
  };
6531
6541
  }, []);
6532
- return configuredItems ? /*#__PURE__*/react.createElement("div", {
6533
- className: "flex text-aqua-pale overflow-hidden items-center"
6534
- }, /*#__PURE__*/react.createElement(ui_src/* Icon */.JO, {
6535
- name: "settings",
6536
- className: "cursor-pointer shrink-0 w-3.5 h-3.5 mr-2.5",
6537
- onClick: () => show({
6542
+ const showConfigurationModal = (0,react.useCallback)(() => {
6543
+ show({
6538
6544
  content: Components_DataSourceConfigurationModalComponent,
6539
6545
  title: t('Configure Data Source'),
6540
6546
  contentProps: {
@@ -6542,14 +6548,30 @@ function DataSourceConfigurationComponent(_ref) {
6542
6548
  configuredItems,
6543
6549
  onHide: hide
6544
6550
  }
6545
- })
6551
+ });
6552
+ }, [configurationAPI, configuredItems]);
6553
+ (0,react.useEffect)(() => {
6554
+ if (!configurationAPI || !configuredItems) {
6555
+ return;
6556
+ }
6557
+ if (configuredItems.length !== configurationAPI.getItemLabels().length) {
6558
+ // Not the correct number of configured items, so show the modal to configure the data source.
6559
+ showConfigurationModal();
6560
+ }
6561
+ }, [configurationAPI, configuredItems, showConfigurationModal]);
6562
+ return configuredItems ? /*#__PURE__*/react.createElement("div", {
6563
+ className: "text-aqua-pale flex items-center overflow-hidden"
6564
+ }, /*#__PURE__*/react.createElement(ui_src/* Icon */.JO, {
6565
+ name: "settings",
6566
+ className: "mr-2.5 h-3.5 w-3.5 shrink-0 cursor-pointer",
6567
+ onClick: showConfigurationModal
6546
6568
  }), configuredItems.map((item, itemIndex) => {
6547
6569
  return /*#__PURE__*/react.createElement("div", {
6548
6570
  key: itemIndex,
6549
6571
  className: "flex overflow-hidden"
6550
6572
  }, /*#__PURE__*/react.createElement("div", {
6551
6573
  key: itemIndex,
6552
- className: "text-ellipsis whitespace-nowrap overflow-hidden"
6574
+ className: "overflow-hidden text-ellipsis whitespace-nowrap"
6553
6575
  }, item.name), itemIndex !== configuredItems.length - 1 && /*#__PURE__*/react.createElement("div", {
6554
6576
  className: "px-2.5"
6555
6577
  }, "|"));
@@ -6651,9 +6673,14 @@ class GoogleCloudDataSourceConfigurationAPI {
6651
6673
  const dataSourceDefinition = this._extensionManager.getDataSourceDefinition(this._dataSourceName);
6652
6674
  const url = dataSourceDefinition.configuration.wadoUriRoot;
6653
6675
  const projectsIndex = url.indexOf('projects');
6676
+ // Split the configured URL into (essentially) pairs (i.e. item type followed by item)
6677
+ // Explicitly: ['projects','aProject','locations','aLocation','datasets','aDataSet','dicomStores','aDicomStore']
6678
+ // Note that a partial configuration will have a subset of the above.
6654
6679
  const urlSplit = url.substring(projectsIndex).split('/');
6655
6680
  const configuredItems = [];
6656
- for (let itemType = 0; itemType < 4; itemType += 1) {
6681
+ for (let itemType = 0;
6682
+ // the number of configured items is either the max (4) or the number extracted from the url split
6683
+ itemType < 4 && (itemType + 1) * 2 < urlSplit.length; itemType += 1) {
6657
6684
  if (itemType === ItemType.projects) {
6658
6685
  const projectId = urlSplit[1];
6659
6686
  const projectUrl = `${initialUrl}/projects/${projectId}`;