@ohif/app 3.7.0-beta.35 → 3.7.0-beta.36

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 (28) hide show
  1. package/dist/{192.bundle.6272e24776573a46ba0e.js → 192.bundle.160fffd248385d501d87.js} +2 -2
  2. package/dist/{199.bundle.017a4d777d4c2b3ae3c7.js → 199.bundle.fe8e31ccab2445a9721d.js} +2 -2
  3. package/dist/{208.bundle.1ddd87553ed279ecf177.js → 208.bundle.ee392e7c48237252ea8e.js} +2 -2
  4. package/dist/{283.bundle.51628bee972a04e8f2a9.js → 283.bundle.b19d7099a6fb8c957fb1.js} +2 -2
  5. package/dist/{351.bundle.33b4d3f8b66453b5d303.js → 351.bundle.2e949640c417cd735688.js} +2 -2
  6. package/dist/{404.bundle.1dce2dd30ff876edc5f3.js → 404.bundle.051cd13557d04cc76630.js} +2 -2
  7. package/dist/{55.bundle.b2c6b4dff2a949d25023.js → 55.bundle.fe53f3784bfe7db4a5a5.js} +2 -2
  8. package/dist/{569.bundle.ee136cf6526a6380633c.js → 569.bundle.e77c17d37a65e5dedfed.js} +2 -2
  9. package/dist/{581.bundle.ab8d1f1e75de3c98dd10.js → 581.bundle.15078e71fe52b53f48b3.js} +2 -2
  10. package/dist/{616.bundle.9ca5b6ebd436fa5c8b73.js → 616.bundle.fc1820b3d98da340218c.js} +2 -2
  11. package/dist/{625.bundle.56cf23e17aba289098b9.js → 625.bundle.7de4074e256c743ca500.js} +2 -2
  12. package/dist/{642.bundle.aba522f4f50f4b897046.js → 642.bundle.f03da99e63dbfdc1cf1c.js} +2 -2
  13. package/dist/{744.bundle.6010b90be6b43b0d9bc8.js → 744.bundle.08e4a5bbc4fd371a50b3.js} +7 -7
  14. package/dist/{790.bundle.9f4c33a790c651348286.js → 790.bundle.6fa09929a3203bcf3f2c.js} +2 -2
  15. package/dist/{799.bundle.6d3320855c9332c7117a.js → 799.bundle.d8e50f1fd6bf4fa3a5e1.js} +1 -1
  16. package/dist/{82.bundle.2e1ab22b6d6980c356f1.js → 82.bundle.11e08acaf3e1f527278d.js} +124 -98
  17. package/dist/{917.bundle.e220de67184c171f631d.js → 917.bundle.e0647888c6fff8e72e95.js} +2 -2
  18. package/dist/{953.bundle.4b8fee7d9484456a99b5.js → 953.bundle.95b0621f1da8dfeaed8a.js} +1 -1
  19. package/dist/{973.bundle.201ccef3cb047506ff92.js → 973.bundle.634f585248ead3160ff2.js} +2 -2
  20. package/dist/{976.bundle.c12649da6fb9662b9f94.js → 976.bundle.9dec94108550ad448773.js} +2 -2
  21. package/dist/{984.bundle.9133d3fdd441a8e6d63f.js → 984.bundle.1149cce5c5ecb63e76a9.js} +4 -4
  22. package/dist/app-config.js +6 -5
  23. package/dist/{app.bundle.3b2fe1badff37d9e939e.js → app.bundle.53e7fd8f8335245828d8.js} +621 -458
  24. package/dist/google.js +5 -4
  25. package/dist/index.html +1 -1
  26. package/dist/sw.js +1 -1
  27. package/package.json +18 -18
  28. /package/dist/{50.bundle.17df79160c1183470b70.js → 50.bundle.260f830a3870cae30cf5.js} +0 -0
@@ -4207,16 +4207,15 @@ exports.Z = function (file, acceptedFiles) {
4207
4207
 
4208
4208
  /***/ }),
4209
4209
 
4210
- /***/ 39852:
4210
+ /***/ 42492:
4211
4211
  /***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => {
4212
4212
 
4213
4213
  "use strict";
4214
4214
 
4215
4215
  // EXPORTS
4216
4216
  __webpack_require__.d(__webpack_exports__, {
4217
- Nr: () => (/* reexport */ useDebounce),
4218
- aM: () => (/* reexport */ useQuery),
4219
- lr: () => (/* reexport */ useSearchParams)
4217
+ N: () => (/* reexport */ useDebounce),
4218
+ l: () => (/* reexport */ useSearchParams/* default */.Z)
4220
4219
  });
4221
4220
 
4222
4221
  // EXTERNAL MODULE: ../../../node_modules/react/index.js
@@ -4250,35 +4249,48 @@ function useDebounce(value, delay) {
4250
4249
 
4251
4250
  return debouncedValue;
4252
4251
  }
4253
- // EXTERNAL MODULE: ../node_modules/react-router-dom/dist/index.js
4254
- var dist = __webpack_require__(65783);
4255
- ;// CONCATENATED MODULE: ./hooks/useQuery.js
4252
+ // EXTERNAL MODULE: ./hooks/useSearchParams.ts
4253
+ var useSearchParams = __webpack_require__(2318);
4254
+ ;// CONCATENATED MODULE: ./hooks/index.js
4256
4255
 
4257
- function useQuery() {
4258
- return new URLSearchParams((0,dist/* useLocation */.TH)().search);
4259
- }
4260
- ;// CONCATENATED MODULE: ./hooks/useSearchParams.js
4256
+
4257
+
4258
+
4259
+ /***/ }),
4260
+
4261
+ /***/ 2318:
4262
+ /***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => {
4263
+
4264
+ "use strict";
4265
+ /* harmony export */ __webpack_require__.d(__webpack_exports__, {
4266
+ /* harmony export */ Z: () => (/* binding */ useSearchParams)
4267
+ /* harmony export */ });
4268
+ /* harmony import */ var react_router__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(14935);
4261
4269
 
4262
4270
 
4263
4271
  /**
4264
- * It returns a Map of the query parameters in the URL, where the keys are
4265
- * lowercase
4266
- * @returns A function that returns a Map of the query parameters.
4272
+ * It returns a URLSearchParams of the query parameters in the URL, where the keys are
4273
+ * either lowercase or maintain their case based on the lowerCaseKeys parameter.
4274
+ * @param {lowerCaseKeys:boolean} true to return lower case keys; false (default) to maintain casing;
4275
+ * @returns {URLSearchParams}
4267
4276
  */
4268
4277
  function useSearchParams() {
4269
- const query = useQuery();
4270
- // make query params case-insensitive
4271
- const searchParams = new Map();
4272
- for (const [key, value] of query) {
4273
- searchParams.set(key.toLowerCase(), value);
4278
+ let options = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : {
4279
+ lowerCaseKeys: false
4280
+ };
4281
+ const {
4282
+ lowerCaseKeys
4283
+ } = options;
4284
+ const searchParams = new URLSearchParams((0,react_router__WEBPACK_IMPORTED_MODULE_0__/* .useLocation */ .TH)().search);
4285
+ if (!lowerCaseKeys) {
4286
+ return searchParams;
4274
4287
  }
4275
- return searchParams;
4288
+ const lowerCaseSearchParams = new URLSearchParams();
4289
+ for (const [key, value] of searchParams) {
4290
+ lowerCaseSearchParams.set(key.toLowerCase(), value);
4291
+ }
4292
+ return lowerCaseSearchParams;
4276
4293
  }
4277
- ;// CONCATENATED MODULE: ./hooks/index.js
4278
-
4279
-
4280
-
4281
-
4282
4294
 
4283
4295
  /***/ }),
4284
4296
 
@@ -4334,10 +4346,12 @@ Compose.propTypes = {
4334
4346
  var ui_src = __webpack_require__(28619);
4335
4347
  // EXTERNAL MODULE: ./state/index.js + 1 modules
4336
4348
  var state = __webpack_require__(22896);
4337
- // EXTERNAL MODULE: ../../core/src/index.ts + 102 modules
4338
- var core_src = __webpack_require__(62771);
4349
+ // EXTERNAL MODULE: ../../core/src/index.ts + 103 modules
4350
+ var core_src = __webpack_require__(87754);
4339
4351
  // EXTERNAL MODULE: ../node_modules/react-router/dist/index.js
4340
4352
  var react_router_dist = __webpack_require__(14935);
4353
+ // EXTERNAL MODULE: ./hooks/useSearchParams.ts
4354
+ var useSearchParams = __webpack_require__(2318);
4341
4355
  ;// CONCATENATED MODULE: ./routes/DataSourceWrapper.tsx
4342
4356
  function _extends() { _extends = Object.assign ? Object.assign.bind() : function (target) { for (var i = 1; i < arguments.length; i++) { var source = arguments[i]; for (var key in source) { if (Object.prototype.hasOwnProperty.call(source, key)) { target[key] = source[key]; } } } return target; }; return _extends.apply(this, arguments); }
4343
4357
  /* eslint-disable react/jsx-props-no-spreading */
@@ -4348,6 +4362,14 @@ function _extends() { _extends = Object.assign ? Object.assign.bind() : function
4348
4362
 
4349
4363
 
4350
4364
 
4365
+
4366
+ /**
4367
+ * Determines if two React Router location objects are the same.
4368
+ */
4369
+ const areLocationsTheSame = (location0, location1) => {
4370
+ return location0.pathname === location1.pathname && location0.search === location1.search && location0.hash === location1.hash;
4371
+ };
4372
+
4351
4373
  /**
4352
4374
  * Uses route properties to determine the data source that should be passed
4353
4375
  * to the child layout template. In some instances, initiates requests and
@@ -4363,33 +4385,10 @@ function DataSourceWrapper(props) {
4363
4385
  } = props;
4364
4386
  const params = (0,react_router_dist/* useParams */.UO)();
4365
4387
  const location = (0,react_router_dist/* useLocation */.TH)();
4366
-
4367
- // TODO - get the variable from the props all the time...
4368
- let dataSourceName = new URLSearchParams(location.search).get('datasources');
4369
- const dataPath = dataSourceName ? `/${dataSourceName}` : '';
4370
- if (!dataSourceName && window.config.defaultDataSourceName) {
4371
- dataSourceName = window.config.defaultDataSourceName;
4372
- } else if (!dataSourceName) {
4373
- // Gets the first defined datasource with the right name
4374
- // Mostly for historical reasons - new configs should use the defaultDataSourceName
4375
- const dataSourceModules = extensionManager.modules[core_src/* MODULE_TYPES */.OB.DATA_SOURCE];
4376
- // TODO: Good usecase for flatmap?
4377
- const webApiDataSources = dataSourceModules.reduce((acc, curr) => {
4378
- const mods = [];
4379
- curr.module.forEach(mod => {
4380
- if (mod.type === 'webApi') {
4381
- mods.push(mod);
4382
- }
4383
- });
4384
- return acc.concat(mods);
4385
- }, []);
4386
- dataSourceName = webApiDataSources.map(ds => ds.name).find(it => extensionManager.getDataSources(it)?.[0] !== undefined);
4387
- }
4388
- const dataSource = extensionManager.getDataSources(dataSourceName)?.[0];
4389
- if (!dataSource) {
4390
- throw new Error(`No data source found for ${dataSourceName}`);
4391
- }
4392
-
4388
+ const lowerCaseSearchParams = (0,useSearchParams/* default */.Z)({
4389
+ lowerCaseKeys: true
4390
+ });
4391
+ const query = (0,useSearchParams/* default */.Z)();
4393
4392
  // Route props --> studies.mapParams
4394
4393
  // mapParams --> studies.search
4395
4394
  // studies.search --> studies.processResults
@@ -4404,9 +4403,84 @@ function DataSourceWrapper(props) {
4404
4403
  pageNumber: 1,
4405
4404
  location: 'Not a valid location, causes first load to occur'
4406
4405
  };
4406
+ const getInitialDataSourceName = (0,react.useCallback)(() => {
4407
+ // TODO - get the variable from the props all the time...
4408
+ let dataSourceName = lowerCaseSearchParams.get('datasources');
4409
+ if (!dataSourceName && window.config.defaultDataSourceName) {
4410
+ return '';
4411
+ }
4412
+ if (!dataSourceName) {
4413
+ // Gets the first defined datasource with the right name
4414
+ // Mostly for historical reasons - new configs should use the defaultDataSourceName
4415
+ const dataSourceModules = extensionManager.modules[core_src/* MODULE_TYPES */.OB.DATA_SOURCE];
4416
+ // TODO: Good usecase for flatmap?
4417
+ const webApiDataSources = dataSourceModules.reduce((acc, curr) => {
4418
+ const mods = [];
4419
+ curr.module.forEach(mod => {
4420
+ if (mod.type === 'webApi') {
4421
+ mods.push(mod);
4422
+ }
4423
+ });
4424
+ return acc.concat(mods);
4425
+ }, []);
4426
+ dataSourceName = webApiDataSources.map(ds => ds.name).find(it => extensionManager.getDataSources(it)?.[0] !== undefined);
4427
+ }
4428
+ return dataSourceName;
4429
+ }, []);
4430
+ const [isDataSourceInitialized, setIsDataSourceInitialized] = (0,react.useState)(false);
4431
+
4432
+ // The path to the data source to be used in the URL for a mode (e.g. mode/dataSourcePath?StudyIntanceUIDs=1.2.3)
4433
+ const [dataSourcePath, setDataSourcePath] = (0,react.useState)(() => {
4434
+ const dataSourceName = getInitialDataSourceName();
4435
+ return dataSourceName ? `/${dataSourceName}` : '';
4436
+ });
4437
+ const [dataSource, setDataSource] = (0,react.useState)(() => {
4438
+ const dataSourceName = getInitialDataSourceName();
4439
+ if (!dataSourceName) {
4440
+ return extensionManager.getActiveDataSource()[0];
4441
+ }
4442
+ const dataSource = extensionManager.getDataSources(dataSourceName)?.[0];
4443
+ if (!dataSource) {
4444
+ throw new Error(`No data source found for ${dataSourceName}`);
4445
+ }
4446
+ return dataSource;
4447
+ });
4407
4448
  const [data, setData] = (0,react.useState)(DEFAULT_DATA);
4408
4449
  const [isLoading, setIsLoading] = (0,react.useState)(false);
4450
+
4451
+ /**
4452
+ * The effect to initialize the data source whenever it changes. Similar to
4453
+ * whenever a different Mode is entered, the Mode's data source is initialized, so
4454
+ * too this DataSourceWrapper must initialize its data source whenever a different
4455
+ * data source is activated. Furthermore, a data source might be initialized
4456
+ * several times as it gets activated/deactivated because the location URL
4457
+ * might change and data sources initialize based on the URL.
4458
+ */
4459
+ (0,react.useEffect)(() => {
4460
+ const initializeDataSource = async () => {
4461
+ await dataSource.initialize({
4462
+ params,
4463
+ query
4464
+ });
4465
+ setIsDataSourceInitialized(true);
4466
+ };
4467
+ initializeDataSource();
4468
+ }, [dataSource]);
4409
4469
  (0,react.useEffect)(() => {
4470
+ const dataSourceChangedCallback = () => {
4471
+ setIsDataSourceInitialized(false);
4472
+ setDataSourcePath('');
4473
+ setDataSource(extensionManager.getActiveDataSource()[0]);
4474
+ // Setting data to DEFAULT_DATA triggers a new query just like it does for the initial load.
4475
+ setData(DEFAULT_DATA);
4476
+ };
4477
+ const sub = extensionManager.subscribe(core_src/* ExtensionManager */.W$.EVENTS.ACTIVE_DATA_SOURCE_CHANGED, dataSourceChangedCallback);
4478
+ return () => sub.unsubscribe();
4479
+ }, []);
4480
+ (0,react.useEffect)(() => {
4481
+ if (!isDataSourceInitialized) {
4482
+ return;
4483
+ }
4410
4484
  const queryFilterValues = _getQueryFilterValues(location.search, STUDIES_LIMIT);
4411
4485
 
4412
4486
  // 204: no content
@@ -4429,7 +4503,10 @@ function DataSourceWrapper(props) {
4429
4503
  const isSamePage = data.pageNumber === queryFilterValues.pageNumber;
4430
4504
  const previousOffset = Math.floor(data.pageNumber * data.resultsPerPage / STUDIES_LIMIT) * (STUDIES_LIMIT - 1);
4431
4505
  const newOffset = Math.floor(queryFilterValues.pageNumber * queryFilterValues.resultsPerPage / STUDIES_LIMIT) * (STUDIES_LIMIT - 1);
4432
- const isLocationUpdated = data.location !== location;
4506
+ // Simply checking data.location !== location is not sufficient because even though the location href (i.e. entire URL)
4507
+ // has not changed, the React Router still provides a new location reference and would result in two study queries
4508
+ // on initial load. Alternatively, window.location.href could be used.
4509
+ const isLocationUpdated = typeof data.location === 'string' || !areLocationsTheSame(data.location, location);
4433
4510
  const isDataInvalid = !isSamePage || !isLoading && (newOffset !== previousOffset || isLocationUpdated);
4434
4511
  if (isDataInvalid) {
4435
4512
  getData();
@@ -4438,13 +4515,13 @@ function DataSourceWrapper(props) {
4438
4515
  console.warn(ex);
4439
4516
  }
4440
4517
  // eslint-disable-next-line react-hooks/exhaustive-deps
4441
- }, [data, location, params, isLoading, setIsLoading]);
4518
+ }, [data, location, params, isLoading, setIsLoading, dataSource, isDataSourceInitialized]);
4442
4519
  // queryFilterValues
4443
4520
 
4444
4521
  // TODO: Better way to pass DataSource?
4445
4522
  return /*#__PURE__*/react.createElement(LayoutTemplate, _extends({}, rest, {
4446
4523
  data: data.studies,
4447
- dataPath: dataPath,
4524
+ dataPath: dataSourcePath,
4448
4525
  dataTotal: data.total,
4449
4526
  dataSource: dataSource,
4450
4527
  isLoadingData: isLoading
@@ -4777,8 +4854,8 @@ const filtersMeta = [{
4777
4854
  gridCol: 2
4778
4855
  }];
4779
4856
  /* harmony default export */ const WorkList_filtersMeta = (filtersMeta);
4780
- // EXTERNAL MODULE: ./hooks/index.js + 3 modules
4781
- var hooks = __webpack_require__(39852);
4857
+ // EXTERNAL MODULE: ./hooks/index.js + 1 modules
4858
+ var hooks = __webpack_require__(42492);
4782
4859
  ;// CONCATENATED MODULE: ./routes/WorkList/WorkList.tsx
4783
4860
 
4784
4861
 
@@ -4834,7 +4911,7 @@ function WorkList(_ref) {
4834
4911
  // ~ Modes
4835
4912
  const [appConfig] = (0,state/* useAppConfig */.M)();
4836
4913
  // ~ Filters
4837
- const searchParams = (0,hooks/* useSearchParams */.lr)();
4914
+ const searchParams = (0,hooks/* useSearchParams */.l)();
4838
4915
  const navigate = (0,dist/* useNavigate */.s0)();
4839
4916
  const STUDIES_LIMIT = 101;
4840
4917
  const queryFilterValues = WorkList_getQueryFilterValues(searchParams);
@@ -4842,7 +4919,7 @@ function WorkList(_ref) {
4842
4919
  ...defaultFilterValues,
4843
4920
  ...queryFilterValues
4844
4921
  });
4845
- const debouncedFilterValues = (0,hooks/* useDebounce */.Nr)(filterValues, 200);
4922
+ const debouncedFilterValues = (0,hooks/* useDebounce */.N)(filterValues, 200);
4846
4923
  const {
4847
4924
  resultsPerPage,
4848
4925
  pageNumber,
@@ -5122,8 +5199,8 @@ function WorkList(_ref) {
5122
5199
  };
5123
5200
  });
5124
5201
  const hasStudies = numOfStudies > 0;
5125
- const versionNumber = "3.7.0-beta.35";
5126
- const commitHash = "d5cbbb037d1fcb52bff278fa4ff3d8fa92b15d10";
5202
+ const versionNumber = "3.7.0-beta.36";
5203
+ const commitHash = "7bbc213f58a1be3560c0414242549007885d0f13";
5127
5204
  const menuOptions = [{
5128
5205
  title: t('Header:About'),
5129
5206
  icon: 'info',
@@ -5173,7 +5250,7 @@ function WorkList(_ref) {
5173
5250
  const {
5174
5251
  component: dicomUploadComponent
5175
5252
  } = customizationService.get('dicomUploadComponent') ?? {};
5176
- const uploadProps = dicomUploadComponent && dataSource.getConfig().dicomUploadEnabled ? {
5253
+ const uploadProps = dicomUploadComponent && dataSource.getConfig()?.dicomUploadEnabled ? {
5177
5254
  title: 'Upload files',
5178
5255
  closeButton: true,
5179
5256
  shouldCloseOnEsc: false,
@@ -6220,9 +6297,15 @@ function ModeRoute(_ref3) {
6220
6297
  } = _ref3;
6221
6298
  // Parse route params/querystring
6222
6299
  const location = (0,react_router_dist/* useLocation */.TH)();
6223
- const query = (0,hooks/* useQuery */.aM)();
6300
+
6301
+ // The react router DOM placeholder map (see https://reactrouter.com/en/main/hooks/use-params).
6224
6302
  const params = (0,react_router_dist/* useParams */.UO)();
6225
- const searchParams = (0,hooks/* useSearchParams */.lr)();
6303
+ // The URL's query search parameters where the keys casing is maintained
6304
+ const query = (0,hooks/* useSearchParams */.l)();
6305
+ // The URL's query search parameters where the keys are all lower case.
6306
+ const lowerCaseSearchParams = (0,hooks/* useSearchParams */.l)({
6307
+ lowerCaseKeys: true
6308
+ });
6226
6309
  const [studyInstanceUIDs, setStudyInstanceUIDs] = (0,react.useState)();
6227
6310
  const [refresh, setRefresh] = (0,react.useState)(false);
6228
6311
  const [ExtensionDependenciesLoaded, setExtensionDependenciesLoaded] = (0,react.useState)(false);
@@ -6247,8 +6330,8 @@ function ModeRoute(_ref3) {
6247
6330
  hotkeys: hotkeyObj,
6248
6331
  hangingProtocol
6249
6332
  } = mode;
6250
- const runTimeHangingProtocolId = searchParams.get('hangingprotocolid');
6251
- const token = searchParams.get('token');
6333
+ const runTimeHangingProtocolId = lowerCaseSearchParams.get('hangingprotocolid');
6334
+ const token = lowerCaseSearchParams.get('token');
6252
6335
  if (token) {
6253
6336
  // if a token is passed in, set the userAuthenticationService to use it
6254
6337
  // for the Authorization header for all requests
@@ -6274,10 +6357,11 @@ function ModeRoute(_ref3) {
6274
6357
  // Preserve the old array interface for hotkeys
6275
6358
  const hotkeys = Array.isArray(hotkeyObj) ? hotkeyObj : hotkeyObj?.hotkeys;
6276
6359
  const hotkeyName = hotkeyObj?.name || 'hotkey-definitions-v2';
6277
- if (dataSourceName === undefined) {
6278
- dataSourceName = extensionManager.defaultDataSourceName;
6360
+
6361
+ // An undefined dataSourceName implies that the active data source that is already set in the ExtensionManager should be used.
6362
+ if (dataSourceName !== undefined) {
6363
+ extensionManager.setActiveDataSource(dataSourceName);
6279
6364
  }
6280
- extensionManager.setActiveDataSource(dataSourceName);
6281
6365
  const dataSource = extensionManager.getActiveDataSource()[0];
6282
6366
 
6283
6367
  // Only handling one route per mode for now
@@ -6340,11 +6424,14 @@ function ModeRoute(_ref3) {
6340
6424
 
6341
6425
  // Todo: this should not be here, data source should not care about params
6342
6426
  const initializeDataSource = async (params, query) => {
6343
- const studyInstanceUIDs = await dataSource.initialize({
6427
+ await dataSource.initialize({
6344
6428
  params,
6345
6429
  query
6346
6430
  });
6347
- setStudyInstanceUIDs(studyInstanceUIDs);
6431
+ setStudyInstanceUIDs(dataSource.getStudyInstanceUIDs({
6432
+ params,
6433
+ query
6434
+ }));
6348
6435
  };
6349
6436
  initializeDataSource(params, query);
6350
6437
  return () => {
@@ -6579,15 +6666,14 @@ function buildModeRoutes(_ref) {
6579
6666
  private: true
6580
6667
  });
6581
6668
  });
6582
- const defaultDataSourceName = extensionManager.defaultDataSourceName;
6583
6669
 
6584
- // Add default DataSource route.
6670
+ // Add active DataSource route.
6671
+ // This is the DataSource route for the active data source defined in ExtensionManager.getActiveDataSource
6585
6672
  const path = `/${mode.routeName}`;
6586
6673
 
6587
6674
  // TODO move up.
6588
6675
  const children = () => /*#__PURE__*/react.createElement(ModeRoute, {
6589
6676
  mode: mode,
6590
- dataSourceName: defaultDataSourceName,
6591
6677
  extensionManager: extensionManager,
6592
6678
  servicesManager: servicesManager,
6593
6679
  commandsManager: commandsManager,
@@ -6682,7 +6768,8 @@ const createRoutes = _ref => {
6682
6768
  private: true,
6683
6769
  props: {
6684
6770
  children: WorkList_WorkList,
6685
- servicesManager
6771
+ servicesManager,
6772
+ extensionManager
6686
6773
  }
6687
6774
  };
6688
6775
  const customRoutes = customizationService.getGlobalCustomization('customRoutes');
@@ -7453,7 +7540,7 @@ function _getImageOrientationPatient(image) {
7453
7540
 
7454
7541
  /***/ }),
7455
7542
 
7456
- /***/ 62771:
7543
+ /***/ 87754:
7457
7544
  /***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => {
7458
7545
 
7459
7546
  "use strict";
@@ -7520,379 +7607,6 @@ const log = {
7520
7607
  timeEnd: console.timeEnd
7521
7608
  };
7522
7609
  /* harmony default export */ const src_log = (log);
7523
- ;// CONCATENATED MODULE: ../../core/src/extensions/ExtensionManager.ts
7524
-
7525
-
7526
-
7527
- /**
7528
- * This is the arguments given to create the extension.
7529
- */
7530
-
7531
- /**
7532
- * The configuration of an extension.
7533
- * This uses type as the extension manager only knows that the configuration
7534
- * is an object of some sort, and doesn't know anything else about it.
7535
- */
7536
-
7537
- /**
7538
- * The parameters passed to the extension.
7539
- */
7540
-
7541
- /**
7542
- * The type of an actual extension instance.
7543
- * This is an interface as it declares possible calls, but extensions can
7544
- * have more values than this.
7545
- */
7546
-
7547
- class ExtensionManager {
7548
- constructor(_ref) {
7549
- var _this = this;
7550
- let {
7551
- commandsManager,
7552
- servicesManager,
7553
- hotkeysManager,
7554
- appConfig = {}
7555
- } = _ref;
7556
- this._commandsManager = void 0;
7557
- this._servicesManager = void 0;
7558
- this._hotkeysManager = void 0;
7559
- /**
7560
- * An array of extensions, or an array of arrays that contains extension
7561
- * configuration pairs.
7562
- *
7563
- * @param {Object[]} extensions - Array of extensions
7564
- */
7565
- this.registerExtensions = async function (extensions) {
7566
- let dataSources = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : [];
7567
- // Todo: we ideally should be able to run registrations in parallel
7568
- // but currently since some extensions need to be registered before
7569
- // others, we need to run them sequentially. We need a postInit hook
7570
- // to avoid this sequential async registration
7571
- for (let i = 0; i < extensions.length; i++) {
7572
- const extension = extensions[i];
7573
- const hasConfiguration = Array.isArray(extension);
7574
- try {
7575
- if (hasConfiguration) {
7576
- // Important: for some reason in the line below the type
7577
- // of extension is not recognized as [ExtensionRegister,
7578
- // ExtensionConfiguration] by babel DON"T CHANGE IT
7579
- // Same for the for loop above don't use
7580
- // for (const extension of extensions)
7581
- const ohifExtension = extension[0];
7582
- const configuration = extension[1];
7583
- await _this.registerExtension(ohifExtension, configuration, dataSources);
7584
- } else {
7585
- await _this.registerExtension(extension, {}, dataSources);
7586
- }
7587
- } catch (error) {
7588
- console.error(error);
7589
- }
7590
- }
7591
- };
7592
- /**
7593
- *
7594
- * TODO: Id Management: SopClassHandlers currently refer to viewport module by id; setting the extension id as viewport module id is a workaround for now
7595
- * @param {Object} extension
7596
- * @param {Object} configuration
7597
- */
7598
- this.registerExtension = async function (extension) {
7599
- let configuration = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : {};
7600
- let dataSources = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : [];
7601
- if (!extension) {
7602
- throw new Error('Attempting to register a null/undefined extension.');
7603
- }
7604
- const extensionId = extension.id;
7605
- if (!extensionId) {
7606
- // Note: Mode framework cannot function without IDs.
7607
- src_log.warn(extension);
7608
- throw new Error(`Extension ID not set`);
7609
- }
7610
- if (_this.registeredExtensionIds.includes(extensionId)) {
7611
- src_log.warn(`Extension ID ${extensionId} has already been registered. Exiting before duplicating modules.`);
7612
- return;
7613
- }
7614
-
7615
- // preRegistrationHook
7616
- if (extension.preRegistration) {
7617
- await extension.preRegistration({
7618
- servicesManager: _this._servicesManager,
7619
- commandsManager: _this._commandsManager,
7620
- hotkeysManager: _this._hotkeysManager,
7621
- extensionManager: _this,
7622
- appConfig: _this._appConfig,
7623
- configuration
7624
- });
7625
- }
7626
- if (extension.onModeEnter) {
7627
- _this._extensionLifeCycleHooks.onModeEnter[extensionId] = extension.onModeEnter;
7628
- }
7629
- if (extension.onModeExit) {
7630
- _this._extensionLifeCycleHooks.onModeExit[extensionId] = extension.onModeExit;
7631
- }
7632
-
7633
- // Register Modules
7634
- _this.moduleTypeNames.forEach(moduleType => {
7635
- const extensionModule = _this._getExtensionModule(moduleType, extension, extensionId, configuration);
7636
- if (extensionModule) {
7637
- switch (moduleType) {
7638
- case MODULE_TYPES.COMMANDS:
7639
- _this._initCommandsModule(extensionModule);
7640
- break;
7641
- case MODULE_TYPES.DATA_SOURCE:
7642
- _this._initDataSourcesModule(extensionModule, extensionId, dataSources);
7643
- break;
7644
- case MODULE_TYPES.HANGING_PROTOCOL:
7645
- _this._initHangingProtocolsModule(extensionModule, extensionId);
7646
- case MODULE_TYPES.TOOLBAR:
7647
- case MODULE_TYPES.VIEWPORT:
7648
- case MODULE_TYPES.PANEL:
7649
- case MODULE_TYPES.SOP_CLASS_HANDLER:
7650
- case MODULE_TYPES.CONTEXT:
7651
- case MODULE_TYPES.LAYOUT_TEMPLATE:
7652
- case MODULE_TYPES.CUSTOMIZATION:
7653
- case MODULE_TYPES.STATE_SYNC:
7654
- case MODULE_TYPES.UTILITY:
7655
- // Default for most extension points,
7656
- // Just adds each entry ready for consumption by mode.
7657
- extensionModule.forEach(element => {
7658
- if (!element.name) {
7659
- throw new Error(`Extension ID ${extensionId} module ${moduleType} element has no name`);
7660
- }
7661
- const id = `${extensionId}.${moduleType}.${element.name}`;
7662
- element.id = id;
7663
- _this.modulesMap[id] = element;
7664
- });
7665
- break;
7666
- default:
7667
- throw new Error(`Module type invalid: ${moduleType}`);
7668
- }
7669
- _this.modules[moduleType].push({
7670
- extensionId,
7671
- module: extensionModule
7672
- });
7673
- }
7674
- });
7675
-
7676
- // Track extension registration
7677
- _this.registeredExtensionIds.push(extensionId);
7678
- };
7679
- this.getModuleEntry = stringEntry => {
7680
- return this.modulesMap[stringEntry];
7681
- };
7682
- this.getDataSources = dataSourceName => {
7683
- if (dataSourceName === undefined) {
7684
- // Default to the activeDataSource
7685
- dataSourceName = this.activeDataSource;
7686
- }
7687
-
7688
- // Note: this currently uses the data source name, which feels weird...
7689
- return this.dataSourceMap[dataSourceName];
7690
- };
7691
- this.getActiveDataSource = () => {
7692
- return this.dataSourceMap[this.activeDataSource];
7693
- };
7694
- this.getDataSource = () => {
7695
- return this.dataSourceMap[this.activeDataSource];
7696
- };
7697
- /**
7698
- * @private
7699
- * @param {string} moduleType
7700
- * @param {Object} extension
7701
- * @param {string} extensionId - Used for logging warnings
7702
- */
7703
- this._getExtensionModule = (moduleType, extension, extensionId, configuration) => {
7704
- const getModuleFnName = 'get' + _capitalizeFirstCharacter(moduleType);
7705
- const getModuleFn = extension[getModuleFnName];
7706
- if (!getModuleFn) {
7707
- return;
7708
- }
7709
- try {
7710
- const extensionModule = extension[getModuleFnName]({
7711
- appConfig: this._appConfig,
7712
- commandsManager: this._commandsManager,
7713
- servicesManager: this._servicesManager,
7714
- hotkeysManager: this._hotkeysManager,
7715
- extensionManager: this,
7716
- configuration
7717
- });
7718
- if (!extensionModule) {
7719
- src_log.warn(`Null or undefined returned when registering the ${getModuleFnName} module for the ${extensionId} extension`);
7720
- }
7721
- return extensionModule;
7722
- } catch (ex) {
7723
- console.log(ex);
7724
- throw new Error(`Exception thrown while trying to call ${getModuleFnName} for the ${extensionId} extension`);
7725
- }
7726
- };
7727
- this._initHangingProtocolsModule = (extensionModule, extensionId) => {
7728
- const {
7729
- hangingProtocolService
7730
- } = this._servicesManager.services;
7731
- extensionModule.forEach(_ref2 => {
7732
- let {
7733
- name,
7734
- protocol
7735
- } = _ref2;
7736
- if (protocol) {
7737
- // Only auto-register if protocol specified, otherwise let mode register
7738
- hangingProtocolService.addProtocol(name, protocol);
7739
- }
7740
- });
7741
- };
7742
- /**
7743
- *
7744
- * @private
7745
- * @param {Object[]} commandDefinitions
7746
- */
7747
- this._initCommandsModule = extensionModule => {
7748
- let {
7749
- definitions,
7750
- defaultContext
7751
- } = extensionModule;
7752
- if (!definitions || Object.keys(definitions).length === 0) {
7753
- src_log.warn('Commands Module contains no command definitions');
7754
- return;
7755
- }
7756
- defaultContext = defaultContext || 'VIEWER';
7757
- if (!this._commandsManager.getContext(defaultContext)) {
7758
- this._commandsManager.createContext(defaultContext);
7759
- }
7760
- Object.keys(definitions).forEach(commandName => {
7761
- const commandDefinition = definitions[commandName];
7762
- const commandHasContextThatDoesNotExist = commandDefinition.context && !this._commandsManager.getContext(commandDefinition.context);
7763
- if (commandHasContextThatDoesNotExist) {
7764
- this._commandsManager.createContext(commandDefinition.context);
7765
- }
7766
- this._commandsManager.registerCommand(commandDefinition.context || defaultContext, commandName, commandDefinition);
7767
- });
7768
- };
7769
- this.modules = {};
7770
- this.registeredExtensionIds = [];
7771
- this.moduleTypeNames = Object.values(MODULE_TYPES);
7772
- //
7773
- this._commandsManager = commandsManager;
7774
- this._servicesManager = servicesManager;
7775
- this._hotkeysManager = hotkeysManager;
7776
- this._appConfig = appConfig;
7777
- this.modulesMap = {};
7778
- this.moduleTypeNames.forEach(moduleType => {
7779
- this.modules[moduleType] = [];
7780
- });
7781
- this._extensionLifeCycleHooks = {
7782
- onModeEnter: {},
7783
- onModeExit: {}
7784
- };
7785
- this.dataSourceMap = {};
7786
- this.dataSourceDefs = {};
7787
- this.defaultDataSourceName = appConfig.defaultDataSourceName;
7788
- this.activeDataSource = undefined;
7789
- }
7790
- setActiveDataSource(dataSourceName) {
7791
- this.activeDataSource = dataSourceName;
7792
- }
7793
-
7794
- /**
7795
- * Calls all the services and extension on mode enters.
7796
- * The service onModeEnter is called first
7797
- * Then registered extensions onModeEnter is called
7798
- * This is supposed to setup the extension for a standard entry.
7799
- */
7800
- onModeEnter() {
7801
- const {
7802
- registeredExtensionIds,
7803
- _servicesManager,
7804
- _commandsManager,
7805
- _hotkeysManager,
7806
- _extensionLifeCycleHooks
7807
- } = this;
7808
-
7809
- // The onModeEnter of the service must occur BEFORE the extension
7810
- // onModeEnter in order to reset the state to a standard state
7811
- // before the extension restores and cached data.
7812
- for (const service of Object.values(_servicesManager.services)) {
7813
- service?.onModeEnter?.();
7814
- }
7815
- registeredExtensionIds.forEach(extensionId => {
7816
- const onModeEnter = _extensionLifeCycleHooks.onModeEnter[extensionId];
7817
- if (typeof onModeEnter === 'function') {
7818
- onModeEnter({
7819
- servicesManager: _servicesManager,
7820
- commandsManager: _commandsManager,
7821
- hotkeysManager: _hotkeysManager
7822
- });
7823
- }
7824
- });
7825
- }
7826
- onModeExit() {
7827
- const {
7828
- registeredExtensionIds,
7829
- _servicesManager,
7830
- _commandsManager,
7831
- _extensionLifeCycleHooks
7832
- } = this;
7833
- registeredExtensionIds.forEach(extensionId => {
7834
- const onModeExit = _extensionLifeCycleHooks.onModeExit[extensionId];
7835
- if (typeof onModeExit === 'function') {
7836
- onModeExit({
7837
- servicesManager: _servicesManager,
7838
- commandsManager: _commandsManager
7839
- });
7840
- }
7841
- });
7842
-
7843
- // The service onModeExit calls must occur after the extension ones
7844
- // so that extension ones can store/restore data.
7845
- for (const service of Object.values(_servicesManager.services)) {
7846
- try {
7847
- service?.onModeExit?.();
7848
- } catch (e) {
7849
- console.warn('onModeExit caught', e);
7850
- }
7851
- }
7852
- }
7853
- _initDataSourcesModule(extensionModule, extensionId) {
7854
- let dataSources = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : [];
7855
- const {
7856
- userAuthenticationService
7857
- } = this._servicesManager.services;
7858
- dataSources.forEach(dataSource => {
7859
- this.dataSourceDefs[dataSource.sourceName] = dataSource;
7860
- });
7861
- extensionModule.forEach(element => {
7862
- const namespace = `${extensionId}.${MODULE_TYPES.DATA_SOURCE}.${element.name}`;
7863
- dataSources.forEach(dataSource => {
7864
- if (dataSource.namespace === namespace) {
7865
- const dataSourceInstance = element.createDataSource(dataSource.configuration, userAuthenticationService);
7866
- if (this.dataSourceMap[dataSource.sourceName]) {
7867
- this.dataSourceMap[dataSource.sourceName].push(dataSourceInstance);
7868
- } else {
7869
- this.dataSourceMap[dataSource.sourceName] = [dataSourceInstance];
7870
- }
7871
- }
7872
- });
7873
- });
7874
- extensionModule.forEach(element => {
7875
- this.modulesMap[`${extensionId}.${MODULE_TYPES.DATA_SOURCE}.${element.name}`] = element;
7876
- });
7877
- }
7878
- }
7879
-
7880
- /**
7881
- * @private
7882
- * @param {string} lower
7883
- */
7884
- function _capitalizeFirstCharacter(lower) {
7885
- return lower.charAt(0).toUpperCase() + lower.substring(1);
7886
- }
7887
- ;// CONCATENATED MODULE: ../../core/src/extensions/index.js
7888
-
7889
-
7890
- const DEFAULT_EXPORTS = {
7891
- ExtensionManager: ExtensionManager,
7892
- MODULE_TYPES: MODULE_TYPES
7893
- };
7894
- /* harmony default export */ const extensions = ((/* unused pure expression or super */ null && (DEFAULT_EXPORTS)));
7895
-
7896
7610
  // EXTERNAL MODULE: ../../core/src/utils/guid.js
7897
7611
  var guid = __webpack_require__(33464);
7898
7612
  ;// CONCATENATED MODULE: ../../core/src/services/_shared/pubSubServiceInterface.js
@@ -14521,6 +14235,450 @@ PanelService.REGISTRATION = {
14521
14235
 
14522
14236
 
14523
14237
 
14238
+ ;// CONCATENATED MODULE: ../../core/src/extensions/ExtensionManager.ts
14239
+
14240
+
14241
+
14242
+
14243
+ /**
14244
+ * This is the arguments given to create the extension.
14245
+ */
14246
+
14247
+ /**
14248
+ * The configuration of an extension.
14249
+ * This uses type as the extension manager only knows that the configuration
14250
+ * is an object of some sort, and doesn't know anything else about it.
14251
+ */
14252
+
14253
+ /**
14254
+ * The parameters passed to the extension.
14255
+ */
14256
+
14257
+ /**
14258
+ * The type of an actual extension instance.
14259
+ * This is an interface as it declares possible calls, but extensions can
14260
+ * have more values than this.
14261
+ */
14262
+
14263
+ class ExtensionManager extends PubSubService {
14264
+ constructor(_ref) {
14265
+ var _this;
14266
+ let {
14267
+ commandsManager,
14268
+ servicesManager,
14269
+ hotkeysManager,
14270
+ appConfig = {}
14271
+ } = _ref;
14272
+ super(ExtensionManager.EVENTS);
14273
+ _this = this;
14274
+ this._commandsManager = void 0;
14275
+ this._servicesManager = void 0;
14276
+ this._hotkeysManager = void 0;
14277
+ /**
14278
+ * An array of extensions, or an array of arrays that contains extension
14279
+ * configuration pairs.
14280
+ *
14281
+ * @param {Object[]} extensions - Array of extensions
14282
+ */
14283
+ this.registerExtensions = async function (extensions) {
14284
+ let dataSources = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : [];
14285
+ // Todo: we ideally should be able to run registrations in parallel
14286
+ // but currently since some extensions need to be registered before
14287
+ // others, we need to run them sequentially. We need a postInit hook
14288
+ // to avoid this sequential async registration
14289
+ for (let i = 0; i < extensions.length; i++) {
14290
+ const extension = extensions[i];
14291
+ const hasConfiguration = Array.isArray(extension);
14292
+ try {
14293
+ if (hasConfiguration) {
14294
+ // Important: for some reason in the line below the type
14295
+ // of extension is not recognized as [ExtensionRegister,
14296
+ // ExtensionConfiguration] by babel DON"T CHANGE IT
14297
+ // Same for the for loop above don't use
14298
+ // for (const extension of extensions)
14299
+ const ohifExtension = extension[0];
14300
+ const configuration = extension[1];
14301
+ await _this.registerExtension(ohifExtension, configuration, dataSources);
14302
+ } else {
14303
+ await _this.registerExtension(extension, {}, dataSources);
14304
+ }
14305
+ } catch (error) {
14306
+ console.error(error);
14307
+ }
14308
+ }
14309
+ };
14310
+ /**
14311
+ *
14312
+ * TODO: Id Management: SopClassHandlers currently refer to viewport module by id; setting the extension id as viewport module id is a workaround for now
14313
+ * @param {Object} extension
14314
+ * @param {Object} configuration
14315
+ */
14316
+ this.registerExtension = async function (extension) {
14317
+ let configuration = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : {};
14318
+ let dataSources = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : [];
14319
+ if (!extension) {
14320
+ throw new Error('Attempting to register a null/undefined extension.');
14321
+ }
14322
+ const extensionId = extension.id;
14323
+ if (!extensionId) {
14324
+ // Note: Mode framework cannot function without IDs.
14325
+ src_log.warn(extension);
14326
+ throw new Error(`Extension ID not set`);
14327
+ }
14328
+ if (_this.registeredExtensionIds.includes(extensionId)) {
14329
+ src_log.warn(`Extension ID ${extensionId} has already been registered. Exiting before duplicating modules.`);
14330
+ return;
14331
+ }
14332
+
14333
+ // preRegistrationHook
14334
+ if (extension.preRegistration) {
14335
+ await extension.preRegistration({
14336
+ servicesManager: _this._servicesManager,
14337
+ commandsManager: _this._commandsManager,
14338
+ hotkeysManager: _this._hotkeysManager,
14339
+ extensionManager: _this,
14340
+ appConfig: _this._appConfig,
14341
+ configuration
14342
+ });
14343
+ }
14344
+ if (extension.onModeEnter) {
14345
+ _this._extensionLifeCycleHooks.onModeEnter[extensionId] = extension.onModeEnter;
14346
+ }
14347
+ if (extension.onModeExit) {
14348
+ _this._extensionLifeCycleHooks.onModeExit[extensionId] = extension.onModeExit;
14349
+ }
14350
+
14351
+ // Register Modules
14352
+ _this.moduleTypeNames.forEach(moduleType => {
14353
+ const extensionModule = _this._getExtensionModule(moduleType, extension, extensionId, configuration);
14354
+ if (extensionModule) {
14355
+ switch (moduleType) {
14356
+ case MODULE_TYPES.COMMANDS:
14357
+ _this._initCommandsModule(extensionModule);
14358
+ break;
14359
+ case MODULE_TYPES.DATA_SOURCE:
14360
+ _this._initDataSourcesModule(extensionModule, extensionId, dataSources);
14361
+ break;
14362
+ case MODULE_TYPES.HANGING_PROTOCOL:
14363
+ _this._initHangingProtocolsModule(extensionModule, extensionId);
14364
+ case MODULE_TYPES.TOOLBAR:
14365
+ case MODULE_TYPES.VIEWPORT:
14366
+ case MODULE_TYPES.PANEL:
14367
+ case MODULE_TYPES.SOP_CLASS_HANDLER:
14368
+ case MODULE_TYPES.CONTEXT:
14369
+ case MODULE_TYPES.LAYOUT_TEMPLATE:
14370
+ case MODULE_TYPES.CUSTOMIZATION:
14371
+ case MODULE_TYPES.STATE_SYNC:
14372
+ case MODULE_TYPES.UTILITY:
14373
+ // Default for most extension points,
14374
+ // Just adds each entry ready for consumption by mode.
14375
+ extensionModule.forEach(element => {
14376
+ if (!element.name) {
14377
+ throw new Error(`Extension ID ${extensionId} module ${moduleType} element has no name`);
14378
+ }
14379
+ const id = `${extensionId}.${moduleType}.${element.name}`;
14380
+ element.id = id;
14381
+ _this.modulesMap[id] = element;
14382
+ });
14383
+ break;
14384
+ default:
14385
+ throw new Error(`Module type invalid: ${moduleType}`);
14386
+ }
14387
+ _this.modules[moduleType].push({
14388
+ extensionId,
14389
+ module: extensionModule
14390
+ });
14391
+ }
14392
+ });
14393
+
14394
+ // Track extension registration
14395
+ _this.registeredExtensionIds.push(extensionId);
14396
+ };
14397
+ this.getModuleEntry = stringEntry => {
14398
+ return this.modulesMap[stringEntry];
14399
+ };
14400
+ this.getDataSources = dataSourceName => {
14401
+ if (dataSourceName === undefined) {
14402
+ // Default to the activeDataSource
14403
+ dataSourceName = this.activeDataSource;
14404
+ }
14405
+
14406
+ // Note: this currently uses the data source name, which feels weird...
14407
+ return this.dataSourceMap[dataSourceName];
14408
+ };
14409
+ this.getActiveDataSource = () => {
14410
+ return this.dataSourceMap[this.activeDataSource];
14411
+ };
14412
+ /**
14413
+ * Gets the data source definition for the given data source name.
14414
+ * If no data source name is provided, the active data source definition is
14415
+ * returned.
14416
+ * @param dataSourceName the data source name
14417
+ * @returns the data source definition
14418
+ */
14419
+ this.getDataSourceDef = dataSourceName => {
14420
+ if (dataSourceName === undefined) {
14421
+ // Default to the activeDataSource
14422
+ dataSourceName = this.activeDataSource;
14423
+ }
14424
+ return this.dataSourceDefs[dataSourceName];
14425
+ };
14426
+ /**
14427
+ * @private
14428
+ * @param {string} moduleType
14429
+ * @param {Object} extension
14430
+ * @param {string} extensionId - Used for logging warnings
14431
+ */
14432
+ this._getExtensionModule = (moduleType, extension, extensionId, configuration) => {
14433
+ const getModuleFnName = 'get' + _capitalizeFirstCharacter(moduleType);
14434
+ const getModuleFn = extension[getModuleFnName];
14435
+ if (!getModuleFn) {
14436
+ return;
14437
+ }
14438
+ try {
14439
+ const extensionModule = extension[getModuleFnName]({
14440
+ appConfig: this._appConfig,
14441
+ commandsManager: this._commandsManager,
14442
+ servicesManager: this._servicesManager,
14443
+ hotkeysManager: this._hotkeysManager,
14444
+ extensionManager: this,
14445
+ configuration
14446
+ });
14447
+ if (!extensionModule) {
14448
+ src_log.warn(`Null or undefined returned when registering the ${getModuleFnName} module for the ${extensionId} extension`);
14449
+ }
14450
+ return extensionModule;
14451
+ } catch (ex) {
14452
+ console.log(ex);
14453
+ throw new Error(`Exception thrown while trying to call ${getModuleFnName} for the ${extensionId} extension`);
14454
+ }
14455
+ };
14456
+ this._initHangingProtocolsModule = (extensionModule, extensionId) => {
14457
+ const {
14458
+ hangingProtocolService
14459
+ } = this._servicesManager.services;
14460
+ extensionModule.forEach(_ref2 => {
14461
+ let {
14462
+ name,
14463
+ protocol
14464
+ } = _ref2;
14465
+ if (protocol) {
14466
+ // Only auto-register if protocol specified, otherwise let mode register
14467
+ hangingProtocolService.addProtocol(name, protocol);
14468
+ }
14469
+ });
14470
+ };
14471
+ /**
14472
+ *
14473
+ * @private
14474
+ * @param {Object[]} commandDefinitions
14475
+ */
14476
+ this._initCommandsModule = extensionModule => {
14477
+ let {
14478
+ definitions,
14479
+ defaultContext
14480
+ } = extensionModule;
14481
+ if (!definitions || Object.keys(definitions).length === 0) {
14482
+ src_log.warn('Commands Module contains no command definitions');
14483
+ return;
14484
+ }
14485
+ defaultContext = defaultContext || 'VIEWER';
14486
+ if (!this._commandsManager.getContext(defaultContext)) {
14487
+ this._commandsManager.createContext(defaultContext);
14488
+ }
14489
+ Object.keys(definitions).forEach(commandName => {
14490
+ const commandDefinition = definitions[commandName];
14491
+ const commandHasContextThatDoesNotExist = commandDefinition.context && !this._commandsManager.getContext(commandDefinition.context);
14492
+ if (commandHasContextThatDoesNotExist) {
14493
+ this._commandsManager.createContext(commandDefinition.context);
14494
+ }
14495
+ this._commandsManager.registerCommand(commandDefinition.context || defaultContext, commandName, commandDefinition);
14496
+ });
14497
+ };
14498
+ this.modules = {};
14499
+ this.registeredExtensionIds = [];
14500
+ this.moduleTypeNames = Object.values(MODULE_TYPES);
14501
+ //
14502
+ this._commandsManager = commandsManager;
14503
+ this._servicesManager = servicesManager;
14504
+ this._hotkeysManager = hotkeysManager;
14505
+ this._appConfig = appConfig;
14506
+ this.modulesMap = {};
14507
+ this.moduleTypeNames.forEach(moduleType => {
14508
+ this.modules[moduleType] = [];
14509
+ });
14510
+ this._extensionLifeCycleHooks = {
14511
+ onModeEnter: {},
14512
+ onModeExit: {}
14513
+ };
14514
+ this.dataSourceMap = {};
14515
+ this.dataSourceDefs = {};
14516
+ this.defaultDataSourceName = appConfig.defaultDataSourceName;
14517
+ this.activeDataSource = appConfig.defaultDataSourceName;
14518
+ }
14519
+ setActiveDataSource(dataSource) {
14520
+ if (this.activeDataSource === dataSource) {
14521
+ return;
14522
+ }
14523
+ this.activeDataSource = dataSource;
14524
+ this._broadcastEvent(ExtensionManager.EVENTS.ACTIVE_DATA_SOURCE_CHANGED, this.dataSourceDefs[this.activeDataSource]);
14525
+ }
14526
+
14527
+ /**
14528
+ * Calls all the services and extension on mode enters.
14529
+ * The service onModeEnter is called first
14530
+ * Then registered extensions onModeEnter is called
14531
+ * This is supposed to setup the extension for a standard entry.
14532
+ */
14533
+ onModeEnter() {
14534
+ const {
14535
+ registeredExtensionIds,
14536
+ _servicesManager,
14537
+ _commandsManager,
14538
+ _hotkeysManager,
14539
+ _extensionLifeCycleHooks
14540
+ } = this;
14541
+
14542
+ // The onModeEnter of the service must occur BEFORE the extension
14543
+ // onModeEnter in order to reset the state to a standard state
14544
+ // before the extension restores and cached data.
14545
+ for (const service of Object.values(_servicesManager.services)) {
14546
+ service?.onModeEnter?.();
14547
+ }
14548
+ registeredExtensionIds.forEach(extensionId => {
14549
+ const onModeEnter = _extensionLifeCycleHooks.onModeEnter[extensionId];
14550
+ if (typeof onModeEnter === 'function') {
14551
+ onModeEnter({
14552
+ servicesManager: _servicesManager,
14553
+ commandsManager: _commandsManager,
14554
+ hotkeysManager: _hotkeysManager
14555
+ });
14556
+ }
14557
+ });
14558
+ }
14559
+ onModeExit() {
14560
+ const {
14561
+ registeredExtensionIds,
14562
+ _servicesManager,
14563
+ _commandsManager,
14564
+ _extensionLifeCycleHooks
14565
+ } = this;
14566
+ registeredExtensionIds.forEach(extensionId => {
14567
+ const onModeExit = _extensionLifeCycleHooks.onModeExit[extensionId];
14568
+ if (typeof onModeExit === 'function') {
14569
+ onModeExit({
14570
+ servicesManager: _servicesManager,
14571
+ commandsManager: _commandsManager
14572
+ });
14573
+ }
14574
+ });
14575
+
14576
+ // The service onModeExit calls must occur after the extension ones
14577
+ // so that extension ones can store/restore data.
14578
+ for (const service of Object.values(_servicesManager.services)) {
14579
+ try {
14580
+ service?.onModeExit?.();
14581
+ } catch (e) {
14582
+ console.warn('onModeExit caught', e);
14583
+ }
14584
+ }
14585
+ }
14586
+ /**
14587
+ * Adds the given data source and optionally sets it as the active data source.
14588
+ * The method does this by first creating the data source.
14589
+ * @param dataSourceDef the data source definition to be added
14590
+ * @param activate flag to indicate if the added data source should be set to the active data source
14591
+ */
14592
+ addDataSource(dataSourceDef) {
14593
+ let options = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : {
14594
+ activate: false
14595
+ };
14596
+ const existingDataSource = this.getDataSources(dataSourceDef.sourceName);
14597
+ if (existingDataSource?.[0]) {
14598
+ // The data source already exists and cannot be added.
14599
+ return;
14600
+ }
14601
+ this._createDataSourceInstance(dataSourceDef);
14602
+ if (options.activate) {
14603
+ this.setActiveDataSource(dataSourceDef.sourceName);
14604
+ }
14605
+ }
14606
+
14607
+ /**
14608
+ * Updates the configuration of the given data source name. It first creates a new data source with
14609
+ * the existing definition and the new configuration passed in.
14610
+ * @param dataSourceName the name of the data source to update
14611
+ * @param dataSourceConfiguration the new configuration to update the data source with
14612
+ */
14613
+ updateDataSourceConfiguration(dataSourceName, dataSourceConfiguration) {
14614
+ const existingDataSource = this.getDataSources(dataSourceName);
14615
+ if (!existingDataSource?.[0]) {
14616
+ // Cannot update a non existent data source.
14617
+ return;
14618
+ }
14619
+ const dataSourceDef = this.dataSourceDefs[dataSourceName];
14620
+ // Update the configuration.
14621
+ dataSourceDef.configuration = dataSourceConfiguration;
14622
+ this._createDataSourceInstance(dataSourceDef);
14623
+ if (this.activeDataSource === dataSourceName) {
14624
+ // When the active data source is changed/set, fire an event to indicate that its configuration has changed.
14625
+ this._broadcastEvent(ExtensionManager.EVENTS.ACTIVE_DATA_SOURCE_CHANGED, dataSourceDef);
14626
+ }
14627
+ }
14628
+
14629
+ /**
14630
+ * Creates a data source instance from the given definition. The definition is
14631
+ * added to dataSourceDefs and the created instance is added to dataSourceMap.
14632
+ * @param dataSourceDef
14633
+ * @returns
14634
+ */
14635
+ _createDataSourceInstance(dataSourceDef) {
14636
+ const module = this.getModuleEntry(dataSourceDef.namespace);
14637
+ if (!module) {
14638
+ return;
14639
+ }
14640
+ this.dataSourceDefs[dataSourceDef.sourceName] = dataSourceDef;
14641
+ const {
14642
+ userAuthenticationService
14643
+ } = this._servicesManager.services;
14644
+ const dataSourceInstance = module.createDataSource(dataSourceDef.configuration, userAuthenticationService);
14645
+ this.dataSourceMap[dataSourceDef.sourceName] = [dataSourceInstance];
14646
+ }
14647
+ _initDataSourcesModule(extensionModule, extensionId) {
14648
+ let dataSources = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : [];
14649
+ extensionModule.forEach(element => {
14650
+ this.modulesMap[`${extensionId}.${MODULE_TYPES.DATA_SOURCE}.${element.name}`] = element;
14651
+ });
14652
+ extensionModule.forEach(element => {
14653
+ const namespace = `${extensionId}.${MODULE_TYPES.DATA_SOURCE}.${element.name}`;
14654
+ dataSources.forEach(dataSource => {
14655
+ if (dataSource.namespace === namespace) {
14656
+ this.addDataSource(dataSource);
14657
+ }
14658
+ });
14659
+ });
14660
+ }
14661
+ }
14662
+
14663
+ /**
14664
+ * @private
14665
+ * @param {string} lower
14666
+ */
14667
+ ExtensionManager.EVENTS = {
14668
+ ACTIVE_DATA_SOURCE_CHANGED: 'event::activedatasourcechanged'
14669
+ };
14670
+ function _capitalizeFirstCharacter(lower) {
14671
+ return lower.charAt(0).toUpperCase() + lower.substring(1);
14672
+ }
14673
+ ;// CONCATENATED MODULE: ../../core/src/extensions/index.js
14674
+
14675
+
14676
+ const DEFAULT_EXPORTS = {
14677
+ ExtensionManager: ExtensionManager,
14678
+ MODULE_TYPES: MODULE_TYPES
14679
+ };
14680
+ /* harmony default export */ const extensions = ((/* unused pure expression or super */ null && (DEFAULT_EXPORTS)));
14681
+
14524
14682
  ;// CONCATENATED MODULE: ../../core/src/classes/CommandsManager.ts
14525
14683
 
14526
14684
  /**
@@ -16269,6 +16427,9 @@ const bindings = [{
16269
16427
 
16270
16428
  // EXTERNAL MODULE: ../../core/src/classes/Hotkey.ts
16271
16429
  var Hotkey = __webpack_require__(57374);
16430
+ ;// CONCATENATED MODULE: ../../core/src/types/DataSource.ts
16431
+
16432
+
16272
16433
  ;// CONCATENATED MODULE: ../../core/src/services/CustomizationService/types.ts
16273
16434
 
16274
16435
 
@@ -16299,6 +16460,7 @@ var IPubSub = __webpack_require__(98844);
16299
16460
 
16300
16461
 
16301
16462
 
16463
+
16302
16464
  // Separate out some generic types
16303
16465
 
16304
16466
 
@@ -16336,7 +16498,8 @@ function create(_ref) {
16336
16498
  deleteStudyMetadataPromise,
16337
16499
  getImageIdsForDisplaySet,
16338
16500
  getImageIdsForInstance,
16339
- getConfig
16501
+ getConfig,
16502
+ getStudyInstanceUIDs
16340
16503
  } = _ref;
16341
16504
  const defaultQuery = {
16342
16505
  studies: {
@@ -16382,7 +16545,8 @@ function create(_ref) {
16382
16545
  deleteStudyMetadataPromise,
16383
16546
  getImageIdsForDisplaySet,
16384
16547
  getImageIdsForInstance,
16385
- getConfig: getConfig || defaultGetConfig
16548
+ getConfig: getConfig || defaultGetConfig,
16549
+ getStudyInstanceUIDs: getStudyInstanceUIDs
16386
16550
  };
16387
16551
  }
16388
16552
  const IWebApiDataSource = {
@@ -20380,7 +20544,7 @@ const detectionOptions = {
20380
20544
  }
20381
20545
  });
20382
20546
  ;// CONCATENATED MODULE: ../../i18n/package.json
20383
- const package_namespaceObject = JSON.parse('{"i8":"3.7.0-beta.34"}');
20547
+ const package_namespaceObject = JSON.parse('{"i8":"3.7.0-beta.35"}');
20384
20548
  ;// CONCATENATED MODULE: ../../i18n/src/utils.js
20385
20549
  const languagesMap = {
20386
20550
  ar: 'Arabic',
@@ -31271,8 +31435,8 @@ ViewportDialogProvider.propTypes = {
31271
31435
  // EXTERNAL MODULE: ../../../node_modules/lodash.isequal/index.js
31272
31436
  var lodash_isequal = __webpack_require__(68652);
31273
31437
  var lodash_isequal_default = /*#__PURE__*/__webpack_require__.n(lodash_isequal);
31274
- // EXTERNAL MODULE: ../../core/src/index.ts + 102 modules
31275
- var src = __webpack_require__(62771);
31438
+ // EXTERNAL MODULE: ../../core/src/index.ts + 103 modules
31439
+ var src = __webpack_require__(87754);
31276
31440
  ;// CONCATENATED MODULE: ../../ui/src/utils/viewportLabels.ts
31277
31441
  const viewportLabels = ['A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J', 'K', 'L', 'M', 'N', 'O', 'P', 'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X', 'Y', 'Z'];
31278
31442
  /* harmony default export */ const utils_viewportLabels = (viewportLabels);
@@ -148578,7 +148742,6 @@ module.exports = warning;
148578
148742
  "use strict";
148579
148743
  /* harmony export */ __webpack_require__.d(__webpack_exports__, {
148580
148744
  /* harmony export */ AW: () => (/* reexport safe */ react_router__WEBPACK_IMPORTED_MODULE_1__.AW),
148581
- /* harmony export */ TH: () => (/* reexport safe */ react_router__WEBPACK_IMPORTED_MODULE_1__.TH),
148582
148745
  /* harmony export */ VK: () => (/* binding */ BrowserRouter),
148583
148746
  /* harmony export */ Z5: () => (/* reexport safe */ react_router__WEBPACK_IMPORTED_MODULE_1__.Z5),
148584
148747
  /* harmony export */ rU: () => (/* binding */ Link),
@@ -154452,7 +154615,7 @@ var selectOrdinal = function selectOrdinal() {
154452
154615
  /******/ // This function allow to reference async chunks
154453
154616
  /******/ __webpack_require__.u = (chunkId) => {
154454
154617
  /******/ // return url for filenames based on template
154455
- /******/ return "" + (chunkId === 18 ? "dicom-microscopy-viewer" : chunkId) + ".bundle." + {"18":"aa60bdf008c32c39cfd7","50":"17df79160c1183470b70","55":"b2c6b4dff2a949d25023","82":"2e1ab22b6d6980c356f1","151":"31ea35044218837bf73f","192":"6272e24776573a46ba0e","199":"017a4d777d4c2b3ae3c7","205":"b5a473c200dcf2bbcdb4","208":"1ddd87553ed279ecf177","270":"2d215f8720350f03e171","283":"51628bee972a04e8f2a9","295":"957b1159fec14b9199a1","351":"33b4d3f8b66453b5d303","381":"0905e683605fcbc0895f","389":"38df7e54d2f632cfa7a0","404":"1dce2dd30ff876edc5f3","531":"2a82fb1d69e5b57cc72b","569":"ee136cf6526a6380633c","581":"ab8d1f1e75de3c98dd10","606":"5d876f5f3dd8287f0a28","616":"9ca5b6ebd436fa5c8b73","625":"56cf23e17aba289098b9","642":"aba522f4f50f4b897046","664":"09abae984223969d1bde","728":"5bef7c8643b42d70a79f","744":"6010b90be6b43b0d9bc8","780":"fd0f13dc92e9caa0581e","790":"9f4c33a790c651348286","799":"6d3320855c9332c7117a","806":"2e7934d0833c4315c292","917":"e220de67184c171f631d","926":"dbc9d0e591cb9217fda2","935":"deeffff0e4f7b528e3c3","953":"4b8fee7d9484456a99b5","973":"201ccef3cb047506ff92","976":"c12649da6fb9662b9f94","984":"9133d3fdd441a8e6d63f"}[chunkId] + ".js";
154618
+ /******/ return "" + (chunkId === 18 ? "dicom-microscopy-viewer" : chunkId) + ".bundle." + {"18":"aa60bdf008c32c39cfd7","50":"260f830a3870cae30cf5","55":"fe53f3784bfe7db4a5a5","82":"11e08acaf3e1f527278d","151":"31ea35044218837bf73f","192":"160fffd248385d501d87","199":"fe8e31ccab2445a9721d","205":"b5a473c200dcf2bbcdb4","208":"ee392e7c48237252ea8e","270":"2d215f8720350f03e171","283":"b19d7099a6fb8c957fb1","295":"957b1159fec14b9199a1","351":"2e949640c417cd735688","381":"0905e683605fcbc0895f","389":"38df7e54d2f632cfa7a0","404":"051cd13557d04cc76630","531":"2a82fb1d69e5b57cc72b","569":"e77c17d37a65e5dedfed","581":"15078e71fe52b53f48b3","606":"5d876f5f3dd8287f0a28","616":"fc1820b3d98da340218c","625":"7de4074e256c743ca500","642":"f03da99e63dbfdc1cf1c","664":"09abae984223969d1bde","728":"5bef7c8643b42d70a79f","744":"08e4a5bbc4fd371a50b3","780":"fd0f13dc92e9caa0581e","790":"6fa09929a3203bcf3f2c","799":"d8e50f1fd6bf4fa3a5e1","806":"2e7934d0833c4315c292","917":"e0647888c6fff8e72e95","926":"dbc9d0e591cb9217fda2","935":"deeffff0e4f7b528e3c3","953":"95b0621f1da8dfeaed8a","973":"634f585248ead3160ff2","976":"9dec94108550ad448773","984":"1149cce5c5ecb63e76a9"}[chunkId] + ".js";
154456
154619
  /******/ };
154457
154620
  /******/ })();
154458
154621
  /******/