diff --git a/extensions/cornerstone/src/commandsModule.ts b/extensions/cornerstone/src/commandsModule.ts
index b87fbaf60..cf1b219a3 100644
--- a/extensions/cornerstone/src/commandsModule.ts
+++ b/extensions/cornerstone/src/commandsModule.ts
@@ -28,6 +28,7 @@ function commandsModule({
toolGroupService,
cineService,
toolbarService,
+ stateSyncService,
uiDialogService,
cornerstoneViewportService,
uiNotificationService,
@@ -616,6 +617,35 @@ function commandsModule({
);
toolGroup.setToolEnabled(ReferenceLinesTool.toolName);
},
+ storePresentation: ({ viewportIndex }) => {
+ const presentation = cornerstoneViewportService.getPresentation(
+ viewportIndex
+ );
+ if (!presentation || !presentation.presentationIds) {
+ return;
+ }
+ const {
+ lutPresentationStore,
+ positionPresentationStore,
+ } = stateSyncService.getState();
+ const { presentationIds } = presentation;
+ const { lutPresentationId, positionPresentationId } =
+ presentationIds || {};
+ const storeState = {};
+ if (lutPresentationId) {
+ storeState.lutPresentationStore = {
+ ...lutPresentationStore,
+ [lutPresentationId]: presentation,
+ };
+ }
+ if (positionPresentationId) {
+ storeState.positionPresentationStore = {
+ ...positionPresentationStore,
+ [positionPresentationId]: presentation,
+ };
+ }
+ stateSyncService.store(storeState);
+ },
};
const definitions = {
@@ -740,6 +770,11 @@ function commandsModule({
toggleReferenceLines: {
commandFn: actions.toggleReferenceLines,
},
+ storePresentation: {
+ commandFn: actions.storePresentation,
+ storeContexts: [],
+ options: {},
+ },
};
return {
diff --git a/platform/core/src/services/ViewportGridService/getPresentationIds.ts b/platform/core/src/services/ViewportGridService/getPresentationIds.ts
index 429917511..decbb0116 100644
--- a/platform/core/src/services/ViewportGridService/getPresentationIds.ts
+++ b/platform/core/src/services/ViewportGridService/getPresentationIds.ts
@@ -10,8 +10,14 @@ const DEFAULT = 'default';
// dragged and dropped the view in twice. For example, it allows displaying
// bone, brain and soft tissue views of a single display set, and to still
// remember the specific changes to each viewport.
-const addUniqueIndex = (arr, key, viewports) => {
+const addUniqueIndex = (arr, key, viewports, isUpdatingSameViewport) => {
arr.push(0);
+
+ // If we are updating the viewport, we should not increment the index
+ if (isUpdatingSameViewport) {
+ return;
+ }
+
// The 128 is just a value that is larger than how many viewports we
// display at once, used as an upper bound on how many unique presentation
// ID's might exist for a single display set at once.
@@ -109,8 +115,30 @@ const getPresentationIds = (viewport, viewports): PresentationIds => {
lutPresentationArr.push(uid);
}
- addUniqueIndex(positionPresentationArr, 'positionPresentationId', viewports);
- addUniqueIndex(lutPresentationArr, 'lutPresentationId', viewports);
+ // only add unique index if the viewport is getting inserted and not updated
+ const isUpdatingSameViewport = viewports.some(v => {
+ return (
+ v.displaySetInstanceUIDs.toString() ===
+ viewport.displaySetInstanceUIDs.toString() &&
+ v.viewportIndex === viewport.viewportIndex
+ );
+ });
+
+ // if it is updating the viewport we should not increment the index since
+ // it might be a layer on the fusion or a SEG layer that is added on
+ // top of the original display set
+ addUniqueIndex(
+ positionPresentationArr,
+ 'positionPresentationId',
+ viewports,
+ isUpdatingSameViewport
+ );
+ addUniqueIndex(
+ lutPresentationArr,
+ 'lutPresentationId',
+ viewports,
+ isUpdatingSameViewport
+ );
const lutPresentationId = lutPresentationArr.join(JOIN_STR);
const positionPresentationId = positionPresentationArr.join(JOIN_STR);
diff --git a/platform/docs/docs/configuration/configurationFiles.md b/platform/docs/docs/configuration/configurationFiles.md
index 85e6344df..40a2d84d3 100644
--- a/platform/docs/docs/configuration/configurationFiles.md
+++ b/platform/docs/docs/configuration/configurationFiles.md
@@ -10,10 +10,11 @@ After following the steps outlined in
OHIF Viewer has data for several studies and their images. You didn't add this
data, so where is it coming from?
-By default, the viewer is configured to connect to a remote server hosted by the
-nice folks over at [dcmjs.org][dcmjs-org]. While convenient for getting started,
-the time may come when you want to develop using your own data either locally or
-remotely.
+By default, the viewer is configured to connect to a Amazon S3 bucket that is hosting
+a Static WADO server (see [Static WADO DICOMWeb](https://github.com/RadicalImaging/static-dicomweb)).
+By default we use `default.js` for the configuration file. You can change this by setting the `APP_CONFIG` environment variable
+and select other options such as `config/local_orthanc.js` or `config/google.js`.
+
## Configuration Files
@@ -172,6 +173,7 @@ if auth headers are used, a preflight request is required.
}
```
- `showLoadingIndicator`: (default to true), if set to false, the loading indicator will not be shown when navigating between studies.
+- `supportsWildcard`: (default to false), if set to true, the datasource will support wildcard matching for patient name and patient id.
- `dangerouslyUseDynamicConfig`: Dynamic config allows user to pass `configUrl` query string. This allows to load config without recompiling application. If the `configUrl` query string is passed, the worklist and modes will load from the referenced json rather than the default .env config. If there is no `configUrl` path provided, the default behaviour is used and there should not be any deviation from current user experience.
Points to consider while using `dangerouslyUseDynamicConfig`:
- User have to enable this feature by setting `dangerouslyUseDynamicConfig.enabled:true`. By default it is `false`.
diff --git a/platform/docs/docs/migration-guide.md b/platform/docs/docs/migration-guide.md
index ae44d9790..af87a0296 100644
--- a/platform/docs/docs/migration-guide.md
+++ b/platform/docs/docs/migration-guide.md
@@ -89,6 +89,16 @@ Since the platform/viewer (@ohif/viewer) is already at v4.12.51, we opted to ren
## Configuration
+:::tip
+There are various configurations available to customize the viewer. Each configuration is represented by a custom-tailored object that should be used with the viewer to work effectively with a specific server. Here are some examples of configuration files found in the platform/app/public/config directory. Some server-specific configurations that you should be aware are: `supportsWildcard`, `bulkDataURI`, `omitQuotationForMultipartRequest`, `staticWado` (Read more about them [here](./configuration/configurationFiles.md)).
+
+- default.js: This is our default configuration designed for our main server, which uses a Static WADO datasource hosted on Amazon S3.
+- local_orthanc.js: Use this configuration when working with our local Orthanc server.
+- local_dcm4chee.js: This configuration is intended for our local dcm4chee server.
+- netlify.js: This configuration is the same as default.js and is used for deployment on Netlify.
+- google.js: Use this configuration to run the viewer against the Google Health API.
+:::
+
OHIF v3 has a new configuration structure. The main difference is that the `servers` is renamed to `dataSources` and the configuration is now asynchronous. Datasources are more abstract and
far more capable than servers. Read more about dataSources [here](./platform/extensions/modules/data-source.md).
@@ -98,6 +108,7 @@ far more capable than servers. Read more about dataSources [here](./platform/ext
- The maxConcurrentMetadataRequests property has been removed in favor of `maxNumRequests`
- The hotkeys array has been updated with different command names and options, and some keys have been removed.
- New properties have been added, including `maxNumberOfWebWorkers`, `omitQuotationForMultipartRequest`, `showWarningMessageForCrossOrigin`, `showCPUFallbackMessage`, `showLoadingIndicator`, `strictZSpacingForVolumeViewport`.
+- you should see if `supportsWildcard` is supported in your server, some servers don't support it and you need to make it false.
## Modes
diff --git a/platform/ui/src/components/ContextMenu/ContextMenu.tsx b/platform/ui/src/components/ContextMenu/ContextMenu.tsx
index ff7432009..0c894956c 100644
--- a/platform/ui/src/components/ContextMenu/ContextMenu.tsx
+++ b/platform/ui/src/components/ContextMenu/ContextMenu.tsx
@@ -5,7 +5,6 @@ import Icon from '../Icon';
const ContextMenu = ({ items, ...props }) => {
if (!items) {
- console.warn('No items for context menu');
return null;
}
return (