diff --git a/README.md b/README.md index bcb0c53311..2516be0a25 100644 --- a/README.md +++ b/README.md @@ -77,8 +77,9 @@ Jellyfin Web is the frontend used for most of the clients available for end user . └── src ├── apps - │   ├── experimental # New experimental app layout - │   └── stable # Classic (stable) app layout + │   ├── dashboard # Admin dashboard app layout and routes + │   ├── experimental # New experimental app layout and routes + │   └── stable # Classic (stable) app layout and routes ├── assets # Static assets ├── components # Higher order visual components and React components ├── controllers # Legacy page views and controllers 🧹 @@ -87,7 +88,6 @@ Jellyfin Web is the frontend used for most of the clients available for end user ├── legacy # Polyfills for legacy browsers ├── libraries # Third party libraries 🧹 ├── plugins # Client plugins - ├── routes # React routes/pages ├── scripts # Random assortment of visual components and utilities 🐉 ├── strings # Translation files ├── styles # Common app Sass stylesheets diff --git a/src/RootApp.tsx b/src/RootApp.tsx index 0d66c15ad2..cc10ca7baa 100644 --- a/src/RootApp.tsx +++ b/src/RootApp.tsx @@ -1,10 +1,12 @@ import loadable from '@loadable/component'; import { ThemeProvider } from '@mui/material/styles'; import { History } from '@remix-run/router'; -import React from 'react'; 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'; @@ -12,6 +14,7 @@ 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')); @@ -21,16 +24,22 @@ const RootAppLayout = () => { 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 ( <> - + { isExperimentalLayout ? : } + + ); }; diff --git a/src/apps/dashboard/App.tsx b/src/apps/dashboard/App.tsx new file mode 100644 index 0000000000..c5ab679297 --- /dev/null +++ b/src/apps/dashboard/App.tsx @@ -0,0 +1,66 @@ +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 = () => ( + + }> + }> + + {ASYNC_ADMIN_ROUTES.map(toDashboardAsyncPageRoute)} + {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' + } + })} + + + } /> + + + {/* Suppress warnings for unhandled routes */} + + + + {/* Redirects for old paths */} + {REDIRECTS.map(toRedirectRoute)} + +); + +export default DashboardApp; diff --git a/src/apps/dashboard/AppLayout.tsx b/src/apps/dashboard/AppLayout.tsx new file mode 100644 index 0000000000..ce74f4989b --- /dev/null +++ b/src/apps/dashboard/AppLayout.tsx @@ -0,0 +1,108 @@ +import AppBar from '@mui/material/AppBar'; +import Box from '@mui/material/Box'; +import { useTheme } from '@mui/material/styles'; +import React, { FC, useCallback, useEffect, useState } from 'react'; +import { Outlet, useLocation } from 'react-router-dom'; + +import AppBody from 'components/AppBody'; +import AppToolbar from 'components/toolbar/AppToolbar'; +import ElevationScroll from 'components/ElevationScroll'; +import { DRAWER_WIDTH } from 'components/ResponsiveDrawer'; +import { useApi } from 'hooks/useApi'; +import { useLocalStorage } from 'hooks/useLocalStorage'; + +import AppDrawer from './components/drawer/AppDrawer'; + +import './AppOverrides.scss'; + +interface AppLayoutProps { + drawerlessPaths: string[] +} + +interface DashboardAppSettings { + isDrawerPinned: boolean +} + +const DEFAULT_APP_SETTINGS: DashboardAppSettings = { + isDrawerPinned: false +}; + +const AppLayout: FC = ({ + drawerlessPaths +}) => { + const [ appSettings, setAppSettings ] = useLocalStorage('DashboardAppSettings', DEFAULT_APP_SETTINGS); + const [ isDrawerActive, setIsDrawerActive ] = useState(appSettings.isDrawerPinned); + const location = useLocation(); + const theme = useTheme(); + const { user } = useApi(); + + const isDrawerAvailable = !drawerlessPaths.some(path => location.pathname.startsWith(`/${path}`)); + 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 ( + + + muiTheme.zIndex.drawer + 1 }} + > + + + + + + + + + + + + + ); +}; + +export default AppLayout; diff --git a/src/apps/dashboard/AppOverrides.scss b/src/apps/dashboard/AppOverrides.scss new file mode 100644 index 0000000000..c8597ee576 --- /dev/null +++ b/src/apps/dashboard/AppOverrides.scss @@ -0,0 +1,22 @@ +// Default MUI breakpoints +// https://mui.com/material-ui/customization/breakpoints/#default-breakpoints +$mui-bp-sm: 600px; +$mui-bp-md: 900px; +$mui-bp-lg: 1200px; +$mui-bp-xl: 1536px; + +// Fix dashboard pages layout to work with drawer +.dashboardDocument { + .mainAnimatedPage { + position: relative; + } + + .skinBody { + position: unset !important; + } + + // Fix the padding of dashboard pages + .content-primary.content-primary { + padding-top: 3.25rem !important; + } +} diff --git a/src/apps/experimental/components/activityTable/LogLevelChip.tsx b/src/apps/dashboard/components/activityTable/LogLevelChip.tsx similarity index 100% rename from src/apps/experimental/components/activityTable/LogLevelChip.tsx rename to src/apps/dashboard/components/activityTable/LogLevelChip.tsx diff --git a/src/apps/experimental/components/activityTable/OverviewCell.tsx b/src/apps/dashboard/components/activityTable/OverviewCell.tsx similarity index 100% rename from src/apps/experimental/components/activityTable/OverviewCell.tsx rename to src/apps/dashboard/components/activityTable/OverviewCell.tsx diff --git a/src/apps/experimental/components/GridActionsCellLink.tsx b/src/apps/dashboard/components/dataGrid/GridActionsCellLink.tsx similarity index 100% rename from src/apps/experimental/components/GridActionsCellLink.tsx rename to src/apps/dashboard/components/dataGrid/GridActionsCellLink.tsx diff --git a/src/apps/dashboard/components/drawer/AppDrawer.tsx b/src/apps/dashboard/components/drawer/AppDrawer.tsx new file mode 100644 index 0000000000..7b1e180123 --- /dev/null +++ b/src/apps/dashboard/components/drawer/AppDrawer.tsx @@ -0,0 +1,29 @@ +import React, { FC } from 'react'; + +import ResponsiveDrawer, { ResponsiveDrawerProps } from 'components/ResponsiveDrawer'; + +import ServerDrawerSection from './sections/ServerDrawerSection'; +import DevicesDrawerSection from './sections/DevicesDrawerSection'; +import LiveTvDrawerSection from './sections/LiveTvDrawerSection'; +import AdvancedDrawerSection from './sections/AdvancedDrawerSection'; +import PluginDrawerSection from './sections/PluginDrawerSection'; + +const AppDrawer: FC = ({ + open = false, + onClose, + onOpen +}) => ( + + + + + + + +); + +export default AppDrawer; diff --git a/src/apps/experimental/components/drawers/dashboard/AdvancedDrawerSection.tsx b/src/apps/dashboard/components/drawer/sections/AdvancedDrawerSection.tsx similarity index 84% rename from src/apps/experimental/components/drawers/dashboard/AdvancedDrawerSection.tsx rename to src/apps/dashboard/components/drawer/sections/AdvancedDrawerSection.tsx index 5a74c68632..97993a76cc 100644 --- a/src/apps/experimental/components/drawers/dashboard/AdvancedDrawerSection.tsx +++ b/src/apps/dashboard/components/drawer/sections/AdvancedDrawerSection.tsx @@ -19,10 +19,10 @@ import ListItemLink from 'components/ListItemLink'; import globalize from 'scripts/globalize'; const PLUGIN_PATHS = [ - '/installedplugins.html', - '/availableplugins.html', - '/repositories.html', - '/addplugin.html', + '/dashboard/plugins', + '/dashboard/plugins/catalog', + '/dashboard/plugins/repositories', + '/dashboard/plugins/add', '/configurationpage' ]; @@ -41,7 +41,7 @@ const AdvancedDrawerSection = () => { } > - + @@ -49,7 +49,7 @@ const AdvancedDrawerSection = () => { - + @@ -57,7 +57,7 @@ const AdvancedDrawerSection = () => { - +
@@ -65,7 +65,7 @@ const AdvancedDrawerSection = () => { - + @@ -73,7 +73,7 @@ const AdvancedDrawerSection = () => { - + @@ -83,19 +83,19 @@ const AdvancedDrawerSection = () => { - + - + - + - + diff --git a/src/apps/experimental/components/drawers/dashboard/DevicesDrawerSection.tsx b/src/apps/dashboard/components/drawer/sections/DevicesDrawerSection.tsx similarity index 88% rename from src/apps/experimental/components/drawers/dashboard/DevicesDrawerSection.tsx rename to src/apps/dashboard/components/drawer/sections/DevicesDrawerSection.tsx index fe3ec09217..6cc7ab79fc 100644 --- a/src/apps/experimental/components/drawers/dashboard/DevicesDrawerSection.tsx +++ b/src/apps/dashboard/components/drawer/sections/DevicesDrawerSection.tsx @@ -12,8 +12,8 @@ import ListItemLink from 'components/ListItemLink'; import globalize from 'scripts/globalize'; const DLNA_PATHS = [ - '/dlnasettings.html', - '/dlnaprofiles.html' + '/dashboard/dlna', + '/dashboard/dlna/profiles' ]; const DevicesDrawerSection = () => { @@ -31,7 +31,7 @@ const DevicesDrawerSection = () => { } > - + @@ -47,7 +47,7 @@ const DevicesDrawerSection = () => { - + @@ -57,10 +57,10 @@ const DevicesDrawerSection = () => { - + - + diff --git a/src/apps/experimental/components/drawers/dashboard/LiveTvDrawerSection.tsx b/src/apps/dashboard/components/drawer/sections/LiveTvDrawerSection.tsx similarity index 92% rename from src/apps/experimental/components/drawers/dashboard/LiveTvDrawerSection.tsx rename to src/apps/dashboard/components/drawer/sections/LiveTvDrawerSection.tsx index e3d20e154a..35ea15ce0d 100644 --- a/src/apps/experimental/components/drawers/dashboard/LiveTvDrawerSection.tsx +++ b/src/apps/dashboard/components/drawer/sections/LiveTvDrawerSection.tsx @@ -20,7 +20,7 @@ const LiveTvDrawerSection = () => { } > - + @@ -28,7 +28,7 @@ const LiveTvDrawerSection = () => { - + diff --git a/src/apps/experimental/components/drawers/dashboard/PluginDrawerSection.tsx b/src/apps/dashboard/components/drawer/sections/PluginDrawerSection.tsx similarity index 100% rename from src/apps/experimental/components/drawers/dashboard/PluginDrawerSection.tsx rename to src/apps/dashboard/components/drawer/sections/PluginDrawerSection.tsx diff --git a/src/apps/experimental/components/drawers/dashboard/ServerDrawerSection.tsx b/src/apps/dashboard/components/drawer/sections/ServerDrawerSection.tsx similarity index 78% rename from src/apps/experimental/components/drawers/dashboard/ServerDrawerSection.tsx rename to src/apps/dashboard/components/drawer/sections/ServerDrawerSection.tsx index 2ed6b73f86..01e26ace84 100644 --- a/src/apps/experimental/components/drawers/dashboard/ServerDrawerSection.tsx +++ b/src/apps/dashboard/components/drawer/sections/ServerDrawerSection.tsx @@ -12,16 +12,16 @@ import ListItemLink from 'components/ListItemLink'; import globalize from 'scripts/globalize'; const LIBRARY_PATHS = [ - '/library.html', - '/librarydisplay.html', - '/metadataimages.html', - '/metadatanfo.html' + '/dashboard/libraries', + '/dashboard/libraries/display', + '/dashboard/libraries/metadata', + '/dashboard/libraries/nfo' ]; const PLAYBACK_PATHS = [ - '/encodingsettings.html', - '/playbackconfiguration.html', - '/streamingsettings.html' + '/dashboard/playback/transcoding', + '/dashboard/playback/resume', + '/dashboard/playback/streaming' ]; const ServerDrawerSection = () => { @@ -40,7 +40,7 @@ const ServerDrawerSection = () => { } > - + @@ -48,7 +48,7 @@ const ServerDrawerSection = () => { - + @@ -56,7 +56,7 @@ const ServerDrawerSection = () => { - + @@ -64,7 +64,7 @@ const ServerDrawerSection = () => { - + @@ -74,22 +74,22 @@ const ServerDrawerSection = () => { - + - + - + - + - + @@ -99,13 +99,13 @@ const ServerDrawerSection = () => { - + - + - + diff --git a/src/apps/dashboard/routes/_asyncRoutes.ts b/src/apps/dashboard/routes/_asyncRoutes.ts new file mode 100644 index 0000000000..09d40de0e8 --- /dev/null +++ b/src/apps/dashboard/routes/_asyncRoutes.ts @@ -0,0 +1,12 @@ +import 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' } +]; diff --git a/src/apps/experimental/routes/legacyRoutes/admin.ts b/src/apps/dashboard/routes/_legacyRoutes.ts similarity index 76% rename from src/apps/experimental/routes/legacyRoutes/admin.ts rename to src/apps/dashboard/routes/_legacyRoutes.ts index 35a3976445..efdd543a42 100644 --- a/src/apps/experimental/routes/legacyRoutes/admin.ts +++ b/src/apps/dashboard/routes/_legacyRoutes.ts @@ -1,170 +1,164 @@ -import { LegacyRoute } from '../../../../components/router/LegacyRoute'; +import type { LegacyRoute } from 'components/router/LegacyRoute'; export const LEGACY_ADMIN_ROUTES: LegacyRoute[] = [ { - path: 'dashboard.html', + path: '/dashboard', pageProps: { controller: 'dashboard/dashboard', view: 'dashboard/dashboard.html' } }, { - path: 'dashboardgeneral.html', + path: 'settings', pageProps: { controller: 'dashboard/general', view: 'dashboard/general.html' } }, { - path: 'networking.html', + path: 'networking', pageProps: { controller: 'dashboard/networking', view: 'dashboard/networking.html' } }, { - path: 'devices.html', + path: 'devices', pageProps: { controller: 'dashboard/devices/devices', view: 'dashboard/devices/devices.html' } }, { - path: 'device.html', + path: 'devices/edit', pageProps: { controller: 'dashboard/devices/device', view: 'dashboard/devices/device.html' } }, { - path: 'dlnaprofile.html', + path: 'dlna/profiles/edit', pageProps: { controller: 'dashboard/dlna/profile', view: 'dashboard/dlna/profile.html' } }, { - path: 'dlnaprofiles.html', + path: 'dlna/profiles', pageProps: { controller: 'dashboard/dlna/profiles', view: 'dashboard/dlna/profiles.html' } }, { - path: 'dlnasettings.html', + path: 'dlna', pageProps: { controller: 'dashboard/dlna/settings', view: 'dashboard/dlna/settings.html' } }, { - path: 'addplugin.html', + path: 'plugins/add', pageProps: { controller: 'dashboard/plugins/add/index', view: 'dashboard/plugins/add/index.html' } }, { - path: 'library.html', + path: 'libraries', pageProps: { controller: 'dashboard/library', view: 'dashboard/library.html' } }, { - path: 'librarydisplay.html', + path: 'libraries/display', pageProps: { controller: 'dashboard/librarydisplay', view: 'dashboard/librarydisplay.html' } }, { - path: 'edititemmetadata.html', - pageProps: { - controller: 'edititemmetadata', - view: 'edititemmetadata.html' - } - }, { - path: 'encodingsettings.html', + path: 'playback/transcoding', pageProps: { controller: 'dashboard/encodingsettings', view: 'dashboard/encodingsettings.html' } }, { - path: 'log.html', + path: 'logs', pageProps: { controller: 'dashboard/logs', view: 'dashboard/logs.html' } }, { - path: 'metadataimages.html', + path: 'libraries/metadata', pageProps: { controller: 'dashboard/metadataImages', view: 'dashboard/metadataimages.html' } }, { - path: 'metadatanfo.html', + path: 'libraries/nfo', pageProps: { controller: 'dashboard/metadatanfo', view: 'dashboard/metadatanfo.html' } }, { - path: 'playbackconfiguration.html', + path: 'playback/resume', pageProps: { controller: 'dashboard/playback', view: 'dashboard/playback.html' } }, { - path: 'availableplugins.html', + path: 'plugins/catalog', pageProps: { controller: 'dashboard/plugins/available/index', view: 'dashboard/plugins/available/index.html' } }, { - path: 'repositories.html', + path: 'plugins/repositories', pageProps: { controller: 'dashboard/plugins/repositories/index', view: 'dashboard/plugins/repositories/index.html' } }, { - path: 'livetvguideprovider.html', + path: 'livetv/guide', pageProps: { controller: 'livetvguideprovider', view: 'livetvguideprovider.html' } }, { - path: 'livetvsettings.html', + path: 'recordings', pageProps: { controller: 'livetvsettings', view: 'livetvsettings.html' } }, { - path: 'livetvstatus.html', + path: 'livetv', pageProps: { controller: 'livetvstatus', view: 'livetvstatus.html' } }, { - path: 'livetvtuner.html', + path: 'livetv/tuner', pageProps: { controller: 'livetvtuner', view: 'livetvtuner.html' } }, { - path: 'installedplugins.html', + path: 'plugins', pageProps: { controller: 'dashboard/plugins/installed/index', view: 'dashboard/plugins/installed/index.html' } }, { - path: 'scheduledtask.html', + path: 'tasks/edit', pageProps: { controller: 'dashboard/scheduledtasks/scheduledtask', view: 'dashboard/scheduledtasks/scheduledtask.html' } }, { - path: 'scheduledtasks.html', + path: 'tasks', pageProps: { controller: 'dashboard/scheduledtasks/scheduledtasks', view: 'dashboard/scheduledtasks/scheduledtasks.html' } }, { - path: 'apikeys.html', + path: 'keys', pageProps: { controller: 'dashboard/apikeys', view: 'dashboard/apikeys.html' } }, { - path: 'streamingsettings.html', + path: 'playback/streaming', pageProps: { view: 'dashboard/streaming.html', controller: 'dashboard/streaming' diff --git a/src/apps/dashboard/routes/_redirects.ts b/src/apps/dashboard/routes/_redirects.ts new file mode 100644 index 0000000000..94211c79c2 --- /dev/null +++ b/src/apps/dashboard/routes/_redirects.ts @@ -0,0 +1,40 @@ +import type { Redirect } from 'components/router/Redirect'; + +export const REDIRECTS: Redirect[] = [ + { from: 'addplugin.html', to: '/dashboard/plugins/add' }, + { from: 'apikeys.html', to: '/dashboard/keys' }, + { from: 'availableplugins.html', to: '/dashboard/plugins/catalog' }, + { from: 'dashboard.html', to: '/dashboard' }, + { from: 'dashboardgeneral.html', to: '/dashboard/settings' }, + { from: 'device.html', to: '/dashboard/devices/edit' }, + { from: 'devices.html', to: '/dashboard/devices' }, + { from: 'dlnaprofile.html', to: '/dashboard/dlna/profiles/edit' }, + { from: 'dlnaprofiles.html', to: '/dashboard/dlna/profiles' }, + { from: 'dlnasettings.html', to: '/dashboard/dlna' }, + { from: 'edititemmetadata.html', to: '/metadata' }, + { from: 'encodingsettings.html', to: '/dashboard/playback/transcoding' }, + { from: 'installedplugins.html', to: '/dashboard/plugins' }, + { from: 'library.html', to: '/dashboard/libraries' }, + { from: 'librarydisplay.html', to: '/dashboard/libraries/display' }, + { from: 'livetvguideprovider.html', to: '/dashboard/livetv/guide' }, + { from: 'livetvsettings.html', to: '/dashboard/recordings' }, + { from: 'livetvstatus.html', to: '/dashboard/livetv' }, + { from: 'livetvtuner.html', to: '/dashboard/livetv/tuner' }, + { from: 'log.html', to: '/dashboard/logs' }, + { from: 'metadataimages.html', to: '/dashboard/libraries/metadata' }, + { from: 'metadatanfo.html', to: '/dashboard/libraries/nfo' }, + { from: 'networking.html', to: '/dashboard/networking' }, + { from: 'notificationsettings.html', to: '/dashboard/notifications' }, + { from: 'playbackconfiguration.html', to: '/dashboard/playback/resume' }, + { from: 'repositories.html', to: '/dashboard/plugins/repositories' }, + { from: 'scheduledtask.html', to: '/dashboard/tasks/edit' }, + { from: 'scheduledtasks.html', to: '/dashboard/tasks' }, + { from: 'serveractivity.html', to: '/dashboard/activity' }, + { from: 'streamingsettings.html', to: '/dashboard/playback/streaming' }, + { from: 'useredit.html', to: '/dashboard/users/profile' }, + { from: 'userlibraryaccess.html', to: '/dashboard/users/access' }, + { from: 'usernew.html', to: '/dashboard/users/add' }, + { from: 'userparentalcontrol.html', to: '/dashboard/users/parentalcontrol' }, + { from: 'userpassword.html', to: '/dashboard/users/password' }, + { from: 'userprofiles.html', to: '/dashboard/users' } +]; diff --git a/src/apps/experimental/routes/dashboard/activity.tsx b/src/apps/dashboard/routes/activity.tsx similarity index 97% rename from src/apps/experimental/routes/dashboard/activity.tsx rename to src/apps/dashboard/routes/activity.tsx index f007e104d3..fa3a9135bd 100644 --- a/src/apps/experimental/routes/dashboard/activity.tsx +++ b/src/apps/dashboard/routes/activity.tsx @@ -19,9 +19,9 @@ import { parseISO8601Date, toLocaleDateString, toLocaleTimeString } from 'script import globalize from 'scripts/globalize'; import { toBoolean } from 'utils/string'; -import LogLevelChip from '../../components/activityTable/LogLevelChip'; -import OverviewCell from '../../components/activityTable/OverviewCell'; -import GridActionsCellLink from '../../components/GridActionsCellLink'; +import LogLevelChip from '../components/activityTable/LogLevelChip'; +import OverviewCell from '../components/activityTable/OverviewCell'; +import GridActionsCellLink from '../components/dataGrid/GridActionsCellLink'; const DEFAULT_PAGE_SIZE = 25; const VIEW_PARAM = 'useractivity'; @@ -68,7 +68,7 @@ const Activity = () => { sx={{ padding: 0 }} title={users[row.UserId]?.Name ?? undefined} component={Link} - to={`/useredit.html?userId=${row.UserId}`} + to={`/dashboard/users/profile?userId=${row.UserId}`} > diff --git a/src/apps/stable/routes/dashboard/notifications.tsx b/src/apps/dashboard/routes/notifications.tsx similarity index 89% rename from src/apps/stable/routes/dashboard/notifications.tsx rename to src/apps/dashboard/routes/notifications.tsx index ca874d1333..6f673c753f 100644 --- a/src/apps/stable/routes/dashboard/notifications.tsx +++ b/src/apps/dashboard/routes/notifications.tsx @@ -9,7 +9,7 @@ const PluginLink = () => ( __html: ` ${globalize.translate('GetThePlugin')} ` diff --git a/src/apps/stable/routes/user/userlibraryaccess.tsx b/src/apps/dashboard/routes/users/access.tsx similarity index 100% rename from src/apps/stable/routes/user/userlibraryaccess.tsx rename to src/apps/dashboard/routes/users/access.tsx diff --git a/src/apps/stable/routes/user/usernew.tsx b/src/apps/dashboard/routes/users/add.tsx similarity index 99% rename from src/apps/stable/routes/user/usernew.tsx rename to src/apps/dashboard/routes/users/add.tsx index 22758500ea..116895e947 100644 --- a/src/apps/stable/routes/user/usernew.tsx +++ b/src/apps/dashboard/routes/users/add.tsx @@ -140,7 +140,7 @@ const UserNew: FunctionComponent = () => { } window.ApiClient.updateUserPolicy(user.Id, user.Policy).then(function () { - Dashboard.navigate('useredit.html?userId=' + user.Id) + Dashboard.navigate('/dashboard/users/profile?userId=' + user.Id) .catch(err => { console.error('[usernew] failed to navigate to edit user page', err); }); diff --git a/src/apps/stable/routes/user/userprofiles.tsx b/src/apps/dashboard/routes/users/index.tsx similarity index 94% rename from src/apps/stable/routes/user/userprofiles.tsx rename to src/apps/dashboard/routes/users/index.tsx index dc8a6e86fd..6789a00ce8 100644 --- a/src/apps/stable/routes/user/userprofiles.tsx +++ b/src/apps/dashboard/routes/users/index.tsx @@ -85,21 +85,21 @@ const UserProfiles: FunctionComponent = () => { callback: function (id: string) { switch (id) { case 'open': - Dashboard.navigate('useredit.html?userId=' + userId) + Dashboard.navigate('/dashboard/users/profile?userId=' + userId) .catch(err => { console.error('[userprofiles] failed to navigate to user edit page', err); }); break; case 'access': - Dashboard.navigate('userlibraryaccess.html?userId=' + userId) + Dashboard.navigate('/dashboard/users/access?userId=' + userId) .catch(err => { console.error('[userprofiles] failed to navigate to user library page', err); }); break; case 'parentalcontrol': - Dashboard.navigate('userparentalcontrol.html?userId=' + userId) + Dashboard.navigate('/dashboard/users/parentalcontrol?userId=' + userId) .catch(err => { console.error('[userprofiles] failed to navigate to parental control page', err); }); @@ -146,7 +146,7 @@ const UserProfiles: FunctionComponent = () => { }); (page.querySelector('#btnAddUser') as HTMLButtonElement).addEventListener('click', function() { - Dashboard.navigate('usernew.html') + Dashboard.navigate('/dashboard/users/add') .catch(err => { console.error('[userprofiles] failed to navigate to new user page', err); }); diff --git a/src/apps/stable/routes/user/userparentalcontrol.tsx b/src/apps/dashboard/routes/users/parentalcontrol.tsx similarity index 100% rename from src/apps/stable/routes/user/userparentalcontrol.tsx rename to src/apps/dashboard/routes/users/parentalcontrol.tsx diff --git a/src/apps/stable/routes/user/userpassword.tsx b/src/apps/dashboard/routes/users/password.tsx similarity index 100% rename from src/apps/stable/routes/user/userpassword.tsx rename to src/apps/dashboard/routes/users/password.tsx diff --git a/src/apps/stable/routes/user/useredit.tsx b/src/apps/dashboard/routes/users/profile.tsx similarity index 99% rename from src/apps/stable/routes/user/useredit.tsx rename to src/apps/dashboard/routes/users/profile.tsx index c4acdfaaee..05d3b72cdf 100644 --- a/src/apps/stable/routes/user/useredit.tsx +++ b/src/apps/dashboard/routes/users/profile.tsx @@ -32,7 +32,7 @@ const getCheckedElementDataIds = (elements: NodeListOf) => ( ); function onSaveComplete() { - Dashboard.navigate('userprofiles.html') + Dashboard.navigate('/dashboard/users') .catch(err => { console.error('[useredit] failed to navigate to user profile', err); }); diff --git a/src/apps/experimental/App.tsx b/src/apps/experimental/App.tsx index 44c6d24b2d..b17e9054ee 100644 --- a/src/apps/experimental/App.tsx +++ b/src/apps/experimental/App.tsx @@ -1,16 +1,16 @@ import React from 'react'; import { Navigate, Route, Routes } from 'react-router-dom'; +import { DASHBOARD_APP_PATHS } from 'apps/dashboard/App'; import { REDIRECTS } from 'apps/stable/routes/_redirects'; import ConnectionRequired from 'components/ConnectionRequired'; -import ServerContentPage from 'components/ServerContentPage'; import { toAsyncPageRoute } from 'components/router/AsyncRoute'; import { toViewManagerPageRoute } from 'components/router/LegacyRoute'; import { toRedirectRoute } from 'components/router/Redirect'; import AppLayout from './AppLayout'; -import { ASYNC_ADMIN_ROUTES, ASYNC_USER_ROUTES } from './routes/asyncRoutes'; -import { LEGACY_ADMIN_ROUTES, LEGACY_PUBLIC_ROUTES, LEGACY_USER_ROUTES } from './routes/legacyRoutes'; +import { ASYNC_USER_ROUTES } from './routes/asyncRoutes'; +import { LEGACY_PUBLIC_ROUTES, LEGACY_USER_ROUTES } from './routes/legacyRoutes'; const ExperimentalApp = () => { return ( @@ -22,16 +22,6 @@ const ExperimentalApp = () => { {LEGACY_USER_ROUTES.map(toViewManagerPageRoute)} - {/* Admin routes */} - }> - {ASYNC_ADMIN_ROUTES.map(toAsyncPageRoute)} - {LEGACY_ADMIN_ROUTES.map(toViewManagerPageRoute)} - - - } /> - - {/* Public routes */} }> } /> @@ -42,6 +32,15 @@ const ExperimentalApp = () => { {/* Redirects for old paths */} {REDIRECTS.map(toRedirectRoute)} + + {/* Ignore dashboard routes */} + {Object.entries(DASHBOARD_APP_PATHS).map(([ key, path ]) => ( + + ))} ); }; diff --git a/src/apps/experimental/AppOverrides.scss b/src/apps/experimental/AppOverrides.scss index c365a5b295..cece6608c1 100644 --- a/src/apps/experimental/AppOverrides.scss +++ b/src/apps/experimental/AppOverrides.scss @@ -10,11 +10,6 @@ $mui-bp-xl: 1536px; position: relative; } -// Fix dashboard pages layout to work with drawer -.dashboardDocument .skinBody { - position: unset; -} - // Hide some items from the user "settings" page that are in the drawer #myPreferencesMenuPage { .lnkQuickConnectPreferences, @@ -26,8 +21,7 @@ $mui-bp-xl: 1536px; // Fix the padding of some pages .homePage.libraryPage, // Home page -.libraryPage:not(.withTabs), // Tabless library pages -.content-primary.content-primary { // Dashboard pages +.libraryPage:not(.withTabs) { // Tabless library pages padding-top: 3.25rem !important; } diff --git a/src/apps/experimental/components/drawers/AppDrawer.tsx b/src/apps/experimental/components/drawers/AppDrawer.tsx index c414e6ba78..21926d6c59 100644 --- a/src/apps/experimental/components/drawers/AppDrawer.tsx +++ b/src/apps/experimental/components/drawers/AppDrawer.tsx @@ -1,23 +1,15 @@ import React, { FC } from 'react'; -import { Route, Routes, useLocation } from 'react-router-dom'; +import { useLocation } from 'react-router-dom'; import ResponsiveDrawer, { ResponsiveDrawerProps } from 'components/ResponsiveDrawer'; -import { ASYNC_ADMIN_ROUTES, ASYNC_USER_ROUTES } from '../../routes/asyncRoutes'; -import { LEGACY_ADMIN_ROUTES, LEGACY_USER_ROUTES } from '../../routes/legacyRoutes'; - -import AdvancedDrawerSection from './dashboard/AdvancedDrawerSection'; -import DevicesDrawerSection from './dashboard/DevicesDrawerSection'; -import LiveTvDrawerSection from './dashboard/LiveTvDrawerSection'; -import PluginDrawerSection from './dashboard/PluginDrawerSection'; -import ServerDrawerSection from './dashboard/ServerDrawerSection'; -import MainDrawerContent from './MainDrawerContent'; +import { ASYNC_USER_ROUTES } from '../../routes/asyncRoutes'; +import { LEGACY_USER_ROUTES } from '../../routes/legacyRoutes'; import { isTabPath } from '../tabs/tabRoutes'; -export const DRAWER_WIDTH = 240; +import MainDrawerContent from './MainDrawerContent'; const DRAWERLESS_ROUTES = [ - 'edititemmetadata.html', // metadata manager 'video' // video player ]; @@ -26,77 +18,29 @@ const MAIN_DRAWER_ROUTES = [ ...LEGACY_USER_ROUTES ].filter(route => !DRAWERLESS_ROUTES.includes(route.path)); -const ADMIN_DRAWER_ROUTES = [ - ...ASYNC_ADMIN_ROUTES, - ...LEGACY_ADMIN_ROUTES, - { path: '/configurationpage' } // Plugin configuration page -].filter(route => !DRAWERLESS_ROUTES.includes(route.path)); - /** Utility function to check if a path has a drawer. */ export const isDrawerPath = (path: string) => ( MAIN_DRAWER_ROUTES.some(route => route.path === path || `/${route.path}` === path) - || ADMIN_DRAWER_ROUTES.some(route => route.path === path || `/${route.path}` === path) ); -const Drawer: FC = ({ children, ...props }) => { - const location = useLocation(); - const hasSecondaryToolBar = isTabPath(location.pathname); - - return ( - - {children} - - ); -}; - const AppDrawer: FC = ({ open = false, onClose, onOpen -}) => ( - - { - MAIN_DRAWER_ROUTES.map(route => ( - - - - } - /> - )) - } - { - ADMIN_DRAWER_ROUTES.map(route => ( - - - - - - - - } - /> - )) - } - -); +}) => { + const location = useLocation(); + const hasSecondaryToolBar = isTabPath(location.pathname); + + return ( + + + + ); +}; export default AppDrawer; diff --git a/src/apps/experimental/components/drawers/MainDrawerContent.tsx b/src/apps/experimental/components/drawers/MainDrawerContent.tsx index 4d2a74b8a9..351076a025 100644 --- a/src/apps/experimental/components/drawers/MainDrawerContent.tsx +++ b/src/apps/experimental/components/drawers/MainDrawerContent.tsx @@ -150,7 +150,7 @@ const MainDrawerContent = () => { } > - + @@ -158,7 +158,7 @@ const MainDrawerContent = () => { - + diff --git a/src/apps/experimental/routes/asyncRoutes/admin.ts b/src/apps/experimental/routes/asyncRoutes/admin.ts deleted file mode 100644 index 7e8c0eca16..0000000000 --- a/src/apps/experimental/routes/asyncRoutes/admin.ts +++ /dev/null @@ -1,12 +0,0 @@ -import { AsyncRoute, AsyncRouteType } from 'components/router/AsyncRoute'; - -export const ASYNC_ADMIN_ROUTES: AsyncRoute[] = [ - { path: 'dashboard/activity', page: 'dashboard/activity', type: AsyncRouteType.Experimental }, - { path: 'notificationsettings.html', page: 'dashboard/notifications' }, - { path: 'usernew.html', page: 'user/usernew' }, - { path: 'userprofiles.html', page: 'user/userprofiles' }, - { path: 'useredit.html', page: 'user/useredit' }, - { path: 'userlibraryaccess.html', page: 'user/userlibraryaccess' }, - { path: 'userparentalcontrol.html', page: 'user/userparentalcontrol' }, - { path: 'userpassword.html', page: 'user/userpassword' } -]; diff --git a/src/apps/experimental/routes/asyncRoutes/index.ts b/src/apps/experimental/routes/asyncRoutes/index.ts index 9dd4fb3c99..e5abc85650 100644 --- a/src/apps/experimental/routes/asyncRoutes/index.ts +++ b/src/apps/experimental/routes/asyncRoutes/index.ts @@ -1,2 +1 @@ -export * from './admin'; export * from './user'; diff --git a/src/apps/experimental/routes/legacyRoutes/index.ts b/src/apps/experimental/routes/legacyRoutes/index.ts index 2931c568e8..bc46c94c54 100644 --- a/src/apps/experimental/routes/legacyRoutes/index.ts +++ b/src/apps/experimental/routes/legacyRoutes/index.ts @@ -1,3 +1,2 @@ -export * from './admin'; export * from './public'; export * from './user'; diff --git a/src/apps/stable/App.tsx b/src/apps/stable/App.tsx index 8285cbc9ec..9b0adbab9c 100644 --- a/src/apps/stable/App.tsx +++ b/src/apps/stable/App.tsx @@ -1,17 +1,17 @@ import React from 'react'; import { Navigate, Outlet, Route, Routes } from 'react-router-dom'; +import { DASHBOARD_APP_PATHS } from 'apps/dashboard/App'; import AppBody from 'components/AppBody'; -import ServerContentPage from 'components/ServerContentPage'; import ConnectionRequired from 'components/ConnectionRequired'; import { toAsyncPageRoute } from 'components/router/AsyncRoute'; import { toViewManagerPageRoute } from 'components/router/LegacyRoute'; - -import { ASYNC_ADMIN_ROUTES, ASYNC_USER_ROUTES } from './routes/asyncRoutes'; -import { LEGACY_ADMIN_ROUTES, LEGACY_PUBLIC_ROUTES, LEGACY_USER_ROUTES } from './routes/legacyRoutes'; -import { REDIRECTS } from './routes/_redirects'; import { toRedirectRoute } from 'components/router/Redirect'; +import { ASYNC_USER_ROUTES } from './routes/asyncRoutes'; +import { LEGACY_PUBLIC_ROUTES, LEGACY_USER_ROUTES } from './routes/legacyRoutes'; +import { REDIRECTS } from './routes/_redirects'; + const Layout = () => ( @@ -27,16 +27,6 @@ const StableApp = () => ( {LEGACY_USER_ROUTES.map(toViewManagerPageRoute)} - {/* Admin routes */} - }> - {ASYNC_ADMIN_ROUTES.map(toAsyncPageRoute)} - {LEGACY_ADMIN_ROUTES.map(toViewManagerPageRoute)} - - - } /> - - {/* Public routes */} }> } /> @@ -50,6 +40,15 @@ const StableApp = () => ( {/* Redirects for old paths */} {REDIRECTS.map(toRedirectRoute)} + + {/* Ignore dashboard routes */} + {Object.entries(DASHBOARD_APP_PATHS).map(([ key, path ]) => ( + + ))} ); diff --git a/src/apps/stable/routes/_redirects.ts b/src/apps/stable/routes/_redirects.ts index fb24865d84..d48c48d995 100644 --- a/src/apps/stable/routes/_redirects.ts +++ b/src/apps/stable/routes/_redirects.ts @@ -1,6 +1,5 @@ import type { Redirect } from 'components/router/Redirect'; export const REDIRECTS: Redirect[] = [ - { from: 'mypreferencesquickconnect.html', to: '/quickconnect' }, - { from: 'serveractivity.html', to: '/dashboard/activity' } + { from: 'mypreferencesquickconnect.html', to: '/quickconnect' } ]; diff --git a/src/apps/stable/routes/asyncRoutes/admin.ts b/src/apps/stable/routes/asyncRoutes/admin.ts deleted file mode 100644 index 72bcc6f32b..0000000000 --- a/src/apps/stable/routes/asyncRoutes/admin.ts +++ /dev/null @@ -1,11 +0,0 @@ -import { AsyncRoute } from '../../../../components/router/AsyncRoute'; - -export const ASYNC_ADMIN_ROUTES: AsyncRoute[] = [ - { path: 'notificationsettings.html', page: 'dashboard/notifications' }, - { path: 'usernew.html', page: 'user/usernew' }, - { path: 'userprofiles.html', page: 'user/userprofiles' }, - { path: 'useredit.html', page: 'user/useredit' }, - { path: 'userlibraryaccess.html', page: 'user/userlibraryaccess' }, - { path: 'userparentalcontrol.html', page: 'user/userparentalcontrol' }, - { path: 'userpassword.html', page: 'user/userpassword' } -]; diff --git a/src/apps/stable/routes/asyncRoutes/index.ts b/src/apps/stable/routes/asyncRoutes/index.ts index 9dd4fb3c99..e5abc85650 100644 --- a/src/apps/stable/routes/asyncRoutes/index.ts +++ b/src/apps/stable/routes/asyncRoutes/index.ts @@ -1,2 +1 @@ -export * from './admin'; export * from './user'; diff --git a/src/apps/stable/routes/legacyRoutes/admin.ts b/src/apps/stable/routes/legacyRoutes/admin.ts deleted file mode 100644 index fd430feeba..0000000000 --- a/src/apps/stable/routes/legacyRoutes/admin.ts +++ /dev/null @@ -1,179 +0,0 @@ -import { LegacyRoute } from '../../../../components/router/LegacyRoute'; - -export const LEGACY_ADMIN_ROUTES: LegacyRoute[] = [ - { - path: 'dashboard.html', - pageProps: { - controller: 'dashboard/dashboard', - view: 'dashboard/dashboard.html' - } - }, { - path: 'dashboardgeneral.html', - pageProps: { - controller: 'dashboard/general', - view: 'dashboard/general.html' - } - }, { - path: 'networking.html', - pageProps: { - controller: 'dashboard/networking', - view: 'dashboard/networking.html' - } - }, { - path: 'devices.html', - pageProps: { - controller: 'dashboard/devices/devices', - view: 'dashboard/devices/devices.html' - } - }, { - path: 'device.html', - pageProps: { - controller: 'dashboard/devices/device', - view: 'dashboard/devices/device.html' - } - }, { - path: 'dlnaprofile.html', - pageProps: { - controller: 'dashboard/dlna/profile', - view: 'dashboard/dlna/profile.html' - } - }, { - path: 'dlnaprofiles.html', - pageProps: { - controller: 'dashboard/dlna/profiles', - view: 'dashboard/dlna/profiles.html' - } - }, { - path: 'dlnasettings.html', - pageProps: { - controller: 'dashboard/dlna/settings', - view: 'dashboard/dlna/settings.html' - } - }, { - path: 'addplugin.html', - pageProps: { - controller: 'dashboard/plugins/add/index', - view: 'dashboard/plugins/add/index.html' - } - }, { - path: 'library.html', - pageProps: { - controller: 'dashboard/library', - view: 'dashboard/library.html' - } - }, { - path: 'librarydisplay.html', - pageProps: { - controller: 'dashboard/librarydisplay', - view: 'dashboard/librarydisplay.html' - } - }, { - path: 'edititemmetadata.html', - pageProps: { - controller: 'edititemmetadata', - view: 'edititemmetadata.html' - } - }, { - path: 'encodingsettings.html', - pageProps: { - controller: 'dashboard/encodingsettings', - view: 'dashboard/encodingsettings.html' - } - }, { - path: 'log.html', - pageProps: { - controller: 'dashboard/logs', - view: 'dashboard/logs.html' - } - }, { - path: 'metadataimages.html', - pageProps: { - controller: 'dashboard/metadataImages', - view: 'dashboard/metadataimages.html' - } - }, { - path: 'metadatanfo.html', - pageProps: { - controller: 'dashboard/metadatanfo', - view: 'dashboard/metadatanfo.html' - } - }, { - path: 'playbackconfiguration.html', - pageProps: { - controller: 'dashboard/playback', - view: 'dashboard/playback.html' - } - }, { - path: 'availableplugins.html', - pageProps: { - controller: 'dashboard/plugins/available/index', - view: 'dashboard/plugins/available/index.html' - } - }, { - path: 'repositories.html', - pageProps: { - controller: 'dashboard/plugins/repositories/index', - view: 'dashboard/plugins/repositories/index.html' - } - }, { - path: 'livetvguideprovider.html', - pageProps: { - controller: 'livetvguideprovider', - view: 'livetvguideprovider.html' - } - }, { - path: 'livetvsettings.html', - pageProps: { - controller: 'livetvsettings', - view: 'livetvsettings.html' - } - }, { - path: 'livetvstatus.html', - pageProps: { - controller: 'livetvstatus', - view: 'livetvstatus.html' - } - }, { - path: 'livetvtuner.html', - pageProps: { - controller: 'livetvtuner', - view: 'livetvtuner.html' - } - }, { - path: 'installedplugins.html', - pageProps: { - controller: 'dashboard/plugins/installed/index', - view: 'dashboard/plugins/installed/index.html' - } - }, { - path: 'scheduledtask.html', - pageProps: { - controller: 'dashboard/scheduledtasks/scheduledtask', - view: 'dashboard/scheduledtasks/scheduledtask.html' - } - }, { - path: 'scheduledtasks.html', - pageProps: { - controller: 'dashboard/scheduledtasks/scheduledtasks', - view: 'dashboard/scheduledtasks/scheduledtasks.html' - } - }, { - path: 'dashboard/activity', - pageProps: { - controller: 'dashboard/serveractivity', - view: 'dashboard/serveractivity.html' - } - }, { - path: 'apikeys.html', - pageProps: { - controller: 'dashboard/apikeys', - view: 'dashboard/apikeys.html' - } - }, { - path: 'streamingsettings.html', - pageProps: { - view: 'dashboard/streaming.html', - controller: 'dashboard/streaming' - } - } -]; diff --git a/src/apps/stable/routes/legacyRoutes/index.ts b/src/apps/stable/routes/legacyRoutes/index.ts index 2931c568e8..bc46c94c54 100644 --- a/src/apps/stable/routes/legacyRoutes/index.ts +++ b/src/apps/stable/routes/legacyRoutes/index.ts @@ -1,3 +1,2 @@ -export * from './admin'; export * from './public'; export * from './user'; diff --git a/src/components/dashboard/users/SectionTabs.tsx b/src/components/dashboard/users/SectionTabs.tsx index 0fad3469df..1befb5912b 100644 --- a/src/components/dashboard/users/SectionTabs.tsx +++ b/src/components/dashboard/users/SectionTabs.tsx @@ -10,28 +10,28 @@ const createLinkElement = (activeTab: string) => ({ is="emby-linkbutton" data-role="button" class="${activeTab === 'useredit' ? 'ui-btn-active' : ''}" - onclick="Dashboard.navigate('useredit.html', true);"> + onclick="Dashboard.navigate('/dashboard/users/profile', true);"> ${globalize.translate('Profile')} + onclick="Dashboard.navigate('/dashboard/users/access', true);"> ${globalize.translate('TabAccess')} + onclick="Dashboard.navigate('/dashboard/users/parentalcontrol', true);"> ${globalize.translate('TabParentalControl')} + onclick="Dashboard.navigate('/dashboard/users/password', true);"> ${globalize.translate('HeaderPassword')} ` }); diff --git a/src/components/dashboard/users/UserCardBox.tsx b/src/components/dashboard/users/UserCardBox.tsx index b535f7a16d..f0fbdf96a7 100644 --- a/src/components/dashboard/users/UserCardBox.tsx +++ b/src/components/dashboard/users/UserCardBox.tsx @@ -11,7 +11,7 @@ const createLinkElement = ({ user, renderImgUrl }: { user: UserDto, renderImgUrl __html: ` ${renderImgUrl} ` diff --git a/src/components/homesections/homesections.js b/src/components/homesections/homesections.js index 6f7be53f6e..27c48f0998 100644 --- a/src/components/homesections/homesections.js +++ b/src/components/homesections/homesections.js @@ -99,7 +99,7 @@ export function loadSections(elem, apiClient, user, userSettings) { const createNowLink = elem.querySelector('#button-createLibrary'); if (createNowLink) { createNowLink.addEventListener('click', function () { - Dashboard.navigate('library.html'); + Dashboard.navigate('dashboard/libraries'); }); } } diff --git a/src/components/router/appRouter.js b/src/components/router/appRouter.js index 253fdee922..c56d7fc6be 100644 --- a/src/components/router/appRouter.js +++ b/src/components/router/appRouter.js @@ -527,7 +527,7 @@ class AppRouter { } if (item === 'manageserver') { - return '#/dashboard.html'; + return '#/dashboard'; } if (item === 'recordedtv') { diff --git a/src/components/toolbar/AppUserMenu.tsx b/src/components/toolbar/AppUserMenu.tsx index 7119a4f504..634d02cf88 100644 --- a/src/components/toolbar/AppUserMenu.tsx +++ b/src/components/toolbar/AppUserMenu.tsx @@ -115,7 +115,7 @@ const AppUserMenu: FC = ({ @@ -127,7 +127,7 @@ const AppUserMenu: FC = ({ diff --git a/src/controllers/dashboard/dashboard.html b/src/controllers/dashboard/dashboard.html index a76cf11971..aed6bb206f 100644 --- a/src/controllers/dashboard/dashboard.html +++ b/src/controllers/dashboard/dashboard.html @@ -3,7 +3,7 @@
- +

${TabServer}

@@ -33,7 +33,7 @@
- +

${HeaderActiveDevices}

@@ -70,7 +70,7 @@
- +

${HeaderPaths}

diff --git a/src/controllers/dashboard/devices/devices.js b/src/controllers/dashboard/devices/devices.js index 1c5ede9531..c62571a1bc 100644 --- a/src/controllers/dashboard/devices/devices.js +++ b/src/controllers/dashboard/devices/devices.js @@ -73,7 +73,7 @@ function showDeviceMenu(view, btn, deviceId) { callback: function (id) { switch (id) { case 'open': - Dashboard.navigate('device.html?id=' + deviceId); + Dashboard.navigate('dashboard/devices/edit?id=' + deviceId); break; case 'delete': @@ -94,7 +94,7 @@ function load(page, devices) { deviceHtml += '
'; deviceHtml += ' diff --git a/src/controllers/dashboard/dlna/profile.js b/src/controllers/dashboard/dlna/profile.js index 0a88f4214e..0f92a3200c 100644 --- a/src/controllers/dashboard/dlna/profile.js +++ b/src/controllers/dashboard/dlna/profile.js @@ -639,7 +639,7 @@ function saveProfile(page, profile) { data: JSON.stringify(profile), contentType: 'application/json' }).then(function () { - Dashboard.navigate('dlnaprofiles.html'); + Dashboard.navigate('dashboard/dlna/profiles'); }, Dashboard.processErrorResponse); } diff --git a/src/controllers/dashboard/dlna/profiles.html b/src/controllers/dashboard/dlna/profiles.html index 6eb60d1c34..f1696632c9 100644 --- a/src/controllers/dashboard/dlna/profiles.html +++ b/src/controllers/dashboard/dlna/profiles.html @@ -8,7 +8,7 @@
diff --git a/src/controllers/dashboard/dlna/profiles.js b/src/controllers/dashboard/dlna/profiles.js index a7c8f045c4..f69a0c6bf0 100644 --- a/src/controllers/dashboard/dlna/profiles.js +++ b/src/controllers/dashboard/dlna/profiles.js @@ -40,7 +40,7 @@ function renderProfiles(page, element, profiles) { html += '
'; html += ''; html += ''; @@ -78,10 +78,10 @@ function deleteProfile(page, id) { function getTabs() { return [{ - href: '#/dlnasettings.html', + href: '#/dashboard/dlna', name: globalize.translate('Settings') }, { - href: '#/dlnaprofiles.html', + href: '#/dashboard/dlna/profiles', name: globalize.translate('TabProfiles') }]; } diff --git a/src/controllers/dashboard/dlna/settings.js b/src/controllers/dashboard/dlna/settings.js index fcc7d7d100..d12b6744af 100644 --- a/src/controllers/dashboard/dlna/settings.js +++ b/src/controllers/dashboard/dlna/settings.js @@ -37,10 +37,10 @@ function onSubmit() { function getTabs() { return [{ - href: '#/dlnasettings.html', + href: '#/dashboard/dlna', name: globalize.translate('Settings') }, { - href: '#/dlnaprofiles.html', + href: '#/dashboard/dlna/profiles', name: globalize.translate('TabProfiles') }]; } diff --git a/src/controllers/dashboard/encodingsettings.js b/src/controllers/dashboard/encodingsettings.js index 9c268c0866..24946cadb7 100644 --- a/src/controllers/dashboard/encodingsettings.js +++ b/src/controllers/dashboard/encodingsettings.js @@ -167,13 +167,13 @@ function setDecodingCodecsVisible(context, value) { function getTabs() { return [{ - href: '#/encodingsettings.html', + href: '#/dashboard/playback/transcoding', name: globalize.translate('Transcoding') }, { - href: '#/playbackconfiguration.html', + href: '#/dashboard/playback/resume', name: globalize.translate('ButtonResume') }, { - href: '#/streamingsettings.html', + href: '#/dashboard/playback/streaming', name: globalize.translate('TabStreaming') }]; } diff --git a/src/controllers/dashboard/library.js b/src/controllers/dashboard/library.js index 51ca3af712..62d9329969 100644 --- a/src/controllers/dashboard/library.js +++ b/src/controllers/dashboard/library.js @@ -360,16 +360,16 @@ function getVirtualFolderHtml(page, virtualFolder, index) { function getTabs() { return [{ - href: '#/library.html', + href: '#/dashboard/libraries', name: globalize.translate('HeaderLibraries') }, { - href: '#/librarydisplay.html', + href: '#/dashboard/libraries/display', name: globalize.translate('Display') }, { - href: '#/metadataimages.html', + href: '#/dashboard/libraries/metadata', name: globalize.translate('Metadata') }, { - href: '#/metadatanfo.html', + href: '#/dashboard/libraries/nfo', name: globalize.translate('TabNfoSettings') }]; } diff --git a/src/controllers/dashboard/librarydisplay.js b/src/controllers/dashboard/librarydisplay.js index b418984fb7..a38608277d 100644 --- a/src/controllers/dashboard/librarydisplay.js +++ b/src/controllers/dashboard/librarydisplay.js @@ -7,16 +7,16 @@ import Dashboard from '../../utils/dashboard'; function getTabs() { return [{ - href: '#/library.html', + href: '#/dashboard/libraries', name: globalize.translate('HeaderLibraries') }, { - href: '#/librarydisplay.html', + href: '#/dashboard/libraries/display', name: globalize.translate('Display') }, { - href: '#/metadataimages.html', + href: '#/dashboard/libraries/metadata', name: globalize.translate('Metadata') }, { - href: '#/metadatanfo.html', + href: '#/dashboard/libraries/nfo', name: globalize.translate('TabNfoSettings') }]; } diff --git a/src/controllers/dashboard/metadataImages.js b/src/controllers/dashboard/metadataImages.js index 53633d6915..779727dc7a 100644 --- a/src/controllers/dashboard/metadataImages.js +++ b/src/controllers/dashboard/metadataImages.js @@ -88,16 +88,16 @@ function onSubmit() { function getTabs() { return [{ - href: '#/library.html', + href: '#/dashboard/libraries', name: globalize.translate('HeaderLibraries') }, { - href: '#/librarydisplay.html', + href: '#/dashboard/libraries/display', name: globalize.translate('Display') }, { - href: '#/metadataimages.html', + href: '#/dashboard/libraries/metadata', name: globalize.translate('Metadata') }, { - href: '#/metadatanfo.html', + href: '#/dashboard/libraries/nfo', name: globalize.translate('TabNfoSettings') }]; } diff --git a/src/controllers/dashboard/metadatanfo.js b/src/controllers/dashboard/metadatanfo.js index 38e2ec71fe..1a68d4d63c 100644 --- a/src/controllers/dashboard/metadatanfo.js +++ b/src/controllers/dashboard/metadatanfo.js @@ -46,16 +46,16 @@ function showConfirmMessage() { function getTabs() { return [{ - href: '#/library.html', + href: '#/dashboard/libraries', name: globalize.translate('HeaderLibraries') }, { - href: '#/librarydisplay.html', + href: '#/dashboard/libraries/display', name: globalize.translate('Display') }, { - href: '#/metadataimages.html', + href: '#/dashboard/libraries/metadata', name: globalize.translate('Metadata') }, { - href: '#/metadatanfo.html', + href: '#/dashboard/libraries/nfo', name: globalize.translate('TabNfoSettings') }]; } diff --git a/src/controllers/dashboard/playback.js b/src/controllers/dashboard/playback.js index f24e77efd9..6b4985df34 100644 --- a/src/controllers/dashboard/playback.js +++ b/src/controllers/dashboard/playback.js @@ -31,13 +31,13 @@ function onSubmit() { function getTabs() { return [{ - href: '#/encodingsettings.html', + href: '#/dashboard/playback/transcoding', name: globalize.translate('Transcoding') }, { - href: '#/playbackconfiguration.html', + href: '#/dashboard/playback/resume', name: globalize.translate('ButtonResume') }, { - href: '#/streamingsettings.html', + href: '#/dashboard/playback/streaming', name: globalize.translate('TabStreaming') }]; } diff --git a/src/controllers/dashboard/plugins/available/index.js b/src/controllers/dashboard/plugins/available/index.js index 78368b2c14..b3445b5cb7 100644 --- a/src/controllers/dashboard/plugins/available/index.js +++ b/src/controllers/dashboard/plugins/available/index.js @@ -120,7 +120,7 @@ function onSearchBarType(searchBar) { function getPluginHtml(plugin, options, installedPlugins) { let html = ''; - let href = plugin.externalUrl ? plugin.externalUrl : '#/addplugin.html?name=' + encodeURIComponent(plugin.name) + '&guid=' + plugin.guid; + let href = plugin.externalUrl ? plugin.externalUrl : '#/dashboard/plugins/add?name=' + encodeURIComponent(plugin.name) + '&guid=' + plugin.guid; if (options.context) { href += '&context=' + options.context; @@ -161,13 +161,13 @@ function getPluginHtml(plugin, options, installedPlugins) { function getTabs() { return [{ - href: '#/installedplugins.html', + href: '#/dashboard/plugins', name: globalize.translate('TabMyPlugins') }, { - href: '#/availableplugins.html', + href: '#/dashboard/plugins/catalog', name: globalize.translate('TabCatalog') }, { - href: '#/repositories.html', + href: '#/dashboard/plugins/repositories', name: globalize.translate('TabRepositories') }]; } diff --git a/src/controllers/dashboard/plugins/installed/index.js b/src/controllers/dashboard/plugins/installed/index.js index f6442710fc..91ebcfdff1 100644 --- a/src/controllers/dashboard/plugins/installed/index.js +++ b/src/controllers/dashboard/plugins/installed/index.js @@ -130,7 +130,7 @@ function populateList(page, plugins, pluginConfigurationPages) { } else { html += '
'; html += '

' + globalize.translate('MessageNoPluginsInstalled') + '

'; - html += '

'; + html += '

'; html += globalize.translate('MessageBrowsePluginCatalog'); html += '

'; html += '
'; @@ -221,13 +221,13 @@ function reloadList(page) { function getTabs() { return [{ - href: '#/installedplugins.html', + href: '#/dashboard/plugins', name: globalize.translate('TabMyPlugins') }, { - href: '#/availableplugins.html', + href: '#/dashboard/plugins/catalog', name: globalize.translate('TabCatalog') }, { - href: '#/repositories.html', + href: '#/dashboard/plugins/repositories', name: globalize.translate('TabRepositories') }]; } diff --git a/src/controllers/dashboard/plugins/repositories/index.js b/src/controllers/dashboard/plugins/repositories/index.js index 3c83b6e394..55ff12a456 100644 --- a/src/controllers/dashboard/plugins/repositories/index.js +++ b/src/controllers/dashboard/plugins/repositories/index.js @@ -105,13 +105,13 @@ function getRepositoryElement(repository) { function getTabs() { return [{ - href: '#/installedplugins.html', + href: '#/dashboard/plugins', name: globalize.translate('TabMyPlugins') }, { - href: '#/availableplugins.html', + href: '#/dashboard/plugins/catalog', name: globalize.translate('TabCatalog') }, { - href: '#/repositories.html', + href: '#/dashboard/plugins/repositories', name: globalize.translate('TabRepositories') }]; } diff --git a/src/controllers/dashboard/scheduledtasks/scheduledtasks.js b/src/controllers/dashboard/scheduledtasks/scheduledtasks.js index f17bc5c935..53966e18d1 100644 --- a/src/controllers/dashboard/scheduledtasks/scheduledtasks.js +++ b/src/controllers/dashboard/scheduledtasks/scheduledtasks.js @@ -53,12 +53,12 @@ function populateList(page, tasks) { html += '
'; } html += '
'; - html += ""; + html += ""; html += ''; html += ''; html += '
'; const textAlignStyle = globalize.getIsRTL() ? 'right' : 'left'; - html += ""; + html += ""; html += "

" + task.Name + '

'; html += "
" + getTaskProgressHtml(task) + '
'; html += '
'; diff --git a/src/controllers/dashboard/serveractivity.html b/src/controllers/dashboard/serveractivity.html deleted file mode 100644 index 29cacd300e..0000000000 --- a/src/controllers/dashboard/serveractivity.html +++ /dev/null @@ -1,12 +0,0 @@ -
-
-
-
-

-
-
-
-
-
-
-
diff --git a/src/controllers/dashboard/serveractivity.js b/src/controllers/dashboard/serveractivity.js deleted file mode 100644 index 72e84a89d5..0000000000 --- a/src/controllers/dashboard/serveractivity.js +++ /dev/null @@ -1,32 +0,0 @@ -import ActivityLog from '../../components/activitylog'; -import globalize from '../../scripts/globalize'; -import { toBoolean } from '../../utils/string.ts'; - -export default function (view, params) { - let activityLog; - - if (toBoolean(params.useractivity, true)) { - view.querySelector('.activityItems').setAttribute('data-useractivity', 'true'); - view.querySelector('.sectionTitle').innerHTML = globalize.translate('HeaderActivity'); - } else { - view.querySelector('.activityItems').setAttribute('data-useractivity', 'false'); - view.querySelector('.sectionTitle').innerHTML = globalize.translate('Alerts'); - } - - view.addEventListener('viewshow', function () { - if (!activityLog) { - activityLog = new ActivityLog({ - serverId: ApiClient.serverId(), - element: view.querySelector('.activityItems') - }); - } - }); - view.addEventListener('viewdestroy', function () { - if (activityLog) { - activityLog.destroy(); - } - - activityLog = null; - }); -} - diff --git a/src/controllers/dashboard/streaming.js b/src/controllers/dashboard/streaming.js index ba9d767517..c02a5cdbde 100644 --- a/src/controllers/dashboard/streaming.js +++ b/src/controllers/dashboard/streaming.js @@ -22,13 +22,13 @@ function onSubmit() { function getTabs() { return [{ - href: '#/encodingsettings.html', + href: '#/dashboard/playback/transcoding', name: globalize.translate('Transcoding') }, { - href: '#/playbackconfiguration.html', + href: '#/dashboard/playback/resume', name: globalize.translate('ButtonResume') }, { - href: '#/streamingsettings.html', + href: '#/dashboard/playback/streaming', name: globalize.translate('TabStreaming') }]; } diff --git a/src/controllers/livetvguideprovider.js b/src/controllers/livetvguideprovider.js index 7a133945f2..e87f2ace33 100644 --- a/src/controllers/livetvguideprovider.js +++ b/src/controllers/livetvguideprovider.js @@ -5,7 +5,7 @@ import { getParameterByName } from '../utils/url.ts'; import Events from '../utils/events.ts'; function onListingsSubmitted() { - Dashboard.navigate('livetvstatus.html'); + Dashboard.navigate('dashboard/livetv'); } function init(page, type, providerId) { diff --git a/src/controllers/livetvstatus.js b/src/controllers/livetvstatus.js index 3c0e304939..8532e8ae2a 100644 --- a/src/controllers/livetvstatus.js +++ b/src/controllers/livetvstatus.js @@ -220,9 +220,9 @@ function getProviderName(providerId) { function getProviderConfigurationUrl(providerId) { switch (providerId.toLowerCase()) { case 'xmltv': - return '#/livetvguideprovider.html?type=xmltv'; + return '#/dashboard/livetv/guide?type=xmltv'; case 'schedulesdirect': - return '#/livetvguideprovider.html?type=schedulesdirect'; + return '#/dashboard/livetv/guide?type=schedulesdirect'; } } @@ -249,7 +249,7 @@ function addProvider(button) { } function addDevice() { - Dashboard.navigate('livetvtuner.html'); + Dashboard.navigate('dashboard/livetv/tuner'); } function showDeviceMenu(button, tunerDeviceId) { @@ -274,7 +274,7 @@ function showDeviceMenu(button, tunerDeviceId) { break; case 'edit': - Dashboard.navigate('livetvtuner.html?id=' + tunerDeviceId); + Dashboard.navigate('dashboard/livetv/tuner?id=' + tunerDeviceId); } }); }); @@ -290,7 +290,7 @@ function onDevicesListClick(e) { if (btnCardOptions) { showDeviceMenu(btnCardOptions, id); } else { - Dashboard.navigate('livetvtuner.html?id=' + id); + Dashboard.navigate('dashboard/livetv/tuner?id=' + id); } } } diff --git a/src/controllers/livetvtuner.js b/src/controllers/livetvtuner.js index 7f6ec20270..de73b608d5 100644 --- a/src/controllers/livetvtuner.js +++ b/src/controllers/livetvtuner.js @@ -96,7 +96,7 @@ function submitForm(page) { contentType: 'application/json' }).then(function () { Dashboard.processServerConfigurationUpdateResult(); - Dashboard.navigate('livetvstatus.html'); + Dashboard.navigate('dashboard/livetv'); }, function () { loading.hide(); Dashboard.alert({ diff --git a/src/controllers/user/menu/index.html b/src/controllers/user/menu/index.html index 1c83bd9d68..8fe6326fc2 100644 --- a/src/controllers/user/menu/index.html +++ b/src/controllers/user/menu/index.html @@ -77,7 +77,7 @@

${HeaderAdmin}

- +
@@ -85,7 +85,7 @@
- +
'; } @@ -376,249 +376,6 @@ function refreshLibraryInfoInDrawer(user) { } } -function refreshDashboardInfoInDrawer(page, apiClient) { - currentDrawerType = 'admin'; - loadNavDrawer(); - - if (navDrawerScrollContainer.querySelector('.adminDrawerLogo')) { - updateDashboardMenuSelectedItem(page); - } else { - createDashboardMenu(page, apiClient); - } -} - -function isUrlInCurrentView(url) { - return window.location.href.toString().toLowerCase().indexOf(url.toLowerCase()) !== -1; -} - -function updateDashboardMenuSelectedItem(page) { - const links = navDrawerScrollContainer.querySelectorAll('.navMenuOption'); - const currentViewId = page.id; - - for (let i = 0, length = links.length; i < length; i++) { - let link = links[i]; - let selected = false; - let pageIds = link.getAttribute('data-pageids'); - - if (pageIds) { - pageIds = pageIds.split('|'); - selected = pageIds.indexOf(currentViewId) != -1; - } - - let pageUrls = link.getAttribute('data-pageurls'); - - if (pageUrls) { - pageUrls = pageUrls.split('|'); - selected = pageUrls.filter(isUrlInCurrentView).length > 0; - } - - if (selected) { - link.classList.add('navMenuOption-selected'); - let title = ''; - link = link.querySelector('.navMenuOptionText') || link; - title += (link.innerText || link.textContent).trim(); - LibraryMenu.setTitle(title); - } else { - link.classList.remove('navMenuOption-selected'); - } - } -} - -function createToolsMenuList(pluginItems) { - const links = [{ - name: globalize.translate('TabServer') - }, { - name: globalize.translate('TabDashboard'), - href: '#/dashboard.html', - pageIds: ['dashboardPage'], - icon: 'dashboard' - }, { - name: globalize.translate('General'), - href: '#/dashboardgeneral.html', - pageIds: ['dashboardGeneralPage'], - icon: 'settings' - }, { - name: globalize.translate('HeaderUsers'), - href: '#/userprofiles.html', - pageIds: ['userProfilesPage', 'newUserPage', 'editUserPage', 'userLibraryAccessPage', 'userParentalControlPage', 'userPasswordPage'], - icon: 'people' - }, { - name: globalize.translate('HeaderLibraries'), - href: '#/library.html', - pageIds: ['mediaLibraryPage', 'librarySettingsPage', 'libraryDisplayPage', 'metadataImagesConfigurationPage', 'metadataNfoPage'], - icon: 'folder' - }, { - name: globalize.translate('TitlePlayback'), - icon: 'play_arrow', - href: '#/encodingsettings.html', - pageIds: ['encodingSettingsPage', 'playbackConfigurationPage', 'streamingSettingsPage'] - }]; - addPluginPagesToMainMenu(links, pluginItems, 'server'); - links.push({ - divider: true, - name: globalize.translate('HeaderDevices') - }); - links.push({ - name: globalize.translate('HeaderDevices'), - href: '#/devices.html', - pageIds: ['devicesPage', 'devicePage'], - icon: 'devices' - }); - links.push({ - name: globalize.translate('HeaderActivity'), - href: '#/dashboard/activity', - pageIds: ['serverActivityPage'], - icon: 'assessment' - }); - links.push({ - name: globalize.translate('DLNA'), - href: '#/dlnasettings.html', - pageIds: ['dlnaSettingsPage', 'dlnaProfilesPage', 'dlnaProfilePage'], - icon: 'input' - }); - links.push({ - divider: true, - name: globalize.translate('LiveTV') - }); - links.push({ - name: globalize.translate('LiveTV'), - href: '#/livetvstatus.html', - pageIds: ['liveTvStatusPage', 'liveTvTunerPage'], - icon: 'live_tv' - }); - links.push({ - name: globalize.translate('HeaderDVR'), - href: '#/livetvsettings.html', - pageIds: ['liveTvSettingsPage'], - icon: 'dvr' - }); - addPluginPagesToMainMenu(links, pluginItems, 'livetv'); - links.push({ - divider: true, - name: globalize.translate('TabAdvanced') - }); - links.push({ - name: globalize.translate('TabNetworking'), - icon: 'cloud', - href: '#/networking.html', - pageIds: ['networkingPage'] - }); - links.push({ - name: globalize.translate('HeaderApiKeys'), - icon: 'vpn_key', - href: '#/apikeys.html', - pageIds: ['apiKeysPage'] - }); - links.push({ - name: globalize.translate('TabLogs'), - href: '#/log.html', - pageIds: ['logPage'], - icon: 'bug_report' - }); - links.push({ - name: globalize.translate('Notifications'), - icon: 'notifications', - href: '#/notificationsettings.html' - }); - links.push({ - name: globalize.translate('TabPlugins'), - icon: 'shopping_cart', - href: '#/installedplugins.html', - pageIds: ['pluginsPage', 'pluginCatalogPage'] - }); - links.push({ - name: globalize.translate('TabScheduledTasks'), - href: '#/scheduledtasks.html', - pageIds: ['scheduledTasksPage', 'scheduledTaskPage'], - icon: 'schedule' - }); - if (hasUnsortedPlugins(pluginItems)) { - links.push({ - divider: true, - name: globalize.translate('TabPlugins') - }); - addPluginPagesToMainMenu(links, pluginItems); - } - return links; -} - -function hasUnsortedPlugins(pluginItems) { - for (const pluginItem of pluginItems) { - if (pluginItem.EnableInMainMenu && pluginItem.MenuSection === undefined) { - return true; - } - } - return false; -} - -function addPluginPagesToMainMenu(links, pluginItems, section) { - for (const pluginItem of pluginItems) { - if (pluginItem.EnableInMainMenu && pluginItem.MenuSection === section) { - links.push({ - name: pluginItem.DisplayName, - icon: pluginItem.MenuIcon || 'folder', - href: Dashboard.getPluginUrl(pluginItem.Name), - pageUrls: [Dashboard.getPluginUrl(pluginItem.Name)] - }); - } - } -} - -function getToolsMenuLinks(apiClient) { - return apiClient.getJSON(apiClient.getUrl('web/configurationpages') + '?pageType=PluginConfiguration&EnableInMainMenu=true').then(createToolsMenuList, function () { - return createToolsMenuList([]); - }); -} - -function getToolsLinkHtml(item) { - let menuHtml = ''; - let pageIds = item.pageIds ? item.pageIds.join('|') : ''; - pageIds = pageIds ? ' data-pageids="' + pageIds + '"' : ''; - let pageUrls = item.pageUrls ? item.pageUrls.join('|') : ''; - pageUrls = pageUrls ? ' data-pageurls="' + pageUrls + '"' : ''; - menuHtml += ''; - - if (item.icon) { - menuHtml += ''; - } - - menuHtml += ''; - menuHtml += escapeHtml(item.name); - menuHtml += ''; - return menuHtml + ''; -} - -function getToolsMenuHtml(apiClient) { - return getToolsMenuLinks(apiClient).then(function (items) { - let menuHtml = ''; - menuHtml += '
'; - - for (const item of items) { - if (item.href) { - menuHtml += getToolsLinkHtml(item); - } else if (item.name) { - menuHtml += '

'; - menuHtml += escapeHtml(item.name); - menuHtml += '

'; - } - } - - return menuHtml + '
'; - }); -} - -function createDashboardMenu(page, apiClient) { - return getToolsMenuHtml(apiClient).then(function (toolsMenuHtml) { - let html = ''; - html += ''; - html += toolsMenuHtml; - navDrawerScrollContainer.innerHTML = html; - updateDashboardMenuSelectedItem(page); - }); -} - function onSidebarLinkClick() { const section = this.getElementsByClassName('sectionName')[0]; const text = section ? section.innerHTML : this.innerHTML; @@ -1026,15 +783,8 @@ pageClassOn('pageshow', 'page', function (e) { const isDashboardPage = page.classList.contains('type-interior'); const isHomePage = page.classList.contains('homePage'); const isLibraryPage = !isDashboardPage && page.classList.contains('libraryPage'); - const apiClient = getCurrentApiClient(); - if (isDashboardPage) { - if (mainDrawerButton) { - mainDrawerButton.classList.remove('hide'); - } - - refreshDashboardInfoInDrawer(page, apiClient); - } else { + if (!isDashboardPage) { if (mainDrawerButton) { if (enableLibraryNavDrawer || (isHomePage && enableLibraryNavDrawerHome)) { mainDrawerButton.classList.remove('hide');