feat: 🎸 1729 - error boundary wrapper (#1764)
* Add error boundaries * Fix PWA e2e. * feat: ErrorBoundaryDialog * replace component to use ErrorBoundaryDialog * add proptypes * fix context * remove ErrorBoundary from extensions Co-authored-by: igoroctaviano <igoroctaviano@gmail.com> Co-authored-by: James A. Petts <jamesapetts@gmail.com>
This commit is contained in:
parent
f01640d009
commit
c02b232b0c
@ -39,7 +39,9 @@ export default {
|
|||||||
const onNewImageHandler = jumpData => {
|
const onNewImageHandler = jumpData => {
|
||||||
commandsManager.runCommand('jumpToImage', jumpData);
|
commandsManager.runCommand('jumpToImage', jumpData);
|
||||||
};
|
};
|
||||||
return <OHIFCornerstoneViewport {...props} onNewImage={onNewImageHandler} />;
|
return (
|
||||||
|
<OHIFCornerstoneViewport {...props} onNewImage={onNewImageHandler} />
|
||||||
|
);
|
||||||
};
|
};
|
||||||
|
|
||||||
return ExtendedOHIFCornerstoneViewport;
|
return ExtendedOHIFCornerstoneViewport;
|
||||||
|
|||||||
@ -31,7 +31,18 @@ const refreshViewport = () => {
|
|||||||
* @param {number} props.isOpen - isOpen
|
* @param {number} props.isOpen - isOpen
|
||||||
* @returns component
|
* @returns component
|
||||||
*/
|
*/
|
||||||
const RTPanel = ({ studies, viewports, activeIndex, isOpen, onContourItemClick }) => {
|
const RTPanel = ({
|
||||||
|
studies,
|
||||||
|
viewports,
|
||||||
|
activeIndex,
|
||||||
|
isOpen,
|
||||||
|
onContourItemClick,
|
||||||
|
activeContexts = [],
|
||||||
|
contexts = {}
|
||||||
|
}) => {
|
||||||
|
const isVTK = () => activeContexts.includes(contexts.VTK);
|
||||||
|
const isCornerstone = () => activeContexts.includes(contexts.CORNERSTONE);
|
||||||
|
|
||||||
const [selectedContour, setSelectedContour] = useState();
|
const [selectedContour, setSelectedContour] = useState();
|
||||||
const DEFAULT_SET_INDEX = 0;
|
const DEFAULT_SET_INDEX = 0;
|
||||||
const DEFAULT_STATE = {
|
const DEFAULT_STATE = {
|
||||||
@ -119,6 +130,7 @@ const RTPanel = ({ studies, viewports, activeIndex, isOpen, onContourItemClick }
|
|||||||
onClick={() => {
|
onClick={() => {
|
||||||
setSelectedContour(isSameContour ? null : ROINumber);
|
setSelectedContour(isSameContour ? null : ROINumber);
|
||||||
|
|
||||||
|
if (isCornerstone()) {
|
||||||
const enabledElements = cornerstone.getEnabledElements();
|
const enabledElements = cornerstone.getEnabledElements();
|
||||||
const element = enabledElements[activeIndex].element;
|
const element = enabledElements[activeIndex].element;
|
||||||
const toolState = cornerstoneTools.getToolState(element, 'stack');
|
const toolState = cornerstoneTools.getToolState(element, 'stack');
|
||||||
@ -146,6 +158,7 @@ const RTPanel = ({ studies, viewports, activeIndex, isOpen, onContourItemClick }
|
|||||||
frameIndex,
|
frameIndex,
|
||||||
activeViewportIndex: activeIndex
|
activeViewportIndex: activeIndex
|
||||||
});
|
});
|
||||||
|
}
|
||||||
}}
|
}}
|
||||||
label={`${ROIName} ${interpretedType}`}
|
label={`${ROIName} ${interpretedType}`}
|
||||||
index={ROINumber}
|
index={ROINumber}
|
||||||
|
|||||||
@ -20,14 +20,21 @@ export default {
|
|||||||
preRegistration({ servicesManager, configuration = {} }) {
|
preRegistration({ servicesManager, configuration = {} }) {
|
||||||
init({ servicesManager, configuration });
|
init({ servicesManager, configuration });
|
||||||
},
|
},
|
||||||
getPanelModule({ commandsManager }) {
|
getPanelModule({ commandsManager, api }) {
|
||||||
const ExtendedRTPanel = props => {
|
const ExtendedRTPanel = props => {
|
||||||
|
const { activeContexts } = api.hooks.useAppContext();
|
||||||
|
|
||||||
const contourItemClickHandler = contourData => {
|
const contourItemClickHandler = contourData => {
|
||||||
commandsManager.runCommand('jumpToImage', contourData);
|
commandsManager.runCommand('jumpToImage', contourData);
|
||||||
};
|
};
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<RTPanel {...props} onContourItemClick={contourItemClickHandler} />
|
<RTPanel
|
||||||
|
{...props}
|
||||||
|
onContourItemClick={contourItemClickHandler}
|
||||||
|
activeContexts={activeContexts}
|
||||||
|
contexts={api.contexts}
|
||||||
|
/>
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|||||||
@ -49,8 +49,8 @@ const SegmentationPanel = ({
|
|||||||
onConfigurationChange,
|
onConfigurationChange,
|
||||||
onDisplaySetLoadFailure,
|
onDisplaySetLoadFailure,
|
||||||
onSelectedSegmentationChange,
|
onSelectedSegmentationChange,
|
||||||
activeContexts,
|
activeContexts = [],
|
||||||
contexts,
|
contexts = {},
|
||||||
}) => {
|
}) => {
|
||||||
const isVTK = () => activeContexts.includes(contexts.VTK);
|
const isVTK = () => activeContexts.includes(contexts.VTK);
|
||||||
const isCornerstone = () => activeContexts.includes(contexts.CORNERSTONE);
|
const isCornerstone = () => activeContexts.includes(contexts.CORNERSTONE);
|
||||||
|
|||||||
@ -46,7 +46,7 @@ export default {
|
|||||||
const onSegmentVisibilityChangeHandler = (segmentNumber, visible) => {
|
const onSegmentVisibilityChangeHandler = (segmentNumber, visible) => {
|
||||||
commandsManager.runCommand('setSegmentConfiguration', {
|
commandsManager.runCommand('setSegmentConfiguration', {
|
||||||
segmentNumber,
|
segmentNumber,
|
||||||
visible
|
visible,
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -55,7 +55,7 @@ export default {
|
|||||||
globalOpacity: configuration.fillAlpha,
|
globalOpacity: configuration.fillAlpha,
|
||||||
outlineThickness: configuration.outlineWidth,
|
outlineThickness: configuration.outlineWidth,
|
||||||
renderOutline: configuration.renderOutline,
|
renderOutline: configuration.renderOutline,
|
||||||
visible: configuration.renderFill
|
visible: configuration.renderFill,
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|||||||
@ -1,3 +1,4 @@
|
|||||||
|
import React from 'react';
|
||||||
import asyncComponent from './asyncComponent.js';
|
import asyncComponent from './asyncComponent.js';
|
||||||
import commandsModule from './commandsModule.js';
|
import commandsModule from './commandsModule.js';
|
||||||
import toolbarModule from './toolbarModule.js';
|
import toolbarModule from './toolbarModule.js';
|
||||||
@ -16,7 +17,8 @@ const vtkExtension = {
|
|||||||
id: 'vtk',
|
id: 'vtk',
|
||||||
|
|
||||||
getViewportModule({ commandsManager }) {
|
getViewportModule({ commandsManager }) {
|
||||||
return withCommandsManager(OHIFVTKViewport, commandsManager);
|
const ExtendedVTKViewport = props => <OHIFVTKViewport {...props} />;
|
||||||
|
return withCommandsManager(ExtendedVTKViewport, commandsManager);
|
||||||
},
|
},
|
||||||
getToolbarModule() {
|
getToolbarModule() {
|
||||||
return toolbarModule;
|
return toolbarModule;
|
||||||
|
|||||||
@ -53,6 +53,7 @@
|
|||||||
"react-dnd-html5-backend": "^9.4.0",
|
"react-dnd-html5-backend": "^9.4.0",
|
||||||
"react-dnd-touch-backend": "^9.4.0",
|
"react-dnd-touch-backend": "^9.4.0",
|
||||||
"react-draggable": "^4.1.0",
|
"react-draggable": "^4.1.0",
|
||||||
|
"react-error-boundary": "^2.2.1",
|
||||||
"react-i18next": "^10.11.0",
|
"react-i18next": "^10.11.0",
|
||||||
"react-modal": "^3.11.1",
|
"react-modal": "^3.11.1",
|
||||||
"react-with-direction": "1.3.0"
|
"react-with-direction": "1.3.0"
|
||||||
|
|||||||
51
platform/ui/src/components/errorBoundary/ErrorBoundary.js
Normal file
51
platform/ui/src/components/errorBoundary/ErrorBoundary.js
Normal file
@ -0,0 +1,51 @@
|
|||||||
|
import React from 'react';
|
||||||
|
import PropTypes from 'prop-types';
|
||||||
|
import { ErrorBoundary } from 'react-error-boundary';
|
||||||
|
import './ErrorFallback.css';
|
||||||
|
|
||||||
|
const ErrorFallback = ({ error, componentStack, resetErrorBoundary }) => {
|
||||||
|
return (
|
||||||
|
<div className="ErrorFallback" role="alert">
|
||||||
|
<p>Something went wrong.</p>
|
||||||
|
<pre>{error.message}</pre>
|
||||||
|
<pre>{componentStack}</pre>
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
const OHIFErrorBoundary = ({
|
||||||
|
context = 'OHIF',
|
||||||
|
onReset = () => {},
|
||||||
|
onError = () => {},
|
||||||
|
fallbackComponent,
|
||||||
|
children,
|
||||||
|
}) => {
|
||||||
|
const onErrorHandler = (error, componentStack) => {
|
||||||
|
console.error(`${context} Error Boundary`, error, componentStack);
|
||||||
|
onError(error, componentStack);
|
||||||
|
};
|
||||||
|
|
||||||
|
const onResetHandler = () => {
|
||||||
|
onReset();
|
||||||
|
};
|
||||||
|
|
||||||
|
return (
|
||||||
|
<ErrorBoundary
|
||||||
|
FallbackComponent={fallbackComponent || ErrorFallback}
|
||||||
|
onReset={onResetHandler}
|
||||||
|
onError={onErrorHandler}
|
||||||
|
>
|
||||||
|
{children}
|
||||||
|
</ErrorBoundary>
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
OHIFErrorBoundary.propTypes = {
|
||||||
|
context: PropTypes.string,
|
||||||
|
onReset: PropTypes.func,
|
||||||
|
onError: PropTypes.func,
|
||||||
|
children: PropTypes.node.isRequired,
|
||||||
|
fallbackComponent: PropTypes.element,
|
||||||
|
};
|
||||||
|
|
||||||
|
export default OHIFErrorBoundary;
|
||||||
@ -0,0 +1,4 @@
|
|||||||
|
.ErrorFallback {
|
||||||
|
padding: 10px;
|
||||||
|
color: var(--active-color);
|
||||||
|
}
|
||||||
1
platform/ui/src/components/errorBoundary/index.js
Normal file
1
platform/ui/src/components/errorBoundary/index.js
Normal file
@ -0,0 +1 @@
|
|||||||
|
export { default as ErrorBoundary } from './ErrorBoundary';
|
||||||
@ -7,7 +7,6 @@ import { AboutContent } from './content/aboutContent/AboutContent';
|
|||||||
import { TabComponents, TabFooter } from './tabComponents';
|
import { TabComponents, TabFooter } from './tabComponents';
|
||||||
import { HotkeyField } from './customForm';
|
import { HotkeyField } from './customForm';
|
||||||
import { LanguageSwitcher } from './languageSwitcher';
|
import { LanguageSwitcher } from './languageSwitcher';
|
||||||
|
|
||||||
import { Checkbox } from './checkbox';
|
import { Checkbox } from './checkbox';
|
||||||
import { CineDialog } from './cineDialog';
|
import { CineDialog } from './cineDialog';
|
||||||
import { ViewportDownloadForm } from './content/viewportDownloadForm';
|
import { ViewportDownloadForm } from './content/viewportDownloadForm';
|
||||||
@ -25,8 +24,10 @@ import {
|
|||||||
} from './studyList';
|
} from './studyList';
|
||||||
import { ToolbarSection } from './toolbarSection';
|
import { ToolbarSection } from './toolbarSection';
|
||||||
import { Tooltip } from './tooltip';
|
import { Tooltip } from './tooltip';
|
||||||
|
import { ErrorBoundary } from './errorBoundary';
|
||||||
|
|
||||||
export {
|
export {
|
||||||
|
ErrorBoundary,
|
||||||
ContextMenu,
|
ContextMenu,
|
||||||
Checkbox,
|
Checkbox,
|
||||||
CineDialog,
|
CineDialog,
|
||||||
|
|||||||
@ -29,6 +29,7 @@ import {
|
|||||||
Tooltip,
|
Tooltip,
|
||||||
AboutContent,
|
AboutContent,
|
||||||
OHIFModal,
|
OHIFModal,
|
||||||
|
ErrorBoundary
|
||||||
} from './components';
|
} from './components';
|
||||||
import { useDebounce, useMedia } from './hooks';
|
import { useDebounce, useMedia } from './hooks';
|
||||||
|
|
||||||
@ -123,6 +124,7 @@ export {
|
|||||||
DialogProvider,
|
DialogProvider,
|
||||||
withDialog,
|
withDialog,
|
||||||
useDialog,
|
useDialog,
|
||||||
|
ErrorBoundary,
|
||||||
// Hooks
|
// Hooks
|
||||||
useDebounce,
|
useDebounce,
|
||||||
useMedia,
|
useMedia,
|
||||||
|
|||||||
@ -1,7 +1,7 @@
|
|||||||
describe('OHIF Microscopy Extension', () => {
|
describe('OHIF Microscopy Extension', () => {
|
||||||
before(() => {
|
before(() => {
|
||||||
cy.openStudyModality('SM');
|
cy.openStudyModality('SM');
|
||||||
cy.expectMinimumThumbnails(6);
|
cy.expectMinimumThumbnails(2);
|
||||||
});
|
});
|
||||||
|
|
||||||
it('checks if series thumbnails are being displayed', () => {
|
it('checks if series thumbnails are being displayed', () => {
|
||||||
|
|||||||
@ -13,6 +13,7 @@ import {
|
|||||||
ModalProvider,
|
ModalProvider,
|
||||||
DialogProvider,
|
DialogProvider,
|
||||||
OHIFModal,
|
OHIFModal,
|
||||||
|
ErrorBoundary
|
||||||
} from '@ohif/ui';
|
} from '@ohif/ui';
|
||||||
|
|
||||||
import {
|
import {
|
||||||
@ -167,6 +168,7 @@ class App extends Component {
|
|||||||
|
|
||||||
if (this._userManager) {
|
if (this._userManager) {
|
||||||
return (
|
return (
|
||||||
|
<ErrorBoundary context='App'>
|
||||||
<Provider store={store}>
|
<Provider store={store}>
|
||||||
<AppProvider config={this._appConfig}>
|
<AppProvider config={this._appConfig}>
|
||||||
<I18nextProvider i18n={i18n}>
|
<I18nextProvider i18n={i18n}>
|
||||||
@ -193,10 +195,12 @@ class App extends Component {
|
|||||||
</I18nextProvider>
|
</I18nextProvider>
|
||||||
</AppProvider>
|
</AppProvider>
|
||||||
</Provider>
|
</Provider>
|
||||||
|
</ErrorBoundary>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
return (
|
return (
|
||||||
|
<ErrorBoundary context='App'>
|
||||||
<Provider store={store}>
|
<Provider store={store}>
|
||||||
<AppProvider config={this._appConfig}>
|
<AppProvider config={this._appConfig}>
|
||||||
<I18nextProvider i18n={i18n}>
|
<I18nextProvider i18n={i18n}>
|
||||||
@ -214,6 +218,7 @@ class App extends Component {
|
|||||||
</I18nextProvider>
|
</I18nextProvider>
|
||||||
</AppProvider>
|
</AppProvider>
|
||||||
</Provider>
|
</Provider>
|
||||||
|
</ErrorBoundary>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -5,7 +5,7 @@ import { Route, Switch } from 'react-router-dom';
|
|||||||
import { NProgress } from '@tanem/react-nprogress';
|
import { NProgress } from '@tanem/react-nprogress';
|
||||||
import { CSSTransition } from 'react-transition-group';
|
import { CSSTransition } from 'react-transition-group';
|
||||||
import { connect } from 'react-redux';
|
import { connect } from 'react-redux';
|
||||||
import { ViewerbaseDragDropContext } from '@ohif/ui';
|
import { ViewerbaseDragDropContext, ErrorBoundary } from '@ohif/ui';
|
||||||
import { SignoutCallbackComponent } from 'redux-oidc';
|
import { SignoutCallbackComponent } from 'redux-oidc';
|
||||||
import asyncComponent from './components/AsyncComponent.js';
|
import asyncComponent from './components/AsyncComponent.js';
|
||||||
import * as RoutesUtil from './routes/routesUtil';
|
import * as RoutesUtil from './routes/routesUtil';
|
||||||
@ -191,7 +191,9 @@ class OHIFStandaloneViewer extends Component {
|
|||||||
{match === null ? (
|
{match === null ? (
|
||||||
<></>
|
<></>
|
||||||
) : (
|
) : (
|
||||||
|
<ErrorBoundary context={match.url}>
|
||||||
<Component match={match} location={this.props.location} />
|
<Component match={match} location={this.props.location} />
|
||||||
|
</ErrorBoundary>
|
||||||
)}
|
)}
|
||||||
</CSSTransition>
|
</CSSTransition>
|
||||||
)}
|
)}
|
||||||
|
|||||||
@ -0,0 +1,52 @@
|
|||||||
|
import React from 'react';
|
||||||
|
import PropTypes from 'prop-types';
|
||||||
|
import { ErrorBoundary } from '@ohif/ui';
|
||||||
|
import { servicesManager } from './../../App';
|
||||||
|
|
||||||
|
const { UIModalService } = servicesManager.services;
|
||||||
|
|
||||||
|
const ErrorBoundaryDialog = ({ context, children }) => {
|
||||||
|
const handleOnError = (error, componentStack) => {
|
||||||
|
const ErrorDialog = () => (
|
||||||
|
<div className="ErrorFallback" role="alert">
|
||||||
|
<div>
|
||||||
|
<h3>
|
||||||
|
{context}: <span>{error.message}</span>
|
||||||
|
</h3>
|
||||||
|
</div>
|
||||||
|
<pre>{componentStack}</pre>
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
|
||||||
|
UIModalService.show({
|
||||||
|
content: ErrorDialog,
|
||||||
|
title: `${context}: ${error.message}`,
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
|
const fallbackComponent = () => (
|
||||||
|
<div className="ErrorFallback" role="alert">
|
||||||
|
<p>
|
||||||
|
Error rendering {context}. <br /> Check the browser console for more
|
||||||
|
details.
|
||||||
|
</p>
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
|
||||||
|
return (
|
||||||
|
<ErrorBoundary
|
||||||
|
fallbackComponent={fallbackComponent}
|
||||||
|
context={context}
|
||||||
|
onError={handleOnError}
|
||||||
|
>
|
||||||
|
{children}
|
||||||
|
</ErrorBoundary>
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
ErrorBoundaryDialog.propTypes = {
|
||||||
|
context: PropTypes.string.isRequired,
|
||||||
|
children: PropTypes.node.isRequired,
|
||||||
|
};
|
||||||
|
|
||||||
|
export default ErrorBoundaryDialog;
|
||||||
@ -0,0 +1,3 @@
|
|||||||
|
import ErrorBoundaryDialog from './ErrorBoundaryDialog';
|
||||||
|
|
||||||
|
export default ErrorBoundaryDialog;
|
||||||
@ -24,7 +24,7 @@ const ViewportGrid = function (props) {
|
|||||||
studies,
|
studies,
|
||||||
viewportData,
|
viewportData,
|
||||||
children,
|
children,
|
||||||
isStudyLoaded
|
isStudyLoaded,
|
||||||
} = props;
|
} = props;
|
||||||
|
|
||||||
const rowSize = 100 / numRows;
|
const rowSize = 100 / numRows;
|
||||||
@ -54,7 +54,7 @@ const ViewportGrid = function (props) {
|
|||||||
});
|
});
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
}, [studies, viewportData, isStudyLoaded]);
|
}, [studies, viewportData, isStudyLoaded, snackbar]);
|
||||||
|
|
||||||
const getViewportPanes = () =>
|
const getViewportPanes = () =>
|
||||||
layout.viewports.map((layout, viewportIndex) => {
|
layout.viewports.map((layout, viewportIndex) => {
|
||||||
|
|||||||
@ -2,8 +2,7 @@ import React, { Component } from 'react';
|
|||||||
import PropTypes from 'prop-types';
|
import PropTypes from 'prop-types';
|
||||||
import classNames from 'classnames';
|
import classNames from 'classnames';
|
||||||
|
|
||||||
import { MODULE_TYPES } from '@ohif/core';
|
import OHIF, { MODULE_TYPES, DICOMSR } from '@ohif/core';
|
||||||
import OHIF, { DICOMSR } from '@ohif/core';
|
|
||||||
import { withDialog } from '@ohif/ui';
|
import { withDialog } from '@ohif/ui';
|
||||||
import moment from 'moment';
|
import moment from 'moment';
|
||||||
import ConnectedHeader from './ConnectedHeader.js';
|
import ConnectedHeader from './ConnectedHeader.js';
|
||||||
@ -11,6 +10,7 @@ import ToolbarRow from './ToolbarRow.js';
|
|||||||
import ConnectedStudyBrowser from './ConnectedStudyBrowser.js';
|
import ConnectedStudyBrowser from './ConnectedStudyBrowser.js';
|
||||||
import ConnectedViewerMain from './ConnectedViewerMain.js';
|
import ConnectedViewerMain from './ConnectedViewerMain.js';
|
||||||
import SidePanel from './../components/SidePanel.js';
|
import SidePanel from './../components/SidePanel.js';
|
||||||
|
import ErrorBoundaryDialog from './../components/ErrorBoundaryDialog';
|
||||||
import { extensionManager } from './../App.js';
|
import { extensionManager } from './../App.js';
|
||||||
|
|
||||||
// Contexts
|
// Contexts
|
||||||
@ -26,6 +26,7 @@ class Viewer extends Component {
|
|||||||
PropTypes.shape({
|
PropTypes.shape({
|
||||||
StudyInstanceUID: PropTypes.string.isRequired,
|
StudyInstanceUID: PropTypes.string.isRequired,
|
||||||
StudyDate: PropTypes.string,
|
StudyDate: PropTypes.string,
|
||||||
|
PatientID: PropTypes.string,
|
||||||
displaySets: PropTypes.arrayOf(
|
displaySets: PropTypes.arrayOf(
|
||||||
PropTypes.shape({
|
PropTypes.shape({
|
||||||
displaySetInstanceUID: PropTypes.string.isRequired,
|
displaySetInstanceUID: PropTypes.string.isRequired,
|
||||||
@ -256,6 +257,7 @@ class Viewer extends Component {
|
|||||||
</WhiteLabelingContext.Consumer>
|
</WhiteLabelingContext.Consumer>
|
||||||
|
|
||||||
{/* TOOLBAR */}
|
{/* TOOLBAR */}
|
||||||
|
<ErrorBoundaryDialog context="ToolbarRow">
|
||||||
<ToolbarRow
|
<ToolbarRow
|
||||||
isLeftSidePanelOpen={this.state.isLeftSidePanelOpen}
|
isLeftSidePanelOpen={this.state.isLeftSidePanelOpen}
|
||||||
isRightSidePanelOpen={this.state.isRightSidePanelOpen}
|
isRightSidePanelOpen={this.state.isRightSidePanelOpen}
|
||||||
@ -292,6 +294,7 @@ class Viewer extends Component {
|
|||||||
}}
|
}}
|
||||||
studies={this.props.studies}
|
studies={this.props.studies}
|
||||||
/>
|
/>
|
||||||
|
</ErrorBoundaryDialog>
|
||||||
|
|
||||||
{/*<ConnectedStudyLoadingMonitor studies={this.props.studies} />*/}
|
{/*<ConnectedStudyLoadingMonitor studies={this.props.studies} />*/}
|
||||||
{/*<StudyPrefetcher studies={this.props.studies} />*/}
|
{/*<StudyPrefetcher studies={this.props.studies} />*/}
|
||||||
@ -299,6 +302,7 @@ class Viewer extends Component {
|
|||||||
{/* VIEWPORTS + SIDEPANELS */}
|
{/* VIEWPORTS + SIDEPANELS */}
|
||||||
<div className="FlexboxLayout">
|
<div className="FlexboxLayout">
|
||||||
{/* LEFT */}
|
{/* LEFT */}
|
||||||
|
<ErrorBoundaryDialog context="LeftSidePanel">
|
||||||
<SidePanel from="left" isOpen={this.state.isLeftSidePanelOpen}>
|
<SidePanel from="left" isOpen={this.state.isLeftSidePanelOpen}>
|
||||||
{VisiblePanelLeft ? (
|
{VisiblePanelLeft ? (
|
||||||
<VisiblePanelLeft
|
<VisiblePanelLeft
|
||||||
@ -313,13 +317,20 @@ class Viewer extends Component {
|
|||||||
/>
|
/>
|
||||||
)}
|
)}
|
||||||
</SidePanel>
|
</SidePanel>
|
||||||
|
</ErrorBoundaryDialog>
|
||||||
|
|
||||||
{/* MAIN */}
|
{/* MAIN */}
|
||||||
<div className={classNames('main-content')}>
|
<div className={classNames('main-content')}>
|
||||||
<ConnectedViewerMain studies={this.props.studies} isStudyLoaded={this.props.isStudyLoaded} />
|
<ErrorBoundaryDialog context="ViewerMain">
|
||||||
|
<ConnectedViewerMain
|
||||||
|
studies={this.props.studies}
|
||||||
|
isStudyLoaded={this.props.isStudyLoaded}
|
||||||
|
/>
|
||||||
|
</ErrorBoundaryDialog>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
{/* RIGHT */}
|
{/* RIGHT */}
|
||||||
|
<ErrorBoundaryDialog context="RightSidePanel">
|
||||||
<SidePanel from="right" isOpen={this.state.isRightSidePanelOpen}>
|
<SidePanel from="right" isOpen={this.state.isRightSidePanelOpen}>
|
||||||
{VisiblePanelRight && (
|
{VisiblePanelRight && (
|
||||||
<VisiblePanelRight
|
<VisiblePanelRight
|
||||||
@ -330,6 +341,7 @@ class Viewer extends Component {
|
|||||||
/>
|
/>
|
||||||
)}
|
)}
|
||||||
</SidePanel>
|
</SidePanel>
|
||||||
|
</ErrorBoundaryDialog>
|
||||||
</div>
|
</div>
|
||||||
</>
|
</>
|
||||||
);
|
);
|
||||||
|
|||||||
@ -1247,7 +1247,7 @@
|
|||||||
pirates "^4.0.0"
|
pirates "^4.0.0"
|
||||||
source-map-support "^0.5.9"
|
source-map-support "^0.5.9"
|
||||||
|
|
||||||
"@babel/runtime@7.1.2", "@babel/runtime@7.5.5", "@babel/runtime@7.6.0", "@babel/runtime@^7.0.0", "@babel/runtime@^7.1.2", "@babel/runtime@^7.2.0", "@babel/runtime@^7.3.1", "@babel/runtime@^7.4.0", "@babel/runtime@^7.4.2", "@babel/runtime@^7.4.4", "@babel/runtime@^7.4.5", "@babel/runtime@^7.5.5", "@babel/runtime@^7.6.0", "@babel/runtime@^7.6.3", "@babel/runtime@^7.7.2", "@babel/runtime@^7.8.4", "@babel/runtime@^7.8.7":
|
"@babel/runtime@7.1.2", "@babel/runtime@7.5.5", "@babel/runtime@7.6.0", "@babel/runtime@^7.0.0", "@babel/runtime@^7.1.2", "@babel/runtime@^7.2.0", "@babel/runtime@^7.3.1", "@babel/runtime@^7.4.0", "@babel/runtime@^7.4.2", "@babel/runtime@^7.4.4", "@babel/runtime@^7.4.5", "@babel/runtime@^7.5.5", "@babel/runtime@^7.6.0", "@babel/runtime@^7.6.3", "@babel/runtime@^7.7.2", "@babel/runtime@^7.8.4", "@babel/runtime@^7.8.7", "@babel/runtime@^7.9.6":
|
||||||
version "7.5.5"
|
version "7.5.5"
|
||||||
resolved "https://registry.yarnpkg.com/@babel/runtime/-/runtime-7.5.5.tgz#74fba56d35efbeca444091c7850ccd494fd2f132"
|
resolved "https://registry.yarnpkg.com/@babel/runtime/-/runtime-7.5.5.tgz#74fba56d35efbeca444091c7850ccd494fd2f132"
|
||||||
integrity sha512-28QvEGyQyNkB0/m2B4FU7IEZGK2NUrcMtT6BZEFALTguLk+AUT6ofsHtPk5QyjAdUkpMJ+/Em+quwz4HOt30AQ==
|
integrity sha512-28QvEGyQyNkB0/m2B4FU7IEZGK2NUrcMtT6BZEFALTguLk+AUT6ofsHtPk5QyjAdUkpMJ+/Em+quwz4HOt30AQ==
|
||||||
@ -15796,6 +15796,13 @@ react-dropzone@^10.1.7:
|
|||||||
file-selector "^0.1.11"
|
file-selector "^0.1.11"
|
||||||
prop-types "^15.7.2"
|
prop-types "^15.7.2"
|
||||||
|
|
||||||
|
react-error-boundary@^2.2.1:
|
||||||
|
version "2.2.1"
|
||||||
|
resolved "https://registry.yarnpkg.com/react-error-boundary/-/react-error-boundary-2.2.1.tgz#32ed74386a90482060cc2fea948bb7135465c4cb"
|
||||||
|
integrity sha512-8SZMkJRFUb0JuluHKwuUtkh5vvVWBg3O/bJIWgNMhMJv529aG//TmcphR3cSMhCWjz1vFZDb4taJd6pmwP5mEQ==
|
||||||
|
dependencies:
|
||||||
|
"@babel/runtime" "^7.9.6"
|
||||||
|
|
||||||
react-error-overlay@^4.0.1:
|
react-error-overlay@^4.0.1:
|
||||||
version "4.0.1"
|
version "4.0.1"
|
||||||
resolved "https://registry.yarnpkg.com/react-error-overlay/-/react-error-overlay-4.0.1.tgz#417addb0814a90f3a7082eacba7cee588d00da89"
|
resolved "https://registry.yarnpkg.com/react-error-overlay/-/react-error-overlay-4.0.1.tgz#417addb0814a90f3a7082eacba7cee588d00da89"
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user