diff --git a/platform/core/package.json b/platform/core/package.json
index 93a9bea38..33d6f60ea 100644
--- a/platform/core/package.json
+++ b/platform/core/package.json
@@ -45,6 +45,7 @@
"lodash.clonedeep": "^4.5.0",
"lodash.merge": "^4.6.1",
"mousetrap": "^1.6.3",
- "validate.js": "^0.12.0"
+ "validate.js": "^0.12.0",
+ "immer": "6.0.2"
}
}
diff --git a/platform/core/src/redux/reducers/viewports.js b/platform/core/src/redux/reducers/viewports.js
index 5396e226c..88c4fc7bd 100644
--- a/platform/core/src/redux/reducers/viewports.js
+++ b/platform/core/src/redux/reducers/viewports.js
@@ -1,5 +1,5 @@
import cloneDeep from 'lodash.clonedeep';
-import merge from 'lodash.merge';
+import produce from 'immer';
import {
CLEAR_VIEWPORT,
@@ -93,12 +93,13 @@ const viewports = (state = DEFAULT_STATE, action) => {
* @return {Object} New state.
*/
case SET_VIEWPORT_ACTIVE: {
- const activeViewportIndex = getActiveViewportIndex(
- state.numRows,
- state.numColumns,
- action.viewportIndex
- );
- return { ...state, activeViewportIndex };
+ return produce(state, draftState => {
+ draftState.activeViewportIndex = getActiveViewportIndex(
+ draftState.numRows,
+ draftState.numColumns,
+ action.viewportIndex
+ );
+ });
}
/**
@@ -163,21 +164,20 @@ const viewports = (state = DEFAULT_STATE, action) => {
* @return {Object} New state.
*/
case SET_VIEWPORT: {
- const layout = cloneDeep(state.layout);
+ return produce(state, draftState => {
+ draftState.viewportSpecificData[action.viewportIndex] =
+ draftState.viewportSpecificData[action.viewportIndex] || {};
- let viewportSpecificData = cloneDeep(state.viewportSpecificData);
- viewportSpecificData[action.viewportIndex] = merge(
- {},
- viewportSpecificData[action.viewportIndex],
- action.viewportSpecificData
- );
+ Object.keys(action.viewportSpecificData).forEach(key => {
+ draftState.viewportSpecificData[action.viewportIndex][key] =
+ action.viewportSpecificData[key];
+ });
- if (action.viewportSpecificData && action.viewportSpecificData.plugin) {
- layout.viewports[action.viewportIndex].plugin =
- action.viewportSpecificData.plugin;
- }
-
- return { ...state, layout, viewportSpecificData };
+ if (action.viewportSpecificData && action.viewportSpecificData.plugin) {
+ draftState.layout.viewports[action.viewportIndex].plugin =
+ action.viewportSpecificData.plugin;
+ }
+ });
}
/**
diff --git a/platform/viewer/src/components/ViewportGrid/ConnectedViewportGrid.js b/platform/viewer/src/components/ViewportGrid/ConnectedViewportGrid.js
index 774b10401..be4b693c0 100644
--- a/platform/viewer/src/components/ViewportGrid/ConnectedViewportGrid.js
+++ b/platform/viewer/src/components/ViewportGrid/ConnectedViewportGrid.js
@@ -2,15 +2,20 @@ import ViewportGrid from './ViewportGrid.js';
import { MODULE_TYPES } from '@ohif/core';
import { connect } from 'react-redux';
import { extensionManager } from './../../App.js';
+import memoize from 'lodash/memoize';
-const mapStateToProps = state => {
+const getAvailableViewportModules = memoize(viewportModules => {
const availableViewportModules = {};
- const viewportModules = extensionManager.modules[MODULE_TYPES.VIEWPORT];
-
viewportModules.forEach(moduleDefinition => {
availableViewportModules[moduleDefinition.extensionId] =
moduleDefinition.module;
});
+ return availableViewportModules;
+});
+
+const mapStateToProps = state => {
+ const viewportModules = extensionManager.modules[MODULE_TYPES.VIEWPORT];
+ const availableViewportModules = getAvailableViewportModules(viewportModules);
// TODO: Use something like state.plugins.defaultPlugin[MODULE_TYPES.VIEWPORT]
let defaultPlugin;
diff --git a/platform/viewer/src/components/ViewportGrid/ViewportGrid.js b/platform/viewer/src/components/ViewportGrid/ViewportGrid.js
index ac17cd8c8..7aa497568 100644
--- a/platform/viewer/src/components/ViewportGrid/ViewportGrid.js
+++ b/platform/viewer/src/components/ViewportGrid/ViewportGrid.js
@@ -39,66 +39,68 @@ const ViewportGrid = function(props) {
});
}, [viewportData]);
- const ViewportPanes = layout.viewports.map((layout, viewportIndex) => {
- const displaySet = viewportData[viewportIndex];
+ const getViewportPanes = () =>
+ layout.viewports.map((layout, viewportIndex) => {
+ const displaySet = viewportData[viewportIndex];
- if (!displaySet) {
- return null;
- }
+ if (!displaySet) {
+ return null;
+ }
- const data = {
- displaySet,
- studies,
- };
+ const data = {
+ displaySet,
+ studies,
+ };
- // JAMES TODO:
+ // JAMES TODO:
- // Use whichever plugin is currently in use in the panel
- // unless nothing is specified. If nothing is specified
- // and the display set has a plugin specified, use that.
- //
- // TODO: Change this logic to:
- // - Plugins define how capable they are of displaying a SopClass
- // - When updating a panel, ensure that the currently enabled plugin
- // in the viewport is capable of rendering this display set. If not
- // then use the most capable available plugin
- const pluginName =
- !layout.plugin && displaySet && displaySet.plugin
- ? displaySet.plugin
- : layout.plugin;
+ // Use whichever plugin is currently in use in the panel
+ // unless nothing is specified. If nothing is specified
+ // and the display set has a plugin specified, use that.
+ //
+ // TODO: Change this logic to:
+ // - Plugins define how capable they are of displaying a SopClass
+ // - When updating a panel, ensure that the currently enabled plugin
+ // in the viewport is capable of rendering this display set. If not
+ // then use the most capable available plugin
+ const pluginName =
+ !layout.plugin && displaySet && displaySet.plugin
+ ? displaySet.plugin
+ : layout.plugin;
- const ViewportComponent = _getViewportComponent(
- data, // Why do we pass this as `ViewportData`, when that's not really what it is?
- viewportIndex,
- children,
- availablePlugins,
- pluginName,
- defaultPluginName
- );
+ const ViewportComponent = _getViewportComponent(
+ data, // Why do we pass this as `ViewportData`, when that's not really what it is?
+ viewportIndex,
+ children,
+ availablePlugins,
+ pluginName,
+ defaultPluginName
+ );
- return (
-