mirror of
https://github.com/jellyfin/jellyfin-web
synced 2025-03-30 19:56:21 +00:00
Merge pull request #6601 from thornbill/catch-all-route
This commit is contained in:
commit
411601ff68
5 changed files with 98 additions and 10 deletions
|
@ -17,6 +17,10 @@ $drawer-width: 240px;
|
|||
left: $drawer-width;
|
||||
}
|
||||
}
|
||||
// The fallback page has no drawer
|
||||
#fallbackPage {
|
||||
left: 0;
|
||||
}
|
||||
|
||||
// Hide some items from the user "settings" page that are in the drawer
|
||||
#myPreferencesMenuPage {
|
||||
|
|
|
@ -5,6 +5,7 @@ import ConnectionRequired from 'components/ConnectionRequired';
|
|||
import { toAsyncPageRoute } from 'components/router/AsyncRoute';
|
||||
import { toViewManagerPageRoute } from 'components/router/LegacyRoute';
|
||||
import ErrorBoundary from 'components/router/ErrorBoundary';
|
||||
import FallbackRoute from 'components/router/FallbackRoute';
|
||||
|
||||
import { ASYNC_USER_ROUTES } from './asyncRoutes';
|
||||
import { LEGACY_PUBLIC_ROUTES, LEGACY_USER_ROUTES } from './legacyRoutes';
|
||||
|
@ -15,9 +16,11 @@ export const EXPERIMENTAL_APP_ROUTES: RouteObject[] = [
|
|||
path: '/*',
|
||||
lazy: () => import('../AppLayout'),
|
||||
children: [
|
||||
{ index: true, element: <Navigate replace to='/home.html' /> },
|
||||
|
||||
{
|
||||
/* User routes: Any child route of this layout is authenticated */
|
||||
element: <ConnectionRequired isUserRequired />,
|
||||
/* User routes */
|
||||
Component: ConnectionRequired,
|
||||
children: [
|
||||
...ASYNC_USER_ROUTES.map(toAsyncPageRoute),
|
||||
...LEGACY_USER_ROUTES.map(toViewManagerPageRoute),
|
||||
|
@ -25,15 +28,26 @@ export const EXPERIMENTAL_APP_ROUTES: RouteObject[] = [
|
|||
// The video page is special since it combines new controls with the legacy view
|
||||
{
|
||||
path: 'video',
|
||||
element: <VideoPage />
|
||||
Component: VideoPage
|
||||
}
|
||||
],
|
||||
ErrorBoundary
|
||||
},
|
||||
|
||||
/* Public routes */
|
||||
{ index: true, element: <Navigate replace to='/home.html' /> },
|
||||
...LEGACY_PUBLIC_ROUTES.map(toViewManagerPageRoute)
|
||||
{
|
||||
/* Public routes */
|
||||
element: <ConnectionRequired isUserRequired={false} />,
|
||||
children: [
|
||||
...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 { toViewManagerPageRoute } from 'components/router/LegacyRoute';
|
||||
import ErrorBoundary from 'components/router/ErrorBoundary';
|
||||
import FallbackRoute from 'components/router/FallbackRoute';
|
||||
|
||||
import AppLayout from '../AppLayout';
|
||||
|
||||
|
@ -16,9 +17,11 @@ export const STABLE_APP_ROUTES: RouteObject[] = [
|
|||
path: '/*',
|
||||
Component: AppLayout,
|
||||
children: [
|
||||
{ index: true, element: <Navigate replace to='/home.html' /> },
|
||||
|
||||
{
|
||||
/* User routes */
|
||||
element: <ConnectionRequired isUserRequired />,
|
||||
Component: ConnectionRequired,
|
||||
children: [
|
||||
...ASYNC_USER_ROUTES.map(toAsyncPageRoute),
|
||||
...LEGACY_USER_ROUTES.map(toViewManagerPageRoute)
|
||||
|
@ -26,9 +29,19 @@ export const STABLE_APP_ROUTES: RouteObject[] = [
|
|||
ErrorBoundary
|
||||
},
|
||||
|
||||
/* Public routes */
|
||||
{ index: true, element: <Navigate replace to='/home.html' /> },
|
||||
...LEGACY_PUBLIC_ROUTES.map(toViewManagerPageRoute)
|
||||
{
|
||||
/* Public routes */
|
||||
element: <ConnectionRequired isUserRequired={false} />,
|
||||
children: [
|
||||
...LEGACY_PUBLIC_ROUTES.map(toViewManagerPageRoute),
|
||||
/* Fallback route for invalid paths */
|
||||
{
|
||||
path: '*',
|
||||
Component: FallbackRoute
|
||||
}
|
||||
]
|
||||
}
|
||||
|
||||
]
|
||||
}
|
||||
];
|
||||
|
|
55
src/components/router/FallbackRoute.tsx
Normal file
55
src/components/router/FallbackRoute.tsx
Normal file
|
@ -0,0 +1,55 @@
|
|||
import React, { useMemo } from 'react';
|
||||
import { Navigate, useLocation } from 'react-router-dom';
|
||||
|
||||
import Page from 'components/Page';
|
||||
import globalize from 'lib/globalize';
|
||||
import LinkButton from 'elements/emby-button/LinkButton';
|
||||
|
||||
const FallbackRoute = () => {
|
||||
const location = useLocation();
|
||||
|
||||
// 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'
|
||||
title={globalize.translate('HeaderPageNotFound')}
|
||||
className='mainAnimatedPage libraryPage'
|
||||
>
|
||||
<div className='padded-left padded-right'>
|
||||
<h1>{globalize.translate('HeaderPageNotFound')}</h1>
|
||||
<p>{globalize.translate('PageNotFound')}</p>
|
||||
<LinkButton
|
||||
className='button-link'
|
||||
href='#/home.html'
|
||||
>
|
||||
{globalize.translate('GoHome')}
|
||||
</LinkButton>
|
||||
</div>
|
||||
</Page>
|
||||
);
|
||||
};
|
||||
|
||||
export default FallbackRoute;
|
|
@ -473,6 +473,7 @@
|
|||
"HeaderNoLyrics": "No lyrics found",
|
||||
"HeaderOnNow": "On Now",
|
||||
"HeaderOtherItems": "Other Items",
|
||||
"HeaderPageNotFound": "Page not found",
|
||||
"HeaderParentalRatings": "Parental Ratings",
|
||||
"HeaderPassword": "Password",
|
||||
"HeaderPasswordReset": "Password Reset",
|
||||
|
@ -1315,6 +1316,7 @@
|
|||
"PackageInstallCancelled": "{0} (version {1}) installation cancelled.",
|
||||
"PackageInstallCompleted": "{0} (version {1}) installation completed.",
|
||||
"PackageInstallFailed": "{0} (version {1}) installation failed.",
|
||||
"PageNotFound": "This is not the page you are looking for.",
|
||||
"ParentalRating": "Parental rating",
|
||||
"PasswordMatchError": "Password and password confirmation must match.",
|
||||
"PasswordRequiredForAdmin": "A password is required for admin accounts.",
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue