mirror of
https://github.com/jellyfin/jellyfin-web
synced 2025-03-30 19:56:21 +00:00
Add basic 404 page and *.html redirect
This commit is contained in:
parent
ed899a77cf
commit
6f670d5c3e
4 changed files with 75 additions and 2 deletions
|
@ -5,6 +5,7 @@ import ConnectionRequired from 'components/ConnectionRequired';
|
||||||
import { toAsyncPageRoute } from 'components/router/AsyncRoute';
|
import { toAsyncPageRoute } from 'components/router/AsyncRoute';
|
||||||
import { toViewManagerPageRoute } from 'components/router/LegacyRoute';
|
import { toViewManagerPageRoute } from 'components/router/LegacyRoute';
|
||||||
import ErrorBoundary from 'components/router/ErrorBoundary';
|
import ErrorBoundary from 'components/router/ErrorBoundary';
|
||||||
|
import FallbackRoute from 'components/router/FallbackRoute';
|
||||||
|
|
||||||
import { ASYNC_USER_ROUTES } from './asyncRoutes';
|
import { ASYNC_USER_ROUTES } from './asyncRoutes';
|
||||||
import { LEGACY_PUBLIC_ROUTES, LEGACY_USER_ROUTES } from './legacyRoutes';
|
import { LEGACY_PUBLIC_ROUTES, LEGACY_USER_ROUTES } from './legacyRoutes';
|
||||||
|
@ -33,7 +34,13 @@ export const EXPERIMENTAL_APP_ROUTES: RouteObject[] = [
|
||||||
|
|
||||||
/* Public routes */
|
/* Public routes */
|
||||||
{ index: true, element: <Navigate replace to='/home.html' /> },
|
{ index: true, element: <Navigate replace to='/home.html' /> },
|
||||||
...LEGACY_PUBLIC_ROUTES.map(toViewManagerPageRoute)
|
...LEGACY_PUBLIC_ROUTES.map(toViewManagerPageRoute),
|
||||||
|
|
||||||
|
/* Fallback route for invalid paths */
|
||||||
|
{
|
||||||
|
path: '*',
|
||||||
|
Component: FallbackRoute
|
||||||
|
}
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
];
|
];
|
||||||
|
|
|
@ -5,6 +5,7 @@ import ConnectionRequired from 'components/ConnectionRequired';
|
||||||
import { toAsyncPageRoute } from 'components/router/AsyncRoute';
|
import { toAsyncPageRoute } from 'components/router/AsyncRoute';
|
||||||
import { toViewManagerPageRoute } from 'components/router/LegacyRoute';
|
import { toViewManagerPageRoute } from 'components/router/LegacyRoute';
|
||||||
import ErrorBoundary from 'components/router/ErrorBoundary';
|
import ErrorBoundary from 'components/router/ErrorBoundary';
|
||||||
|
import FallbackRoute from 'components/router/FallbackRoute';
|
||||||
|
|
||||||
import AppLayout from '../AppLayout';
|
import AppLayout from '../AppLayout';
|
||||||
|
|
||||||
|
@ -28,7 +29,13 @@ export const STABLE_APP_ROUTES: RouteObject[] = [
|
||||||
|
|
||||||
/* Public routes */
|
/* Public routes */
|
||||||
{ index: true, element: <Navigate replace to='/home.html' /> },
|
{ index: true, element: <Navigate replace to='/home.html' /> },
|
||||||
...LEGACY_PUBLIC_ROUTES.map(toViewManagerPageRoute)
|
...LEGACY_PUBLIC_ROUTES.map(toViewManagerPageRoute),
|
||||||
|
|
||||||
|
/* Fallback route for invalid paths */
|
||||||
|
{
|
||||||
|
path: '*',
|
||||||
|
Component: FallbackRoute
|
||||||
|
}
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
];
|
];
|
||||||
|
|
57
src/components/router/FallbackRoute.tsx
Normal file
57
src/components/router/FallbackRoute.tsx
Normal file
|
@ -0,0 +1,57 @@
|
||||||
|
import React, { useEffect, useMemo } from 'react';
|
||||||
|
import { Navigate, useLocation } from 'react-router-dom';
|
||||||
|
|
||||||
|
import loading from 'components/loading/loading';
|
||||||
|
import Page from 'components/Page';
|
||||||
|
import globalize from 'lib/globalize';
|
||||||
|
import LinkButton from 'elements/emby-button/LinkButton';
|
||||||
|
|
||||||
|
const FallbackRoute = () => {
|
||||||
|
const location = useLocation();
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
loading.hide();
|
||||||
|
}, []);
|
||||||
|
|
||||||
|
// Check if the requested path should be redirected
|
||||||
|
const to = useMemo(() => {
|
||||||
|
const _to = {
|
||||||
|
search: location.search,
|
||||||
|
hash: location.hash
|
||||||
|
};
|
||||||
|
|
||||||
|
// If a path ends in ".html", redirect to the path with it removed
|
||||||
|
if (location.pathname.endsWith('.html')) {
|
||||||
|
return { ..._to, pathname: location.pathname.slice(0, -5) };
|
||||||
|
}
|
||||||
|
}, [ location ]);
|
||||||
|
|
||||||
|
if (to) {
|
||||||
|
console.warn('[FallbackRoute] You are using a deprecated URL format. This will stop working in a future Jellyfin update.');
|
||||||
|
|
||||||
|
return (
|
||||||
|
<Navigate
|
||||||
|
replace
|
||||||
|
to={to}
|
||||||
|
/>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
return (
|
||||||
|
<Page
|
||||||
|
id='fallbackPage'
|
||||||
|
className='mainAnimatedPage libraryPage'
|
||||||
|
>
|
||||||
|
<h1>{globalize.translate('HeaderPageNotFound')}</h1>
|
||||||
|
<p>{globalize.translate('PageNotFound')}</p>
|
||||||
|
<LinkButton
|
||||||
|
className='button-link'
|
||||||
|
href='#/home.html'
|
||||||
|
>
|
||||||
|
{globalize.translate('GoHome')}
|
||||||
|
</LinkButton>
|
||||||
|
</Page>
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
export default FallbackRoute;
|
|
@ -473,6 +473,7 @@
|
||||||
"HeaderNoLyrics": "No lyrics found",
|
"HeaderNoLyrics": "No lyrics found",
|
||||||
"HeaderOnNow": "On Now",
|
"HeaderOnNow": "On Now",
|
||||||
"HeaderOtherItems": "Other Items",
|
"HeaderOtherItems": "Other Items",
|
||||||
|
"HeaderPageNotFound": "Page not found",
|
||||||
"HeaderParentalRatings": "Parental Ratings",
|
"HeaderParentalRatings": "Parental Ratings",
|
||||||
"HeaderPassword": "Password",
|
"HeaderPassword": "Password",
|
||||||
"HeaderPasswordReset": "Password Reset",
|
"HeaderPasswordReset": "Password Reset",
|
||||||
|
@ -1315,6 +1316,7 @@
|
||||||
"PackageInstallCancelled": "{0} (version {1}) installation cancelled.",
|
"PackageInstallCancelled": "{0} (version {1}) installation cancelled.",
|
||||||
"PackageInstallCompleted": "{0} (version {1}) installation completed.",
|
"PackageInstallCompleted": "{0} (version {1}) installation completed.",
|
||||||
"PackageInstallFailed": "{0} (version {1}) installation failed.",
|
"PackageInstallFailed": "{0} (version {1}) installation failed.",
|
||||||
|
"PageNotFound": "This is not the page you are looking for.",
|
||||||
"ParentalRating": "Parental rating",
|
"ParentalRating": "Parental rating",
|
||||||
"PasswordMatchError": "Password and password confirmation must match.",
|
"PasswordMatchError": "Password and password confirmation must match.",
|
||||||
"PasswordRequiredForAdmin": "A password is required for admin accounts.",
|
"PasswordRequiredForAdmin": "A password is required for admin accounts.",
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue