@ohif/app 3.13.0-beta.84 → 3.13.0-beta.85

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 (42) hide show
  1. package/dist/{1608.bundle.26306ea38618db59eff7.js → 1608.bundle.260a63b73f447e8d6b4f.js} +2 -2
  2. package/dist/{1933.bundle.0e0fde6b8da6c4ec5886.js → 1933.bundle.5e7f2bf67090bce902d7.js} +7 -7
  3. package/dist/{213.bundle.b9c5230a0608ed364eb2.js → 213.bundle.d8f826a12be93c12fc4b.js} +2 -2
  4. package/dist/{2424.bundle.063ec6460f5d81169c66.js → 2424.bundle.c8e1db274780fba640d0.js} +2 -2
  5. package/dist/{2701.bundle.6873805ddfdccc7a8b1e.js → 2701.bundle.66741b0ff04e0670b245.js} +2 -2
  6. package/dist/{3138.bundle.c068f3f3a414c363407f.js → 3138.bundle.9ee596ce0cce3718b288.js} +4 -4
  7. package/dist/{3461.bundle.5b4b50cd34e6d58eef46.js → 3461.bundle.d8c9a5f054ae93ee41b0.js} +2 -2
  8. package/dist/{2851.bundle.9f0cacde205ccf644808.js → 3617.bundle.17e4b2c55914a7965d7a.js} +385 -94
  9. package/dist/{3754.bundle.d2435bb372912595708c.js → 3754.bundle.477cfd7fc3ff13e9dc67.js} +2 -2
  10. package/dist/{4202.bundle.4fcd0de412907efd5b53.js → 4202.bundle.f11dd0ba0c2462296f46.js} +1 -1
  11. package/dist/{4819.bundle.d534d8be9c78f859948c.js → 4819.bundle.fa12d8e34d563afc7ef2.js} +10 -8
  12. package/dist/{5015.bundle.b3b9781e75cbecf5421c.js → 5015.bundle.0c9d3f85b176698ae943.js} +2 -2
  13. package/dist/{5028.bundle.f0d440303bb298e3f7cf.js → 5028.bundle.70b6411d33fd4ad807c5.js} +2 -2
  14. package/dist/{5802.bundle.cd36386cbe1613913ed4.js → 5802.bundle.da6055b6bf1a3db7b6d5.js} +4 -4
  15. package/dist/{7166.bundle.60abfa4adc75c7c44bf6.js → 7166.bundle.9759a456ece3232088ba.js} +12 -12
  16. package/dist/{8305.bundle.343dcefe229756239584.js → 8305.bundle.de5ad4cd2bfd2078a2c2.js} +6 -6
  17. package/dist/{8558.bundle.53ba6a72ddf25a64011f.js → 8558.bundle.c0c1684a450ae03cf021.js} +3 -3
  18. package/dist/{8583.bundle.279d6346025b02299108.js → 8583.bundle.5c11629c65dd2d45719f.js} +6 -6
  19. package/dist/{9845.bundle.8c450e8d65a78a5afcd3.js → 9845.bundle.32ec30c841edca0929c5.js} +2 -2
  20. package/dist/{9862.bundle.6d793a997f85d73002e9.js → 9862.bundle.f92516a34b9cef88c56f.js} +1 -1
  21. package/dist/app-config.js +4 -3
  22. package/dist/{app.bundle.1a697c4783c74e73e8ae.js → app.bundle.4fc5031387d6a24c892a.js} +57117 -23680
  23. package/dist/app.bundle.css +1 -1
  24. package/dist/google.js +2 -1
  25. package/dist/index.html +1 -1
  26. package/dist/sw.js +1 -1
  27. package/package.json +20 -20
  28. /package/dist/{1459.bundle.d47189e3c73cb9c597f7.js → 1459.bundle.43b419e5d9c9bb86ea99.js} +0 -0
  29. /package/dist/{2018.bundle.8526870f1e140859cca5.js → 2018.bundle.15d8143e0ea9191efdc2.js} +0 -0
  30. /package/dist/{2108.bundle.aea8d3b39486dd5ab39e.js → 2108.bundle.142ee8d405727d02b16a.js} +0 -0
  31. /package/dist/{4406.bundle.573d234b4641d23cf8db.js → 4406.bundle.a872cad05ed37995411b.js} +0 -0
  32. /package/dist/{4507.bundle.d95642a2848a279028b0.js → 4507.bundle.3625326bdc5829bbd2a6.js} +0 -0
  33. /package/dist/{5261.bundle.2655560097e9250eac44.js → 5261.bundle.42a4f54304863f2ad2fe.js} +0 -0
  34. /package/dist/{5457.bundle.ab72c70edec4a71c7495.js → 5457.bundle.62249b1c71f10f09910a.js} +0 -0
  35. /package/dist/{5485.bundle.22acb7ba47d10328d897.js → 5485.bundle.7a262933e9a06728382c.js} +0 -0
  36. /package/dist/{6027.bundle.c37f1f82c206f1095594.js → 6027.bundle.7338ede4a7c32b92ca8c.js} +0 -0
  37. /package/dist/{6939.bundle.41fbdef87597b5172ec6.js → 6939.bundle.3c0c61a33499a5b7e4ee.js} +0 -0
  38. /package/dist/{7159.bundle.fb9df255868960f69765.js → 7159.bundle.cf46bf2542c6b1af39b3.js} +0 -0
  39. /package/dist/{7639.bundle.94859225df85cbe4d570.js → 7639.bundle.1a77b5441c0f737cf606.js} +0 -0
  40. /package/dist/{8499.bundle.b442636640885ce4f6ef.js → 8499.bundle.2eb3104fe7dc7b2b4117.js} +0 -0
  41. /package/dist/{85.bundle.61e81c2838c5b1819198.js → 85.bundle.4347621a78643dfa6d81.js} +0 -0
  42. /package/dist/{9927.bundle.17fed5a59287bffbf3e6.js → 9927.bundle.296debf586da57755777.js} +0 -0
@@ -1,5 +1,5 @@
1
1
  "use strict";
2
- (globalThis["webpackChunk"] = globalThis["webpackChunk"] || []).push([[2851],{
2
+ (globalThis["webpackChunk"] = globalThis["webpackChunk"] || []).push([[3617],{
3
3
 
4
4
  /***/ 52675
5
5
  (__unused_webpack_module, __webpack_exports__, __webpack_require__) {
@@ -8,7 +8,7 @@
8
8
  /* harmony export */ A: () => (/* binding */ MoreDropdownMenu)
9
9
  /* harmony export */ });
10
10
  /* harmony import */ var react__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(86326);
11
- /* harmony import */ var _ohif_ui_next__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(564);
11
+ /* harmony import */ var _ohif_ui_next__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(19289);
12
12
  /* harmony import */ var _ohif_core__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(42356);
13
13
  function _extends() { return _extends = Object.assign ? Object.assign.bind() : function (n) { for (var e = 1; e < arguments.length; e++) { var t = arguments[e]; for (var r in t) ({}).hasOwnProperty.call(t, r) && (n[r] = t[r]); } return n; }, _extends.apply(null, arguments); }
14
14
 
@@ -123,8 +123,8 @@ __webpack_require__.d(__webpack_exports__, {
123
123
 
124
124
  // EXTERNAL MODULE: ../../../node_modules/react/index.js
125
125
  var react = __webpack_require__(86326);
126
- // EXTERNAL MODULE: ../../ui-next/src/index.ts + 3085 modules
127
- var src = __webpack_require__(564);
126
+ // EXTERNAL MODULE: ../../ui-next/src/index.ts + 3667 modules
127
+ var src = __webpack_require__(19289);
128
128
  // EXTERNAL MODULE: ../../core/src/index.ts + 69 modules
129
129
  var core_src = __webpack_require__(42356);
130
130
  // EXTERNAL MODULE: ../../../node_modules/react-router-dom/dist/index.js
@@ -155,6 +155,8 @@ const defaultViewPresets = [{
155
155
 
156
156
  // EXTERNAL MODULE: ../../../extensions/default/src/Components/MoreDropdownMenu.tsx
157
157
  var MoreDropdownMenu = __webpack_require__(52675);
158
+ // EXTERNAL MODULE: ../../core/src/utils/thumbnailNoImageModalities.ts
159
+ var thumbnailNoImageModalities = __webpack_require__(23842);
158
160
  ;// ../../../extensions/default/src/Panels/StudyBrowser/PanelStudyBrowser.tsx
159
161
 
160
162
 
@@ -164,12 +166,12 @@ var MoreDropdownMenu = __webpack_require__(52675);
164
166
 
165
167
 
166
168
 
169
+
167
170
  const {
168
171
  sortStudyInstances,
169
172
  formatDate,
170
173
  createStudyBrowserTabs
171
174
  } = core_src/* utils */.Wp;
172
- const thumbnailNoImageModalities = ['SR', 'SEG', 'RTSTRUCT', 'RTPLAN', 'RTDOSE', 'DOC', 'PMAP'];
173
175
 
174
176
  /**
175
177
  * Study Browser component that displays and manages studies and their display sets
@@ -309,7 +311,7 @@ function PanelStudyBrowser({
309
311
  }
310
312
  let currentDisplaySets = displaySetService.activeDisplaySets;
311
313
  // filter non based on the list of modalities that are supported by cornerstone
312
- currentDisplaySets = currentDisplaySets.filter(ds => !thumbnailNoImageModalities.includes(ds.Modality) || ds.thumbnailSrc === null);
314
+ currentDisplaySets = currentDisplaySets.filter(ds => !thumbnailNoImageModalities/* thumbnailNoImageModalities */.w.includes(ds.Modality) || ds.thumbnailSrc === null);
313
315
  if (!currentDisplaySets.length) {
314
316
  return;
315
317
  }
@@ -578,7 +580,7 @@ function _mapDisplaySets(displaySets, displaySetLoadingState, thumbnailImageSrcM
578
580
  return [...thumbnailDisplaySets, ...thumbnailNoImageDisplaySets];
579
581
  }
580
582
  function _getComponentType(ds) {
581
- if (thumbnailNoImageModalities.includes(ds.Modality) || ds?.unsupported || ds.thumbnailSrc === null) {
583
+ if (thumbnailNoImageModalities/* thumbnailNoImageModalities */.w.includes(ds.Modality) || ds?.unsupported || ds.thumbnailSrc === null) {
582
584
  return 'thumbnailNoImage';
583
585
  }
584
586
  return 'thumbnail';
@@ -618,7 +620,7 @@ function _findTabAndStudyOfDisplaySet(displaySetInstanceUID, tabs, currentTabNam
618
620
  /* harmony export */ T: () => (/* binding */ PanelStudyBrowserHeader)
619
621
  /* harmony export */ });
620
622
  /* harmony import */ var react__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(86326);
621
- /* harmony import */ var _ohif_ui_next__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(564);
623
+ /* harmony import */ var _ohif_ui_next__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(19289);
622
624
 
623
625
 
624
626
 
@@ -745,7 +747,7 @@ function Toolbar({
745
747
 
746
748
  /***/ },
747
749
 
748
- /***/ 62851
750
+ /***/ 23617
749
751
  (__unused_webpack_module, __webpack_exports__, __webpack_require__) {
750
752
 
751
753
 
@@ -848,7 +850,8 @@ function processResults(qidoStudies) {
848
850
  instances: Number(getString(qidoStudy['00201208'])) || 0,
849
851
  // number
850
852
  description: getString(qidoStudy['00081030']) || '',
851
- modalities: getString(getModalities(qidoStudy['00080060'], qidoStudy['00080061'])) || ''
853
+ modalities: getString(getModalities(qidoStudy['00080060'], qidoStudy['00080061'])) || '',
854
+ referringPhysicianName: src/* utils */.Wp.formatPN(getName(qidoStudy['00080090'])) || '' // Referring Physician's Name
852
855
  }));
853
856
  return studies;
854
857
  }
@@ -936,7 +939,9 @@ function mapParams(params, options = {}) {
936
939
  }
937
940
  const commaSeparatedFields = ['00081030',
938
941
  // Study Description
939
- '00080060' // Modality
942
+ '00080060',
943
+ // Modality
944
+ '00080090' // Referring Physician's Name
940
945
  // Add more fields here if you want them in the result
941
946
  ].join(',');
942
947
  const useWildcard = params?.disableWildcard !== undefined ? !params.disableWildcard : options.supportsWildcard;
@@ -2135,6 +2140,229 @@ function fixBulkDataURI(value, instance, dicomWebConfig) {
2135
2140
  }
2136
2141
  }
2137
2142
 
2143
+ ;// ../../../extensions/default/src/DicomWebDataSource/retrieveThumbnail.ts
2144
+ /**
2145
+ * The subset of the data source's `retrieve` object the thumbnail strategies
2146
+ * call back into for the directURL and bulkData-backed renderings.
2147
+ */
2148
+
2149
+ /**
2150
+ * Builds the `getThumbnailSrc` function for a given thumbnail context,
2151
+ * selecting the strategy from `config.thumbnailRendering` /
2152
+ * `config.thumbnailRequestStrategy`.
2153
+ *
2154
+ * Extracted from the DICOMweb data source so the thumbnail strategies live
2155
+ * apart from the data source wiring. The `retrieve` dependency provides the
2156
+ * `directURL` and `bulkDataURI` callbacks the data source used to reach via
2157
+ * `this`.
2158
+ */
2159
+ function getGetThumbnailSrc({
2160
+ thumbnailContext,
2161
+ imageId,
2162
+ config,
2163
+ getAuthorizationHeader,
2164
+ qidoDicomWebClient,
2165
+ retrieve
2166
+ }) {
2167
+ const thumbnailRendering = config.thumbnailRendering;
2168
+ if (!thumbnailRendering) {
2169
+ return function getThumbnailSrc() {
2170
+ console.warn('thumbnailRendering is not configured; returning null thumbnail src.');
2171
+ return null;
2172
+ };
2173
+ }
2174
+ if (thumbnailRendering === 'wadors') {
2175
+ return function getThumbnailSrc(options) {
2176
+ if (!imageId) {
2177
+ return null;
2178
+ }
2179
+ if (!options?.getImageSrc) {
2180
+ return null;
2181
+ }
2182
+ // Note: options.signal (Cornerstone-backed loadImageToCanvas via getImageSrc) does
2183
+ // not currently expose an AbortSignal hook, so abort is not propagated to the
2184
+ // underlying image load. We short-circuit only if already aborted at call time.
2185
+ if (options?.signal?.aborted) {
2186
+ return null;
2187
+ }
2188
+ return options.getImageSrc(imageId);
2189
+ };
2190
+ }
2191
+
2192
+ // thumbnailDirect is for plain <img src> URLs without auth headers; never use fetch here.
2193
+ // No network call happens at this layer (the <img> element loads the URL later), so
2194
+ // options.signal is not applicable here.
2195
+ if (thumbnailRendering === 'thumbnailDirect') {
2196
+ return function getThumbnailSrc() {
2197
+ return retrieve.directURL({
2198
+ instance: thumbnailContext,
2199
+ defaultPath: '/thumbnail',
2200
+ defaultType: 'image/jpeg',
2201
+ singlepart: true,
2202
+ tag: 'Absent'
2203
+ });
2204
+ };
2205
+ }
2206
+ const thumbnailRequestStrategy = config.thumbnailRequestStrategy || 'bulkDataRetrieve';
2207
+ if (thumbnailRequestStrategy === 'fetch') {
2208
+ return async function getThumbnailSrc(options) {
2209
+ return fetchThumbnailWithQidoFallbackForSeries(thumbnailContext, thumbnailRendering, config.wadoRoot, getAuthorizationHeader, qidoDicomWebClient, options?.signal);
2210
+ };
2211
+ }
2212
+ if (thumbnailRendering === 'thumbnail') {
2213
+ return async function getThumbnailSrc(options) {
2214
+ // Note: this path goes through bulkDataURI -> dicomweb-client retrieveBulkData,
2215
+ // which is XHR-based and does NOT honor AbortSignal. The underlying request will
2216
+ // run to completion server-side even if signal aborts; we only short-circuit
2217
+ // before kicking it off if already aborted.
2218
+ if (options?.signal?.aborted) {
2219
+ return null;
2220
+ }
2221
+ const endpoint = buildThumbnailEndpointPath(thumbnailContext, thumbnailRendering, new URLSearchParams({
2222
+ accept: 'image/jpeg'
2223
+ }));
2224
+ const bulkDataURI = `${config.wadoRoot}${endpoint}`;
2225
+ return URL.createObjectURL(new Blob([await retrieve.bulkDataURI({
2226
+ BulkDataURI: bulkDataURI.replace('wadors:', ''),
2227
+ defaultType: 'image/jpeg',
2228
+ mediaTypes: ['image/jpeg'],
2229
+ thumbnail: true
2230
+ })], {
2231
+ type: 'image/jpeg'
2232
+ }));
2233
+ };
2234
+ }
2235
+ if (thumbnailRendering === 'rendered') {
2236
+ return async function getThumbnailSrc(options) {
2237
+ // Note: this path goes through bulkDataURI -> dicomweb-client retrieveBulkData,
2238
+ // which is XHR-based and does NOT honor AbortSignal. The underlying request will
2239
+ // run to completion server-side even if signal aborts; we only short-circuit
2240
+ // before kicking it off if already aborted.
2241
+ if (options?.signal?.aborted) {
2242
+ return null;
2243
+ }
2244
+ const endpoint = buildThumbnailEndpointPath(thumbnailContext, thumbnailRendering, new URLSearchParams({
2245
+ accept: 'image/jpeg'
2246
+ }));
2247
+ const bulkDataURI = `${config.wadoRoot}${endpoint}`;
2248
+ return URL.createObjectURL(new Blob([await retrieve.bulkDataURI({
2249
+ BulkDataURI: bulkDataURI.replace('wadors:', ''),
2250
+ defaultType: 'image/jpeg',
2251
+ mediaTypes: ['image/jpeg'],
2252
+ thumbnail: true
2253
+ })], {
2254
+ type: 'image/jpeg'
2255
+ }));
2256
+ };
2257
+ }
2258
+ return function getThumbnailSrc() {
2259
+ console.warn(`Unsupported thumbnailRendering "${thumbnailRendering}"; returning null thumbnail src.`);
2260
+ return null;
2261
+ };
2262
+ }
2263
+ function buildThumbnailEndpointPath(thumbnailContext, thumbnailRendering, queryParams) {
2264
+ const {
2265
+ StudyInstanceUID,
2266
+ SeriesInstanceUID,
2267
+ SOPInstanceUID
2268
+ } = thumbnailContext;
2269
+ const basePath = SeriesInstanceUID && SOPInstanceUID ? `/studies/${StudyInstanceUID}/series/${SeriesInstanceUID}/instances/${SOPInstanceUID}/${thumbnailRendering}` : SeriesInstanceUID ? `/studies/${StudyInstanceUID}/series/${SeriesInstanceUID}/${thumbnailRendering}` : `/studies/${StudyInstanceUID}/${thumbnailRendering}`;
2270
+ if (!queryParams) {
2271
+ return basePath;
2272
+ }
2273
+ const queryString = queryParams.toString();
2274
+ return queryString ? `${basePath}?${queryString}` : basePath;
2275
+ }
2276
+ function getThumbnailFetchRequest(thumbnailContext, thumbnailRendering, wadoRoot, getAuthorizationHeader) {
2277
+ const endpointPath = buildThumbnailEndpointPath(thumbnailContext, thumbnailRendering,
2278
+ // Thumbnails for some data source (e.g. dcm4chee) are pixelated by default, so we need to set the viewport to 256,256 to get a better thumbnail.
2279
+ new URLSearchParams({
2280
+ viewport: '256,256'
2281
+ }));
2282
+ const headers = {
2283
+ ...getAuthorizationHeader(),
2284
+ Accept: 'image/jpeg'
2285
+ };
2286
+ return {
2287
+ url: `${wadoRoot}${endpointPath}`,
2288
+ endpointPath,
2289
+ headers
2290
+ };
2291
+ }
2292
+ async function fetchThumbnailObjectURL(thumbnailContext, thumbnailRendering, wadoRoot, getAuthorizationHeader, signal) {
2293
+ const fetchRequest = getThumbnailFetchRequest(thumbnailContext, thumbnailRendering, wadoRoot, getAuthorizationHeader);
2294
+ try {
2295
+ const response = await fetch(fetchRequest.url, {
2296
+ method: 'GET',
2297
+ headers: fetchRequest.headers,
2298
+ signal
2299
+ });
2300
+ if (!response.ok) {
2301
+ console.warn(`thumbnail fetch failed with status ${response.status} for ${fetchRequest.endpointPath}`);
2302
+ return null;
2303
+ }
2304
+ const blob = await response.blob();
2305
+ return URL.createObjectURL(blob);
2306
+ } catch (error) {
2307
+ if (error?.name === 'AbortError') {
2308
+ return null;
2309
+ }
2310
+ console.warn('thumbnail fetch failed', error);
2311
+ return null;
2312
+ }
2313
+ }
2314
+
2315
+ /**
2316
+ * When thumbnailRequestStrategy is fetch: try WADO GET for the given context; if it fails and the
2317
+ * context is series-level (no SOPInstanceUID), QIDO one instance and retry fetch once.
2318
+ */
2319
+ async function fetchThumbnailWithQidoFallbackForSeries(thumbnailContext, thumbnailRendering, wadoRoot, getAuthorizationHeader, qidoClient, signal) {
2320
+ const sopInstanceUidTag = '00080018';
2321
+ const initialThumbnailUrl = await fetchThumbnailObjectURL(thumbnailContext, thumbnailRendering, wadoRoot, getAuthorizationHeader, signal);
2322
+ if (initialThumbnailUrl) {
2323
+ return initialThumbnailUrl;
2324
+ }
2325
+ if (signal?.aborted) {
2326
+ return null;
2327
+ }
2328
+ if (thumbnailContext.SOPInstanceUID) {
2329
+ return null;
2330
+ }
2331
+ if (!thumbnailContext.StudyInstanceUID || !thumbnailContext.SeriesInstanceUID) {
2332
+ return null;
2333
+ }
2334
+ try {
2335
+ qidoClient.headers = getAuthorizationHeader();
2336
+ // Note: qidoClient.searchForInstances is XHR-based (dicomweb-client) and does not honor
2337
+ // AbortSignal. If signal aborts mid-request the network call still completes; we just
2338
+ // short-circuit before issuing a follow-up fetch below.
2339
+ const instances = await qidoClient.searchForInstances({
2340
+ studyInstanceUID: thumbnailContext.StudyInstanceUID,
2341
+ seriesInstanceUID: thumbnailContext.SeriesInstanceUID,
2342
+ queryParams: {
2343
+ limit: 1,
2344
+ includefield: sopInstanceUidTag
2345
+ }
2346
+ });
2347
+ if (signal?.aborted) {
2348
+ return null;
2349
+ }
2350
+ const firstInstance = instances?.[0];
2351
+ const sopAttr = firstInstance?.[sopInstanceUidTag];
2352
+ const sopValues = sopAttr?.Value;
2353
+ const SOPInstanceUID = Array.isArray(sopValues) && sopValues.length ? String(sopValues[0]) : undefined;
2354
+ if (!SOPInstanceUID) {
2355
+ return null;
2356
+ }
2357
+ return fetchThumbnailObjectURL({
2358
+ ...thumbnailContext,
2359
+ SOPInstanceUID
2360
+ }, thumbnailRendering, wadoRoot, getAuthorizationHeader, signal);
2361
+ } catch (error) {
2362
+ console.warn('thumbnail fetch QIDO fallback failed', error);
2363
+ return null;
2364
+ }
2365
+ }
2138
2366
  ;// ../../../extensions/default/src/DicomWebDataSource/index.ts
2139
2367
 
2140
2368
 
@@ -2146,6 +2374,7 @@ function fixBulkDataURI(value, instance, dicomWebConfig) {
2146
2374
 
2147
2375
 
2148
2376
 
2377
+
2149
2378
  const {
2150
2379
  DicomMetaDictionary,
2151
2380
  DicomDict
@@ -2302,65 +2531,15 @@ function createDicomWebApi(dicomWebConfig, servicesManager) {
2302
2531
  * or is already retrieved, or a promise to a URL for such use if a BulkDataURI
2303
2532
  */
2304
2533
 
2305
- getGetThumbnailSrc: function (instance, imageId) {
2306
- if (dicomWebConfig.thumbnailRendering === 'wadors') {
2307
- return function getThumbnailSrc(options) {
2308
- if (!imageId) {
2309
- return null;
2310
- }
2311
- if (!options?.getImageSrc) {
2312
- return null;
2313
- }
2314
- return options.getImageSrc(imageId);
2315
- };
2316
- }
2317
- if (dicomWebConfig.thumbnailRendering === 'thumbnailDirect') {
2318
- return function getThumbnailSrc() {
2319
- return this.directURL({
2320
- instance: instance,
2321
- defaultPath: '/thumbnail',
2322
- defaultType: 'image/jpeg',
2323
- singlepart: true,
2324
- tag: 'Absent'
2325
- });
2326
- }.bind(this);
2327
- }
2328
- if (dicomWebConfig.thumbnailRendering === 'thumbnail') {
2329
- return async function getThumbnailSrc() {
2330
- const {
2331
- StudyInstanceUID,
2332
- SeriesInstanceUID,
2333
- SOPInstanceUID
2334
- } = instance;
2335
- const bulkDataURI = `${dicomWebConfig.wadoRoot}/studies/${StudyInstanceUID}/series/${SeriesInstanceUID}/instances/${SOPInstanceUID}/thumbnail?accept=image/jpeg`;
2336
- return URL.createObjectURL(new Blob([await this.bulkDataURI({
2337
- BulkDataURI: bulkDataURI.replace('wadors:', ''),
2338
- defaultType: 'image/jpeg',
2339
- mediaTypes: ['image/jpeg'],
2340
- thumbnail: true
2341
- })], {
2342
- type: 'image/jpeg'
2343
- }));
2344
- }.bind(this);
2345
- }
2346
- if (dicomWebConfig.thumbnailRendering === 'rendered') {
2347
- return async function getThumbnailSrc() {
2348
- const {
2349
- StudyInstanceUID,
2350
- SeriesInstanceUID,
2351
- SOPInstanceUID
2352
- } = instance;
2353
- const bulkDataURI = `${dicomWebConfig.wadoRoot}/studies/${StudyInstanceUID}/series/${SeriesInstanceUID}/instances/${SOPInstanceUID}/rendered?accept=image/jpeg`;
2354
- return URL.createObjectURL(new Blob([await this.bulkDataURI({
2355
- BulkDataURI: bulkDataURI.replace('wadors:', ''),
2356
- defaultType: 'image/jpeg',
2357
- mediaTypes: ['image/jpeg'],
2358
- thumbnail: true
2359
- })], {
2360
- type: 'image/jpeg'
2361
- }));
2362
- }.bind(this);
2363
- }
2534
+ getGetThumbnailSrc: function (thumbnailContext, imageId) {
2535
+ return getGetThumbnailSrc({
2536
+ thumbnailContext,
2537
+ imageId,
2538
+ config: dicomWebConfig,
2539
+ getAuthorizationHeader,
2540
+ qidoDicomWebClient,
2541
+ retrieve: this
2542
+ });
2364
2543
  },
2365
2544
  directURL: params => {
2366
2545
  return utils_getDirectURL({
@@ -3436,6 +3615,7 @@ function createDicomWebProxyApi(dicomWebProxyConfig, servicesManager) {
3436
3615
  }
3437
3616
  },
3438
3617
  retrieve: {
3618
+ getGetThumbnailSrc: (...args) => dicomWebDelegate.retrieve.getGetThumbnailSrc(...args),
3439
3619
  directURL: (...args) => dicomWebDelegate.retrieve.directURL(...args),
3440
3620
  series: {
3441
3621
  metadata: async (...args) => dicomWebDelegate.retrieve.series.metadata(...args)
@@ -3684,6 +3864,12 @@ function createMergeDataSourceApi(mergeConfig, servicesManager, extensionManager
3684
3864
  }
3685
3865
  },
3686
3866
  retrieve: {
3867
+ getGetThumbnailSrc: (...args) => callForDefaultDataSource({
3868
+ path: 'retrieve.getGetThumbnailSrc',
3869
+ args,
3870
+ defaultDataSourceName,
3871
+ extensionManager
3872
+ }),
3687
3873
  bulkDataURI: (...args) => callForAllDataSourcesAsync({
3688
3874
  mergeMap,
3689
3875
  path: 'retrieve.bulkDataURI',
@@ -3790,8 +3976,8 @@ var react = __webpack_require__(86326);
3790
3976
  // EXTERNAL MODULE: ../../../node_modules/prop-types/index.js
3791
3977
  var prop_types = __webpack_require__(97598);
3792
3978
  var prop_types_default = /*#__PURE__*/__webpack_require__.n(prop_types);
3793
- // EXTERNAL MODULE: ../../ui-next/src/index.ts + 3085 modules
3794
- var ui_next_src = __webpack_require__(564);
3979
+ // EXTERNAL MODULE: ../../ui-next/src/index.ts + 3667 modules
3980
+ var ui_next_src = __webpack_require__(19289);
3795
3981
  // EXTERNAL MODULE: ./state/index.js + 1 modules
3796
3982
  var state = __webpack_require__(45981);
3797
3983
  // EXTERNAL MODULE: ../../../node_modules/react-router-dom/dist/index.js
@@ -3926,8 +4112,8 @@ function HeaderPatientInfo({
3926
4112
  ;// ../../../extensions/default/src/ViewerLayout/HeaderPatientInfo/index.js
3927
4113
 
3928
4114
  /* harmony default export */ const ViewerLayout_HeaderPatientInfo = (HeaderPatientInfo_HeaderPatientInfo);
3929
- // EXTERNAL MODULE: ./index.js + 44 modules
3930
- var index = __webpack_require__(7984);
4115
+ // EXTERNAL MODULE: ./index.js + 52 modules
4116
+ var index = __webpack_require__(19072);
3931
4117
  ;// ../../../extensions/default/src/ViewerLayout/ViewerHeader.tsx
3932
4118
 
3933
4119
 
@@ -4868,8 +5054,8 @@ function getPanelModule({
4868
5054
  }];
4869
5055
  }
4870
5056
  /* harmony default export */ const src_getPanelModule = (getPanelModule);
4871
- // EXTERNAL MODULE: ../../i18n/src/index.js + 286 modules
4872
- var i18n_src = __webpack_require__(89010);
5057
+ // EXTERNAL MODULE: ../../i18n/src/index.js + 288 modules
5058
+ var i18n_src = __webpack_require__(81499);
4873
5059
  ;// ../../../extensions/default/package.json
4874
5060
  const package_namespaceObject = /*#__PURE__*/JSON.parse('{"UU":"@ohif/extension-default"}');
4875
5061
  ;// ../../../extensions/default/src/id.js
@@ -10276,6 +10462,7 @@ function DataSourceConfigurationComponent({
10276
10462
  } = servicesManager.services;
10277
10463
  const [configurationAPI, setConfigurationAPI] = (0,react.useState)();
10278
10464
  const [configuredItems, setConfiguredItems] = (0,react.useState)();
10465
+ const [itemLabels, setItemLabels] = (0,react.useState)([]);
10279
10466
  (0,react.useEffect)(() => {
10280
10467
  let shouldUpdate = true;
10281
10468
  const dataSourceChangedCallback = async () => {
@@ -10289,6 +10476,7 @@ function DataSourceConfigurationComponent({
10289
10476
  }
10290
10477
  const configAPI = configurationAPIFactory(activeDataSourceDef.sourceName);
10291
10478
  setConfigurationAPI(configAPI);
10479
+ setItemLabels(configAPI.getItemLabels());
10292
10480
 
10293
10481
  // New configuration API means that the existing configured items must be cleared.
10294
10482
  setConfiguredItems(null);
@@ -10326,22 +10514,35 @@ function DataSourceConfigurationComponent({
10326
10514
  showConfigurationModal();
10327
10515
  }
10328
10516
  }, [configurationAPI, configuredItems, showConfigurationModal]);
10329
- return configuredItems ? /*#__PURE__*/react.createElement("div", {
10330
- className: "text-muted-foreground flex items-center overflow-hidden"
10331
- }, /*#__PURE__*/react.createElement(ui_next_src/* Icons */.FI1.Settings, {
10332
- className: "mr-2.5 h-3.5 w-3.5 shrink-0 cursor-pointer",
10517
+ return configuredItems ? /*#__PURE__*/react.createElement(ui_next_src/* HoverCard */.jcX, null, /*#__PURE__*/react.createElement(ui_next_src/* HoverCardTrigger */.d05, {
10518
+ asChild: true
10519
+ }, /*#__PURE__*/react.createElement(ui_next_src/* Button */.$nd, {
10520
+ variant: "ghost",
10521
+ size: "sm",
10522
+ className: "gap-1 text-sm",
10333
10523
  onClick: showConfigurationModal
10334
- }), configuredItems.map((item, itemIndex) => {
10335
- return /*#__PURE__*/react.createElement("div", {
10336
- key: itemIndex,
10337
- className: "flex overflow-hidden"
10338
- }, /*#__PURE__*/react.createElement("div", {
10339
- key: itemIndex,
10340
- className: "overflow-hidden text-ellipsis whitespace-nowrap"
10341
- }, item.name), itemIndex !== configuredItems.length - 1 && /*#__PURE__*/react.createElement("div", {
10342
- className: "px-2.5"
10343
- }, "|"));
10344
- })) : /*#__PURE__*/react.createElement(react.Fragment, null);
10524
+ }, /*#__PURE__*/react.createElement(ui_next_src/* Icons */.FI1.CloudSettings, {
10525
+ className: "h-5 w-5"
10526
+ }), "Source")), /*#__PURE__*/react.createElement(ui_next_src/* HoverCardContent */.Etv, {
10527
+ align: "center",
10528
+ className: "w-72 p-0"
10529
+ }, /*#__PURE__*/react.createElement(ui_next_src/* Card */.ZpM, {
10530
+ className: "border-0 shadow-none"
10531
+ }, /*#__PURE__*/react.createElement(ui_next_src/* CardHeader */.aRn, {
10532
+ className: "p-3 pb-1"
10533
+ }, /*#__PURE__*/react.createElement(ui_next_src/* CardDescription */.BTJ, {
10534
+ className: "text-sm"
10535
+ }, /*#__PURE__*/react.createElement("span", {
10536
+ className: "text-foreground font-semibold"
10537
+ }, t('Data Source'), ":"), ' ', t('Configure the server connection and storage settings'))), /*#__PURE__*/react.createElement(ui_next_src/* CardContent */.Wux, {
10538
+ className: "grid grid-cols-[auto_1fr] gap-x-3 gap-y-1 p-3 pt-0 text-sm"
10539
+ }, /*#__PURE__*/react.createElement("div", {
10540
+ className: "bg-input col-span-2 my-2 h-px"
10541
+ }), itemLabels.map((label, index) => /*#__PURE__*/react.createElement(react.Fragment, {
10542
+ key: label
10543
+ }, /*#__PURE__*/react.createElement("span", {
10544
+ className: "text-muted-foreground"
10545
+ }, t(label)), /*#__PURE__*/react.createElement("span", null, configuredItems[index]?.name ?? '—'))))))) : null;
10345
10546
  }
10346
10547
  /* harmony default export */ const Components_DataSourceConfigurationComponent = (DataSourceConfigurationComponent);
10347
10548
  ;// ../../../extensions/default/src/DataSourceConfigurationAPI/GoogleCloudDataSourceConfigurationAPI.ts
@@ -10614,8 +10815,8 @@ function AboutModalDefault() {
10614
10815
  name
10615
10816
  } = (0,browser_detect_es5/* default */.A)();
10616
10817
  const browser = `${name[0].toUpperCase()}${name.substr(1)} ${version}`;
10617
- const versionNumber = "3.13.0-beta.84";
10618
- const commitHash = "bdcafc12de5e4f73a1a96cab9c0830d49315c044";
10818
+ const versionNumber = "3.13.0-beta.85";
10819
+ const commitHash = "daae4c144e7cb80bbee7c05d9fceef8b332ed2a0";
10619
10820
  const [main, beta] = versionNumber.split('-');
10620
10821
  return /*#__PURE__*/react.createElement(ui_next_src/* AboutModal */.VTU, {
10621
10822
  className: "w-[400px]"
@@ -11219,6 +11420,94 @@ function waitForElement(selector, maxAttempts = 20, interval = 25) {
11219
11420
  defaultSortFunctionName: ''
11220
11421
  }
11221
11422
  });
11423
+ ;// ../../../extensions/default/src/customizations/workListCustomization.ts
11424
+
11425
+
11426
+ /**
11427
+ * Default customization values for the WorkList study-list route.
11428
+ *
11429
+ * - `workList.variant`: `'default' | 'legacy'` (default: `'default'`)
11430
+ * Selects which study-list route is mounted at `/`.
11431
+ * - `'default'`: the new ui-next WorkList.
11432
+ * - `'legacy'`: the pre-3.13 WorkList (now `LegacyWorkList`). Useful as an
11433
+ * opt-out while integrators migrate to the new study list.
11434
+ *
11435
+ * - `workList.previewSeriesView`: `'all' | 'thumbnails' | 'list'` (default: `'all'`)
11436
+ * Controls which series views are available in the preview panel.
11437
+ * - `'all'`: thumbnails/list toggle is visible; defaults to thumbnails.
11438
+ * - `'thumbnails'`: toggle hidden; locked to thumbnails view.
11439
+ * - `'list'`: toggle hidden; locked to list view.
11440
+ * Note: the preview is forced to `'list'` when the active data source either:
11441
+ * - declares `thumbnailRendering` as `'wadors'` or `'thumbnailDirect'`, or
11442
+ * - declares `thumbnailRequestStrategy` as `'bulkDataRetrieve'` (default value).
11443
+ * Currently only applies when `workList.variant` is `'default'`.
11444
+ *
11445
+ * - `workList.columns`: `ColumnDef[]` (default: `StudyList.defaultColumns`)
11446
+ * The column set for the WorkList table, as a value (not a function). Because
11447
+ * it is a plain array, override it with immutability-helper commands:
11448
+ * - reorder / insert / remove: `$splice`
11449
+ * - relabel / resize / reprioritize (all plain data in `meta`): `$set` / `$merge`
11450
+ * - replace a renderer: `$set` a new `cell` / `header` function
11451
+ * - `$apply: (cols) => ColumnDef[]`: receive the current columns and return the
11452
+ * new array. Use it for anything the other commands don't express cleanly —
11453
+ * moves, conditional inserts, or any edit keyed off a column's `id` rather
11454
+ * than its position (e.g. `cols.find(c => c.id === 'modalities')`).
11455
+ * Use `StudyList.textColumn(id, label, meta?)` to build a simple display-only
11456
+ * column without writing the accessor/header/cell wiring.
11457
+ *
11458
+ * Gotchas / limitations:
11459
+ * - A `ColumnDef`'s `accessorFn` / `cell` / `header` / `filterFn` / `sortingFn`
11460
+ * are functions: `$set`/`$push` accept them, but they are not serializable,
11461
+ * so columns that render anything beyond plain text still need code.
11462
+ * - The trailing `actions` column should stay last for correct layout (its
11463
+ * hover menu is right-aligned to sit at the row end) — this is cosmetic,
11464
+ * not a hard requirement. Insert new columns *before* it with `$splice`
11465
+ * (a `$push` lands after it, leaving the actions menu mid-row).
11466
+ * - Index-based commands (e.g. `{ 2: { meta: { label: { $set: '…' } } } }`)
11467
+ * are position-fragile; prefer `$apply` for id-based edits.
11468
+ * If the merged value is not an array, WorkList falls back to the defaults.
11469
+ * Currently only applies when `workList.variant` is `'default'`.
11470
+ *
11471
+ * - `workList.renderPreviewContent`: `(React, props) => ReactNode` (default: undefined)
11472
+ * Render function for the preview panel content. Receives the host React and
11473
+ * `{ study, series, seriesView, onThumbnailImageError }`:
11474
+ * - `study`: the selected `StudyRow` (`null` when nothing is selected).
11475
+ * - `series`: the study's series; each item has the raw data-source fields
11476
+ * (`seriesInstanceUid`, `modality`, `description`, `seriesDate`,
11477
+ * `seriesNumber`, `numSeriesInstances`, etc.) plus `thumbnailStatus` added
11478
+ * by the shell, which is one of `{ status: 'loading' }`,
11479
+ * `{ status: 'ready', src }`, `{ status: 'notAvailable' }`, or
11480
+ * `{ status: 'notApplicable' }`. The `src` in the `'ready'` form is the
11481
+ * URL to render in an `<img>`.
11482
+ * - `seriesView`: `'all' | 'thumbnails' | 'list'`, resolved from
11483
+ * `workList.previewSeriesView` with `'list'` forced for data sources that
11484
+ * can't produce thumbnails. Honor it if your layout has both views.
11485
+ * - `onThumbnailImageError(seriesUID)`: call when an `<img>` you render fails
11486
+ * to load. The shell marks that series as `notAvailable` and revokes its
11487
+ * blob URL if needed.
11488
+ * Use this to change the preview layout while keeping the fetch/abort/thumbnail
11489
+ * logic intact. When unset (or not a function), the built-in
11490
+ * `<StudyList.PreviewContainer>` layout is used.
11491
+ * Currently only applies when `workList.variant` is `'default'`.
11492
+ *
11493
+ * - `workList.settingsMenuItems`: `(defaults) => SettingsMenuItem[]` (default: identity)
11494
+ * Builds the items in the WorkList settings popover. Receives the default
11495
+ * items (`about`, `userPreferences`, and `logout` when OIDC is configured)
11496
+ * and must return a
11497
+ * `SettingsMenuItem[]`. Each item is `{ id, label, onClick }`. Use this to
11498
+ * reorder, remove, or insert items without rebuilding the popover shell. If
11499
+ * the returned value is not an array, WorkList falls back to the defaults.
11500
+ * Currently only applies when `workList.variant` is `'default'`.
11501
+ */
11502
+ function getWorkListCustomization() {
11503
+ return {
11504
+ 'workList.variant': 'default',
11505
+ 'workList.previewSeriesView': 'all',
11506
+ 'workList.columns': ui_next_src/* StudyList */.Slc.defaultColumns,
11507
+ 'workList.renderPreviewContent': undefined,
11508
+ 'workList.settingsMenuItems': defaults => defaults
11509
+ };
11510
+ }
11222
11511
  ;// ../../../extensions/default/src/getCustomizationModule.tsx
11223
11512
 
11224
11513
 
@@ -11243,6 +11532,7 @@ function waitForElement(selector, maxAttempts = 20, interval = 25) {
11243
11532
 
11244
11533
 
11245
11534
 
11535
+
11246
11536
 
11247
11537
 
11248
11538
  /**
@@ -11294,7 +11584,8 @@ function getCustomizationModule({
11294
11584
  ...reportDialogCustomization,
11295
11585
  ...hotkeyBindingsCustomization,
11296
11586
  ...onboardingCustomization,
11297
- ...instanceSortingCriteriaCustomization
11587
+ ...instanceSortingCriteriaCustomization,
11588
+ ...getWorkListCustomization()
11298
11589
  }
11299
11590
  }];
11300
11591
  }
@@ -18,8 +18,8 @@ var react = __webpack_require__(86326);
18
18
  var esm = __webpack_require__(15327);
19
19
  // EXTERNAL MODULE: ../../core/src/index.ts + 69 modules
20
20
  var src = __webpack_require__(42356);
21
- // EXTERNAL MODULE: ../../ui-next/src/index.ts + 3085 modules
22
- var ui_next_src = __webpack_require__(564);
21
+ // EXTERNAL MODULE: ../../ui-next/src/index.ts + 3667 modules
22
+ var ui_next_src = __webpack_require__(19289);
23
23
  // EXTERNAL MODULE: ../../../extensions/cornerstone/src/state.ts
24
24
  var state = __webpack_require__(71353);
25
25
  ;// ../../../extensions/cornerstone/src/Viewport/OHIFCornerstoneViewport.css