From 9c3417c23ae829babde7285abe65ae0ece5eec00 Mon Sep 17 00:00:00 2001 From: Charles Zhao Date: Fri, 15 Apr 2022 18:51:11 +0800 Subject: [PATCH] feat(console): add react error boundary --- .../src/components/AppContent/index.tsx | 17 +++-- .../ErrorBoundary/index.module.scss | 34 ++++++++++ .../src/components/ErrorBoundary/index.tsx | 65 +++++++++++++++++++ 3 files changed, 109 insertions(+), 7 deletions(-) create mode 100644 packages/console/src/components/ErrorBoundary/index.module.scss create mode 100644 packages/console/src/components/ErrorBoundary/index.tsx diff --git a/packages/console/src/components/AppContent/index.tsx b/packages/console/src/components/AppContent/index.tsx index bef552816..b1edff1ce 100644 --- a/packages/console/src/components/AppContent/index.tsx +++ b/packages/console/src/components/AppContent/index.tsx @@ -2,6 +2,7 @@ import { useLogto } from '@logto/react'; import React, { useEffect } from 'react'; import { Outlet, useHref } from 'react-router-dom'; +import ErrorBoundary from '../ErrorBoundary'; import Sidebar from './components/Sidebar'; import Topbar from './components/Topbar'; import * as styles from './index.module.scss'; @@ -36,15 +37,17 @@ const AppContent = ({ theme }: Props) => { } return ( -
- -
- -
- + +
+ +
+ +
+ +
-
+ ); }; diff --git a/packages/console/src/components/ErrorBoundary/index.module.scss b/packages/console/src/components/ErrorBoundary/index.module.scss new file mode 100644 index 000000000..7d5a99a05 --- /dev/null +++ b/packages/console/src/components/ErrorBoundary/index.module.scss @@ -0,0 +1,34 @@ +@use '@/scss/underscore' as _; + +.container { + overflow-y: auto; + height: 100vh; + + .wrapper { + display: flex; + flex-direction: column; + background-color: var(--color-layer-1); + color: var(--color-text); + padding: _.unit(6); + width: 858px; + min-height: 100%; + margin: 0 auto; + + > *:not(:first-child) { + margin-top: _.unit(6); + } + + img { + height: 300px; + } + + img, + h2 { + margin: 0 auto; + } + + details { + white-space: pre-wrap; + } + } +} diff --git a/packages/console/src/components/ErrorBoundary/index.tsx b/packages/console/src/components/ErrorBoundary/index.tsx new file mode 100644 index 000000000..951e32c89 --- /dev/null +++ b/packages/console/src/components/ErrorBoundary/index.tsx @@ -0,0 +1,65 @@ +import { conditional } from '@silverhand/essentials'; +import React, { Component, ReactNode } from 'react'; +import { Namespace, TFunction, withTranslation } from 'react-i18next'; + +import ErrorImage from '@/assets/images/table-error.svg'; + +import * as styles from './index.module.scss'; + +type Props = { + children: ReactNode; + t: TFunction; +}; + +type State = { + callStack?: string; + componentStack?: string; + errorMessage?: string; + hasError: boolean; +}; + +class ErrorBoundary extends Component { + static getDerivedStateFromError(error: Error) { + const errorMessage = conditional( + typeof error === 'object' && typeof error.message === 'string' && error.message + ); + + const callStack = conditional( + typeof error === 'object' && + typeof error.stack === 'string' && + error.stack.split('\n').slice(1).join('\n') + ); + + return { callStack, errorMessage, hasError: true }; + } + + public state: State = { + callStack: undefined, + errorMessage: undefined, + hasError: false, + }; + + render() { + const { children, t } = this.props; + const { callStack, errorMessage, hasError } = this.state; + + if (hasError) { + return ( +
+
+ oops +

{t('errors.something_went_wrong')}

+
+ {errorMessage} + {callStack} +
+
+
+ ); + } + + return children; + } +} + +export default withTranslation()(ErrorBoundary);