mirror of
https://github.com/jellyfin/jellyfin-web
synced 2025-03-30 19:56:21 +00:00
Add error boundary for page crashes
This commit is contained in:
parent
9186c0af41
commit
0d9a8680fb
5 changed files with 85 additions and 3 deletions
|
@ -7,6 +7,7 @@ import { toAsyncPageRoute } from 'components/router/AsyncRoute';
|
|||
import { toViewManagerPageRoute } from 'components/router/LegacyRoute';
|
||||
import { LEGACY_ADMIN_ROUTES } from './_legacyRoutes';
|
||||
import ServerContentPage from 'components/ServerContentPage';
|
||||
import ErrorBoundary from '../../../components/router/ErrorBoundary';
|
||||
|
||||
export const DASHBOARD_APP_PATHS = {
|
||||
Dashboard: 'dashboard',
|
||||
|
@ -26,7 +27,8 @@ export const DASHBOARD_APP_ROUTES: RouteObject[] = [
|
|||
children: [
|
||||
...ASYNC_ADMIN_ROUTES.map(toAsyncPageRoute),
|
||||
...LEGACY_ADMIN_ROUTES.map(toViewManagerPageRoute)
|
||||
]
|
||||
],
|
||||
errorElement: <ErrorBoundary pageClasses={[ 'type-interior' ]} />
|
||||
},
|
||||
|
||||
/* NOTE: The metadata editor might deserve a dedicated app in the future */
|
||||
|
|
|
@ -6,6 +6,8 @@ import ConnectionRequired from 'components/ConnectionRequired';
|
|||
import { toAsyncPageRoute } from 'components/router/AsyncRoute';
|
||||
import { toViewManagerPageRoute } from 'components/router/LegacyRoute';
|
||||
import { toRedirectRoute } from 'components/router/Redirect';
|
||||
import ErrorBoundary from 'components/router/ErrorBoundary';
|
||||
|
||||
import AppLayout from '../AppLayout';
|
||||
|
||||
import { ASYNC_USER_ROUTES } from './asyncRoutes';
|
||||
|
@ -29,7 +31,8 @@ export const EXPERIMENTAL_APP_ROUTES: RouteObject[] = [
|
|||
path: 'video',
|
||||
element: <VideoPage />
|
||||
}
|
||||
]
|
||||
],
|
||||
ErrorBoundary
|
||||
},
|
||||
|
||||
/* Public routes */
|
||||
|
|
|
@ -5,6 +5,7 @@ import ConnectionRequired from 'components/ConnectionRequired';
|
|||
import { toAsyncPageRoute } from 'components/router/AsyncRoute';
|
||||
import { toViewManagerPageRoute } from 'components/router/LegacyRoute';
|
||||
import { toRedirectRoute } from 'components/router/Redirect';
|
||||
import ErrorBoundary from 'components/router/ErrorBoundary';
|
||||
|
||||
import AppLayout from '../AppLayout';
|
||||
|
||||
|
@ -23,7 +24,8 @@ export const STABLE_APP_ROUTES: RouteObject[] = [
|
|||
children: [
|
||||
...ASYNC_USER_ROUTES.map(toAsyncPageRoute),
|
||||
...LEGACY_USER_ROUTES.map(toViewManagerPageRoute)
|
||||
]
|
||||
],
|
||||
ErrorBoundary
|
||||
},
|
||||
|
||||
/* Public routes */
|
||||
|
|
67
src/components/router/ErrorBoundary.tsx
Normal file
67
src/components/router/ErrorBoundary.tsx
Normal file
|
@ -0,0 +1,67 @@
|
|||
import Alert from '@mui/material/Alert/Alert';
|
||||
import AlertTitle from '@mui/material/AlertTitle/AlertTitle';
|
||||
import Box from '@mui/material/Box/Box';
|
||||
import Paper from '@mui/material/Paper/Paper';
|
||||
import Typography from '@mui/material/Typography/Typography';
|
||||
import classNames from 'classnames';
|
||||
import React, { type FC, useEffect } from 'react';
|
||||
import { useRouteError } from 'react-router-dom';
|
||||
|
||||
import loading from 'components/loading/loading';
|
||||
import Page from 'components/Page';
|
||||
|
||||
interface ErrorBoundaryParams {
|
||||
pageClasses?: string[]
|
||||
}
|
||||
|
||||
const ErrorBoundary: FC<ErrorBoundaryParams> = ({
|
||||
pageClasses = [ 'libraryPage' ]
|
||||
}) => {
|
||||
const error = useRouteError() as Error;
|
||||
|
||||
useEffect(() => {
|
||||
loading.hide();
|
||||
}, []);
|
||||
|
||||
return (
|
||||
<Page
|
||||
id='errorBoundary'
|
||||
className={classNames('mainAnimatedPage', pageClasses)}
|
||||
>
|
||||
<Box className='content-primary'>
|
||||
<Alert severity='error'>
|
||||
<AlertTitle>
|
||||
{error.name}
|
||||
</AlertTitle>
|
||||
|
||||
<Typography>
|
||||
{error.message}
|
||||
</Typography>
|
||||
|
||||
{error.stack && (
|
||||
<Paper
|
||||
variant='outlined'
|
||||
sx={{
|
||||
marginTop: 1,
|
||||
backgroundColor: 'transparent'
|
||||
}}
|
||||
>
|
||||
<Box
|
||||
component='pre'
|
||||
sx={{
|
||||
overflow: 'auto',
|
||||
margin: 2,
|
||||
maxHeight: '25rem' // 20 lines
|
||||
}}
|
||||
>
|
||||
{error.stack}
|
||||
</Box>
|
||||
</Paper>
|
||||
)}
|
||||
</Alert>
|
||||
</Box>
|
||||
</Page>
|
||||
);
|
||||
};
|
||||
|
||||
export default ErrorBoundary;
|
|
@ -41,6 +41,14 @@ export const DEFAULT_THEME_OPTIONS: ThemeOptions = {
|
|||
}
|
||||
},
|
||||
components: {
|
||||
MuiAlert: {
|
||||
styleOverrides: {
|
||||
message: {
|
||||
// NOTE: This seems like a bug. Block content does not fill the container width.
|
||||
flexGrow: 1
|
||||
}
|
||||
}
|
||||
},
|
||||
MuiButton: {
|
||||
defaultProps: {
|
||||
variant: 'contained'
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue