diff --git a/README.md b/README.md
index edc142726..6f74abd22 100644
--- a/README.md
+++ b/README.md
@@ -119,8 +119,7 @@ window.config = {
};
```
-- Install the viewer:
- `window.OHIFStandaloneViewer.installViewer(window.config);`
+- Install the viewer: `window.OHIFStandaloneViewer.installViewer(window.config);`
This exact setup is demonstrated in this
[CodeSandbox](https://codesandbox.io/s/ohif-viewer-script-tag-usage-c4u4t) and
diff --git a/docs/latest/deployment/recipes/nginx--image-archive.md b/docs/latest/deployment/recipes/nginx--image-archive.md
index baaf64ae4..beb1fec33 100644
--- a/docs/latest/deployment/recipes/nginx--image-archive.md
+++ b/docs/latest/deployment/recipes/nginx--image-archive.md
@@ -121,11 +121,7 @@ likely want to update:
#### OHIF Viewer
-The OHIF Viewer's configuration is imported from a static `.js` file and made
-available globally at `window.config`. The configuration we use is set to a
-specific file when we build the viewer, and determined by the env variable:
-`APP_CONFIG`. You can see where we set its value in the `dockerfile` for this
-solution:
+The OHIF Viewer's configuration is imported from a static `.js` file. The configuration we use is set to a specific file when we build the viewer, and determined by the env variable: `APP_CONFIG`. You can see where we set its value in the `dockerfile` for this solution:
`ENV APP_CONFIG=config/docker_openresty-orthanc.js`
diff --git a/docs/latest/deployment/recipes/user-account-control.md b/docs/latest/deployment/recipes/user-account-control.md
index 609c54995..bed05787d 100644
--- a/docs/latest/deployment/recipes/user-account-control.md
+++ b/docs/latest/deployment/recipes/user-account-control.md
@@ -122,11 +122,7 @@ likely want to update:
#### OHIF Viewer
-The OHIF Viewer's configuration is imported from a static `.js` file and made
-available globally at `window.config`. The configuration we use is set to a
-specific file when we build the viewer, and determined by the env variable:
-`APP_CONFIG`. You can see where we set its value in the `dockerfile` for this
-solution:
+The OHIF Viewer's configuration is imported from a static `.js` file. The configuration we use is set to a specific file when we build the viewer, and determined by the env variable: `APP_CONFIG`. You can see where we set its value in the `dockerfile` for this solution:
`ENV APP_CONFIG=config/docker_openresty-orthanc-keycloak.js`
diff --git a/platform/viewer/src/App.js b/platform/viewer/src/App.js
index b39dc6421..d20504700 100644
--- a/platform/viewer/src/App.js
+++ b/platform/viewer/src/App.js
@@ -25,12 +25,15 @@ import { OidcProvider } from 'redux-oidc';
import PropTypes from 'prop-types';
import { Provider } from 'react-redux';
import { BrowserRouter as Router } from 'react-router-dom';
-import WhiteLabellingContext from './WhiteLabellingContext';
import { getActiveContexts } from './store/layout/selectors.js';
import i18n from '@ohif/i18n';
import setupTools from './setupTools.js';
import store from './store';
-import UserManagerContext from './UserManagerContext';
+
+// Contexts
+import WhiteLabellingContext from './context/WhiteLabellingContext';
+import UserManagerContext from './context/UserManagerContext';
+import AppContext from './context/AppContext';
// ~~~~ APP SETUP
initCornerstoneTools({
@@ -74,10 +77,66 @@ class App extends Component {
extensions: [],
};
+ _appConfig;
+ _userManager;
+
constructor(props) {
super(props);
- if (this.props.oidc.length) {
+ this.appConfig = props;
+ const { servers, extensions, hotkeys, oidc } = props;
+
+ this.initUserManager(oidc);
+ _initExtensions(extensions, hotkeys);
+ _initServers(servers);
+ initWebWorkers();
+ }
+
+ render() {
+ const userManager = this._userManager;
+ const config = {
+ appConfig: this._appConfig,
+ };
+
+ if (userManager) {
+ return (
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ );
+ }
+
+ return (
+
+
+
+
+
+
+
+
+
+
+
+ );
+ }
+
+ initUserManager(oidc) {
+ if (oidc && !!oidc.length) {
const firstOpenIdClient = this.props.oidc[0];
const { protocol, host } = window.location;
@@ -102,58 +161,18 @@ class App extends Component {
),
});
- this.userManager = getUserManagerForOpenIdConnectClient(
+ this._userManager = getUserManagerForOpenIdConnectClient(
store,
openIdConnectConfiguration
);
}
-
- _initExtensions(this.props.extensions);
- _initServers(this.props.servers);
- initWebWorkers();
- }
-
- render() {
- const userManager = this.userManager;
-
- if (userManager) {
- return (
-
-
-
-
-
-
-
-
-
-
-
-
-
- );
- }
-
- return (
-
-
-
-
-
-
-
-
-
- );
}
}
/**
* @param
*/
-function _initExtensions(extensions) {
+function _initExtensions(extensions, hotkeys) {
const defaultExtensions = [
GenericViewerCommands,
MeasurementsPanel,
@@ -163,8 +182,8 @@ function _initExtensions(extensions) {
extensionManager.registerExtensions(mergedExtensions);
// Must run after extension commands are registered
- if (window.config.hotkeys) {
- hotkeysManager.setHotkeys(window.config.hotkeys, true);
+ if (hotkeys) {
+ hotkeysManager.setHotkeys(hotkeys, true);
}
}
diff --git a/platform/viewer/src/OHIFStandaloneViewer.js b/platform/viewer/src/OHIFStandaloneViewer.js
index c8f1007da..9d6bdd685 100644
--- a/platform/viewer/src/OHIFStandaloneViewer.js
+++ b/platform/viewer/src/OHIFStandaloneViewer.js
@@ -20,6 +20,9 @@ import './OHIFStandaloneViewer.css';
import './variables.css';
import './theme-tide.css';
+// Contexts
+import AppContext from './context/AppContext';
+
// Dynamic Import Routes (CodeSplitting)
// const IHEInvokeImageDisplay = asyncComponent(() =>
// import('./routes/IHEInvokeImageDisplay.js')
@@ -37,6 +40,7 @@ import './theme-tide.css';
const reload = () => window.location.reload();
class OHIFStandaloneViewer extends Component {
+ static contextType = AppContext;
state = {
isLoading: false,
};
@@ -63,7 +67,7 @@ class OHIFStandaloneViewer extends Component {
render() {
const { user, userManager } = this.props;
-
+ const { appConfig = {} } = this.context;
const userNotLoggedIn = userManager && (!user || user.expired);
if (userNotLoggedIn) {
const pathname = this.props.location.pathname;
@@ -140,9 +144,7 @@ class OHIFStandaloneViewer extends Component {
];
const showStudyList =
- window.config && window.config.showStudyList !== undefined
- ? window.config.showStudyList
- : true;
+ appConfig.showStudyList !== undefined ? appConfig.showStudyList : true;
if (showStudyList) {
routes.push({
path: '/studylist',
diff --git a/platform/viewer/src/components/Header/Header.js b/platform/viewer/src/components/Header/Header.js
index d618606c7..4ac7d81f6 100644
--- a/platform/viewer/src/components/Header/Header.js
+++ b/platform/viewer/src/components/Header/Header.js
@@ -11,13 +11,17 @@ import { AboutModal } from '@ohif/ui';
import { hotkeysManager } from './../../App.js';
import { withTranslation } from 'react-i18next';
+// Context
+import AppContext from './../../context/AppContext';
+
class Header extends Component {
+ static contextType = AppContext;
static propTypes = {
home: PropTypes.bool.isRequired,
location: PropTypes.object.isRequired,
children: PropTypes.node,
t: PropTypes.func.isRequired,
- userManager: PropTypes.object
+ userManager: PropTypes.object,
};
static defaultProps = {
@@ -63,10 +67,10 @@ class Header extends Component {
if (this.props.user && this.props.userManager) {
this.options.push({
title: t('Logout'),
- icon: { name: 'power-off' },
- onClick: () => {
- this.props.userManager.signoutRedirect();
- },
+ icon: { name: 'power-off' },
+ onClick: () => {
+ this.props.userManager.signoutRedirect();
+ },
});
}
@@ -82,10 +86,9 @@ class Header extends Component {
render() {
const { t } = this.props;
+ const { appConfig = {} } = this.context;
const showStudyList =
- window.config.showStudyList !== undefined
- ? window.config.showStudyList
- : true;
+ appConfig.showStudyList !== undefined ? appConfig.showStudyList : true;
return (
diff --git a/platform/viewer/src/connectedComponents/Viewer.js b/platform/viewer/src/connectedComponents/Viewer.js
index f0363ed65..fe2a0ee8b 100644
--- a/platform/viewer/src/connectedComponents/Viewer.js
+++ b/platform/viewer/src/connectedComponents/Viewer.js
@@ -5,7 +5,6 @@ import classNames from 'classnames';
import { MODULE_TYPES } from '@ohif/core';
import OHIF from '@ohif/core';
import moment from 'moment';
-import WhiteLabellingContext from '../WhiteLabellingContext.js';
import ConnectedHeader from './ConnectedHeader.js';
import ConnectedToolbarRow from './ConnectedToolbarRow.js';
import ConnectedLabellingOverlay from './ConnectedLabellingOverlay';
@@ -13,7 +12,11 @@ import ConnectedStudyBrowser from './ConnectedStudyBrowser.js';
import ConnectedViewerMain from './ConnectedViewerMain.js';
import SidePanel from './../components/SidePanel.js';
import { extensionManager } from './../App.js';
-import UserManagerContext from '../UserManagerContext';
+
+// Contexts
+import WhiteLabellingContext from '../context/WhiteLabellingContext.js';
+import UserManagerContext from '../context/UserManagerContext';
+
import './Viewer.css';
/**
* Inits OHIF Hanging Protocol's onReady.
diff --git a/platform/viewer/src/context/AppContext.js b/platform/viewer/src/context/AppContext.js
new file mode 100644
index 000000000..82bec40c4
--- /dev/null
+++ b/platform/viewer/src/context/AppContext.js
@@ -0,0 +1,5 @@
+import React from 'react';
+
+let AppContext = React.createContext({});
+
+export default AppContext;
diff --git a/platform/viewer/src/UserManagerContext.js b/platform/viewer/src/context/UserManagerContext.js
similarity index 100%
rename from platform/viewer/src/UserManagerContext.js
rename to platform/viewer/src/context/UserManagerContext.js
diff --git a/platform/viewer/src/WhiteLabellingContext.js b/platform/viewer/src/context/WhiteLabellingContext.js
similarity index 77%
rename from platform/viewer/src/WhiteLabellingContext.js
rename to platform/viewer/src/context/WhiteLabellingContext.js
index 345b767fc..d13f9246b 100644
--- a/platform/viewer/src/WhiteLabellingContext.js
+++ b/platform/viewer/src/context/WhiteLabellingContext.js
@@ -1,4 +1,4 @@
-import OHIFLogo from './components/OHIFLogo/OHIFLogo.js';
+import OHIFLogo from '../components/OHIFLogo/OHIFLogo.js';
import React from 'react';
const defaultContextValues = {
diff --git a/platform/viewer/src/studylist/StudyListRouting.js b/platform/viewer/src/studylist/StudyListRouting.js
index cd23827e6..8023df157 100644
--- a/platform/viewer/src/studylist/StudyListRouting.js
+++ b/platform/viewer/src/studylist/StudyListRouting.js
@@ -1,9 +1,12 @@
-import React from 'react';
+import React, { useContext } from 'react';
import PropTypes from 'prop-types';
import { withRouter } from 'react-router-dom';
import queryString from 'query-string';
import ConnectedStudyList from './ConnectedStudyList';
+// Contexts
+import AppContext from '../context/AppContext';
+
// TODO: Move to @ohif/ui
function toLowerCaseFirstLetter(word) {
@@ -22,16 +25,20 @@ function getFilters({ search }) {
}
function StudyListRouting({ location }) {
+ const { appConfig = {} } = useContext(AppContext);
+
const filters = location ? getFilters(location) : undefined;
let studyListFunctionsEnabled = false;
- if (window.config && window.config.studyListFunctionsEnabled) {
- studyListFunctionsEnabled = window.config.studyListFunctionsEnabled;
+ if (appConfig.studyListFunctionsEnabled) {
+ studyListFunctionsEnabled = appConfig.studyListFunctionsEnabled;
}
- return ;
+ return (
+
+ );
}
StudyListRouting.propTypes = {
diff --git a/platform/viewer/src/studylist/StudyListWithData.js b/platform/viewer/src/studylist/StudyListWithData.js
index ddf5956ed..656cf64f0 100644
--- a/platform/viewer/src/studylist/StudyListWithData.js
+++ b/platform/viewer/src/studylist/StudyListWithData.js
@@ -10,10 +10,14 @@ import moment from 'moment';
import ConnectedDicomFilesUploader from '../googleCloud/ConnectedDicomFilesUploader';
import ConnectedDicomStorePicker from '../googleCloud/ConnectedDicomStorePicker';
import filesToStudies from '../lib/filesToStudies.js';
-import UserManagerContext from '../UserManagerContext';
-import WhiteLabellingContext from '../WhiteLabellingContext';
+
+// Contexts
+import UserManagerContext from '../context/UserManagerContext';
+import WhiteLabellingContext from '../context/WhiteLabellingContext';
+import AppContext from '../context/AppContext';
class StudyListWithData extends Component {
+ static contextType = AppContext;
state = {
searchData: {},
studies: [],
@@ -51,9 +55,10 @@ class StudyListWithData extends Component {
};
componentDidMount() {
+ const { appConfig = {} } = this.context;
// TODO: Avoid using timepoints here
//const params = { studyInstanceUids, seriesInstanceUids, timepointId, timepointsFilter={} };
- if (!this.props.server && window.config.enableGoogleCloudAdapter) {
+ if (!this.props.server && appConfig.enableGoogleCloudAdapter) {
this.setState({
modalComponentId: 'DicomStorePicker',
});
@@ -184,6 +189,7 @@ class StudyListWithData extends Component {
};
render() {
+ const { appConfig = {} } = this.context;
const onDrop = async acceptedFiles => {
try {
const studies = await filesToStudies(acceptedFiles);
@@ -203,8 +209,7 @@ class StudyListWithData extends Component {
let healthCareApiButtons = null;
let healthCareApiWindows = null;
- // TODO: This should probably be a prop
- if (window.config.enableGoogleCloudAdapter) {
+ if (appConfig.enableGoogleCloudAdapter) {
healthCareApiWindows = (