diff --git a/extensions/default/src/ViewerLayout/index.tsx b/extensions/default/src/ViewerLayout/index.tsx index e045bca33..a71caeb2f 100644 --- a/extensions/default/src/ViewerLayout/index.tsx +++ b/extensions/default/src/ViewerLayout/index.tsx @@ -1,7 +1,12 @@ import React, { useEffect, useState } from 'react'; import PropTypes from 'prop-types'; -import { SidePanel, ErrorBoundary, LoadingIndicatorProgress } from '@ohif/ui'; +import { + SidePanel, + ErrorBoundary, + LoadingIndicatorProgress, + InvestigationalUseDialog, +} from '@ohif/ui'; import { ServicesManager, HangingProtocolService, CommandsManager } from '@ohif/core'; import { useAppConfig } from '@state'; import ViewerHeader from './ViewerHeader'; @@ -152,6 +157,8 @@ function ViewerLayout({ ) : null} + + ); } diff --git a/platform/app/src/routes/WorkList/WorkList.tsx b/platform/app/src/routes/WorkList/WorkList.tsx index 50cfccf29..05a5e0994 100644 --- a/platform/app/src/routes/WorkList/WorkList.tsx +++ b/platform/app/src/routes/WorkList/WorkList.tsx @@ -27,6 +27,7 @@ import { UserPreferences, LoadingIndicatorProgress, useSessionStorage, + InvestigationalUseDialog, Button, ButtonEnums, } from '@ohif/ui'; @@ -527,6 +528,7 @@ function WorkList({ isReturnEnabled={false} WhiteLabeling={appConfig.whiteLabeling} /> +
100 ? 101 : numOfStudies} diff --git a/platform/docs/docs/configuration/configurationFiles.md b/platform/docs/docs/configuration/configurationFiles.md index 71ba36b06..959e8d5ae 100644 --- a/platform/docs/docs/configuration/configurationFiles.md +++ b/platform/docs/docs/configuration/configurationFiles.md @@ -122,6 +122,8 @@ Here are a list of some options available: decoding. Defaults to minimum of `navigator.hardwareConcurrency` and what is specified by `maxNumberOfWebWorkers`. Some windows machines require smaller values. - `acceptHeader` : accept header to request specific dicom transfer syntax ex : [ 'multipart/related; type=image/jls; q=1', 'multipart/related; type=application/octet-stream; q=0.1' ] +- `investigationalUseDialog`: This should contain an object with `option` value, it can be either `always` which always shows the dialog once per session, `never` which never shows the dialog, or `configure` which shows the dialog once and won't show it again until a set number of days defined by the user, if it's set to configure, you are required to add an additional property `days` which is the number of days to wait before showing the dialog again. +- `groupEnabled`: boolean, if set to true, all valid modes for the study get grouped together first, then the rest of the modes. If false, all modes are shown in the order they are defined in the configuration. - `requestTransferSyntaxUID` : Request a specific Transfer syntax from dicom web server ex: 1.2.840.10008.1.2.4.80 (applied only if acceptHeader is not set) - `omitQuotationForMultipartRequest`: Some servers (e.g., .NET) require the `multipart/related` request to be sent without quotation marks. Defaults to `false`. If your server doesn't require this, then setting this flag to `true` might improve performance (by removing the need for preflight requests). Also note that if auth headers are used, a preflight request is required. diff --git a/platform/ui/src/assets/icons/illustration-investigational-use.svg b/platform/ui/src/assets/icons/illustration-investigational-use.svg new file mode 100644 index 000000000..5ca03db68 --- /dev/null +++ b/platform/ui/src/assets/icons/illustration-investigational-use.svg @@ -0,0 +1,20 @@ + + + illustration-investigational-use + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/platform/ui/src/components/Header/Header.tsx b/platform/ui/src/components/Header/Header.tsx index 3bf7a6926..18fdbabc4 100644 --- a/platform/ui/src/components/Header/Header.tsx +++ b/platform/ui/src/components/Header/Header.tsx @@ -58,7 +58,6 @@ function Header({
{children}
- {t('INVESTIGATIONAL USE ONLY')} { + const { option, days } = dialogConfiguration; + const [isHidden, setIsHidden] = useState(true); + + useEffect(() => { + const dialogLocalState = localStorage.getItem('investigationalUseDialog'); + const dialogSessionState = sessionStorage.getItem('investigationalUseDialog'); + + switch (option) { + case showDialogOption.NeverShowDialog: + setIsHidden(true); + break; + case showDialogOption.AlwaysShowDialog: + setIsHidden(!!dialogSessionState); + break; + case showDialogOption.ShowOnceAndConfigure: + if (dialogLocalState) { + const { expiryDate } = JSON.parse(dialogLocalState); + const isExpired = new Date() > new Date(expiryDate); + setIsHidden(!isExpired); + } else { + setIsHidden(false); + } + break; + default: + setIsHidden(true); + } + }, [option, days]); + + const handleConfirmAndHide = () => { + const expiryDate = new Date(); + + switch (option) { + case showDialogOption.ShowOnceAndConfigure: + expiryDate.setDate(expiryDate.getDate() + days); + localStorage.setItem('investigationalUseDialog', JSON.stringify({ expiryDate })); + break; + case showDialogOption.AlwaysShowDialog: + sessionStorage.setItem('investigationalUseDialog', 'hidden'); + break; + } + setIsHidden(true); + }; + + if (isHidden) { + return null; + } + + return ( +
+
+
+ +
+
+ OHIF Viewer is{' '} + for investigational use only +
+
+ window.open('https://ohif.org/', '_blank')} + > + Learn more about OHIF Viewer + +
+
+
+ +
+
+ ); +}; + +InvestigationalUseDialog.propTypes = { + dialogConfiguration: PropTypes.shape({ + option: PropTypes.oneOf(Object.values(showDialogOption)).isRequired, + days: PropTypes.number, + }).isRequired, +}; + +InvestigationalUseDialog.defaultProps = { + dialogConfiguration: { + option: showDialogOption.AlwaysShowDialog, + }, +}; + +export default InvestigationalUseDialog; diff --git a/platform/ui/src/components/InvestigationalUseDialog/index.js b/platform/ui/src/components/InvestigationalUseDialog/index.js new file mode 100644 index 000000000..4d9c6d5ce --- /dev/null +++ b/platform/ui/src/components/InvestigationalUseDialog/index.js @@ -0,0 +1,3 @@ +import InvestigationalUseDialog from './InvestigationalUseDialog'; + +export default InvestigationalUseDialog; diff --git a/platform/ui/src/components/index.js b/platform/ui/src/components/index.js index c65728641..11cc227ac 100644 --- a/platform/ui/src/components/index.js +++ b/platform/ui/src/components/index.js @@ -79,6 +79,7 @@ import PanelSection from './PanelSection'; import AdvancedToolbox from './AdvancedToolbox'; import InputDoubleRange from './InputDoubleRange'; import LegacyButtonGroup from './LegacyButtonGroup'; +import InvestigationalUseDialog from './InvestigationalUseDialog'; import MeasurementItem from './MeasurementTable/MeasurementItem'; export { @@ -164,5 +165,6 @@ export { ViewportPane, ViewportOverlay, WindowLevelMenuItem, + InvestigationalUseDialog, MeasurementItem, }; diff --git a/platform/ui/src/index.js b/platform/ui/src/index.js index b1f57d0f2..0ae27d0df 100644 --- a/platform/ui/src/index.js +++ b/platform/ui/src/index.js @@ -117,6 +117,7 @@ export { WindowLevelMenuItem, ImageScrollbar, ViewportOverlay, + InvestigationalUseDialog, MeasurementItem, } from './components';