1
0
Fork 0
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:
Grady Hallenbeck 2023-10-06 20:09:19 -07:00
parent ff885b9b21
commit cd11e6e36f
9 changed files with 107 additions and 100 deletions

View file

@ -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>
</> </>
); );
}; };

View file

@ -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}) {

View file

@ -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;

View file

@ -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 }
]; ];

View 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' />
}
]
}
]
}
];

View file

@ -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[] = [
{ {

View file

@ -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 }) {

View file

@ -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';

View file

@ -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,