From adedc8c382e18a2e86a569e3d023cc55a157363f Mon Sep 17 00:00:00 2001
From: Joe Boccanfuso <109477394+jbocce@users.noreply.github.com>
Date: Wed, 30 Aug 2023 09:27:48 -0400
Subject: [PATCH] feat(data source UI config): Popup the configuration dialogue
whenever a data source is not fully configured (#3620)
---
extensions/cornerstone-dicom-sr/package.json | 6 +--
extensions/cornerstone/package.json | 10 ++--
.../DataSourceConfigurationComponent.tsx | 40 +++++++++++-----
.../DataSourceConfigurationModalComponent.tsx | 13 ++++--
.../GoogleCloudDataSourceConfigurationAPI.ts | 11 ++++-
extensions/measurement-tracking/package.json | 4 +-
platform/app/package.json | 2 +-
platform/app/src/routes/DataSourceWrapper.tsx | 12 ++++-
platform/core/package.json | 2 +-
yarn.lock | 46 +++++++++----------
10 files changed, 93 insertions(+), 53 deletions(-)
diff --git a/extensions/cornerstone-dicom-sr/package.json b/extensions/cornerstone-dicom-sr/package.json
index ce1530172..6090a360f 100644
--- a/extensions/cornerstone-dicom-sr/package.json
+++ b/extensions/cornerstone-dicom-sr/package.json
@@ -44,9 +44,9 @@
},
"dependencies": {
"@babel/runtime": "^7.20.13",
- "@cornerstonejs/adapters": "^1.11.1",
- "@cornerstonejs/core": "^1.11.1",
- "@cornerstonejs/tools": "^1.11.1",
+ "@cornerstonejs/adapters": "^1.11.4",
+ "@cornerstonejs/core": "^1.11.4",
+ "@cornerstonejs/tools": "^1.11.4",
"classnames": "^2.3.2"
}
}
diff --git a/extensions/cornerstone/package.json b/extensions/cornerstone/package.json
index b3e1d8f0d..7d11734d2 100644
--- a/extensions/cornerstone/package.json
+++ b/extensions/cornerstone/package.json
@@ -36,7 +36,7 @@
"@cornerstonejs/codec-libjpeg-turbo-8bit": "^1.2.2",
"@cornerstonejs/codec-openjpeg": "^1.2.2",
"@cornerstonejs/codec-openjph": "^2.4.2",
- "@cornerstonejs/dicom-image-loader": "^1.11.1",
+ "@cornerstonejs/dicom-image-loader": "^1.11.4",
"@ohif/core": "3.7.0-beta.61",
"@ohif/ui": "3.7.0-beta.61",
"dcmjs": "^0.29.6",
@@ -52,10 +52,10 @@
},
"dependencies": {
"@babel/runtime": "^7.20.13",
- "@cornerstonejs/adapters": "^1.11.1",
- "@cornerstonejs/core": "^1.11.1",
- "@cornerstonejs/streaming-image-volume-loader": "^1.11.1",
- "@cornerstonejs/tools": "^1.11.1",
+ "@cornerstonejs/adapters": "^1.11.4",
+ "@cornerstonejs/core": "^1.11.4",
+ "@cornerstonejs/streaming-image-volume-loader": "^1.11.4",
+ "@cornerstonejs/tools": "^1.11.4",
"@kitware/vtk.js": "27.3.1",
"html2canvas": "^1.4.1",
"lodash.debounce": "4.0.8",
diff --git a/extensions/default/src/Components/DataSourceConfigurationComponent.tsx b/extensions/default/src/Components/DataSourceConfigurationComponent.tsx
index 768f55696..c9606c54e 100644
--- a/extensions/default/src/Components/DataSourceConfigurationComponent.tsx
+++ b/extensions/default/src/Components/DataSourceConfigurationComponent.tsx
@@ -1,4 +1,4 @@
-import React, { ReactElement, useEffect, useState } from 'react';
+import React, { ReactElement, useCallback, useEffect, useState } from 'react';
import { useTranslation } from 'react-i18next';
import { Icon, useModal } from '@ohif/ui';
import { ExtensionManager, ServicesManager, Types } from '@ohif/core';
@@ -48,6 +48,9 @@ function DataSourceConfigurationComponent({
const configAPI = configurationAPIFactory(activeDataSourceDef.sourceName);
setConfigurationAPI(configAPI);
+ // New configuration API means that the existing configured items must be cleared.
+ setConfiguredItems(null);
+
configAPI.getConfiguredItems().then(list => {
if (shouldUpdate) {
setConfiguredItems(list);
@@ -68,22 +71,35 @@ function DataSourceConfigurationComponent({
};
}, []);
+ const showConfigurationModal = useCallback(() => {
+ show({
+ content: DataSourceConfigurationModalComponent,
+ title: t('Configure Data Source'),
+ contentProps: {
+ configurationAPI,
+ configuredItems,
+ onHide: hide,
+ },
+ });
+ }, [configurationAPI, configuredItems]);
+
+ useEffect(() => {
+ if (!configurationAPI || !configuredItems) {
+ return;
+ }
+
+ if (configuredItems.length !== configurationAPI.getItemLabels().length) {
+ // Not the correct number of configured items, so show the modal to configure the data source.
+ showConfigurationModal();
+ }
+ }, [configurationAPI, configuredItems, showConfigurationModal]);
+
return configuredItems ? (
- show({
- content: DataSourceConfigurationModalComponent,
- title: t('Configure Data Source'),
- contentProps: {
- configurationAPI,
- configuredItems,
- onHide: hide,
- },
- })
- }
+ onClick={showConfigurationModal}
>
{configuredItems.map((item, itemIndex) => {
return (
diff --git a/extensions/default/src/Components/DataSourceConfigurationModalComponent.tsx b/extensions/default/src/Components/DataSourceConfigurationModalComponent.tsx
index 74145d3b0..b10267740 100644
--- a/extensions/default/src/Components/DataSourceConfigurationModalComponent.tsx
+++ b/extensions/default/src/Components/DataSourceConfigurationModalComponent.tsx
@@ -27,14 +27,19 @@ function DataSourceConfigurationModalComponent({
const [selectedItems, setSelectedItems] = useState(configuredItems);
- // Determines whether to show the full configuration for the data source.
- // This typically occurs when the configuration component is first displayed.
- const [showFullConfig, setShowFullConfig] = useState(true);
-
const [errorMessage, setErrorMessage] = useState();
const [itemLabels] = useState(configurationAPI.getItemLabels());
+ // Determines whether to show the full/existing configuration for the data source.
+ // A full or complete configuration is one where the data source (path) has the
+ // maximum/required number of path items. Anything less is considered not complete and
+ // the configuration starts from scratch (i.e. as if no items are configured at all).
+ // TODO: consider configuration starting from a partial (i.e. non-empty) configuration
+ const [showFullConfig, setShowFullConfig] = useState(
+ itemLabels.length === configuredItems.length
+ );
+
/**
* The index of the selected item that is considered current and for which
* its sub-items should be displayed in the items list component. When the
diff --git a/extensions/default/src/DataSourceConfigurationAPI/GoogleCloudDataSourceConfigurationAPI.ts b/extensions/default/src/DataSourceConfigurationAPI/GoogleCloudDataSourceConfigurationAPI.ts
index d95cbd8ea..919592379 100644
--- a/extensions/default/src/DataSourceConfigurationAPI/GoogleCloudDataSourceConfigurationAPI.ts
+++ b/extensions/default/src/DataSourceConfigurationAPI/GoogleCloudDataSourceConfigurationAPI.ts
@@ -145,10 +145,19 @@ class GoogleCloudDataSourceConfigurationAPI
const url = dataSourceDefinition.configuration.wadoUriRoot;
const projectsIndex = url.indexOf('projects');
+ // Split the configured URL into (essentially) pairs (i.e. item type followed by item)
+ // Explicitly: ['projects','aProject','locations','aLocation','datasets','aDataSet','dicomStores','aDicomStore']
+ // Note that a partial configuration will have a subset of the above.
const urlSplit = url.substring(projectsIndex).split('/');
const configuredItems = [];
- for (let itemType = 0; itemType < 4; itemType += 1) {
+
+ for (
+ let itemType = 0;
+ // the number of configured items is either the max (4) or the number extracted from the url split
+ itemType < 4 && (itemType + 1) * 2 < urlSplit.length;
+ itemType += 1
+ ) {
if (itemType === ItemType.projects) {
const projectId = urlSplit[1];
const projectUrl = `${initialUrl}/projects/${projectId}`;
diff --git a/extensions/measurement-tracking/package.json b/extensions/measurement-tracking/package.json
index 4672f381e..f06b179be 100644
--- a/extensions/measurement-tracking/package.json
+++ b/extensions/measurement-tracking/package.json
@@ -30,8 +30,8 @@
"start": "yarn run dev"
},
"peerDependencies": {
- "@cornerstonejs/core": "^1.11.1",
- "@cornerstonejs/tools": "^1.11.1",
+ "@cornerstonejs/core": "^1.11.4",
+ "@cornerstonejs/tools": "^1.11.4",
"@ohif/core": "3.7.0-beta.61",
"@ohif/extension-cornerstone-dicom-sr": "3.7.0-beta.61",
"@ohif/ui": "3.7.0-beta.61",
diff --git a/platform/app/package.json b/platform/app/package.json
index e4bd26f66..ac3397a07 100644
--- a/platform/app/package.json
+++ b/platform/app/package.json
@@ -50,7 +50,7 @@
"@cornerstonejs/codec-libjpeg-turbo-8bit": "^1.2.2",
"@cornerstonejs/codec-openjpeg": "^1.2.2",
"@cornerstonejs/codec-openjph": "^2.4.2",
- "@cornerstonejs/dicom-image-loader": "^1.11.1",
+ "@cornerstonejs/dicom-image-loader": "^1.11.4",
"@ohif/core": "3.7.0-beta.61",
"@ohif/extension-cornerstone": "3.7.0-beta.61",
"@ohif/extension-cornerstone-dicom-rt": "3.7.0-beta.61",
diff --git a/platform/app/src/routes/DataSourceWrapper.tsx b/platform/app/src/routes/DataSourceWrapper.tsx
index c137546d9..91ae58642 100644
--- a/platform/app/src/routes/DataSourceWrapper.tsx
+++ b/platform/app/src/routes/DataSourceWrapper.tsx
@@ -125,6 +125,7 @@ function DataSourceWrapper(props) {
useEffect(() => {
const dataSourceChangedCallback = () => {
+ setIsLoading(false);
setIsDataSourceInitialized(false);
setDataSourcePath('');
setDataSource(extensionManager.getActiveDataSource()[0]);
@@ -191,7 +192,16 @@ function DataSourceWrapper(props) {
(!isLoading && (newOffset !== previousOffset || isLocationUpdated));
if (isDataInvalid) {
- getData().catch(() => navigate('/notfoundserver', '_self'));
+ getData().catch(() => {
+ // If there is a data source configuration API, then the Worklist will popup the dialog to attempt to configure it
+ // and attempt to resolve this issue.
+ if (dataSource.getConfig().configurationAPI) {
+ return;
+ }
+
+ // No data source configuration API, so navigate to the not found server page.
+ navigate('/notfoundserver', '_self');
+ });
}
} catch (ex) {
console.warn(ex);
diff --git a/platform/core/package.json b/platform/core/package.json
index a866a113f..9c0f71b5f 100644
--- a/platform/core/package.json
+++ b/platform/core/package.json
@@ -35,7 +35,7 @@
"@cornerstonejs/codec-libjpeg-turbo-8bit": "^1.2.2",
"@cornerstonejs/codec-openjpeg": "^1.2.2",
"@cornerstonejs/codec-openjph": "^2.4.2",
- "@cornerstonejs/dicom-image-loader": "^1.11.1",
+ "@cornerstonejs/dicom-image-loader": "^1.11.4",
"@ohif/ui": "3.7.0-beta.61",
"cornerstone-math": "0.1.9",
"dicom-parser": "^1.8.21"
diff --git a/yarn.lock b/yarn.lock
index 583f87236..24e1a3e59 100644
--- a/yarn.lock
+++ b/yarn.lock
@@ -1376,10 +1376,10 @@
resolved "https://registry.yarnpkg.com/@colors/colors/-/colors-1.5.0.tgz#bb504579c1cae923e6576a4f5da43d25f97bdbd9"
integrity sha512-ooWCrlZP11i8GImSjTHYHLkvFDP48nS4+204nGb1RiX/WXYHmJA2III9/e2DWVabCESdW7hBAEzHRqUn9OUVvQ==
-"@cornerstonejs/adapters@^1.11.1":
- version "1.11.1"
- resolved "https://registry.yarnpkg.com/@cornerstonejs/adapters/-/adapters-1.11.1.tgz#d6c2b0dc0742a0ffd76e9ed86f911bbd8bc94c05"
- integrity sha512-ggSToAWv6fn7J4mq412P6xGV5IdbtHqRR4ZGap12ytus9HCCZLZ3a+lWx21+Rc9zILj8H/58WWb/pYvN0Itp5g==
+"@cornerstonejs/adapters@^1.11.4":
+ version "1.11.4"
+ resolved "https://registry.yarnpkg.com/@cornerstonejs/adapters/-/adapters-1.11.4.tgz#b318fe3180b7ceda5537420e8cd4e8d2ddac68f3"
+ integrity sha512-Qb7qfg0HD06yvpu8KgXkstvmrTUIbFft2HWblUbLe0gxO3ze+1LE2ZAT2qXyvC+nfchPTH2Ybo1D3yBxO7CPdQ==
dependencies:
"@babel/runtime-corejs2" "^7.17.8"
buffer "^6.0.3"
@@ -1428,43 +1428,43 @@
resolved "https://registry.yarnpkg.com/@cornerstonejs/codec-openjph/-/codec-openjph-2.4.2.tgz#e96721d56f6ec96f7f95c16321d88cc8467d8d81"
integrity sha512-lgdvBvvNezleY+4pIe2ceUsJzlZe/0PipdeubQ3vZZOz3xxtHHMR1XFCl4fgd8gosR8COHuD7h6q+MwgrwBsng==
-"@cornerstonejs/core@^1.11.1":
- version "1.11.1"
- resolved "https://registry.yarnpkg.com/@cornerstonejs/core/-/core-1.11.1.tgz#308904eabcd54bf8529ba174ff714a2aa7cd0be7"
- integrity sha512-QgGVRiS2ceDSC0kZlYyYw6owqh6rn7FaYuyJAYis1JCk1yG6xIUfcb6GMuubuEgEammc26i8EfU1H5FLxpHm2g==
+"@cornerstonejs/core@^1.11.4":
+ version "1.11.4"
+ resolved "https://registry.yarnpkg.com/@cornerstonejs/core/-/core-1.11.4.tgz#035a950a04641a103924ab93b30f257fd884fc8c"
+ integrity sha512-5kS6xgBimkfjjvd/o+6o4c0NvYVw2lCGDvow3hC5V7aCd6Pn8eo2BaU45QJ8y0A0NJ9xmtr37yb3v8+7lfkGSw==
dependencies:
"@kitware/vtk.js" "27.3.1"
detect-gpu "^5.0.22"
gl-matrix "^3.4.3"
lodash.clonedeep "4.5.0"
-"@cornerstonejs/dicom-image-loader@^1.11.1":
- version "1.11.1"
- resolved "https://registry.yarnpkg.com/@cornerstonejs/dicom-image-loader/-/dicom-image-loader-1.11.1.tgz#0a7786b97828038f6faca088b40cc2b96c7db362"
- integrity sha512-5/ocRRoYiwKKcKR01oGwWQp3imPEEYJcHull7MuwMWS1mZgYvok0QGs5Wz51rY8qJZCuM7nvkKxI21YzQkxISw==
+"@cornerstonejs/dicom-image-loader@^1.11.4":
+ version "1.11.4"
+ resolved "https://registry.yarnpkg.com/@cornerstonejs/dicom-image-loader/-/dicom-image-loader-1.11.4.tgz#4daa4f91e9a5f23fa8f39ebb3c73dcc148184b68"
+ integrity sha512-Hw5XS+SN7VF/C70CzYd8alK/91SccSbNArVc9erwrBP4EmLWOj9XmKMNiV7KXS7d60G0nEAzCKo+e0wQWOvxWA==
dependencies:
"@cornerstonejs/codec-charls" "^1.2.3"
"@cornerstonejs/codec-libjpeg-turbo-8bit" "^1.2.2"
"@cornerstonejs/codec-openjpeg" "^1.2.2"
"@cornerstonejs/codec-openjph" "^2.4.2"
- "@cornerstonejs/core" "^1.11.1"
+ "@cornerstonejs/core" "^1.11.4"
dicom-parser "^1.8.9"
pako "^2.0.4"
uuid "^9.0.0"
-"@cornerstonejs/streaming-image-volume-loader@^1.11.1":
- version "1.11.1"
- resolved "https://registry.yarnpkg.com/@cornerstonejs/streaming-image-volume-loader/-/streaming-image-volume-loader-1.11.1.tgz#4f48b9af36da090f51e91b9736d892c4450244cd"
- integrity sha512-S++wH3u037Gw5I51DWNwvqYaJl9W8vNhebTSzQIgZO3TVShzJo+0zQWdrsXrqOSzn9+0d4H6yEdxjKvsDRYBMw==
+"@cornerstonejs/streaming-image-volume-loader@^1.11.4":
+ version "1.11.4"
+ resolved "https://registry.yarnpkg.com/@cornerstonejs/streaming-image-volume-loader/-/streaming-image-volume-loader-1.11.4.tgz#ca166f7488e8bba78e8e2216b5fc00e36ed2000b"
+ integrity sha512-gucQKRjU+UET1BGho4gOi0iy9iT0WoUnuXqb3zS9y7FrBr10VW6F51kbm+BaS0H0PTHqlC5nwHNrsxWavOqleg==
dependencies:
- "@cornerstonejs/core" "^1.11.1"
+ "@cornerstonejs/core" "^1.11.4"
-"@cornerstonejs/tools@^1.11.1":
- version "1.11.1"
- resolved "https://registry.yarnpkg.com/@cornerstonejs/tools/-/tools-1.11.1.tgz#537caff00b53b7d37ea31d5aa67ec09298ce8057"
- integrity sha512-kt6UTHT24PffiEDuHSTOiRTSfYHaluWTY27bigr0wdnrMYMlO0oignFXiSJAJ0FzLZUhuRZeN7qs1fLXhOlcrA==
+"@cornerstonejs/tools@^1.11.4":
+ version "1.11.4"
+ resolved "https://registry.yarnpkg.com/@cornerstonejs/tools/-/tools-1.11.4.tgz#20ae1501d6f18346230f4b9bf62e23e30343407a"
+ integrity sha512-OLo69mbL2mgAUKuXSFLif+aJtbqT6hlWI5F6MsqgVun0BP1qLn2FgCfNwSphco4ejjiJG9CSnPBhfdcCxveaoA==
dependencies:
- "@cornerstonejs/core" "^1.11.1"
+ "@cornerstonejs/core" "^1.11.4"
lodash.clonedeep "4.5.0"
lodash.get "^4.4.2"