Merge pull request #4660 from thornbill/routes-layout-refactor
Refactor routes to use layout elements
This commit is contained in:
commit
13aa3c9efa
7 changed files with 189 additions and 196 deletions
|
@ -1,114 +1,43 @@
|
||||||
import React, { useCallback, useEffect, useState } from 'react';
|
import React from 'react';
|
||||||
import AppBar from '@mui/material/AppBar';
|
import { Navigate, Route, Routes } from 'react-router-dom';
|
||||||
import Box from '@mui/material/Box';
|
|
||||||
import { ThemeProvider } from '@mui/material/styles';
|
|
||||||
import { useLocation } from 'react-router-dom';
|
|
||||||
|
|
||||||
import AppHeader from 'components/AppHeader';
|
import ConnectionRequired from 'components/ConnectionRequired';
|
||||||
import Backdrop from 'components/Backdrop';
|
import ServerContentPage from 'components/ServerContentPage';
|
||||||
import { useApi } from 'hooks/useApi';
|
import { toAsyncPageRoute } from 'components/router/AsyncRoute';
|
||||||
import { useLocalStorage } from 'hooks/useLocalStorage';
|
import { toViewManagerPageRoute } from 'components/router/LegacyRoute';
|
||||||
|
|
||||||
import AppToolbar from './components/AppToolbar';
|
import AppLayout from './AppLayout';
|
||||||
import AppDrawer, { DRAWER_WIDTH, isDrawerPath } from './components/drawers/AppDrawer';
|
import { ASYNC_ADMIN_ROUTES, ASYNC_USER_ROUTES } from './routes/asyncRoutes';
|
||||||
import ElevationScroll from './components/ElevationScroll';
|
import { LEGACY_ADMIN_ROUTES, LEGACY_PUBLIC_ROUTES, LEGACY_USER_ROUTES } from './routes/legacyRoutes';
|
||||||
import { ExperimentalAppRoutes } from './routes/AppRoutes';
|
|
||||||
import theme from './theme';
|
|
||||||
|
|
||||||
import './AppOverrides.scss';
|
|
||||||
|
|
||||||
interface ExperimentalAppSettings {
|
|
||||||
isDrawerPinned: boolean
|
|
||||||
}
|
|
||||||
|
|
||||||
const DEFAULT_EXPERIMENTAL_APP_SETTINGS: ExperimentalAppSettings = {
|
|
||||||
isDrawerPinned: false
|
|
||||||
};
|
|
||||||
|
|
||||||
const ExperimentalApp = () => {
|
const ExperimentalApp = () => {
|
||||||
const [ appSettings, setAppSettings ] = useLocalStorage<ExperimentalAppSettings>('ExperimentalAppSettings', DEFAULT_EXPERIMENTAL_APP_SETTINGS);
|
|
||||||
const [ isDrawerActive, setIsDrawerActive ] = useState(appSettings.isDrawerPinned);
|
|
||||||
const { user } = useApi();
|
|
||||||
const location = useLocation();
|
|
||||||
|
|
||||||
const isDrawerAvailable = isDrawerPath(location.pathname);
|
|
||||||
const isDrawerOpen = isDrawerActive && isDrawerAvailable && Boolean(user);
|
|
||||||
|
|
||||||
useEffect(() => {
|
|
||||||
if (isDrawerActive !== appSettings.isDrawerPinned) {
|
|
||||||
setAppSettings({
|
|
||||||
...appSettings,
|
|
||||||
isDrawerPinned: isDrawerActive
|
|
||||||
});
|
|
||||||
}
|
|
||||||
}, [ appSettings, isDrawerActive, setAppSettings ]);
|
|
||||||
|
|
||||||
const onToggleDrawer = useCallback(() => {
|
|
||||||
setIsDrawerActive(!isDrawerActive);
|
|
||||||
}, [ isDrawerActive, setIsDrawerActive ]);
|
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<ThemeProvider theme={theme}>
|
<Routes>
|
||||||
<Backdrop />
|
<Route path='/*' element={<AppLayout />}>
|
||||||
|
{/* User routes */}
|
||||||
|
<Route element={<ConnectionRequired />}>
|
||||||
|
{ASYNC_USER_ROUTES.map(toAsyncPageRoute)}
|
||||||
|
{LEGACY_USER_ROUTES.map(toViewManagerPageRoute)}
|
||||||
|
</Route>
|
||||||
|
|
||||||
<div style={{ display: 'none' }}>
|
{/* Admin routes */}
|
||||||
{/*
|
<Route element={<ConnectionRequired isAdminRequired />}>
|
||||||
* TODO: These components are not used, but views interact with them directly so the need to be
|
{ASYNC_ADMIN_ROUTES.map(toAsyncPageRoute)}
|
||||||
* present in the dom. We add them in a hidden element to prevent errors.
|
{LEGACY_ADMIN_ROUTES.map(toViewManagerPageRoute)}
|
||||||
*/}
|
|
||||||
<AppHeader />
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<Box sx={{ display: 'flex' }}>
|
<Route path='configurationpage' element={
|
||||||
<ElevationScroll elevate={isDrawerOpen}>
|
<ServerContentPage view='/web/configurationpage' />
|
||||||
<AppBar
|
} />
|
||||||
position='fixed'
|
</Route>
|
||||||
sx={{ zIndex: (muiTheme) => muiTheme.zIndex.drawer + 1 }}
|
|
||||||
>
|
|
||||||
<AppToolbar
|
|
||||||
isDrawerOpen={isDrawerOpen}
|
|
||||||
onDrawerButtonClick={onToggleDrawer}
|
|
||||||
/>
|
|
||||||
</AppBar>
|
|
||||||
</ElevationScroll>
|
|
||||||
|
|
||||||
<AppDrawer
|
{/* Public routes */}
|
||||||
open={isDrawerOpen}
|
<Route element={<ConnectionRequired isUserRequired={false} />}>
|
||||||
onClose={onToggleDrawer}
|
<Route index element={<Navigate replace to='/home.html' />} />
|
||||||
onOpen={onToggleDrawer}
|
|
||||||
/>
|
|
||||||
|
|
||||||
<Box
|
{LEGACY_PUBLIC_ROUTES.map(toViewManagerPageRoute)}
|
||||||
component='main'
|
</Route>
|
||||||
sx={{
|
</Route>
|
||||||
width: '100%',
|
</Routes>
|
||||||
flexGrow: 1,
|
|
||||||
transition: theme.transitions.create('margin', {
|
|
||||||
easing: theme.transitions.easing.sharp,
|
|
||||||
duration: theme.transitions.duration.leavingScreen
|
|
||||||
}),
|
|
||||||
marginLeft: 0,
|
|
||||||
...(isDrawerAvailable && {
|
|
||||||
marginLeft: {
|
|
||||||
sm: `-${DRAWER_WIDTH}px`
|
|
||||||
}
|
|
||||||
}),
|
|
||||||
...(isDrawerActive && {
|
|
||||||
transition: theme.transitions.create('margin', {
|
|
||||||
easing: theme.transitions.easing.easeOut,
|
|
||||||
duration: theme.transitions.duration.enteringScreen
|
|
||||||
}),
|
|
||||||
marginLeft: 0
|
|
||||||
})
|
|
||||||
}}
|
|
||||||
>
|
|
||||||
<div className='mainAnimatedPages skinBody' />
|
|
||||||
<div className='skinBody'>
|
|
||||||
<ExperimentalAppRoutes />
|
|
||||||
</div>
|
|
||||||
</Box>
|
|
||||||
</Box>
|
|
||||||
</ThemeProvider>
|
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
114
src/apps/experimental/AppLayout.tsx
Normal file
114
src/apps/experimental/AppLayout.tsx
Normal file
|
@ -0,0 +1,114 @@
|
||||||
|
import React, { useCallback, useEffect, useState } from 'react';
|
||||||
|
import AppBar from '@mui/material/AppBar';
|
||||||
|
import Box from '@mui/material/Box';
|
||||||
|
import { ThemeProvider } from '@mui/material/styles';
|
||||||
|
import { Outlet, useLocation } from 'react-router-dom';
|
||||||
|
|
||||||
|
import AppHeader from 'components/AppHeader';
|
||||||
|
import Backdrop from 'components/Backdrop';
|
||||||
|
import { useApi } from 'hooks/useApi';
|
||||||
|
import { useLocalStorage } from 'hooks/useLocalStorage';
|
||||||
|
|
||||||
|
import AppToolbar from './components/AppToolbar';
|
||||||
|
import AppDrawer, { DRAWER_WIDTH, isDrawerPath } from './components/drawers/AppDrawer';
|
||||||
|
import ElevationScroll from './components/ElevationScroll';
|
||||||
|
import theme from './theme';
|
||||||
|
|
||||||
|
import './AppOverrides.scss';
|
||||||
|
|
||||||
|
interface ExperimentalAppSettings {
|
||||||
|
isDrawerPinned: boolean
|
||||||
|
}
|
||||||
|
|
||||||
|
const DEFAULT_EXPERIMENTAL_APP_SETTINGS: ExperimentalAppSettings = {
|
||||||
|
isDrawerPinned: false
|
||||||
|
};
|
||||||
|
|
||||||
|
const AppLayout = () => {
|
||||||
|
const [ appSettings, setAppSettings ] = useLocalStorage<ExperimentalAppSettings>('ExperimentalAppSettings', DEFAULT_EXPERIMENTAL_APP_SETTINGS);
|
||||||
|
const [ isDrawerActive, setIsDrawerActive ] = useState(appSettings.isDrawerPinned);
|
||||||
|
const { user } = useApi();
|
||||||
|
const location = useLocation();
|
||||||
|
|
||||||
|
const isDrawerAvailable = isDrawerPath(location.pathname);
|
||||||
|
const isDrawerOpen = isDrawerActive && isDrawerAvailable && Boolean(user);
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
if (isDrawerActive !== appSettings.isDrawerPinned) {
|
||||||
|
setAppSettings({
|
||||||
|
...appSettings,
|
||||||
|
isDrawerPinned: isDrawerActive
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}, [ appSettings, isDrawerActive, setAppSettings ]);
|
||||||
|
|
||||||
|
const onToggleDrawer = useCallback(() => {
|
||||||
|
setIsDrawerActive(!isDrawerActive);
|
||||||
|
}, [ isDrawerActive, setIsDrawerActive ]);
|
||||||
|
|
||||||
|
return (
|
||||||
|
<ThemeProvider theme={theme}>
|
||||||
|
<Backdrop />
|
||||||
|
|
||||||
|
<div style={{ display: 'none' }}>
|
||||||
|
{/*
|
||||||
|
* TODO: These components are not used, but views interact with them directly so the need to be
|
||||||
|
* present in the dom. We add them in a hidden element to prevent errors.
|
||||||
|
*/}
|
||||||
|
<AppHeader />
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<Box sx={{ display: 'flex' }}>
|
||||||
|
<ElevationScroll elevate={isDrawerOpen}>
|
||||||
|
<AppBar
|
||||||
|
position='fixed'
|
||||||
|
sx={{ zIndex: (muiTheme) => muiTheme.zIndex.drawer + 1 }}
|
||||||
|
>
|
||||||
|
<AppToolbar
|
||||||
|
isDrawerOpen={isDrawerOpen}
|
||||||
|
onDrawerButtonClick={onToggleDrawer}
|
||||||
|
/>
|
||||||
|
</AppBar>
|
||||||
|
</ElevationScroll>
|
||||||
|
|
||||||
|
<AppDrawer
|
||||||
|
open={isDrawerOpen}
|
||||||
|
onClose={onToggleDrawer}
|
||||||
|
onOpen={onToggleDrawer}
|
||||||
|
/>
|
||||||
|
|
||||||
|
<Box
|
||||||
|
component='main'
|
||||||
|
sx={{
|
||||||
|
width: '100%',
|
||||||
|
flexGrow: 1,
|
||||||
|
transition: theme.transitions.create('margin', {
|
||||||
|
easing: theme.transitions.easing.sharp,
|
||||||
|
duration: theme.transitions.duration.leavingScreen
|
||||||
|
}),
|
||||||
|
marginLeft: 0,
|
||||||
|
...(isDrawerAvailable && {
|
||||||
|
marginLeft: {
|
||||||
|
sm: `-${DRAWER_WIDTH}px`
|
||||||
|
}
|
||||||
|
}),
|
||||||
|
...(isDrawerActive && {
|
||||||
|
transition: theme.transitions.create('margin', {
|
||||||
|
easing: theme.transitions.easing.easeOut,
|
||||||
|
duration: theme.transitions.duration.enteringScreen
|
||||||
|
}),
|
||||||
|
marginLeft: 0
|
||||||
|
})
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
<div className='mainAnimatedPages skinBody' />
|
||||||
|
<div className='skinBody'>
|
||||||
|
<Outlet />
|
||||||
|
</div>
|
||||||
|
</Box>
|
||||||
|
</Box>
|
||||||
|
</ThemeProvider>
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
export default AppLayout;
|
|
@ -80,9 +80,6 @@ const AppDrawer: FC<ResponsiveDrawerProps> = ({
|
||||||
/>
|
/>
|
||||||
))
|
))
|
||||||
}
|
}
|
||||||
|
|
||||||
{/* Suppress warnings for unhandled routes */}
|
|
||||||
<Route path='*' element={null} />
|
|
||||||
</Routes>
|
</Routes>
|
||||||
);
|
);
|
||||||
|
|
||||||
|
|
|
@ -83,9 +83,6 @@ const AppTabs: FC<AppTabsParams> = ({
|
||||||
/>
|
/>
|
||||||
))
|
))
|
||||||
}
|
}
|
||||||
|
|
||||||
{/* Suppress warnings for unhandled routes */}
|
|
||||||
<Route path='*' element={null} />
|
|
||||||
</Routes>
|
</Routes>
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|
|
@ -1,42 +0,0 @@
|
||||||
import React from 'react';
|
|
||||||
import { Navigate, Route, Routes } from 'react-router-dom';
|
|
||||||
|
|
||||||
import ConnectionRequired from 'components/ConnectionRequired';
|
|
||||||
import ServerContentPage from 'components/ServerContentPage';
|
|
||||||
import { toAsyncPageRoute } from 'components/router/AsyncRoute';
|
|
||||||
import { toViewManagerPageRoute } from 'components/router/LegacyRoute';
|
|
||||||
|
|
||||||
import { ASYNC_ADMIN_ROUTES, ASYNC_USER_ROUTES } from './asyncRoutes';
|
|
||||||
import { LEGACY_ADMIN_ROUTES, LEGACY_PUBLIC_ROUTES, LEGACY_USER_ROUTES } from './legacyRoutes';
|
|
||||||
|
|
||||||
export const ExperimentalAppRoutes = () => (
|
|
||||||
<Routes>
|
|
||||||
<Route path='/'>
|
|
||||||
{/* User routes */}
|
|
||||||
<Route path='/' element={<ConnectionRequired />}>
|
|
||||||
{ASYNC_USER_ROUTES.map(toAsyncPageRoute)}
|
|
||||||
{LEGACY_USER_ROUTES.map(toViewManagerPageRoute)}
|
|
||||||
</Route>
|
|
||||||
|
|
||||||
{/* Admin routes */}
|
|
||||||
<Route path='/' element={<ConnectionRequired isAdminRequired />}>
|
|
||||||
{ASYNC_ADMIN_ROUTES.map(toAsyncPageRoute)}
|
|
||||||
{LEGACY_ADMIN_ROUTES.map(toViewManagerPageRoute)}
|
|
||||||
|
|
||||||
<Route path='configurationpage' element={
|
|
||||||
<ServerContentPage view='/web/configurationpage' />
|
|
||||||
} />
|
|
||||||
</Route>
|
|
||||||
|
|
||||||
{/* Public routes */}
|
|
||||||
<Route path='/' element={<ConnectionRequired isUserRequired={false} />}>
|
|
||||||
<Route index element={<Navigate replace to='/home.html' />} />
|
|
||||||
|
|
||||||
{LEGACY_PUBLIC_ROUTES.map(toViewManagerPageRoute)}
|
|
||||||
</Route>
|
|
||||||
|
|
||||||
{/* Suppress warnings for unhandled routes */}
|
|
||||||
<Route path='*' element={null} />
|
|
||||||
</Route>
|
|
||||||
</Routes>
|
|
||||||
);
|
|
|
@ -1,19 +1,58 @@
|
||||||
import React from 'react';
|
import React from 'react';
|
||||||
|
import { Navigate, Outlet, Route, Routes } from 'react-router-dom';
|
||||||
|
|
||||||
import AppHeader from '../../components/AppHeader';
|
import AppHeader from 'components/AppHeader';
|
||||||
import Backdrop from '../../components/Backdrop';
|
import Backdrop from 'components/Backdrop';
|
||||||
import { AppRoutes } from './routes/AppRoutes';
|
import ServerContentPage from 'components/ServerContentPage';
|
||||||
|
import ConnectionRequired from 'components/ConnectionRequired';
|
||||||
|
import { toAsyncPageRoute } from 'components/router/AsyncRoute';
|
||||||
|
import { toViewManagerPageRoute } from 'components/router/LegacyRoute';
|
||||||
|
|
||||||
const StableApp = () => (
|
import { ASYNC_ADMIN_ROUTES, ASYNC_USER_ROUTES } from './routes/asyncRoutes';
|
||||||
|
import { LEGACY_ADMIN_ROUTES, LEGACY_PUBLIC_ROUTES, LEGACY_USER_ROUTES } from './routes/legacyRoutes';
|
||||||
|
|
||||||
|
const Layout = () => (
|
||||||
<>
|
<>
|
||||||
<Backdrop />
|
<Backdrop />
|
||||||
<AppHeader />
|
<AppHeader />
|
||||||
|
|
||||||
<div className='mainAnimatedPages skinBody' />
|
<div className='mainAnimatedPages skinBody' />
|
||||||
<div className='skinBody'>
|
<div className='skinBody'>
|
||||||
<AppRoutes />
|
<Outlet />
|
||||||
</div>
|
</div>
|
||||||
</>
|
</>
|
||||||
);
|
);
|
||||||
|
|
||||||
|
const StableApp = () => (
|
||||||
|
<Routes>
|
||||||
|
<Route element={<Layout />}>
|
||||||
|
{/* User routes */}
|
||||||
|
<Route path='/' element={<ConnectionRequired />}>
|
||||||
|
{ASYNC_USER_ROUTES.map(toAsyncPageRoute)}
|
||||||
|
{LEGACY_USER_ROUTES.map(toViewManagerPageRoute)}
|
||||||
|
</Route>
|
||||||
|
|
||||||
|
{/* Admin routes */}
|
||||||
|
<Route path='/' element={<ConnectionRequired isAdminRequired />}>
|
||||||
|
{ASYNC_ADMIN_ROUTES.map(toAsyncPageRoute)}
|
||||||
|
{LEGACY_ADMIN_ROUTES.map(toViewManagerPageRoute)}
|
||||||
|
|
||||||
|
<Route path='configurationpage' element={
|
||||||
|
<ServerContentPage view='/web/configurationpage' />
|
||||||
|
} />
|
||||||
|
</Route>
|
||||||
|
|
||||||
|
{/* Public routes */}
|
||||||
|
<Route path='/' element={<ConnectionRequired isUserRequired={false} />}>
|
||||||
|
<Route index element={<Navigate replace to='/home.html' />} />
|
||||||
|
|
||||||
|
{LEGACY_PUBLIC_ROUTES.map(toViewManagerPageRoute)}
|
||||||
|
</Route>
|
||||||
|
|
||||||
|
{/* Suppress warnings for unhandled routes */}
|
||||||
|
<Route path='*' element={null} />
|
||||||
|
</Route>
|
||||||
|
</Routes>
|
||||||
|
);
|
||||||
|
|
||||||
export default StableApp;
|
export default StableApp;
|
||||||
|
|
|
@ -1,41 +0,0 @@
|
||||||
import React from 'react';
|
|
||||||
import { Navigate, Route, Routes } from 'react-router-dom';
|
|
||||||
|
|
||||||
import ConnectionRequired from '../../../components/ConnectionRequired';
|
|
||||||
import ServerContentPage from '../../../components/ServerContentPage';
|
|
||||||
import { toAsyncPageRoute } from '../../../components/router/AsyncRoute';
|
|
||||||
import { toViewManagerPageRoute } from '../../../components/router/LegacyRoute';
|
|
||||||
import { ASYNC_ADMIN_ROUTES, ASYNC_USER_ROUTES } from './asyncRoutes';
|
|
||||||
import { LEGACY_ADMIN_ROUTES, LEGACY_PUBLIC_ROUTES, LEGACY_USER_ROUTES } from './legacyRoutes';
|
|
||||||
|
|
||||||
export const AppRoutes = () => (
|
|
||||||
<Routes>
|
|
||||||
<Route path='/'>
|
|
||||||
{/* User routes */}
|
|
||||||
<Route path='/' element={<ConnectionRequired />}>
|
|
||||||
{ASYNC_USER_ROUTES.map(toAsyncPageRoute)}
|
|
||||||
{LEGACY_USER_ROUTES.map(toViewManagerPageRoute)}
|
|
||||||
</Route>
|
|
||||||
|
|
||||||
{/* Admin routes */}
|
|
||||||
<Route path='/' element={<ConnectionRequired isAdminRequired />}>
|
|
||||||
{ASYNC_ADMIN_ROUTES.map(toAsyncPageRoute)}
|
|
||||||
{LEGACY_ADMIN_ROUTES.map(toViewManagerPageRoute)}
|
|
||||||
|
|
||||||
<Route path='configurationpage' element={
|
|
||||||
<ServerContentPage view='/web/configurationpage' />
|
|
||||||
} />
|
|
||||||
</Route>
|
|
||||||
|
|
||||||
{/* Public routes */}
|
|
||||||
<Route path='/' element={<ConnectionRequired isUserRequired={false} />}>
|
|
||||||
<Route index element={<Navigate replace to='/home.html' />} />
|
|
||||||
|
|
||||||
{LEGACY_PUBLIC_ROUTES.map(toViewManagerPageRoute)}
|
|
||||||
</Route>
|
|
||||||
|
|
||||||
{/* Suppress warnings for unhandled routes */}
|
|
||||||
<Route path='*' element={null} />
|
|
||||||
</Route>
|
|
||||||
</Routes>
|
|
||||||
);
|
|
Loading…
Add table
Add a link
Reference in a new issue