Skip to content

Commit

Permalink
Merge pull request #4834 from grhallenbeck/dev-react-router
Browse files Browse the repository at this point in the history
Migrate React Router to React Data Router pattern
  • Loading branch information
thornbill authored Nov 3, 2023
2 parents e712006 + c9420da commit 35429ca
Show file tree
Hide file tree
Showing 17 changed files with 347 additions and 303 deletions.
1 change: 1 addition & 0 deletions CONTRIBUTORS.md
Original file line number Diff line number Diff line change
Expand Up @@ -71,6 +71,7 @@
- [scampower3](https://github.com/scampower3)
- [LittleBigOwI] (https://github.com/LittleBigOwI/)
- [Nate G](https://github.com/GGProGaming)
- [Grady Hallenbeck](https://github.com/grhallenbeck)

# Emby Contributors

Expand Down
56 changes: 16 additions & 40 deletions src/RootApp.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -4,59 +4,35 @@ import { History } from '@remix-run/router';
import { QueryClient, QueryClientProvider } from '@tanstack/react-query';
import { ReactQueryDevtools } from '@tanstack/react-query-devtools';
import React from 'react';
import { useLocation } from 'react-router-dom';

import { DASHBOARD_APP_PATHS } from 'apps/dashboard/App';
import AppHeader from 'components/AppHeader';
import Backdrop from 'components/Backdrop';
import { HistoryRouter } from 'components/router/HistoryRouter';
import { ApiProvider } from 'hooks/useApi';
import { WebConfigProvider } from 'hooks/useWebConfig';
import theme from 'themes/theme';

const DashboardApp = loadable(() => import('./apps/dashboard/App'));
const ExperimentalApp = loadable(() => import('./apps/experimental/App'));
const StableApp = loadable(() => import('./apps/stable/App'));
const StableAppRouter = loadable(() => import('./apps/stable/AppRouter'));
const RootAppRouter = loadable(() => import('./RootAppRouter'));

const queryClient = new QueryClient();

const RootAppLayout = () => {
const RootApp = ({ history }: Readonly<{ history: History }>) => {
const layoutMode = localStorage.getItem('layout');
const isExperimentalLayout = layoutMode === 'experimental';

const location = useLocation();
const isNewLayoutPath = Object.values(DASHBOARD_APP_PATHS)
.some(path => location.pathname.startsWith(`/${path}`));

return (
<>
<Backdrop />
<AppHeader isHidden={isExperimentalLayout || isNewLayoutPath} />

{
isExperimentalLayout ?
<ExperimentalApp /> :
<StableApp />
}

<DashboardApp />
</>
<QueryClientProvider client={queryClient}>
<ApiProvider>
<WebConfigProvider>
<ThemeProvider theme={theme}>
{isExperimentalLayout ?
<RootAppRouter history={history} /> :
<StableAppRouter history={history} />
}
</ThemeProvider>
</WebConfigProvider>
</ApiProvider>
<ReactQueryDevtools initialIsOpen={false} />
</QueryClientProvider>
);
};

const RootApp = ({ history }: { history: History }) => (
<QueryClientProvider client={queryClient}>
<ApiProvider>
<WebConfigProvider>
<ThemeProvider theme={theme}>
<HistoryRouter history={history}>
<RootAppLayout />
</HistoryRouter>
</ThemeProvider>
</WebConfigProvider>
</ApiProvider>
<ReactQueryDevtools initialIsOpen={false} />
</QueryClientProvider>
);

export default RootApp;
41 changes: 41 additions & 0 deletions src/RootAppRouter.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@

import { History } from '@remix-run/router';
import React from 'react';
import {
RouterProvider,
createHashRouter,
Outlet
} from 'react-router-dom';

import { EXPERIMENTAL_APP_ROUTES } from 'apps/experimental/routes/routes';
import AppHeader from 'components/AppHeader';
import Backdrop from 'components/Backdrop';
import { useLegacyRouterSync } from 'hooks/useLegacyRouterSync';
import { DASHBOARD_APP_ROUTES } from 'apps/dashboard/routes/routes';

const router = createHashRouter([
{
element: <RootAppLayout />,
children: [
...EXPERIMENTAL_APP_ROUTES,
...DASHBOARD_APP_ROUTES
]
}
]);

export default function RootAppRouter({ history }: Readonly<{ history: History}>) {
useLegacyRouterSync({ router, history });

return <RouterProvider router={router} />;
}

function RootAppLayout() {
return (
<>
<Backdrop />
<AppHeader isHidden />

<Outlet />
</>
);
}
66 changes: 0 additions & 66 deletions src/apps/dashboard/App.tsx

This file was deleted.

18 changes: 9 additions & 9 deletions src/apps/dashboard/routes/_asyncRoutes.ts
Original file line number Diff line number Diff line change
@@ -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[] = [
{ path: 'activity' },
{ path: 'notifications' },
{ path: 'users' },
{ path: 'users/access' },
{ path: 'users/add' },
{ path: 'users/parentalcontrol' },
{ path: 'users/password' },
{ path: 'users/profile' }
{ path: 'activity', type: AsyncRouteType.Dashboard },
{ path: 'notifications', type: AsyncRouteType.Dashboard },
{ path: 'users', type: AsyncRouteType.Dashboard },
{ path: 'users/access', type: AsyncRouteType.Dashboard },
{ path: 'users/add', type: AsyncRouteType.Dashboard },
{ path: 'users/parentalcontrol', type: AsyncRouteType.Dashboard },
{ path: 'users/password', type: AsyncRouteType.Dashboard },
{ path: 'users/profile', type: AsyncRouteType.Dashboard }
];
49 changes: 49 additions & 0 deletions src/apps/dashboard/routes/routes.tsx
Original file line number Diff line number Diff line change
@@ -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 { toAsyncPageRoute } from 'components/router/AsyncRoute';
import { toViewManagerPageRoute } 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(toAsyncPageRoute),
...LEGACY_ADMIN_ROUTES.map(toViewManagerPageRoute)
]
},

/* NOTE: The metadata editor might deserve a dedicated app in the future */
toViewManagerPageRoute({
path: DASHBOARD_APP_PATHS.MetadataManager,
pageProps: {
controller: 'edititemmetadata',
view: 'edititemmetadata.html'
}
}),

{
path: DASHBOARD_APP_PATHS.PluginConfig,
element: <ServerContentPage view='/web/configurationpage' />
}
]
}
]
}
];
48 changes: 0 additions & 48 deletions src/apps/experimental/App.tsx

This file was deleted.

42 changes: 42 additions & 0 deletions src/apps/experimental/routes/routes.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
import React from 'react';
import { RouteObject, redirect } from 'react-router-dom';

import { REDIRECTS } from 'apps/dashboard/routes/_redirects';
import { DASHBOARD_APP_PATHS } from 'apps/dashboard/routes/routes';
import ConnectionRequired from 'components/ConnectionRequired';
import { toAsyncPageRoute } from 'components/router/AsyncRoute';
import { toViewManagerPageRoute } from 'components/router/LegacyRoute';
import { toRedirectRoute } from 'components/router/Redirect';
import AppLayout from '../AppLayout';
import { ASYNC_USER_ROUTES } from './asyncRoutes';
import { LEGACY_PUBLIC_ROUTES, LEGACY_USER_ROUTES } from './legacyRoutes';

export const EXPERIMENTAL_APP_ROUTES: RouteObject[] = [
{
path: '/*',
element: <AppLayout />,
children: [
{
/* User routes: Any child route of this layout is authenticated */
element: <ConnectionRequired isUserRequired />,
children: [
...ASYNC_USER_ROUTES.map(toAsyncPageRoute),
...LEGACY_USER_ROUTES.map(toViewManagerPageRoute)
]
},

/* Public routes */
{ index: true, loader: () => redirect('/home.html') },
...LEGACY_PUBLIC_ROUTES.map(toViewManagerPageRoute)
]
},

/* Redirects for old paths */
...REDIRECTS.map(toRedirectRoute),

/* Ignore dashboard routes */
...Object.entries(DASHBOARD_APP_PATHS).map(([, path]) => ({
path: `/${path}/*`,
element: null
}))
];
Loading

0 comments on commit 35429ca

Please sign in to comment.