diff --git a/src/apps/dashboard/routes/routes.tsx b/src/apps/dashboard/routes/routes.tsx
index 7bbeb3fc4e..16385ddf3e 100644
--- a/src/apps/dashboard/routes/routes.tsx
+++ b/src/apps/dashboard/routes/routes.tsx
@@ -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:
},
/* NOTE: The metadata editor might deserve a dedicated app in the future */
diff --git a/src/apps/experimental/routes/routes.tsx b/src/apps/experimental/routes/routes.tsx
index 47e0a9f7f5..c9e32899dc 100644
--- a/src/apps/experimental/routes/routes.tsx
+++ b/src/apps/experimental/routes/routes.tsx
@@ -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:
}
- ]
+ ],
+ ErrorBoundary
},
/* Public routes */
diff --git a/src/apps/stable/routes/routes.tsx b/src/apps/stable/routes/routes.tsx
index 300092c9fe..e5f800d20b 100644
--- a/src/apps/stable/routes/routes.tsx
+++ b/src/apps/stable/routes/routes.tsx
@@ -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 */
diff --git a/src/components/router/ErrorBoundary.tsx b/src/components/router/ErrorBoundary.tsx
new file mode 100644
index 0000000000..e195d2d989
--- /dev/null
+++ b/src/components/router/ErrorBoundary.tsx
@@ -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 = ({
+ pageClasses = [ 'libraryPage' ]
+}) => {
+ const error = useRouteError() as Error;
+
+ useEffect(() => {
+ loading.hide();
+ }, []);
+
+ return (
+
+
+
+
+ {error.name}
+
+
+
+ {error.message}
+
+
+ {error.stack && (
+
+
+ {error.stack}
+
+
+ )}
+
+
+
+ );
+};
+
+export default ErrorBoundary;
diff --git a/src/themes/defaults.ts b/src/themes/defaults.ts
index 31f85d79c3..7f92f0c4b2 100644
--- a/src/themes/defaults.ts
+++ b/src/themes/defaults.ts
@@ -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'