diff --git a/platform/ui/index.js b/platform/ui/index.js index 2025cfb3b..66f9fad21 100644 --- a/platform/ui/index.js +++ b/platform/ui/index.js @@ -32,6 +32,7 @@ export { DateRange, Dialog, EmptyStudies, + ErrorBoundary, ExpandableToolbarButton, ListMenu, Icon, diff --git a/platform/ui/package.json b/platform/ui/package.json index 17619f2cf..601b7862d 100644 --- a/platform/ui/package.json +++ b/platform/ui/package.json @@ -42,6 +42,7 @@ "react-dnd": "^10.0.2", "react-dnd-html5-backend": "^10.0.2", "react-dnd-touch-backend": "^10.0.2", + "react-error-boundary": "2.2.x", "react-dom": "16.11.0", "react-modal": "^3.11.2", "react-powerplug": "1.0.0", diff --git a/platform/ui/src/components/ErrorBoundary/ErrorBoundary.jsx b/platform/ui/src/components/ErrorBoundary/ErrorBoundary.jsx new file mode 100644 index 000000000..b75b35710 --- /dev/null +++ b/platform/ui/src/components/ErrorBoundary/ErrorBoundary.jsx @@ -0,0 +1,51 @@ +import React from 'react'; +import { ErrorBoundary as ReactErrorBoundary } from 'react-error-boundary'; +import './ErrorFallback.css'; + +const isProduction = process.env.NODE_ENV === 'production'; + +const ErrorFallback = ({ error, componentStack, resetErrorBoundary }) => { + return ( +
+

Something went wrong.

+ {isProduction && ( + Sorry, something went wrong there. Try again. + )} + {!isProduction &&
{error.message}
} + {!isProduction &&
{componentStack}
} +
+ ); +}; + +ErrorFallback.propTypes = { + resetErrorBoundary: PropTypes +}; + +const ErrorBoundary = ({ + context = 'RCT', + onReset = () => { }, + onError = () => { }, + fallbackComponent, + children +}) => { + const onErrorHandler = (error, componentStack) => { + console.error(`${context} Error Boundary`, error, componentStack); + onError(error, componentStack); + }; + + const onResetHandler = () => { + onReset(); + }; + + return ( + + {children} + + ); +}; + +export default ErrorBoundary; diff --git a/platform/ui/src/components/ErrorBoundary/ErrorBoundary.mdx b/platform/ui/src/components/ErrorBoundary/ErrorBoundary.mdx new file mode 100644 index 000000000..bb65df025 --- /dev/null +++ b/platform/ui/src/components/ErrorBoundary/ErrorBoundary.mdx @@ -0,0 +1,59 @@ +--- +name: Error Boundary +menu: Data Display +route: components/errorBoundary +--- + +import { Playground, Props } from 'docz'; +import { ErrorBoundary } from '@ohif/ui'; + +# Error Boundary + +This component can be used to display a message or handle unhandled errors. + +## Import + +```javascript +import { ErrorBoundary } from '@ohif/ui'; +``` + +## Basic usage + + +
+ + {() => { + throw new Error('Error!'); + return

; + }} +
+
+
+ +## Custom error fallback + + + {() => { + const CustomFallback = ({ error, componentStack, resetErrorBoundary }) => { + return ( +
+

This is a custom fallback!

+
+ ); + }; + return ( +
+ + {() => { + throw new Error('Error!'); + return

; + }} +
+
+ ); + }} +
+ +## Properties + + diff --git a/platform/ui/src/components/ErrorBoundary/ErrorFallback.css b/platform/ui/src/components/ErrorBoundary/ErrorFallback.css new file mode 100644 index 000000000..34d62ccf4 --- /dev/null +++ b/platform/ui/src/components/ErrorBoundary/ErrorFallback.css @@ -0,0 +1,21 @@ +.ErrorFallback { + padding: 10px; + + &, + pre { + color: #7cc5e9; + } + + p { + font-weight: bold; + } + + span { + color: gray; + } + + pre { + background-color: black; + border: none; + } +} diff --git a/platform/ui/src/components/ErrorBoundary/index.js b/platform/ui/src/components/ErrorBoundary/index.js new file mode 100644 index 000000000..b54419282 --- /dev/null +++ b/platform/ui/src/components/ErrorBoundary/index.js @@ -0,0 +1,2 @@ +import ErrorBoundary from './ErrorBoundary'; +export default ErrorBoundary; diff --git a/platform/ui/src/components/index.js b/platform/ui/src/components/index.js index 04b5270cc..76d4f2729 100644 --- a/platform/ui/src/components/index.js +++ b/platform/ui/src/components/index.js @@ -3,6 +3,7 @@ import ButtonGroup from './ButtonGroup'; import DateRange from './DateRange'; import Dialog from './Dialog'; import EmptyStudies from './EmptyStudies'; +import ErrorBoundary from './ErrorBoundary'; import Icon from './Icon'; import IconButton from './IconButton'; import Input from './Input'; @@ -54,6 +55,7 @@ export { DateRange, Dialog, EmptyStudies, + ErrorBoundary, ExpandableToolbarButton, ListMenu, Icon, diff --git a/yarn.lock b/yarn.lock index a045e8f39..6b7ba067c 100644 --- a/yarn.lock +++ b/yarn.lock @@ -18075,6 +18075,13 @@ react-dropzone@^10.1.7: file-selector "^0.1.12" prop-types "^15.7.2" +react-error-boundary@2.2.x: + version "2.2.3" + resolved "https://registry.yarnpkg.com/react-error-boundary/-/react-error-boundary-2.2.3.tgz#34c8238012d3b4148cec47a1b3cec669d5206578" + integrity sha512-Jiaiu6CJ4ho3sMCVI7gg+O/JB5vlFFZGwlnpFBTCOSyheYRTzz+FhBMo7tfnCTB/ZR0LaMzAPGbZGrEzAOd0eg== + dependencies: + "@babel/runtime" "^7.9.6" + react-error-overlay@^3.0.0: version "3.0.0" resolved "https://registry.yarnpkg.com/react-error-overlay/-/react-error-overlay-3.0.0.tgz#c2bc8f4d91f1375b3dad6d75265d51cd5eeaf655"