mirror of
https://github.com/OpenNebula/one.git
synced 2025-03-23 22:50:09 +03:00
parent
c5ccd9e83d
commit
bb715f162e
@ -22,6 +22,8 @@ import {
|
||||
|
||||
import loadable from '@loadable/component'
|
||||
|
||||
import { T } from 'client/constants'
|
||||
|
||||
const Dashboard = loadable(
|
||||
() => import('client/containers/Dashboard/Provision'),
|
||||
{ ssr: false }
|
||||
@ -64,48 +66,48 @@ export const PATH = {
|
||||
|
||||
export const ENDPOINTS = [
|
||||
{
|
||||
label: 'Dashboard',
|
||||
title: T.Dashboard,
|
||||
path: PATH.DASHBOARD,
|
||||
sidebar: true,
|
||||
icon: DashboardIcon,
|
||||
Component: Dashboard,
|
||||
},
|
||||
{
|
||||
label: 'Providers',
|
||||
title: T.Providers,
|
||||
path: PATH.PROVIDERS.LIST,
|
||||
sidebar: true,
|
||||
icon: ProvidersIcon,
|
||||
Component: Providers,
|
||||
},
|
||||
{
|
||||
label: 'Create Provider',
|
||||
title: T.CreateProvider,
|
||||
path: PATH.PROVIDERS.CREATE,
|
||||
Component: CreateProvider,
|
||||
},
|
||||
{
|
||||
label: 'Edit Provider template',
|
||||
title: T.UpdateProvider,
|
||||
path: PATH.PROVIDERS.EDIT,
|
||||
Component: CreateProvider,
|
||||
},
|
||||
{
|
||||
label: 'Provisions',
|
||||
title: T.Provisions,
|
||||
path: PATH.PROVISIONS.LIST,
|
||||
sidebar: true,
|
||||
icon: ProvisionsIcon,
|
||||
Component: Provisions,
|
||||
},
|
||||
{
|
||||
label: 'Create Provision',
|
||||
title: T.CreateProvision,
|
||||
path: PATH.PROVISIONS.CREATE,
|
||||
Component: CreateProvision,
|
||||
},
|
||||
{
|
||||
label: 'Edit Provision template',
|
||||
title: 'Edit Provision template',
|
||||
path: PATH.PROVISIONS.EDIT,
|
||||
Component: CreateProvision,
|
||||
},
|
||||
{
|
||||
label: 'Settings',
|
||||
title: T.Settings,
|
||||
path: PATH.SETTINGS,
|
||||
sidebar: true,
|
||||
icon: SettingsIcon,
|
||||
|
@ -13,12 +13,15 @@
|
||||
* See the License for the specific language governing permissions and *
|
||||
* limitations under the License. *
|
||||
* ------------------------------------------------------------------------- */
|
||||
import loadable from '@loadable/component'
|
||||
import {
|
||||
ReportColumns as DashboardIcon,
|
||||
Settings as SettingsIcon,
|
||||
} from 'iconoir-react'
|
||||
|
||||
import loadable from '@loadable/component'
|
||||
|
||||
import { T } from 'client/constants'
|
||||
|
||||
const Dashboard = loadable(
|
||||
() => import('client/containers/Dashboard/Sunstone'),
|
||||
{ ssr: false }
|
||||
@ -43,7 +46,7 @@ export const PATH = {
|
||||
|
||||
export const ENDPOINTS = [
|
||||
{
|
||||
label: 'Dashboard',
|
||||
title: T.Dashboard,
|
||||
path: PATH.DASHBOARD,
|
||||
sidebar: true,
|
||||
icon: DashboardIcon,
|
||||
@ -51,7 +54,7 @@ export const ENDPOINTS = [
|
||||
Component: Dashboard,
|
||||
},
|
||||
{
|
||||
label: 'Settings',
|
||||
title: T.Settings,
|
||||
path: PATH.SETTINGS,
|
||||
sidebar: true,
|
||||
icon: SettingsIcon,
|
||||
@ -59,13 +62,13 @@ export const ENDPOINTS = [
|
||||
Component: Settings,
|
||||
},
|
||||
{
|
||||
label: 'Guacamole',
|
||||
title: 'Guacamole', // no need to translate
|
||||
disableLayout: true,
|
||||
path: PATH.GUACAMOLE,
|
||||
Component: Guacamole,
|
||||
},
|
||||
{
|
||||
label: 'WebMKS',
|
||||
title: 'WebMKS', // no need to translate
|
||||
disableLayout: true,
|
||||
path: PATH.WMKS,
|
||||
Component: WebMKS,
|
||||
|
@ -204,23 +204,24 @@ export const PATH = {
|
||||
|
||||
const ENDPOINTS = [
|
||||
{
|
||||
label: T.Instances,
|
||||
title: T.Instances,
|
||||
icon: InstancesIcons,
|
||||
routes: [
|
||||
{
|
||||
label: T.VMs,
|
||||
title: T.VMs,
|
||||
path: PATH.INSTANCE.VMS.LIST,
|
||||
sidebar: true,
|
||||
icon: VmsIcons,
|
||||
Component: VirtualMachines,
|
||||
},
|
||||
{
|
||||
label: (params) => [T.VMDetailId, params.id],
|
||||
title: T.VM,
|
||||
description: (params) => `#${params?.id}`,
|
||||
path: PATH.INSTANCE.VMS.DETAIL,
|
||||
Component: VirtualMachineDetail,
|
||||
},
|
||||
{
|
||||
label: T.VirtualRouters,
|
||||
title: T.VirtualRouters,
|
||||
path: PATH.INSTANCE.VROUTERS.LIST,
|
||||
sidebar: true,
|
||||
icon: VRoutersIcons,
|
||||
@ -229,80 +230,85 @@ const ENDPOINTS = [
|
||||
],
|
||||
},
|
||||
{
|
||||
label: T.Templates,
|
||||
title: T.Templates,
|
||||
icon: TemplatesIcon,
|
||||
routes: [
|
||||
{
|
||||
label: T.VMTemplates,
|
||||
title: T.VMTemplates,
|
||||
path: PATH.TEMPLATE.VMS.LIST,
|
||||
sidebar: true,
|
||||
icon: TemplateIcon,
|
||||
Component: VmTemplates,
|
||||
},
|
||||
{
|
||||
label: T.InstantiateVmTemplate,
|
||||
title: T.InstantiateVmTemplate,
|
||||
description: (_, state) =>
|
||||
state?.ID !== undefined && `#${state.ID} ${state.NAME}`,
|
||||
path: PATH.TEMPLATE.VMS.INSTANTIATE,
|
||||
Component: InstantiateVmTemplate,
|
||||
},
|
||||
{
|
||||
label: T.CreateVmTemplate,
|
||||
title: (_, state) =>
|
||||
state?.ID !== undefined ? T.UpdateVmTemplate : T.CreateVmTemplate,
|
||||
description: (_, state) =>
|
||||
state?.ID !== undefined && `#${state.ID} ${state.NAME}`,
|
||||
path: PATH.TEMPLATE.VMS.CREATE,
|
||||
Component: CreateVmTemplate,
|
||||
},
|
||||
],
|
||||
},
|
||||
{
|
||||
label: T.Storage,
|
||||
title: T.Storage,
|
||||
icon: StorageIcon,
|
||||
routes: [
|
||||
{
|
||||
label: T.Datastores,
|
||||
title: T.Datastores,
|
||||
path: PATH.STORAGE.DATASTORES.LIST,
|
||||
sidebar: true,
|
||||
icon: DatastoreIcon,
|
||||
Component: Datastores,
|
||||
},
|
||||
{
|
||||
label: T.Images,
|
||||
title: T.Images,
|
||||
path: PATH.STORAGE.IMAGES.LIST,
|
||||
sidebar: true,
|
||||
icon: ImageIcon,
|
||||
Component: Images,
|
||||
},
|
||||
{
|
||||
label: T.Marketplaces,
|
||||
title: T.Marketplaces,
|
||||
path: PATH.STORAGE.MARKETPLACES.LIST,
|
||||
sidebar: true,
|
||||
icon: MarketplaceIcon,
|
||||
Component: Marketplaces,
|
||||
},
|
||||
{
|
||||
label: T.Apps,
|
||||
title: T.Apps,
|
||||
path: PATH.STORAGE.MARKETPLACE_APPS.LIST,
|
||||
sidebar: true,
|
||||
icon: MarketplaceAppIcon,
|
||||
Component: MarketplaceApps,
|
||||
},
|
||||
{
|
||||
label: T.CreateMarketApp,
|
||||
title: T.CreateMarketApp,
|
||||
path: PATH.STORAGE.MARKETPLACE_APPS.CREATE,
|
||||
Component: CreateMarketplaceApp,
|
||||
},
|
||||
],
|
||||
},
|
||||
{
|
||||
label: T.Networks,
|
||||
title: T.Networks,
|
||||
icon: NetworksIcon,
|
||||
routes: [
|
||||
{
|
||||
label: T.VirtualNetworks,
|
||||
title: T.VirtualNetworks,
|
||||
path: PATH.NETWORK.VNETS.LIST,
|
||||
sidebar: true,
|
||||
icon: NetworkIcon,
|
||||
Component: VirtualNetworks,
|
||||
},
|
||||
{
|
||||
label: T.NetworkTemplates,
|
||||
title: T.NetworkTemplates,
|
||||
path: PATH.NETWORK.VN_TEMPLATES.LIST,
|
||||
sidebar: true,
|
||||
icon: NetworkTemplateIcon,
|
||||
@ -311,40 +317,42 @@ const ENDPOINTS = [
|
||||
],
|
||||
},
|
||||
{
|
||||
label: T.Infrastructure,
|
||||
title: T.Infrastructure,
|
||||
icon: InfrastructureIcon,
|
||||
routes: [
|
||||
{
|
||||
label: T.Clusters,
|
||||
title: T.Clusters,
|
||||
path: PATH.INFRASTRUCTURE.CLUSTERS.LIST,
|
||||
sidebar: true,
|
||||
icon: ClusterIcon,
|
||||
Component: Clusters,
|
||||
},
|
||||
{
|
||||
label: (params) => [T.ClusterDetailId, params.id],
|
||||
title: T.Cluster,
|
||||
description: (params) => `#${params?.id}`,
|
||||
path: PATH.INFRASTRUCTURE.CLUSTERS.DETAIL,
|
||||
Component: ClusterDetail,
|
||||
},
|
||||
{
|
||||
label: T.Hosts,
|
||||
title: T.Hosts,
|
||||
path: PATH.INFRASTRUCTURE.HOSTS.LIST,
|
||||
sidebar: true,
|
||||
icon: HostIcon,
|
||||
Component: Hosts,
|
||||
},
|
||||
{
|
||||
label: T.CreateHost,
|
||||
title: T.CreateHost,
|
||||
path: PATH.INFRASTRUCTURE.HOSTS.CREATE,
|
||||
Component: CreateHost,
|
||||
},
|
||||
{
|
||||
label: (params) => [T.HostDetailId, params.id],
|
||||
title: T.Host,
|
||||
description: (params) => `#${params?.id}`,
|
||||
path: PATH.INFRASTRUCTURE.HOSTS.DETAIL,
|
||||
Component: HostDetail,
|
||||
},
|
||||
{
|
||||
label: T.Zones,
|
||||
title: T.Zones,
|
||||
path: PATH.INFRASTRUCTURE.ZONES.LIST,
|
||||
sidebar: true,
|
||||
icon: ZoneIcon,
|
||||
@ -353,30 +361,32 @@ const ENDPOINTS = [
|
||||
],
|
||||
},
|
||||
{
|
||||
label: T.System,
|
||||
title: T.System,
|
||||
icon: SystemIcon,
|
||||
routes: [
|
||||
{
|
||||
label: T.Users,
|
||||
title: T.Users,
|
||||
path: PATH.SYSTEM.USERS.LIST,
|
||||
sidebar: true,
|
||||
icon: UserIcon,
|
||||
Component: Users,
|
||||
},
|
||||
{
|
||||
label: (params) => [T.UserDetailId, params.id],
|
||||
title: T.User,
|
||||
description: (params) => `#${params?.id}`,
|
||||
path: PATH.SYSTEM.USERS.DETAIL,
|
||||
Component: UserDetail,
|
||||
},
|
||||
{
|
||||
label: T.Groups,
|
||||
title: T.Groups,
|
||||
path: PATH.SYSTEM.GROUPS.LIST,
|
||||
sidebar: true,
|
||||
icon: GroupIcon,
|
||||
Component: Groups,
|
||||
},
|
||||
{
|
||||
label: (params) => [T.GroupDetailId, params.id],
|
||||
title: T.Group,
|
||||
description: (params) => `#${params?.id}`,
|
||||
path: PATH.SYSTEM.GROUPS.DETAIL,
|
||||
Component: GroupDetail,
|
||||
},
|
||||
|
@ -14,30 +14,23 @@
|
||||
* limitations under the License. *
|
||||
* ------------------------------------------------------------------------- */
|
||||
/* eslint-disable jsdoc/require-jsdoc */
|
||||
import { useRef, useEffect, useMemo } from 'react'
|
||||
import { useRef, useMemo } from 'react'
|
||||
import PropTypes from 'prop-types'
|
||||
import { useParams } from 'react-router-dom'
|
||||
import { Box, Container } from '@mui/material'
|
||||
import { CSSTransition } from 'react-transition-group'
|
||||
|
||||
import { useGeneral, useGeneralApi } from 'client/features/General'
|
||||
import { useGeneral } from 'client/features/General'
|
||||
import Header from 'client/components/Header'
|
||||
import Footer from 'client/components/Footer'
|
||||
import internalStyles from 'client/components/HOC/InternalLayout/styles'
|
||||
import { sidebar, footer } from 'client/theme/defaults'
|
||||
|
||||
const InternalLayout = ({ title, disableLayout, children }) => {
|
||||
const InternalLayout = ({ children, ...route }) => {
|
||||
const classes = internalStyles()
|
||||
const container = useRef()
|
||||
const { isFixMenu } = useGeneral()
|
||||
const { changeTitle } = useGeneralApi()
|
||||
const params = useParams()
|
||||
|
||||
useEffect(() => {
|
||||
changeTitle(typeof title === 'function' ? title(params) : title)
|
||||
}, [title])
|
||||
|
||||
if (disableLayout) {
|
||||
if (route.disableLayout) {
|
||||
return (
|
||||
<Box data-cy="main-layout" className={classes.root}>
|
||||
<Box
|
||||
@ -64,7 +57,7 @@ const InternalLayout = ({ title, disableLayout, children }) => {
|
||||
[isFixMenu]
|
||||
)}
|
||||
>
|
||||
<Header scrollContainer={container.current} />
|
||||
<Header scrollContainer={container.current} route={route} />
|
||||
<Box component="main" className={classes.main}>
|
||||
<CSSTransition
|
||||
in
|
||||
@ -92,7 +85,6 @@ const InternalLayout = ({ title, disableLayout, children }) => {
|
||||
}
|
||||
|
||||
InternalLayout.propTypes = {
|
||||
title: PropTypes.oneOfType([PropTypes.string, PropTypes.func]),
|
||||
disableLayout: PropTypes.bool,
|
||||
children: PropTypes.any,
|
||||
}
|
||||
|
@ -13,9 +13,10 @@
|
||||
* See the License for the specific language governing permissions and *
|
||||
* limitations under the License. *
|
||||
* ------------------------------------------------------------------------- */
|
||||
/* eslint-disable jsdoc/require-jsdoc */
|
||||
import { useMemo } from 'react'
|
||||
|
||||
import { memo, useMemo } from 'react'
|
||||
import PropTypes from 'prop-types'
|
||||
import { useParams, useLocation } from 'react-router-dom'
|
||||
|
||||
import {
|
||||
AppBar,
|
||||
@ -37,12 +38,25 @@ import Zone from 'client/components/Header/Zone'
|
||||
import { Translate } from 'client/components/HOC'
|
||||
import { sentenceCase } from 'client/utils'
|
||||
|
||||
const Header = () => {
|
||||
const Header = memo(({ route: { title, description } = {} }) => {
|
||||
const { isOneAdmin } = useAuth()
|
||||
const { fixMenu } = useGeneralApi()
|
||||
const { appTitle, title, isBeta, withGroupSwitcher } = useGeneral()
|
||||
const { appTitle, isBeta, withGroupSwitcher } = useGeneral()
|
||||
|
||||
const params = useParams()
|
||||
const { state } = useLocation()
|
||||
|
||||
const appAsSentence = useMemo(() => sentenceCase(appTitle), [appTitle])
|
||||
|
||||
const [ensuredTitle, ensuredDescription] = useMemo(() => {
|
||||
if (!title) return []
|
||||
|
||||
const ensure = (label) =>
|
||||
typeof label === 'function' ? label(params, state) : label
|
||||
|
||||
return [ensure(title), ensure(description)]
|
||||
}, [params, state, title, description])
|
||||
|
||||
return (
|
||||
<AppBar data-cy="header" elevation={0} position="absolute">
|
||||
<Toolbar>
|
||||
@ -58,10 +72,9 @@ const Header = () => {
|
||||
<Box
|
||||
flexGrow={1}
|
||||
ml={2}
|
||||
sx={{
|
||||
display: { xs: 'none', sm: 'inline-flex' },
|
||||
userSelect: 'none',
|
||||
}}
|
||||
alignItems="baseline"
|
||||
display={{ xs: 'none', sm: 'inline-flex' }}
|
||||
sx={{ userSelect: 'none' }}
|
||||
>
|
||||
<Typography variant="h6" data-cy="header-app-title">
|
||||
{'One'}
|
||||
@ -83,22 +96,35 @@ const Header = () => {
|
||||
</Typography>
|
||||
)}
|
||||
</Typography>
|
||||
{title && (
|
||||
<Typography
|
||||
variant="h6"
|
||||
data-cy="header-description"
|
||||
sx={{
|
||||
display: { xs: 'none', md: 'block' },
|
||||
'&::before': {
|
||||
content: '"|"',
|
||||
margin: '0.5em',
|
||||
color: 'primary.contrastText',
|
||||
},
|
||||
}}
|
||||
>
|
||||
<Translate word={title} />
|
||||
</Typography>
|
||||
)}
|
||||
<Box
|
||||
alignItems="baseline"
|
||||
display={{ xs: 'none', md: 'inline-flex' }}
|
||||
gap=".5em"
|
||||
sx={{
|
||||
'&::before': { content: '"|"', ml: '.5em' },
|
||||
}}
|
||||
>
|
||||
{ensuredTitle && (
|
||||
<Typography
|
||||
noWrap
|
||||
variant="subtitle1"
|
||||
data-cy="header-title"
|
||||
sx={{ color: 'primary.contrastText' }}
|
||||
>
|
||||
<Translate word={ensuredTitle} />
|
||||
</Typography>
|
||||
)}
|
||||
{ensuredDescription && (
|
||||
<Typography
|
||||
noWrap
|
||||
variant="subtitle2"
|
||||
data-cy="header-description"
|
||||
sx={{ color: 'text.secondary' }}
|
||||
>
|
||||
<Translate word={ensuredDescription} />
|
||||
</Typography>
|
||||
)}
|
||||
</Box>
|
||||
</Box>
|
||||
<Stack
|
||||
direction="row"
|
||||
@ -113,10 +139,13 @@ const Header = () => {
|
||||
</Toolbar>
|
||||
</AppBar>
|
||||
)
|
||||
}
|
||||
})
|
||||
|
||||
Header.propTypes = {
|
||||
route: PropTypes.object,
|
||||
scrollContainer: PropTypes.object,
|
||||
}
|
||||
|
||||
Header.displayName = 'Header'
|
||||
|
||||
export default Header
|
||||
|
@ -38,12 +38,12 @@ import { Translate } from 'client/components/HOC'
|
||||
* Renders nested list options for sidebar.
|
||||
*
|
||||
* @param {object} props - Props
|
||||
* @param {string} props.label - Label
|
||||
* @param {string} props.title - Title
|
||||
* @param {object[]} props.routes - Nested list of routes
|
||||
* @param {ReactElement} props.icon - Icon
|
||||
* @returns {ReactElement} Sidebar option that includes other list of routes
|
||||
*/
|
||||
const SidebarCollapseItem = ({ label = '', routes = [], icon: Icon }) => {
|
||||
const SidebarCollapseItem = ({ title = '', routes = [], icon: Icon }) => {
|
||||
const classes = sidebarStyles()
|
||||
const { pathname } = useLocation()
|
||||
const { isFixMenu } = useGeneral()
|
||||
@ -75,8 +75,8 @@ const SidebarCollapseItem = ({ label = '', routes = [], icon: Icon }) => {
|
||||
</ListItemIcon>
|
||||
)}
|
||||
<ListItemText
|
||||
data-cy={label.toLocaleLowerCase()}
|
||||
primary={<Translate word={label} />}
|
||||
data-cy={title.toLocaleLowerCase()}
|
||||
primary={<Translate word={title} />}
|
||||
{...(expanded && { className: 'open' })}
|
||||
primaryTypographyProps={{ variant: 'body1' }}
|
||||
/>
|
||||
@ -90,10 +90,7 @@ const SidebarCollapseItem = ({ label = '', routes = [], icon: Icon }) => {
|
||||
>
|
||||
<List component="div" disablePadding>
|
||||
{routes
|
||||
?.filter(
|
||||
({ sidebar = false, ...route }) =>
|
||||
sidebar && typeof route.label === 'string'
|
||||
)
|
||||
?.filter(({ sidebar = false }) => sidebar)
|
||||
?.map((subItem, index) => (
|
||||
<SidebarLink key={`subitem-${index}`} isSubItem {...subItem} />
|
||||
))}
|
||||
@ -104,7 +101,7 @@ const SidebarCollapseItem = ({ label = '', routes = [], icon: Icon }) => {
|
||||
}
|
||||
|
||||
SidebarCollapseItem.propTypes = {
|
||||
label: PropTypes.string.isRequired,
|
||||
title: PropTypes.string.isRequired,
|
||||
icon: PropTypes.oneOfType([PropTypes.node, PropTypes.object]),
|
||||
routes: PropTypes.arrayOf(
|
||||
PropTypes.shape({
|
||||
|
@ -31,7 +31,7 @@ import { Translate } from 'client/components/HOC'
|
||||
|
||||
const SidebarLink = memo(
|
||||
({
|
||||
label = '',
|
||||
title = '',
|
||||
path = '/',
|
||||
icon: Icon,
|
||||
devMode = false,
|
||||
@ -63,7 +63,7 @@ const SidebarLink = memo(
|
||||
</ListItemIcon>
|
||||
)}
|
||||
<ListItemText
|
||||
primary={<Translate word={label} />}
|
||||
primary={<Translate word={title} />}
|
||||
primaryTypographyProps={{
|
||||
...(devMode && { component: DevTypography }),
|
||||
'data-cy': 'main-menu-item-text',
|
||||
@ -76,7 +76,7 @@ const SidebarLink = memo(
|
||||
)
|
||||
|
||||
SidebarLink.propTypes = {
|
||||
label: PropTypes.string.isRequired,
|
||||
title: PropTypes.string.isRequired,
|
||||
path: PropTypes.string.isRequired,
|
||||
icon: PropTypes.any,
|
||||
devMode: PropTypes.bool,
|
||||
|
@ -57,16 +57,18 @@ module.exports = {
|
||||
Create: 'Create',
|
||||
CreateHost: 'Create Host',
|
||||
CreateMarketApp: 'Create Marketplace App',
|
||||
CreateProvider: 'Create Provider',
|
||||
CreateProvision: 'Create Provision',
|
||||
CreateVmTemplate: 'Create VM Template',
|
||||
CurrentGroup: 'Current group: %s',
|
||||
CurrentOwner: 'Current owner: %s',
|
||||
Delete: 'Delete',
|
||||
DeleteAllImages: 'Delete all images',
|
||||
DeleteDb: 'Delete database',
|
||||
DeleteScheduleAction: 'Delete schedule action: %s',
|
||||
DeleteSeveralTemplates: 'Delete several Templates',
|
||||
DeleteTemplate: 'Delete Template',
|
||||
DeleteSomething: 'Delete: %s',
|
||||
DeleteAllImages: 'Delete all images',
|
||||
DeleteTemplate: 'Delete Template',
|
||||
Deploy: 'Deploy',
|
||||
Detach: 'Detach',
|
||||
DetachSomething: 'Detach: %s',
|
||||
@ -152,7 +154,9 @@ module.exports = {
|
||||
UnReschedule: 'Un-Reschedule',
|
||||
Unshare: 'Unshare',
|
||||
Update: 'Update',
|
||||
UpdateProvider: 'Update Provider',
|
||||
UpdateScheduleAction: 'Update schedule action: %s',
|
||||
UpdateVmTemplate: 'Update VM Template',
|
||||
|
||||
/* questions */
|
||||
Yes: 'Yes',
|
||||
@ -285,10 +289,8 @@ module.exports = {
|
||||
|
||||
/* sections - system */
|
||||
User: 'User',
|
||||
UserDetailId: 'User #%s',
|
||||
Users: 'Users',
|
||||
Group: 'Group',
|
||||
GroupDetailId: 'Group #%s',
|
||||
Groups: 'Groups',
|
||||
VDC: 'VDC',
|
||||
VDCs: 'VDCs',
|
||||
@ -297,10 +299,8 @@ module.exports = {
|
||||
|
||||
/* sections - infrastructure */
|
||||
Cluster: 'Cluster',
|
||||
ClusterDetailId: 'Cluster #%s',
|
||||
Clusters: 'Clusters',
|
||||
Host: 'Host',
|
||||
HostDetailId: 'Host #%s',
|
||||
Hosts: 'Hosts',
|
||||
Infrastructure: 'Infrastructure',
|
||||
Zone: 'Zone',
|
||||
@ -333,7 +333,6 @@ module.exports = {
|
||||
/* sections - templates & instances */
|
||||
Instances: 'Instances',
|
||||
VM: 'VM',
|
||||
VMDetailId: 'VM #%s',
|
||||
VMs: 'VMs',
|
||||
VirtualRouter: 'Virtual Router',
|
||||
VirtualRouters: 'Virtual Routers',
|
||||
|
@ -18,7 +18,6 @@ import { createAction } from '@reduxjs/toolkit'
|
||||
export const fixMenu = createAction('Fix menu')
|
||||
export const changeZone = createAction('Change zone')
|
||||
export const changeLoading = createAction('Change loading')
|
||||
export const changeTitle = createAction('Change title')
|
||||
export const changeAppTitle = createAction('Change App title')
|
||||
|
||||
export const dismissSnackbar = createAction('Dismiss snackbar')
|
||||
|
@ -29,7 +29,6 @@ export const useGeneralApi = () => {
|
||||
return {
|
||||
fixMenu: (isFixed) => dispatch(actions.fixMenu(isFixed)),
|
||||
changeLoading: (isLoading) => dispatch(actions.changeLoading(isLoading)),
|
||||
changeTitle: (title) => dispatch(actions.changeTitle(title)),
|
||||
changeAppTitle: (appTitle) => dispatch(actions.changeAppTitle(appTitle)),
|
||||
changeZone: (zone) => dispatch(actions.changeZone(zone)),
|
||||
|
||||
|
@ -22,7 +22,6 @@ import { APPS_IN_BETA, APPS_WITH_SWITCHER } from 'client/constants'
|
||||
|
||||
const initial = {
|
||||
zone: 0,
|
||||
title: null,
|
||||
appTitle: null,
|
||||
isBeta: false,
|
||||
withGroupSwitcher: false,
|
||||
@ -54,10 +53,6 @@ const { name, reducer } = createSlice({
|
||||
...state,
|
||||
isLoading: !!payload,
|
||||
}))
|
||||
.addCase(actions.changeTitle, (state, { payload }) => ({
|
||||
...state,
|
||||
title: payload,
|
||||
}))
|
||||
.addCase(actions.changeAppTitle, (state, { payload: appTitle }) => {
|
||||
const lowerAppTitle = String(appTitle).toLowerCase()
|
||||
const isBeta = APPS_IN_BETA?.includes(lowerAppTitle)
|
||||
|
@ -13,8 +13,8 @@
|
||||
* See the License for the specific language governing permissions and *
|
||||
* limitations under the License. *
|
||||
* ------------------------------------------------------------------------- */
|
||||
import loadable from '@loadable/component'
|
||||
import { Code as DevIcon } from 'iconoir-react'
|
||||
import loadable from '@loadable/component'
|
||||
|
||||
const TestApi = loadable(() => import('client/containers/TestApi'), {
|
||||
ssr: false,
|
||||
@ -30,7 +30,7 @@ export const PATH = {
|
||||
|
||||
export const ENDPOINTS = [
|
||||
{
|
||||
label: 'Test API',
|
||||
title: 'Test API', // no need to translate
|
||||
path: PATH.TEST_API,
|
||||
devMode: true,
|
||||
sidebar: true,
|
||||
@ -38,7 +38,7 @@ export const ENDPOINTS = [
|
||||
Component: TestApi,
|
||||
},
|
||||
{
|
||||
label: 'Test Form',
|
||||
title: 'Test Form', // no need to translate
|
||||
path: PATH.TEST_FORM,
|
||||
devMode: true,
|
||||
sidebar: true,
|
||||
|
@ -28,9 +28,9 @@ import {
|
||||
import { ProtectedRoute, NoAuthRoute } from 'client/components/Route'
|
||||
import { InternalLayout } from 'client/components/HOC'
|
||||
|
||||
const renderRoute = ({ Component, label, disableLayout, ...rest }, index) => (
|
||||
<ProtectedRoute key={index} exact {...rest}>
|
||||
<InternalLayout title={label} disableLayout={disableLayout}>
|
||||
const renderRoute = ({ Component, ...route }) => (
|
||||
<ProtectedRoute key={route.path} exact {...route}>
|
||||
<InternalLayout {...route}>
|
||||
<Component fallback={<LinearProgress color="secondary" />} />
|
||||
</InternalLayout>
|
||||
</ProtectedRoute>
|
||||
|
Loading…
x
Reference in New Issue
Block a user