Files
hetty/admin/src/components/Layout.tsx

252 lines
7.1 KiB
TypeScript
Raw Normal View History

import React from "react";
import {
Theme,
useTheme,
Toolbar,
IconButton,
Typography,
Divider,
List,
Tooltip,
2022-01-28 20:20:15 +01:00
styled,
CSSObject,
Box,
ListItemText,
} from "@mui/material";
import MuiAppBar, { AppBarProps as MuiAppBarProps } from "@mui/material/AppBar";
import MuiDrawer from "@mui/material/Drawer";
import MuiListItemButton, { ListItemButtonProps } from "@mui/material/ListItemButton";
import MuiListItemIcon, { ListItemIconProps } from "@mui/material/ListItemIcon";
2020-09-23 23:43:20 +02:00
import Link from "next/link";
2022-01-28 20:20:15 +01:00
import MenuIcon from "@mui/icons-material/Menu";
import HomeIcon from "@mui/icons-material/Home";
import SettingsEthernetIcon from "@mui/icons-material/SettingsEthernet";
import SendIcon from "@mui/icons-material/Send";
import FolderIcon from "@mui/icons-material/Folder";
import LocationSearchingIcon from "@mui/icons-material/LocationSearching";
import ChevronLeftIcon from "@mui/icons-material/ChevronLeft";
import ChevronRightIcon from "@mui/icons-material/ChevronRight";
export enum Page {
Home,
2020-10-11 17:09:39 +02:00
GetStarted,
Projects,
ProxySetup,
ProxyLogs,
Sender,
2020-10-29 20:54:17 +01:00
Scope,
}
const drawerWidth = 240;
2022-01-28 20:20:15 +01:00
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: 56,
});
const DrawerHeader = styled("div")(({ theme }) => ({
display: "flex",
alignItems: "center",
justifyContent: "flex-start",
padding: theme.spacing(0, 1),
// necessary for content to be below app bar
...theme.mixins.toolbar,
}));
interface AppBarProps extends MuiAppBarProps {
open?: boolean;
}
const AppBar = styled(MuiAppBar, {
shouldForwardProp: (prop) => prop !== "open",
})<AppBarProps>(({ theme, open }) => ({
backgroundColor: theme.palette.secondary.dark,
zIndex: theme.zIndex.drawer + 1,
transition: theme.transitions.create(["width", "margin"], {
easing: theme.transitions.easing.sharp,
duration: theme.transitions.duration.leavingScreen,
}),
...(open && {
marginLeft: drawerWidth,
width: `calc(100% - ${drawerWidth}px)`,
transition: theme.transitions.create(["width", "margin"], {
easing: theme.transitions.easing.sharp,
duration: theme.transitions.duration.enteringScreen,
}),
}),
}));
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),
}),
}));
const ListItemButton = styled(MuiListItemButton)<ListItemButtonProps>(({ theme }) => ({
[theme.breakpoints.up("sm")]: {
px: 1,
},
"&.MuiListItemButton-root": {
"&.Mui-selected": {
backgroundColor: theme.palette.primary.main,
"& .MuiListItemIcon-root": {
color: theme.palette.secondary.dark,
},
2022-01-28 20:20:15 +01:00
"& .MuiListItemText-root": {
color: theme.palette.secondary.dark,
},
},
2022-01-28 20:20:15 +01:00
},
}));
const ListItemIcon = styled(MuiListItemIcon)<ListItemIconProps>(() => ({
minWidth: 42,
}));
interface Props {
children: React.ReactNode;
title: string;
page: Page;
}
export function Layout({ title, page, children }: Props): JSX.Element {
const theme = useTheme();
const [open, setOpen] = React.useState(false);
const handleDrawerOpen = () => {
setOpen(true);
};
const handleDrawerClose = () => {
setOpen(false);
};
2022-01-28 20:20:15 +01:00
const SiteTitle = styled("span")({
...(title !== "" && {
color: theme.palette.primary.main,
marginRight: 4,
}),
});
return (
2022-02-22 14:10:39 +01:00
<Box sx={{ display: "flex", height: "100%" }}>
2022-01-28 20:20:15 +01:00
<AppBar position="fixed" open={open}>
<Toolbar>
<IconButton
color="inherit"
2022-01-28 20:20:15 +01:00
aria-label="Open drawer"
onClick={handleDrawerOpen}
edge="start"
2022-01-28 20:20:15 +01:00
sx={{
mr: 5,
...(open && { display: "none" }),
}}
>
<MenuIcon />
</IconButton>
2022-01-28 20:20:15 +01:00
<Box
sx={{
display: "flex",
justifyContent: "space-around",
width: "100%",
}}
>
<Typography variant="h5" noWrap sx={{ width: "100%" }}>
<SiteTitle>Hetty://</SiteTitle>
{title}
</Typography>
<Box sx={{ flexShrink: 0, pt: 0.75 }}>v{process.env.NEXT_PUBLIC_VERSION || "0.0"}</Box>
</Box>
</Toolbar>
</AppBar>
2022-01-28 20:20:15 +01:00
<Drawer variant="permanent" open={open}>
<DrawerHeader>
<IconButton onClick={handleDrawerClose}>
2022-01-28 20:20:15 +01:00
{theme.direction === "rtl" ? <ChevronRightIcon /> : <ChevronLeftIcon />}
</IconButton>
2022-01-28 20:20:15 +01:00
</DrawerHeader>
<Divider />
2022-01-28 20:20:15 +01:00
<List sx={{ p: 0 }}>
2020-09-23 23:43:20 +02:00
<Link href="/" passHref>
2022-01-28 20:20:15 +01:00
<ListItemButton key="home" selected={page === Page.Home}>
2020-09-23 23:43:20 +02:00
<Tooltip title="Home">
2022-01-28 20:20:15 +01:00
<ListItemIcon>
2020-09-23 23:43:20 +02:00
<HomeIcon />
</ListItemIcon>
</Tooltip>
<ListItemText primary="Home" />
2022-01-28 20:20:15 +01:00
</ListItemButton>
2020-09-23 23:43:20 +02:00
</Link>
<Link href="/proxy/logs" passHref>
2022-01-28 20:20:15 +01:00
<ListItemButton key="proxyLogs" selected={page === Page.ProxyLogs}>
2020-09-23 23:43:20 +02:00
<Tooltip title="Proxy">
2022-01-28 20:20:15 +01:00
<ListItemIcon>
2020-09-23 23:43:20 +02:00
<SettingsEthernetIcon />
</ListItemIcon>
</Tooltip>
<ListItemText primary="Proxy" />
2022-01-28 20:20:15 +01:00
</ListItemButton>
2020-09-23 23:43:20 +02:00
</Link>
<Link href="/sender" passHref>
2022-01-28 20:20:15 +01:00
<ListItemButton key="sender" selected={page === Page.Sender}>
2020-09-23 23:43:20 +02:00
<Tooltip title="Sender">
2022-01-28 20:20:15 +01:00
<ListItemIcon>
2020-09-23 23:43:20 +02:00
<SendIcon />
</ListItemIcon>
</Tooltip>
<ListItemText primary="Sender" />
2022-01-28 20:20:15 +01:00
</ListItemButton>
2020-09-23 23:43:20 +02:00
</Link>
2020-10-29 20:54:17 +01:00
<Link href="/scope" passHref>
2022-01-28 20:20:15 +01:00
<ListItemButton key="scope" selected={page === Page.Scope}>
2020-10-29 20:54:17 +01:00
<Tooltip title="Scope">
2022-01-28 20:20:15 +01:00
<ListItemIcon>
2020-10-29 20:54:17 +01:00
<LocationSearchingIcon />
</ListItemIcon>
</Tooltip>
<ListItemText primary="Scope" />
2022-01-28 20:20:15 +01:00
</ListItemButton>
2020-10-29 20:54:17 +01:00
</Link>
2020-10-11 17:09:39 +02:00
<Link href="/projects" passHref>
2022-01-28 20:20:15 +01:00
<ListItemButton key="projects" selected={page === Page.Projects}>
2020-10-11 17:09:39 +02:00
<Tooltip title="Projects">
2022-01-28 20:20:15 +01:00
<ListItemIcon>
2020-10-11 17:09:39 +02:00
<FolderIcon />
</ListItemIcon>
</Tooltip>
<ListItemText primary="Projects" />
2022-01-28 20:20:15 +01:00
</ListItemButton>
2020-10-11 17:09:39 +02:00
</Link>
</List>
</Drawer>
2022-02-22 14:10:39 +01:00
<Box component="main" sx={{ flexGrow: 1, mx: 3, mt: 11 }}>
{children}
2022-01-28 20:20:15 +01:00
</Box>
</Box>
);
}
export default Layout;