Migrate Sidebar to typescript and MUI 5
parent
14f16677c9
commit
c981660442
|
@ -0,0 +1,19 @@
|
||||||
|
import React from "react";
|
||||||
|
import * as MuiIcons from "./list";
|
||||||
|
import { Icon as MuiIcon, IconProps } from "@mui/material";
|
||||||
|
|
||||||
|
interface Props extends IconProps {
|
||||||
|
code?: string | null;
|
||||||
|
fallback?: JSX.Element;
|
||||||
|
}
|
||||||
|
|
||||||
|
const DynamicIcon: React.FC<Props> = ({ code, fallback, ...res }) => {
|
||||||
|
if (code && code in MuiIcons) {
|
||||||
|
const Icon = MuiIcons[code as keyof typeof MuiIcons] as typeof MuiIcon;
|
||||||
|
return <Icon {...res} />;
|
||||||
|
} else {
|
||||||
|
return <>{fallback ?? ""}</>;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
export default DynamicIcon;
|
|
@ -0,0 +1,4 @@
|
||||||
|
import DynamicIcon from "./DynamicIcon";
|
||||||
|
|
||||||
|
export * from "./list";
|
||||||
|
export { DynamicIcon };
|
|
@ -0,0 +1 @@
|
||||||
|
export { Home, Dashboard, Dns, DeviceHub, Build, Settings, FeaturedPlayList, Info } from "@mui/icons-material";
|
|
@ -1,33 +0,0 @@
|
||||||
import React, { useState } from "react";
|
|
||||||
import { useTheme } from "@mui/material/styles";
|
|
||||||
import AppRoutes from "./AppRoutes";
|
|
||||||
import TopBar from "./TopBar";
|
|
||||||
import Sidebar from "./Sidebar";
|
|
||||||
import { getStyles } from "./styles";
|
|
||||||
|
|
||||||
const AppLayout = () => {
|
|
||||||
const [open, setOpen] = useState(false);
|
|
||||||
const theme = useTheme();
|
|
||||||
const styles = getStyles(theme);
|
|
||||||
|
|
||||||
const handleDrawerOpen = () => {
|
|
||||||
setOpen(true);
|
|
||||||
};
|
|
||||||
|
|
||||||
const handleDrawerClose = () => {
|
|
||||||
setOpen(false);
|
|
||||||
};
|
|
||||||
|
|
||||||
return (
|
|
||||||
<div style={styles.root}>
|
|
||||||
<TopBar open={open} handleDrawerOpen={handleDrawerOpen} />
|
|
||||||
<Sidebar open={open} handleDrawerClose={handleDrawerClose} />
|
|
||||||
<main style={styles.content}>
|
|
||||||
<div style={styles.toolbar} />
|
|
||||||
<AppRoutes />
|
|
||||||
</main>
|
|
||||||
</div>
|
|
||||||
);
|
|
||||||
};
|
|
||||||
|
|
||||||
export default AppLayout;
|
|
|
@ -0,0 +1,54 @@
|
||||||
|
import React, { useState, useMemo } from "react";
|
||||||
|
import { styled } from "@mui/material/styles";
|
||||||
|
import AppRoutes from "./AppRoutes";
|
||||||
|
import TopBar from "./TopBar";
|
||||||
|
import Sidebar from "./SideBar";
|
||||||
|
|
||||||
|
import { drawerWidth } from "./constants";
|
||||||
|
import { Box } from "@mui/material";
|
||||||
|
|
||||||
|
const DrawerHeader = styled("div")(({ theme }) => ({
|
||||||
|
display: "flex",
|
||||||
|
alignItems: "center",
|
||||||
|
justifyContent: "flex-end",
|
||||||
|
padding: theme.spacing(0, 1),
|
||||||
|
// necessary for content to be below app bar
|
||||||
|
...theme.mixins.toolbar
|
||||||
|
}));
|
||||||
|
|
||||||
|
const AppLayout = () => {
|
||||||
|
const [open, setOpen] = useState(false);
|
||||||
|
|
||||||
|
const handleDrawerOpen = () => {
|
||||||
|
setOpen(true);
|
||||||
|
};
|
||||||
|
|
||||||
|
const handleDrawerClose = () => {
|
||||||
|
setOpen(false);
|
||||||
|
};
|
||||||
|
|
||||||
|
return (
|
||||||
|
<Box sx={{ display: "flex", minHeight: "100vh" }}>
|
||||||
|
<TopBar open={open} onDrawerOpen={handleDrawerOpen} />
|
||||||
|
<Sidebar open={open} onDrawerOpen={handleDrawerOpen} onDrawerClose={handleDrawerClose} />
|
||||||
|
<Box
|
||||||
|
component="main"
|
||||||
|
sx={{
|
||||||
|
flexGrow: 1,
|
||||||
|
display: "flex",
|
||||||
|
flexDirection: "column",
|
||||||
|
paddingTop: 2,
|
||||||
|
paddingBottom: 1,
|
||||||
|
paddingLeft: 1,
|
||||||
|
paddingRight: 1,
|
||||||
|
width: `calc(100% - ${drawerWidth}px)`
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
<DrawerHeader />
|
||||||
|
<AppRoutes />
|
||||||
|
</Box>
|
||||||
|
</Box>
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
export default AppLayout;
|
|
@ -0,0 +1,84 @@
|
||||||
|
import React from "react";
|
||||||
|
import { SxProps, Theme } from "@mui/material/styles";
|
||||||
|
import List from "@mui/material/List";
|
||||||
|
import ListItem from "@mui/material/ListItem";
|
||||||
|
import ListItemButton from "@mui/material/ListItemButton";
|
||||||
|
import ListItemIcon from "@mui/material/ListItemIcon";
|
||||||
|
import ListItemText from "@mui/material/ListItemText";
|
||||||
|
import Badge from "@mui/material/Badge";
|
||||||
|
import { ExpandLess, ExpandMore } from "@mui/icons-material";
|
||||||
|
import { Collapse, Divider, Tooltip } from "@mui/material";
|
||||||
|
|
||||||
|
type MenuItemProps = {
|
||||||
|
open: boolean;
|
||||||
|
icon: React.ReactNode;
|
||||||
|
label: string;
|
||||||
|
onClick?: () => void;
|
||||||
|
subMenus?: MenuItemProps[];
|
||||||
|
sx?: SxProps<Theme>;
|
||||||
|
};
|
||||||
|
|
||||||
|
const MenuItem: React.FC<MenuItemProps> = ({ open, icon, label, onClick, subMenus, sx }) => {
|
||||||
|
const [openSubMenu, setOpenSubMenu] = React.useState(false);
|
||||||
|
|
||||||
|
const handleSubMenuToggle = () => {
|
||||||
|
setOpenSubMenu(!openSubMenu);
|
||||||
|
};
|
||||||
|
|
||||||
|
return (
|
||||||
|
<>
|
||||||
|
<ListItem disablePadding sx={{ display: "block" }}>
|
||||||
|
<Tooltip title={open ? undefined : label} placement="right" arrow>
|
||||||
|
<ListItemButton
|
||||||
|
sx={{
|
||||||
|
minHeight: 48,
|
||||||
|
justifyContent: open ? "initial" : "center",
|
||||||
|
px: 2.5,
|
||||||
|
...sx
|
||||||
|
}}
|
||||||
|
onClick={onClick ? onClick : handleSubMenuToggle}
|
||||||
|
>
|
||||||
|
<ListItemIcon
|
||||||
|
sx={{
|
||||||
|
minWidth: 0,
|
||||||
|
mr: open ? 3 : "auto",
|
||||||
|
justifyContent: "center"
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
{open || !subMenus ? (
|
||||||
|
icon
|
||||||
|
) : (
|
||||||
|
<Badge badgeContent={openSubMenu ? <ExpandLess fontSize="small" /> : <ExpandMore fontSize="small" />}>
|
||||||
|
{icon}
|
||||||
|
</Badge>
|
||||||
|
)}
|
||||||
|
</ListItemIcon>
|
||||||
|
<ListItemText
|
||||||
|
primary={label}
|
||||||
|
sx={{ opacity: open ? 1 : 0, overflow: "hidden", textOverflow: "ellipsis", whiteSpace: "nowrap" }}
|
||||||
|
/>
|
||||||
|
{subMenus && open && (
|
||||||
|
<ListItemIcon sx={{ minWidth: 0, ml: "auto" }}>
|
||||||
|
{openSubMenu ? <ExpandLess /> : <ExpandMore />}
|
||||||
|
</ListItemIcon>
|
||||||
|
)}
|
||||||
|
</ListItemButton>
|
||||||
|
</Tooltip>
|
||||||
|
</ListItem>
|
||||||
|
{subMenus && (
|
||||||
|
<Collapse in={openSubMenu} timeout="auto" unmountOnExit>
|
||||||
|
<List component="div" disablePadding>
|
||||||
|
{subMenus.map((subItem, index) => (
|
||||||
|
<React.Fragment key={index}>
|
||||||
|
<MenuItem key={index} {...subItem} sx={{ marginLeft: subItem.open ? 2 : 0 }} />
|
||||||
|
{index === subMenus.length - 1 && <Divider />}
|
||||||
|
</React.Fragment>
|
||||||
|
))}
|
||||||
|
</List>
|
||||||
|
</Collapse>
|
||||||
|
)}
|
||||||
|
</>
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
export default MenuItem;
|
|
@ -0,0 +1,149 @@
|
||||||
|
import * as React from "react";
|
||||||
|
import { styled, Theme, CSSObject } from "@mui/material/styles";
|
||||||
|
import MuiDrawer from "@mui/material/Drawer";
|
||||||
|
import List from "@mui/material/List";
|
||||||
|
import Divider from "@mui/material/Divider";
|
||||||
|
import IconButton from "@mui/material/IconButton";
|
||||||
|
import ChevronLeftIcon from "@mui/icons-material/ChevronLeft";
|
||||||
|
import ChevronRightIcon from "@mui/icons-material/ChevronRight";
|
||||||
|
import { useNavigate } from "react-router-dom";
|
||||||
|
import { drawerWidth } from "./constants";
|
||||||
|
import {
|
||||||
|
SettingsOutlined,
|
||||||
|
HelpOutlineOutlined,
|
||||||
|
PollOutlined,
|
||||||
|
DashboardOutlined,
|
||||||
|
TuneOutlined
|
||||||
|
} from "@mui/icons-material";
|
||||||
|
import MenuItem from "./MenuItem";
|
||||||
|
import { useTranslation } from "react-i18next";
|
||||||
|
import { menu } from "./constants";
|
||||||
|
|
||||||
|
const openedMixin = (theme: Theme): CSSObject => ({
|
||||||
|
width: drawerWidth,
|
||||||
|
transition: theme.transitions.create("width", {
|
||||||
|
easing: theme.transitions.easing.sharp,
|
||||||
|
duration: theme.transitions.duration.enteringScreen
|
||||||
|
}),
|
||||||
|
overflowX: "hidden"
|
||||||
|
});
|
||||||
|
|
||||||
|
const closedMixin = (theme: Theme): CSSObject => ({
|
||||||
|
transition: theme.transitions.create("width", {
|
||||||
|
easing: theme.transitions.easing.sharp,
|
||||||
|
duration: theme.transitions.duration.leavingScreen
|
||||||
|
}),
|
||||||
|
overflowX: "hidden",
|
||||||
|
width: `calc(${theme.spacing(7)} + 1px)`,
|
||||||
|
[theme.breakpoints.up("sm")]: {
|
||||||
|
width: `calc(${theme.spacing(8)} + 1px)`
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
const DrawerHeader = styled("div")(({ theme }) => ({
|
||||||
|
display: "flex",
|
||||||
|
alignItems: "center",
|
||||||
|
justifyContent: "flex-end",
|
||||||
|
padding: theme.spacing(0, 1),
|
||||||
|
// necessary for content to be below app bar
|
||||||
|
...theme.mixins.toolbar
|
||||||
|
}));
|
||||||
|
|
||||||
|
const Drawer = styled(MuiDrawer, { shouldForwardProp: prop => prop !== "open" })(({ theme, open }) => ({
|
||||||
|
width: drawerWidth,
|
||||||
|
flexShrink: 0,
|
||||||
|
whiteSpace: "nowrap",
|
||||||
|
boxSizing: "border-box",
|
||||||
|
...(open && {
|
||||||
|
...openedMixin(theme),
|
||||||
|
"& .MuiDrawer-paper": openedMixin(theme)
|
||||||
|
}),
|
||||||
|
...(!open && {
|
||||||
|
...closedMixin(theme),
|
||||||
|
"& .MuiDrawer-paper": closedMixin(theme)
|
||||||
|
})
|
||||||
|
}));
|
||||||
|
|
||||||
|
type SideBarProps = {
|
||||||
|
open: boolean;
|
||||||
|
onDrawerOpen: () => void;
|
||||||
|
onDrawerClose: () => void;
|
||||||
|
};
|
||||||
|
|
||||||
|
const SideBar: React.FC<SideBarProps> = ({ open, onDrawerOpen, onDrawerClose }) => {
|
||||||
|
const navigate = useNavigate();
|
||||||
|
const { t } = useTranslation();
|
||||||
|
|
||||||
|
menu.sort((a, b) => (a.order || 0) - (b.order || 0));
|
||||||
|
|
||||||
|
return (
|
||||||
|
<Drawer variant="permanent" open={open}>
|
||||||
|
<DrawerHeader>
|
||||||
|
<IconButton onClick={open ? onDrawerClose : onDrawerOpen}>
|
||||||
|
{open ? <ChevronLeftIcon /> : <ChevronRightIcon />}
|
||||||
|
</IconButton>
|
||||||
|
</DrawerHeader>
|
||||||
|
<Divider />
|
||||||
|
|
||||||
|
{menu.map((section, index) => {
|
||||||
|
const isLast = index === menu.length - 1;
|
||||||
|
return (
|
||||||
|
<React.Fragment key={`section-${section.order}`}>
|
||||||
|
<List>
|
||||||
|
{section.items
|
||||||
|
.sort((i1, i2) => i1.order - i2.order)
|
||||||
|
.map(item => (
|
||||||
|
<MenuItem
|
||||||
|
key={`${item.code}-${index}`}
|
||||||
|
open={open}
|
||||||
|
icon={item.icon}
|
||||||
|
label={t(item.name)}
|
||||||
|
onClick={item.subMenus ? undefined : () => navigate(item.route)}
|
||||||
|
subMenus={item.subMenus?.map(si => ({
|
||||||
|
open,
|
||||||
|
icon: si.icon,
|
||||||
|
label: t(si.name),
|
||||||
|
onClick: () => navigate(si.route)
|
||||||
|
}))}
|
||||||
|
/>
|
||||||
|
))}
|
||||||
|
</List>
|
||||||
|
{!isLast && <Divider />}
|
||||||
|
</React.Fragment>
|
||||||
|
);
|
||||||
|
})}
|
||||||
|
|
||||||
|
<Divider />
|
||||||
|
<List>
|
||||||
|
<MenuItem
|
||||||
|
open={open}
|
||||||
|
icon={<SettingsOutlined />}
|
||||||
|
label={"Settings"}
|
||||||
|
subMenus={[
|
||||||
|
{
|
||||||
|
open,
|
||||||
|
icon: <DashboardOutlined />,
|
||||||
|
label: "Dashboards",
|
||||||
|
onClick: () => navigate("/configurator/dashboards")
|
||||||
|
},
|
||||||
|
{
|
||||||
|
open,
|
||||||
|
icon: <PollOutlined />,
|
||||||
|
label: "Charts",
|
||||||
|
onClick: () => navigate("/configurator/charts")
|
||||||
|
},
|
||||||
|
{
|
||||||
|
open,
|
||||||
|
icon: <TuneOutlined />,
|
||||||
|
label: "Filters",
|
||||||
|
onClick: () => navigate("/configurator/filters")
|
||||||
|
}
|
||||||
|
]}
|
||||||
|
/>
|
||||||
|
<MenuItem open={open} icon={<HelpOutlineOutlined />} label={"Help"} onClick={() => navigate("/help")} />
|
||||||
|
</List>
|
||||||
|
</Drawer>
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
export default SideBar;
|
|
@ -1,143 +0,0 @@
|
||||||
import React, { useState } from "react";
|
|
||||||
import PropTypes from "prop-types";
|
|
||||||
import clsx from "clsx";
|
|
||||||
import { useTheme } from "@mui/material/styles";
|
|
||||||
import { Drawer, List, Divider, IconButton, ListItemIcon, ListItemText } from "@mui/material";
|
|
||||||
import ChevronLeftIcon from "@mui/icons-material/ChevronLeft";
|
|
||||||
import ChevronRightIcon from "@mui/icons-material/ChevronRight";
|
|
||||||
import ListItem from "@mui/material/ListItem";
|
|
||||||
import BuildIcon from "@mui/icons-material/Build";
|
|
||||||
import DnsIcon from "@mui/icons-material/Dns";
|
|
||||||
import DeviceHubIcon from "@mui/icons-material/DeviceHub";
|
|
||||||
import SettingsIcon from "@mui/icons-material/Settings";
|
|
||||||
import DashboardIcon from "@mui/icons-material/Dashboard";
|
|
||||||
import FeaturedPlayListIcon from "@mui/icons-material/FeaturedPlayList";
|
|
||||||
import { useNavigate } from "react-router-dom";
|
|
||||||
import { useTranslation } from "react-i18next";
|
|
||||||
import { getStyles } from "./styles";
|
|
||||||
|
|
||||||
const menu = [
|
|
||||||
{
|
|
||||||
order: 0,
|
|
||||||
items: [
|
|
||||||
{
|
|
||||||
code: "dashboard",
|
|
||||||
name: "Menu.Dashboard",
|
|
||||||
route: "/dashboard",
|
|
||||||
icon: <DashboardIcon />,
|
|
||||||
order: 0
|
|
||||||
},
|
|
||||||
{
|
|
||||||
code: "machines",
|
|
||||||
name: "Menu.Machines",
|
|
||||||
route: "/machines",
|
|
||||||
icon: <DnsIcon />,
|
|
||||||
order: 1
|
|
||||||
},
|
|
||||||
{
|
|
||||||
code: "system",
|
|
||||||
name: "Menu.System",
|
|
||||||
route: "/system",
|
|
||||||
icon: <DeviceHubIcon />,
|
|
||||||
order: 2
|
|
||||||
}
|
|
||||||
]
|
|
||||||
},
|
|
||||||
{
|
|
||||||
order: 1,
|
|
||||||
items: [
|
|
||||||
{
|
|
||||||
code: "administration",
|
|
||||||
name: "Menu.Administration",
|
|
||||||
route: "/administration",
|
|
||||||
icon: <BuildIcon />,
|
|
||||||
order: 0
|
|
||||||
},
|
|
||||||
{
|
|
||||||
code: "settings",
|
|
||||||
name: "Menu.Settings",
|
|
||||||
route: "/settings",
|
|
||||||
icon: <SettingsIcon />,
|
|
||||||
order: 1
|
|
||||||
}
|
|
||||||
]
|
|
||||||
},
|
|
||||||
{
|
|
||||||
order: 2,
|
|
||||||
items: [
|
|
||||||
{
|
|
||||||
code: "about",
|
|
||||||
name: "Menu.About",
|
|
||||||
route: "/about",
|
|
||||||
icon: <FeaturedPlayListIcon />,
|
|
||||||
order: 0
|
|
||||||
}
|
|
||||||
]
|
|
||||||
}
|
|
||||||
];
|
|
||||||
|
|
||||||
const sortedMenu = menu.sort((i1, i2) => i1 - i2);
|
|
||||||
|
|
||||||
const Sidebar = ({ open, handleDrawerClose }) => {
|
|
||||||
const [selected, setSelected] = useState(null);
|
|
||||||
const theme = useTheme();
|
|
||||||
const styles = getStyles(theme);
|
|
||||||
const navigate = useNavigate();
|
|
||||||
const { t } = useTranslation();
|
|
||||||
|
|
||||||
const handleClick = route => () => {
|
|
||||||
setSelected(route);
|
|
||||||
navigate(route);
|
|
||||||
};
|
|
||||||
|
|
||||||
const isSelected = key => selected === key;
|
|
||||||
|
|
||||||
return (
|
|
||||||
<Drawer
|
|
||||||
variant="permanent"
|
|
||||||
sx={clsx(styles.drawer, {
|
|
||||||
[styles.drawerOpen]: open,
|
|
||||||
[styles.drawerClose]: !open
|
|
||||||
})}
|
|
||||||
classes={{
|
|
||||||
paper: clsx({
|
|
||||||
[styles.drawerOpen]: open,
|
|
||||||
[styles.drawerClose]: !open
|
|
||||||
})
|
|
||||||
}}
|
|
||||||
>
|
|
||||||
<div style={styles.toolbar}>
|
|
||||||
<IconButton onClick={handleDrawerClose}>
|
|
||||||
{theme.direction === "rtl" ? <ChevronRightIcon /> : <ChevronLeftIcon />}
|
|
||||||
</IconButton>
|
|
||||||
</div>
|
|
||||||
<Divider />
|
|
||||||
|
|
||||||
{sortedMenu.map((menu, index) => {
|
|
||||||
const isLast = index === sortedMenu.length - 1;
|
|
||||||
return (
|
|
||||||
<React.Fragment key={`menu-${menu.order}`}>
|
|
||||||
<List>
|
|
||||||
{menu.items
|
|
||||||
.sort((i1, i2) => i1 - i2)
|
|
||||||
.map(item => (
|
|
||||||
<ListItem button key={item.code} onClick={handleClick(item.route)} selected={isSelected(item.route)}>
|
|
||||||
<ListItemIcon>{item.icon}</ListItemIcon>
|
|
||||||
<ListItemText primary={t(item.name)} />
|
|
||||||
</ListItem>
|
|
||||||
))}
|
|
||||||
</List>
|
|
||||||
{!isLast && <Divider />}
|
|
||||||
</React.Fragment>
|
|
||||||
);
|
|
||||||
})}
|
|
||||||
</Drawer>
|
|
||||||
);
|
|
||||||
};
|
|
||||||
|
|
||||||
Sidebar.propTypes = {
|
|
||||||
open: PropTypes.bool.isRequired,
|
|
||||||
handleDrawerClose: PropTypes.func.isRequired
|
|
||||||
};
|
|
||||||
|
|
||||||
export default Sidebar;
|
|
|
@ -1 +1,3 @@
|
||||||
|
export * from "./menu";
|
||||||
|
|
||||||
export const drawerWidth = 240;
|
export const drawerWidth = 240;
|
|
@ -0,0 +1,98 @@
|
||||||
|
import React from "react";
|
||||||
|
import { Dashboard, Dns, DeviceHub, Build, Settings, Info } from "../../icons";
|
||||||
|
|
||||||
|
type MenuItem = {
|
||||||
|
code: string;
|
||||||
|
name: string;
|
||||||
|
route: string;
|
||||||
|
icon: JSX.Element;
|
||||||
|
order: number;
|
||||||
|
subMenus?: MenuItem[];
|
||||||
|
};
|
||||||
|
|
||||||
|
type MenuSection = {
|
||||||
|
order: number;
|
||||||
|
items: MenuItem[];
|
||||||
|
};
|
||||||
|
|
||||||
|
type Menu = MenuSection[];
|
||||||
|
|
||||||
|
const menu: Menu = [
|
||||||
|
{
|
||||||
|
order: 0,
|
||||||
|
items: [
|
||||||
|
{
|
||||||
|
code: "dashboard",
|
||||||
|
name: "Menu.Dashboard",
|
||||||
|
route: "/dashboard",
|
||||||
|
icon: <Dashboard />,
|
||||||
|
order: 0
|
||||||
|
},
|
||||||
|
{
|
||||||
|
code: "machines",
|
||||||
|
name: "Menu.Machines",
|
||||||
|
route: "/machines",
|
||||||
|
icon: <Dns />,
|
||||||
|
order: 1
|
||||||
|
},
|
||||||
|
{
|
||||||
|
code: "system",
|
||||||
|
name: "Menu.System",
|
||||||
|
route: "/system",
|
||||||
|
icon: <DeviceHub />,
|
||||||
|
order: 2
|
||||||
|
}
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
order: 1,
|
||||||
|
items: [
|
||||||
|
{
|
||||||
|
code: "administration",
|
||||||
|
name: "Menu.Administration",
|
||||||
|
route: "/administration",
|
||||||
|
icon: <Build />,
|
||||||
|
order: 0,
|
||||||
|
subMenus: [
|
||||||
|
{
|
||||||
|
code: "machines",
|
||||||
|
name: "Menu.Machines",
|
||||||
|
route: "/administration/machines",
|
||||||
|
icon: <Build />,
|
||||||
|
order: 0
|
||||||
|
},
|
||||||
|
{
|
||||||
|
code: "agents",
|
||||||
|
name: "Menu.Agents",
|
||||||
|
route: "/administration/agents",
|
||||||
|
icon: <Build />,
|
||||||
|
order: 1
|
||||||
|
}
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
code: "settings",
|
||||||
|
name: "Menu.Settings",
|
||||||
|
route: "/settings",
|
||||||
|
icon: <Settings />,
|
||||||
|
order: 1
|
||||||
|
}
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
order: 2,
|
||||||
|
items: [
|
||||||
|
{
|
||||||
|
code: "about",
|
||||||
|
name: "Menu.About",
|
||||||
|
route: "/about",
|
||||||
|
icon: <Info />,
|
||||||
|
order: 0
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
];
|
||||||
|
|
||||||
|
export type { MenuItem, MenuSection, Menu };
|
||||||
|
export { menu };
|
||||||
|
export default menu;
|
|
@ -1,9 +1,6 @@
|
||||||
const drawerWidth = 240;
|
const drawerWidth = 240;
|
||||||
|
|
||||||
const getStyles = theme => ({
|
const getStyles = theme => ({
|
||||||
root: {
|
|
||||||
display: "flex"
|
|
||||||
},
|
|
||||||
appBar: {
|
appBar: {
|
||||||
zIndex: theme.zIndex.drawer + 1,
|
zIndex: theme.zIndex.drawer + 1,
|
||||||
transition: theme.transitions.create(["width", "margin"], {
|
transition: theme.transitions.create(["width", "margin"], {
|
||||||
|
@ -30,36 +27,6 @@ const getStyles = theme => ({
|
||||||
flexShrink: 0,
|
flexShrink: 0,
|
||||||
whiteSpace: "nowrap"
|
whiteSpace: "nowrap"
|
||||||
},
|
},
|
||||||
drawerOpen: {
|
|
||||||
width: drawerWidth,
|
|
||||||
transition: theme.transitions.create("width", {
|
|
||||||
easing: theme.transitions.easing.sharp,
|
|
||||||
duration: theme.transitions.duration.enteringScreen
|
|
||||||
})
|
|
||||||
},
|
|
||||||
drawerClose: {
|
|
||||||
transition: theme.transitions.create("width", {
|
|
||||||
easing: theme.transitions.easing.sharp,
|
|
||||||
duration: theme.transitions.duration.leavingScreen
|
|
||||||
}),
|
|
||||||
overflowX: "hidden",
|
|
||||||
width: theme.spacing(7) + 1,
|
|
||||||
[theme.breakpoints.up("sm")]: {
|
|
||||||
width: theme.spacing(9) + 1
|
|
||||||
}
|
|
||||||
},
|
|
||||||
toolbar: {
|
|
||||||
display: "flex",
|
|
||||||
alignItems: "center",
|
|
||||||
justifyContent: "flex-end",
|
|
||||||
padding: theme.spacing(0, 1),
|
|
||||||
// necessary for content to be below app bar
|
|
||||||
...theme.mixins.toolbar
|
|
||||||
},
|
|
||||||
content: {
|
|
||||||
flexGrow: 1,
|
|
||||||
padding: theme.spacing(2)
|
|
||||||
},
|
|
||||||
menuItemIcon: {
|
menuItemIcon: {
|
||||||
minWidth: "26px"
|
minWidth: "26px"
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue