mirror of
https://github.com/logto-io/logto.git
synced 2024-12-16 20:26:19 -05:00
refactor(console): handling cloud errors
This commit is contained in:
parent
07e04eac55
commit
2a7c623240
6 changed files with 41 additions and 20 deletions
|
@ -17,6 +17,7 @@ import initI18n from '@/i18n/init';
|
|||
|
||||
import { adminTenantEndpoint } from './consts';
|
||||
import { isCloud } from './consts/cloud';
|
||||
import ErrorBoundary from './containers/ErrorBoundary';
|
||||
import AppConfirmModalProvider from './contexts/AppConfirmModalProvider';
|
||||
import AppEndpointsProvider from './contexts/AppEndpointsProvider';
|
||||
import TenantsProvider, { TenantsContext } from './contexts/TenantsProvider';
|
||||
|
@ -68,9 +69,11 @@ const Content = () => {
|
|||
|
||||
const App = () => {
|
||||
return (
|
||||
<TenantsProvider>
|
||||
<Content />
|
||||
</TenantsProvider>
|
||||
<ErrorBoundary>
|
||||
<TenantsProvider>
|
||||
<Content />
|
||||
</TenantsProvider>
|
||||
</ErrorBoundary>
|
||||
);
|
||||
};
|
||||
export default App;
|
||||
|
|
|
@ -6,8 +6,8 @@ import ErrorDark from '@/assets/images/error-dark.svg';
|
|||
import Error from '@/assets/images/error.svg';
|
||||
import KeyboardArrowDown from '@/assets/images/keyboard-arrow-down.svg';
|
||||
import KeyboardArrowUp from '@/assets/images/keyboard-arrow-up.svg';
|
||||
import { useTheme } from '@/hooks/use-theme';
|
||||
import { onKeyDownHandler } from '@/utils/a11y';
|
||||
import { getThemeFromLocalStorage } from '@/utils/theme';
|
||||
|
||||
import * as styles from './index.module.scss';
|
||||
|
||||
|
@ -22,7 +22,7 @@ type Props = {
|
|||
const AppError = ({ title, errorCode, errorMessage, callStack, children }: Props) => {
|
||||
const { t } = useTranslation(undefined, { keyPrefix: 'admin_console' });
|
||||
const [isDetailsOpen, setIsDetailsOpen] = useState(false);
|
||||
const theme = useTheme();
|
||||
const theme = getThemeFromLocalStorage(); // Should be able to use the component in an offline environment
|
||||
|
||||
return (
|
||||
<div className={styles.container}>
|
||||
|
|
|
@ -1,12 +1,7 @@
|
|||
import { AppearanceMode } from '@logto/schemas';
|
||||
import { trySafe } from '@silverhand/essentials';
|
||||
import { z } from 'zod';
|
||||
|
||||
import IllustrationDark from '@/assets/images/loading-illustration-dark.svg';
|
||||
import Illustration from '@/assets/images/loading-illustration.svg';
|
||||
import { Daisy as Spinner } from '@/components/Spinner';
|
||||
import { themeStorageKey } from '@/consts';
|
||||
import { getTheme } from '@/utils/theme';
|
||||
import { getThemeFromLocalStorage } from '@/utils/theme';
|
||||
|
||||
import * as styles from './index.module.scss';
|
||||
|
||||
|
@ -14,10 +9,7 @@ import * as styles from './index.module.scss';
|
|||
* An fullscreen loading component fetches local stored theme without sending request.
|
||||
*/
|
||||
export const AppLoadingOffline = () => {
|
||||
const theme = getTheme(
|
||||
trySafe(() => z.nativeEnum(AppearanceMode).parse(localStorage.getItem(themeStorageKey))) ??
|
||||
AppearanceMode.SyncWithSystem
|
||||
);
|
||||
const theme = getThemeFromLocalStorage();
|
||||
|
||||
return (
|
||||
<div className={styles.container}>
|
||||
|
|
|
@ -16,10 +16,8 @@ type State = {
|
|||
};
|
||||
|
||||
class ErrorBoundary extends Component<Props, State> {
|
||||
static getDerivedStateFromError(error: Error) {
|
||||
const errorMessage = conditional(
|
||||
typeof error === 'object' && typeof error.message === 'string' && error.message
|
||||
);
|
||||
static getDerivedStateFromError(error: Error): State {
|
||||
const errorMessage = String(error);
|
||||
|
||||
const callStack = conditional(
|
||||
typeof error === 'object' &&
|
||||
|
@ -36,6 +34,24 @@ class ErrorBoundary extends Component<Props, State> {
|
|||
hasError: false,
|
||||
};
|
||||
|
||||
promiseRejectionHandler(error: unknown) {
|
||||
this.setState(
|
||||
ErrorBoundary.getDerivedStateFromError(
|
||||
error instanceof Error ? error : new Error(String(error))
|
||||
)
|
||||
);
|
||||
}
|
||||
|
||||
componentDidMount(): void {
|
||||
window.addEventListener('unhandledrejection', (event) => {
|
||||
this.promiseRejectionHandler(event.reason);
|
||||
});
|
||||
}
|
||||
|
||||
componentWillUnmount(): void {
|
||||
window.removeEventListener('unhandledrejection', this.promiseRejectionHandler);
|
||||
}
|
||||
|
||||
render() {
|
||||
const { children } = this.props;
|
||||
const { callStack, errorMessage, hasError } = this.state;
|
||||
|
|
|
@ -4,7 +4,7 @@ import useApi, { RequestError } from './use-api';
|
|||
import useSwrFetcher from './use-swr-fetcher';
|
||||
|
||||
const useSwrOptions = (): SWRConfiguration => {
|
||||
const api = useApi({ hideErrorToast: true });
|
||||
const api = useApi();
|
||||
const fetcher = useSwrFetcher(api);
|
||||
|
||||
return {
|
||||
|
|
|
@ -1,4 +1,8 @@
|
|||
import { AppearanceMode } from '@logto/schemas';
|
||||
import { trySafe } from '@silverhand/essentials';
|
||||
import { z } from 'zod';
|
||||
|
||||
import { themeStorageKey } from '@/consts';
|
||||
|
||||
export const getTheme = (appearanceMode: AppearanceMode) => {
|
||||
if (appearanceMode !== AppearanceMode.SyncWithSystem) {
|
||||
|
@ -10,3 +14,9 @@ export const getTheme = (appearanceMode: AppearanceMode) => {
|
|||
|
||||
return theme;
|
||||
};
|
||||
|
||||
export const getThemeFromLocalStorage = () =>
|
||||
getTheme(
|
||||
trySafe(() => z.nativeEnum(AppearanceMode).parse(localStorage.getItem(themeStorageKey))) ??
|
||||
AppearanceMode.SyncWithSystem
|
||||
);
|
||||
|
|
Loading…
Reference in a new issue