mirror of
https://github.com/jellyfin/jellyfin-web
synced 2025-03-30 19:56:21 +00:00
feat: migrate dashboard app to use react data router
This commit is contained in:
parent
ff885b9b21
commit
cd11e6e36f
9 changed files with 107 additions and 100 deletions
|
@ -5,15 +5,13 @@ import { QueryClient, QueryClientProvider } from '@tanstack/react-query';
|
||||||
import { ReactQueryDevtools } from '@tanstack/react-query-devtools';
|
import { ReactQueryDevtools } from '@tanstack/react-query-devtools';
|
||||||
import React from 'react';
|
import React from 'react';
|
||||||
|
|
||||||
import { DASHBOARD_APP_PATHS } from 'apps/dashboard/App';
|
import { DASHBOARD_APP_PATHS } from 'apps/dashboard/routes/routes';
|
||||||
import AppHeader from 'components/AppHeader';
|
import AppHeader from 'components/AppHeader';
|
||||||
import Backdrop from 'components/Backdrop';
|
import Backdrop from 'components/Backdrop';
|
||||||
import { ApiProvider } from 'hooks/useApi';
|
import { ApiProvider } from 'hooks/useApi';
|
||||||
import { WebConfigProvider } from 'hooks/useWebConfig';
|
import { WebConfigProvider } from 'hooks/useWebConfig';
|
||||||
import theme from 'themes/theme';
|
import theme from 'themes/theme';
|
||||||
import { HistoryRouter } from 'components/router/HistoryRouter';
|
|
||||||
|
|
||||||
const DashboardApp = loadable(() => import('./apps/dashboard/App'));
|
|
||||||
const StableAppRouter = loadable(() => import('./apps/stable/AppRouter'));
|
const StableAppRouter = loadable(() => import('./apps/stable/AppRouter'));
|
||||||
const RootAppRouter = loadable(() => import('./RootAppRouter'));
|
const RootAppRouter = loadable(() => import('./RootAppRouter'));
|
||||||
|
|
||||||
|
@ -35,10 +33,6 @@ const RootAppLayout = ({ history }: { history: History }) => {
|
||||||
<RootAppRouter history={history} /> :
|
<RootAppRouter history={history} /> :
|
||||||
<StableAppRouter history={history} />
|
<StableAppRouter history={history} />
|
||||||
}
|
}
|
||||||
|
|
||||||
<HistoryRouter history={history}>
|
|
||||||
<DashboardApp />
|
|
||||||
</HistoryRouter>
|
|
||||||
</>
|
</>
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|
|
@ -1,13 +1,18 @@
|
||||||
|
|
||||||
import { History } from '@remix-run/router';
|
import { History } from '@remix-run/router';
|
||||||
import React from 'react';
|
import React from 'react';
|
||||||
import { RouterProvider, createHashRouter } from 'react-router-dom';
|
import {
|
||||||
|
RouterProvider,
|
||||||
|
createHashRouter
|
||||||
|
} from 'react-router-dom';
|
||||||
|
|
||||||
import { EXPERIMENTAL_APP_ROUTES } from 'apps/experimental/routes/routes';
|
import { EXPERIMENTAL_APP_ROUTES } from 'apps/experimental/routes/routes';
|
||||||
import { useLegacyRouterSync } from 'hooks/useLegacyRouterSync';
|
import { useLegacyRouterSync } from 'hooks/useLegacyRouterSync';
|
||||||
|
import { DASHBOARD_APP_ROUTES } from 'apps/dashboard/routes/routes';
|
||||||
|
|
||||||
const router = createHashRouter([
|
const router = createHashRouter([
|
||||||
...EXPERIMENTAL_APP_ROUTES
|
...EXPERIMENTAL_APP_ROUTES,
|
||||||
|
...DASHBOARD_APP_ROUTES
|
||||||
]);
|
]);
|
||||||
|
|
||||||
export default function RootAppRouter({ history }: { history: History}) {
|
export default function RootAppRouter({ history }: { history: History}) {
|
||||||
|
|
|
@ -1,66 +0,0 @@
|
||||||
import loadable from '@loadable/component';
|
|
||||||
import React from 'react';
|
|
||||||
import { Route, Routes } from 'react-router-dom';
|
|
||||||
|
|
||||||
import ConnectionRequired from 'components/ConnectionRequired';
|
|
||||||
import { toViewManagerPageRoute } from 'components/router/LegacyRoute';
|
|
||||||
import { AsyncPageProps, AsyncRoute, toAsyncPageRoute } from 'components/router/AsyncRoute';
|
|
||||||
import { toRedirectRoute } from 'components/router/Redirect';
|
|
||||||
import ServerContentPage from 'components/ServerContentPage';
|
|
||||||
|
|
||||||
import AppLayout from './AppLayout';
|
|
||||||
import { REDIRECTS } from './routes/_redirects';
|
|
||||||
import { ASYNC_ADMIN_ROUTES } from './routes/_asyncRoutes';
|
|
||||||
import { LEGACY_ADMIN_ROUTES } from './routes/_legacyRoutes';
|
|
||||||
|
|
||||||
const DashboardAsyncPage = loadable(
|
|
||||||
(props: { page: string }) => import(/* webpackChunkName: "[request]" */ `./routes/${props.page}`),
|
|
||||||
{ cacheKey: (props: AsyncPageProps) => props.page }
|
|
||||||
);
|
|
||||||
|
|
||||||
const toDashboardAsyncPageRoute = (route: AsyncRoute) => (
|
|
||||||
toAsyncPageRoute({
|
|
||||||
...route,
|
|
||||||
element: DashboardAsyncPage
|
|
||||||
})
|
|
||||||
);
|
|
||||||
|
|
||||||
export const DASHBOARD_APP_PATHS = {
|
|
||||||
Dashboard: 'dashboard',
|
|
||||||
MetadataManager: 'metadata',
|
|
||||||
PluginConfig: 'configurationpage'
|
|
||||||
};
|
|
||||||
|
|
||||||
const DashboardApp = () => (
|
|
||||||
<Routes>
|
|
||||||
<Route element={<ConnectionRequired isAdminRequired />}>
|
|
||||||
<Route element={<AppLayout drawerlessPaths={[ DASHBOARD_APP_PATHS.MetadataManager ]} />}>
|
|
||||||
<Route path={DASHBOARD_APP_PATHS.Dashboard}>
|
|
||||||
{ASYNC_ADMIN_ROUTES.map(toDashboardAsyncPageRoute)}
|
|
||||||
{LEGACY_ADMIN_ROUTES.map(toViewManagerPageRoute)}
|
|
||||||
</Route>
|
|
||||||
|
|
||||||
{/* NOTE: The metadata editor might deserve a dedicated app in the future */}
|
|
||||||
{toViewManagerPageRoute({
|
|
||||||
path: DASHBOARD_APP_PATHS.MetadataManager,
|
|
||||||
pageProps: {
|
|
||||||
controller: 'edititemmetadata',
|
|
||||||
view: 'edititemmetadata.html'
|
|
||||||
}
|
|
||||||
})}
|
|
||||||
|
|
||||||
<Route path={DASHBOARD_APP_PATHS.PluginConfig} element={
|
|
||||||
<ServerContentPage view='/web/configurationpage' />
|
|
||||||
} />
|
|
||||||
</Route>
|
|
||||||
</Route>
|
|
||||||
|
|
||||||
{/* Suppress warnings for unhandled routes */}
|
|
||||||
<Route path='*' element={null} />
|
|
||||||
|
|
||||||
{/* Redirects for old paths */}
|
|
||||||
{REDIRECTS.map(toRedirectRoute)}
|
|
||||||
</Routes>
|
|
||||||
);
|
|
||||||
|
|
||||||
export default DashboardApp;
|
|
|
@ -1,12 +1,12 @@
|
||||||
import type { AsyncRoute } from 'components/router/AsyncRoute';
|
import { AsyncRouteType, type AsyncRoute } from 'components/router/AsyncRoute';
|
||||||
|
|
||||||
export const ASYNC_ADMIN_ROUTES: AsyncRoute[] = [
|
export const ASYNC_ADMIN_ROUTES: AsyncRoute[] = [
|
||||||
{ path: 'activity' },
|
{ path: 'activity', type: AsyncRouteType.Dashboard },
|
||||||
{ path: 'notifications' },
|
{ path: 'notifications', type: AsyncRouteType.Dashboard },
|
||||||
{ path: 'users' },
|
{ path: 'users', type: AsyncRouteType.Dashboard },
|
||||||
{ path: 'users/access' },
|
{ path: 'users/access', type: AsyncRouteType.Dashboard },
|
||||||
{ path: 'users/add' },
|
{ path: 'users/add', type: AsyncRouteType.Dashboard },
|
||||||
{ path: 'users/parentalcontrol' },
|
{ path: 'users/parentalcontrol', type: AsyncRouteType.Dashboard },
|
||||||
{ path: 'users/password' },
|
{ path: 'users/password', type: AsyncRouteType.Dashboard },
|
||||||
{ path: 'users/profile' }
|
{ path: 'users/profile', type: AsyncRouteType.Dashboard }
|
||||||
];
|
];
|
||||||
|
|
49
src/apps/dashboard/routes/routes.tsx
Normal file
49
src/apps/dashboard/routes/routes.tsx
Normal file
|
@ -0,0 +1,49 @@
|
||||||
|
import React from 'react';
|
||||||
|
import { RouteObject } from 'react-router-dom';
|
||||||
|
import AppLayout from '../AppLayout';
|
||||||
|
import ConnectionRequired from 'components/ConnectionRequired';
|
||||||
|
import { ASYNC_ADMIN_ROUTES } from './_asyncRoutes';
|
||||||
|
import { toAsyncPageRouteConfig } from 'components/router/AsyncRoute';
|
||||||
|
import { toViewManagerPageRouteConfig } from 'components/router/LegacyRoute';
|
||||||
|
import { LEGACY_ADMIN_ROUTES } from './_legacyRoutes';
|
||||||
|
import ServerContentPage from 'components/ServerContentPage';
|
||||||
|
|
||||||
|
export const DASHBOARD_APP_PATHS = {
|
||||||
|
Dashboard: 'dashboard',
|
||||||
|
MetadataManager: 'metadata',
|
||||||
|
PluginConfig: 'configurationpage'
|
||||||
|
};
|
||||||
|
|
||||||
|
export const DASHBOARD_APP_ROUTES: RouteObject[] = [
|
||||||
|
{
|
||||||
|
element: <ConnectionRequired isAdminRequired />,
|
||||||
|
children: [
|
||||||
|
{
|
||||||
|
element: <AppLayout drawerlessPaths={[ DASHBOARD_APP_PATHS.MetadataManager ]} />,
|
||||||
|
children: [
|
||||||
|
{
|
||||||
|
path: DASHBOARD_APP_PATHS.Dashboard,
|
||||||
|
children: [
|
||||||
|
...ASYNC_ADMIN_ROUTES.map(toAsyncPageRouteConfig),
|
||||||
|
...LEGACY_ADMIN_ROUTES.map(toViewManagerPageRouteConfig)
|
||||||
|
]
|
||||||
|
},
|
||||||
|
|
||||||
|
/* NOTE: The metadata editor might deserve a dedicated app in the future */
|
||||||
|
toViewManagerPageRouteConfig({
|
||||||
|
path: DASHBOARD_APP_PATHS.MetadataManager,
|
||||||
|
pageProps: {
|
||||||
|
controller: 'edititemmetadata',
|
||||||
|
view: 'edititemmetadata.html'
|
||||||
|
}
|
||||||
|
}),
|
||||||
|
|
||||||
|
{
|
||||||
|
path: DASHBOARD_APP_PATHS.PluginConfig,
|
||||||
|
element: <ServerContentPage view='/web/configurationpage' />
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
];
|
|
@ -2,6 +2,7 @@ import React from 'react';
|
||||||
import { RouteObject, redirect } from 'react-router-dom';
|
import { RouteObject, redirect } from 'react-router-dom';
|
||||||
|
|
||||||
import { REDIRECTS } from 'apps/dashboard/routes/_redirects';
|
import { REDIRECTS } from 'apps/dashboard/routes/_redirects';
|
||||||
|
import { DASHBOARD_APP_PATHS } from 'apps/dashboard/routes/routes';
|
||||||
import ConnectionRequired from 'components/ConnectionRequired';
|
import ConnectionRequired from 'components/ConnectionRequired';
|
||||||
import { toAsyncPageRouteConfig } from 'components/router/AsyncRoute';
|
import { toAsyncPageRouteConfig } from 'components/router/AsyncRoute';
|
||||||
import { toViewManagerPageRouteConfig } from 'components/router/LegacyRoute';
|
import { toViewManagerPageRouteConfig } from 'components/router/LegacyRoute';
|
||||||
|
@ -9,7 +10,6 @@ import { toRedirectRouteConfig } from 'components/router/Redirect';
|
||||||
import AppLayout from '../AppLayout';
|
import AppLayout from '../AppLayout';
|
||||||
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';
|
||||||
import { DASHBOARD_APP_PATHS } from 'apps/dashboard/App';
|
|
||||||
|
|
||||||
export const EXPERIMENTAL_APP_ROUTES: RouteObject[] = [
|
export const EXPERIMENTAL_APP_ROUTES: RouteObject[] = [
|
||||||
{
|
{
|
||||||
|
|
|
@ -2,11 +2,13 @@ import { History } from '@remix-run/router';
|
||||||
import React from 'react';
|
import React from 'react';
|
||||||
import { RouterProvider, createHashRouter } from 'react-router-dom';
|
import { RouterProvider, createHashRouter } from 'react-router-dom';
|
||||||
|
|
||||||
import { STABLE_APP_ROUTES } from './routes/routes';
|
import { DASHBOARD_APP_ROUTES } from 'apps/dashboard/routes/routes';
|
||||||
import { useLegacyRouterSync } from 'hooks/useLegacyRouterSync';
|
import { useLegacyRouterSync } from 'hooks/useLegacyRouterSync';
|
||||||
|
import { STABLE_APP_ROUTES } from './routes/routes';
|
||||||
|
|
||||||
const router = createHashRouter([
|
const router = createHashRouter([
|
||||||
...STABLE_APP_ROUTES
|
...STABLE_APP_ROUTES,
|
||||||
|
...DASHBOARD_APP_ROUTES
|
||||||
]);
|
]);
|
||||||
|
|
||||||
export default function StableAppRouter({ history }: { history: History }) {
|
export default function StableAppRouter({ history }: { history: History }) {
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
import { RouteObject, redirect } from 'react-router-dom';
|
import { RouteObject, redirect } from 'react-router-dom';
|
||||||
import React from 'react';
|
import React from 'react';
|
||||||
|
|
||||||
import { DASHBOARD_APP_PATHS } from 'apps/dashboard/App';
|
import { DASHBOARD_APP_PATHS } from 'apps/dashboard/routes/routes';
|
||||||
import ConnectionRequired from 'components/ConnectionRequired';
|
import ConnectionRequired from 'components/ConnectionRequired';
|
||||||
import { toAsyncPageRouteConfig } from 'components/router/AsyncRoute';
|
import { toAsyncPageRouteConfig } from 'components/router/AsyncRoute';
|
||||||
import { toViewManagerPageRouteConfig } from 'components/router/LegacyRoute';
|
import { toViewManagerPageRouteConfig } from 'components/router/LegacyRoute';
|
||||||
|
|
|
@ -4,7 +4,8 @@ import { Route } from 'react-router-dom';
|
||||||
|
|
||||||
export enum AsyncRouteType {
|
export enum AsyncRouteType {
|
||||||
Stable,
|
Stable,
|
||||||
Experimental
|
Experimental,
|
||||||
|
Dashboard,
|
||||||
}
|
}
|
||||||
|
|
||||||
export interface AsyncRoute {
|
export interface AsyncRoute {
|
||||||
|
@ -26,6 +27,11 @@ export interface AsyncPageProps {
|
||||||
page: string
|
page: string
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const DashboardAsyncPage = loadable(
|
||||||
|
(props: { page: string }) => import(/* webpackChunkName: "[request]" */ `../../apps/dashboard/routes/${props.page}`),
|
||||||
|
{ cacheKey: (props: AsyncPageProps) => props.page }
|
||||||
|
);
|
||||||
|
|
||||||
const ExperimentalAsyncPage = loadable(
|
const ExperimentalAsyncPage = loadable(
|
||||||
(props: { page: string }) => import(/* webpackChunkName: "[request]" */ `../../apps/experimental/routes/${props.page}`),
|
(props: { page: string }) => import(/* webpackChunkName: "[request]" */ `../../apps/experimental/routes/${props.page}`),
|
||||||
{ cacheKey: (props: AsyncPageProps) => props.page }
|
{ cacheKey: (props: AsyncPageProps) => props.page }
|
||||||
|
@ -37,12 +43,20 @@ const StableAsyncPage = loadable(
|
||||||
);
|
);
|
||||||
|
|
||||||
export const toAsyncPageRoute = ({ path, page, element, type = AsyncRouteType.Stable }: AsyncRoute) => {
|
export const toAsyncPageRoute = ({ path, page, element, type = AsyncRouteType.Stable }: AsyncRoute) => {
|
||||||
const Element = element
|
let Element = element;
|
||||||
|| (
|
if (!Element) {
|
||||||
type === AsyncRouteType.Experimental ?
|
switch (type) {
|
||||||
ExperimentalAsyncPage :
|
case AsyncRouteType.Dashboard:
|
||||||
StableAsyncPage
|
Element = DashboardAsyncPage;
|
||||||
);
|
break;
|
||||||
|
case AsyncRouteType.Experimental:
|
||||||
|
Element = ExperimentalAsyncPage;
|
||||||
|
break;
|
||||||
|
case AsyncRouteType.Stable:
|
||||||
|
default:
|
||||||
|
Element = StableAsyncPage;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<Route
|
<Route
|
||||||
|
@ -54,11 +68,20 @@ export const toAsyncPageRoute = ({ path, page, element, type = AsyncRouteType.St
|
||||||
};
|
};
|
||||||
|
|
||||||
export function toAsyncPageRouteConfig({ path, page, element, type = AsyncRouteType.Stable }: AsyncRoute) {
|
export function toAsyncPageRouteConfig({ path, page, element, type = AsyncRouteType.Stable }: AsyncRoute) {
|
||||||
const Element = element || (
|
let Element = element;
|
||||||
type === AsyncRouteType.Experimental ?
|
if (!Element) {
|
||||||
ExperimentalAsyncPage :
|
switch (type) {
|
||||||
StableAsyncPage
|
case AsyncRouteType.Dashboard:
|
||||||
);
|
Element = DashboardAsyncPage;
|
||||||
|
break;
|
||||||
|
case AsyncRouteType.Experimental:
|
||||||
|
Element = ExperimentalAsyncPage;
|
||||||
|
break;
|
||||||
|
case AsyncRouteType.Stable:
|
||||||
|
default:
|
||||||
|
Element = StableAsyncPage;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
return {
|
return {
|
||||||
path,
|
path,
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue