React-admin - Create sub menu - reactjs

How to create sub menu in react-admin, because in admin-on-rest i can use prop menuItems in MenuItem Component.
Does react-admin have same props for this case?
I try create my own component, but with prop primary in ListItemText for give list name my app always show error Uncaught TypeError: Cannot read property '#global'
Thank you

As previously explained by the maintainers/developers of react-admin, this feature is not offered by react-admin.
If you want a sub-menu, you should create a custom menu, following the instructions given in the official react-admin documentation and implement the Material-UI's nested-list logic.
This is a simple example of what your sub-menu could look like, according to the links I provided:
<List component="nav" >
<ListItem button onClick={this.handleClick}>
<ListItemIcon>
<InboxIcon />
</ListItemIcon>
<ListItemText inset primary="YOUR-SECTION-TITLE" />
{this.state.open ? <ExpandLess /> : <ExpandMore />}
</ListItem>
<Collapse in={this.state.open} timeout="auto" unmountOnExit>
<List component="div" disablePadding>
<MenuItemLink to="/your-api-endpoint-1" primaryText="API-ENDPOINT-1" onClick={this.props.onMenuClick} />
<MenuItemLink to="/your-api-endpoint-2" primaryText="API-ENDPOINT-2" onClick={this.props.onMenuClick} />
<MenuItemLink to="/your-api-endpoint-3" primaryText="API-ENDPOINT-3" onClick={this.props.onMenuClick} />
</List>
</Collapse>
</List>

Simple submenu component compatible with React Admin v4 https://marmelab.com/react-admin/Menu.html
import * as React from 'react';
import { useState } from 'react';
import PropTypes from 'prop-types';
import ExpandMoreIcon from '#mui/icons-material/ExpandMore';
import { List, ListItem, ListItemText, Collapse } from '#mui/material';
import { useTranslate, useSidebarState } from 'react-admin';
export const SubMenu = (props: SubMenuProps) => {
const { isDropdownOpen = false, primaryText, leftIcon, children, ...rest } = props;
const translate = useTranslate();
const [open] = useSidebarState();
const [isOpen, setIsOpen] = useState(isDropdownOpen);
const handleToggle = () => {
setIsOpen(!isOpen);
};
return (
<React.Fragment>
<ListItem
dense
button
onClick={handleToggle}
sx={{
paddingLeft: '1rem',
color: 'rgba(0, 0, 0, 0.54)',
}}
>
{isOpen ? <ExpandMoreIcon /> : leftIcon}
<ListItemText
inset
disableTypography
primary={translate(primaryText)}
sx={{
paddingLeft: 2,
fontSize: '1rem',
color: 'rgba(0, 0, 0, 0.6)',
}}
/>
</ListItem>
<Collapse in={isOpen} timeout="auto" unmountOnExit>
<List
component="div"
disablePadding
sx={open ? {
paddingLeft: '25px',
transition: 'padding-left 195ms cubic-bezier(0.4, 0, 0.6, 1) 0ms',
} : {
paddingLeft: 0,
transition: 'padding-left 195ms cubic-bezier(0.4, 0, 0.6, 1) 0ms',
}}
>
{children}
</List>
</Collapse>
</React.Fragment>
)
}
export type SubMenuProps = {
children?: React.ReactNode;
isDropdownOpen?: boolean;
leftIcon?: React.ReactElement;
primaryText?: string;
};
export default SubMenu;
Usage:
import * as React from 'react';
import { Menu } from 'react-admin';
import BookIcon from '#mui/icons-material/Book';
import PeopleIcon from '#mui/icons-material/People';
import LabelIcon from '#mui/icons-material/Label';
import SubMenu from './SubMenu';
export const MainMenu = () => (
<Menu>
<Menu.DashboardItem />
<SubMenu primaryText="CMS" leftIcon={<BookIcon />}>
<Menu.Item to="/admin/pages" primaryText="Pages" leftIcon={<BookIcon />}/>
<Menu.Item to="/admin/articles" primaryText="Articles" leftIcon={<PeopleIcon />}/>
</SubMenu>
<Menu.Item to="/custom-route" primaryText="Miscellaneous" leftIcon={<LabelIcon />}/>
</Menu>
);

Related

Share values and events across different components in React

I am trying to build a dashboard app with basic AppBar and a drawer based on this Demo
https://codesandbox.io/s/nj3u0q?file=/demo.tsx
But in this Demo, AppBar and Drawer and the Main content are all in a single page.
But I made it as separate components and did the layout like this
RootContainer.tsx
import * as React from 'react';
import { styled, useTheme } from '#mui/material/styles';
import Box from '#mui/material/Box';
import CssBaseline from '#mui/material/CssBaseline';
import MuiAppBar, { AppBarProps as MuiAppBarProps } from '#mui/material/AppBar';
import Drawer from './Drawer';
import AppBar from './AppBar';
import Main from './MainContent';
export default function PersistentDrawerLeft() {
const [open, setOpen] = React.useState(false);
return (
<Box sx={{ display: 'flex' }}>
<CssBaseline />
<AppBar />
<Drawer />
<Main />
</Box>
);
}
Appbar.tsx
import * as React from 'react';
import { styled, useTheme } from '#mui/material/styles';
import MuiAppBar, { AppBarProps as MuiAppBarProps } from '#mui/material/AppBar';
import Toolbar from '#mui/material/Toolbar';
import Typography from '#mui/material/Typography';
import IconButton from '#mui/material/IconButton';
import MenuIcon from '#mui/icons-material/Menu';
const drawerWidth = 240;
interface AppBarProps extends MuiAppBarProps {
open?: boolean;
}
const AppBar = styled(MuiAppBar, {
shouldForwardProp: (prop) => prop !== 'open',
})<AppBarProps>(({ theme, open }) => ({
transition: theme.transitions.create(['margin', 'width'], {
easing: theme.transitions.easing.sharp,
duration: theme.transitions.duration.leavingScreen,
}),
...(open && {
width: `calc(100% - ${drawerWidth}px)`,
marginLeft: `${drawerWidth}px`,
transition: theme.transitions.create(['margin', 'width'], {
easing: theme.transitions.easing.easeOut,
duration: theme.transitions.duration.enteringScreen,
}),
}),
}));
export default function AppBar() {
const theme = useTheme();
const [open, setOpen] = React.useState(false);
const handleDrawerOpen = () => {
setOpen(true);
};
return (
<AppBar position="fixed" style={{background:'#002a5e'}} open={open}>
<Toolbar>
<IconButton
color="inherit"
aria-label="open drawer"
onClick={handleDrawerOpen}
edge="start"
sx={{ mr: 2, ...(open && { display: 'none' }) }}
>
<MenuIcon />
</IconButton>
<Typography variant="h6" noWrap component="div">
Test
</Typography>
</Toolbar>
</AppBar>
);
}
But the problem is when I click the sandwich button on the appbar, it reduces its width to show the Drawer, but the drawer not at all showing.
Drawer.tsx
import * as React from "react";
import { styled, useTheme } from "#mui/material/styles";
import Drawer 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 ListItem from "#mui/material/ListItem";
import ListItemButton from "#mui/material/ListItemButton";
import ListItemIcon from "#mui/material/ListItemIcon";
import ListItemText from "#mui/material/ListItemText";
import InboxIcon from "#mui/icons-material/MoveToInbox";
import MailIcon from "#mui/icons-material/Mail";
const drawerWidth = 240;
const DrawerHeader = styled("div")(({ theme }) => ({
display: "flex",
alignItems: "center",
padding: theme.spacing(0, 1),
// necessary for content to be below app bar
...theme.mixins.toolbar,
justifyContent: "flex-end",
}));
export default function Drawer() {
const theme = useTheme();
const [open, setOpen] = React.useState(false);
const handleDrawerOpen = () => {
setOpen(true);
};
const handleDrawerClose = () => {
setOpen(false);
};
return (
<Drawer
sx={{
width: drawerWidth,
flexShrink: 0,
"& .MuiDrawer-paper": {
width: drawerWidth,
boxSizing: "border-box",
},
}}
variant="persistent"
anchor="left"
open={open}
>
<DrawerHeader>
<IconButton onClick={handleDrawerClose}>
{theme.direction === "ltr" ? (
<ChevronLeftIcon />
) : (
<ChevronRightIcon />
)}
</IconButton>
</DrawerHeader>
<Divider />
<List>
{["Manage Recipe", "Reports", "Settings"].map((text, index) => (
<ListItem key={text} disablePadding>
<ListItemButton>
<ListItemIcon>
{index % 2 === 0 ? <InboxIcon /> : <MailIcon />}
</ListItemIcon>
<ListItemText primary={text} />
</ListItemButton>
</ListItem>
))}
</List>
</Drawer>
);
}
I guess this problem is because the open constant is not getting updated into the drawer component. I am pretty new or only fews days of experience in react. Please help how can share these click event and constant in appbar to the drawer
It looks like with the separation, each component is having their own open state and handling functions, therefore the behavior is not shared.
Try pass these as props from the parent to communicate with children components.
React document about: Passing Props to a Component
There seems to be already a open state in the parent component RootContainer, so perhaps this state and handlers can be passed as props to the components, such as below example.
Over simplified example from forked demo: codesandbox
Define state and handler in the parent component, and pass these down to the children:
RootContainer.tsx
export default function PersistentDrawerLeft() {
const [open, setOpen] = React.useState(false);
const handleDrawerOpen = () => {
setOpen(true);
};
const handleDrawerClose = () => {
setOpen(false);
};
return (
<Box sx={{ display: "flex" }}>
<CssBaseline />
<AppBar open={open} onDrawerOpen={handleDrawerOpen} />
<Drawer open={open} onDrawerClose={handleDrawerClose} />
<Main />
</Box>
);
}
Have each child component use the open state and handlers from the props, instead of their own, so that they share the same state:
Appbar.tsx
export default function AppBar({ open, onDrawerOpen }) {
const theme = useTheme();
return (
<AppBar position="fixed" style={{ background: "#002a5e" }} open={open}>
<Toolbar>
<IconButton
color="inherit"
aria-label="open drawer"
onClick={onDrawerOpen}
edge="start"
sx={{ mr: 2, ...(open && { display: "none" }) }}
>
<MenuIcon />
</IconButton>
<Typography variant="h6" noWrap component="div">
Test
</Typography>
</Toolbar>
</AppBar>
);
}
Drawer.tsx
export default function Drawer({ open, onDrawerClose }) {
const theme = useTheme();
return (
<Drawer
sx={{
width: drawerWidth,
flexShrink: 0,
"& .MuiDrawer-paper": {
width: drawerWidth,
boxSizing: "border-box"
}
}}
variant="persistent"
anchor="left"
open={open}
>
<DrawerHeader>
<IconButton onClick={onDrawerClose}>
{theme.direction === "ltr" ? (
<ChevronLeftIcon />
) : (
<ChevronRightIcon />
)}
</IconButton>
</DrawerHeader>
<Divider />
<List>
{["Manage Recipe", "Reports", "Settings"].map((text, index) => (
<ListItem key={text} disablePadding>
<ListItemButton>
<ListItemIcon>
{index % 2 === 0 ? <InboxIcon /> : <MailIcon />}
</ListItemIcon>
<ListItemText primary={text} />
</ListItemButton>
</ListItem>
))}
</List>
</Drawer>
);
}
Hope this will help.

Material UI persistent drawer - content body not resizing

I have an application with a persistent drawer. The drawer contains linked routes to various other components.
In general the drawer itself works fine, but the loaded components are not resizing, when the drawer opens or closes.
In the samples on the mui doc pages this functionality in implemented in the styled main component. Means the content is in the same component as the drawer. This is different in my app, where i have an index file with the routes, a navigationbar file with the drawer and the other components with their respective files.
So, how do i implement this resizing with loaded components?
index.tsx
import React from "react";
import ReactDOM from "react-dom";
import { BrowserRouter as Router, Route, Switch } from "react-router-dom";
import "bootstrap/dist/css/bootstrap.min.css";
import NavigationBar from "./ADBPM-Components/NavigationBar";
import Login from "./login";
import PrivateRoute from "./login/PrivateRoute";
import Authenticator from "./login/auth";
import NotFound from "./notFound";
import WelcomeScreen from "./welcomeScreen";
import Test from "./test";
//Check if already authenticated
Authenticator.refreshState(() => {
refreshPage();
});
export const refreshPage = () => {
ReactDOM.render(
<Router>
<div>
<PrivateRoute noRedirect path="/" component={NavigationBar} />
<Switch>
<PrivateRoute exact path="/" component={WelcomeScreen} />
<PrivateRoute path="/test" component={Test} />
<PrivateRoute path="/changepass" component={ChangePassword} />
<PrivateRoute path="/createuser" component={CreateUser} />
<Route path="/login" component={Login} />
<Route path="/signup" component={CreateUser} />
<PrivateRoute path="/" component={NotFound} />
</Switch>
</div>
</Router>,
document.getElementById("app")
);
};
NavigationBar.tsx
import * as React from "react";
import { withRouter } from "react-router";
import { Link } from "react-router-dom";
import { Divider } from "#material-ui/core";
import Box from '#mui/material/Box';
import Toolbar from '#mui/material/Toolbar';
import Typography from '#mui/material/Typography';
import IconButton from '#mui/material/IconButton';
import MenuIcon from '#mui/icons-material/Menu';
import Drawer from '#mui/material/Drawer';
import MuiAppBar, { AppBarProps as MuiAppBarProps } from '#mui/material/AppBar';
import { styled, useTheme } from '#mui/material/styles';
import List from '#mui/material/List';
import ListItem from '#mui/material/ListItem';
import ListItemIcon from '#mui/material/ListItemIcon';
import ChevronLeftIcon from '#mui/icons-material/ChevronLeft';
import ChevronRightIcon from '#mui/icons-material/ChevronRight';
import ListItemText from '#mui/material/ListItemText';
import CssBaseline from '#mui/material/CssBaseline';
import PeopleIcon from '#mui/icons-material/People';
import QueryStatsIcon from '#mui/icons-material/QueryStats';
import BuildIcon from '#mui/icons-material/Build';
import RequestPageIcon from '#mui/icons-material/RequestPage';
import LogoutOutlinedIcon from '#mui/icons-material/LogoutOutlined';
import PasswordIcon from '#mui/icons-material/Password';
import SupervisedUserCircleIcon from '#mui/icons-material/SupervisedUserCircle';
import TableViewIcon from '#mui/icons-material/TableView';
import Authenticator from "../login/auth";
import * as pack from "../../package.json";
import { Fragment } from "react";
const drawerWidth = 240;
interface AppBarProps extends MuiAppBarProps {
open?: boolean;
}
const AppBar = styled(MuiAppBar, {
shouldForwardProp: (prop) => prop !== 'open',
})<AppBarProps>(({ theme, open }) => ({
transition: theme.transitions.create(['margin', 'width'], {
easing: theme.transitions.easing.sharp,
duration: theme.transitions.duration.leavingScreen,
}),
...(open && {
width: `calc(100% - ${drawerWidth}px)`,
marginLeft: `${drawerWidth}px`,
transition: theme.transitions.create(['margin', 'width'], {
easing: theme.transitions.easing.easeOut,
duration: theme.transitions.duration.enteringScreen,
}),
}),
}));
const DrawerHeader = styled('div')(({ theme }) => ({
display: 'flex',
alignItems: 'center',
padding: theme.spacing(0, 1),
// necessary for content to be below app bar
...theme.mixins.toolbar,
justifyContent: 'flex-end',
}));
function NavigationBar() {
const theme = useTheme();
const [open, setOpen] = React.useState(false);
const handleDrawerOpen = () => {
setOpen(true);
};
const handleDrawerClose = () => {
setOpen(false);
};
return (
<Fragment>
<Box sx={{ display: 'flex' }}>
<CssBaseline />
<AppBar position="fixed" open={open}>
<Toolbar>
<IconButton
color="inherit"
aria-label="open drawer"
onClick={handleDrawerOpen}
edge="start"
sx={{ mr: 2, ...(open && { display: 'none' }) }}
>
<MenuIcon />
</IconButton>
<Typography variant="h6" component="div" sx={{ flexGrow: 1 }}>
ADBPM ({pack.version})
</Typography>
<Typography variant="h6" component="div" sx={{ flexGrow: 1 }} align="right">
{` Logged in as ${Authenticator.user}`}
</Typography>
</Toolbar>
</AppBar>
<Drawer
sx={{
width: drawerWidth,
flexShrink: 0,
'& .MuiDrawer-paper': {
width: drawerWidth,
boxSizing: 'border-box',
},
}}
variant="persistent"
anchor="left"
open={open}
>
<DrawerHeader>
<IconButton onClick={handleDrawerClose}>
{theme.direction === 'ltr' ? <ChevronLeftIcon /> : <ChevronRightIcon />}
</IconButton>
</DrawerHeader>
<Divider />
<List>
<ListItem button key='Test' component={Link} to="/test">
<ListItemIcon>
<QueryStatsIcon />
</ListItemIcon>
<ListItemText primary='Test' />
</ListItem>
</List>
<Divider />
<List>
<ListItem button key='Change My Password' component={Link} to="/changepass">
<ListItemIcon>
<PasswordIcon />
</ListItemIcon>
<ListItemText primary='Change My Password' />
</ListItem>
<ListItem button key='LogOut' onClick={() => {Authenticator.logout();}}>
<ListItemIcon>
<LogoutOutlinedIcon />
</ListItemIcon>
<ListItemText primary='LogOut' />
</ListItem>
</List>
</Drawer>
</Box>
<Toolbar />
</Fragment>
);
}
export default withRouter(NavigationBar);
test.tsx
import React from "react";
import { RouteComponentProps } from "react-router";
class Test extends React.Component{
constructor(props: RouteComponentProps){
super(props);
}
render(): JSX.Element {
return (
<div>
<h4>
It is only a Test.
</h4>
</div>
);
}
}
export default Test;
I had a similar problem.
I ended up wrapping the router in a Box element with the styling in the Persistent Drawer demo.
https://codesandbox.io/s/2g979p?file=/demo.js:966-1552
const Main = styled(Box, { shouldForwardProp: (prop) => prop !== 'open' })(
({ theme, open }) => ({
flexGrow: 1,
padding: theme.spacing(3),
transition: theme.transitions.create('margin', {
easing: theme.transitions.easing.sharp,
duration: theme.transitions.duration.leavingScreen,
}),
marginLeft: `-${drawerWidth}px`,
...(open && {
transition: theme.transitions.create('margin', {
easing: theme.transitions.easing.easeOut,
duration: theme.transitions.duration.enteringScreen,
}),
marginLeft: 0,
}),
}),
);

Material-UI ListItem "flex-start" not working

I am using the Material-UI List item (https://material-ui.com/components/lists/)
And I would like to "left-justify" my items in my list item to the left. Apparantly I can do this with the flex property "flex-start" which I can set on the alignItems property of a ListItem like so :
<List>
<ListItem alignItems="flex-start">
<ListItemText primary={"First Element "} />
<ListItemText primary={" Second Element"} />
</ListItem>
</List>
However this does not seem to work as they are evenly spaced out when I see it in the browser.
Am I doing something wrong?
Try this...
import { makeStyles } from '#material-ui/core/styles';
const useStyles = makeStyles({
root: {
display:'flex',
alignItems:'flex-start',
flexDirection: "row"
},
});
export default function MyComponent(props) {
const classes = useStyles(props);
return (
<List className={classes.root}>
<ListItem>
<ListItemText primary={"First Element "} />
</ListItem>
<ListItem>
<ListItemText primary={"Second Element "} />
</ListItem>
</List>
);
}
ListItemText has default flex: 1 1 auto; style. You need to change it like:
import React from "react";
import { makeStyles } from "#material-ui/core/styles";
import { List, ListItem, ListItemText } from "#material-ui/core";
const useStyles = makeStyles((theme) => ({
root: {
"& .MuiListItemText-root": {
flex: "initial"
}
}
}));
export default function CustomStyles() {
const classes = useStyles();
return (
<List classes={classes}>
<ListItem alignItems="flex-start">
<ListItemText primary={"First Element "} />
<ListItemText primary={" Second Element"} />
</ListItem>
</List>
);
}

Change style of children in MaterialUI only in one element

I am using <ListItemIcon/> from Material-UI. In one component I use two different Icons and I want them to be different sizes and other styles in general. <ListItemIcon/> is build with svg which has class name MuiSvgIcon-root - this is where I should change the fontSize of Icon. I dont know how to do it. When I do
const useStyles = makeStyles({
root:{
fontSize: "2rem"
}
},{name: 'MuiSvgIcon'});
It changes setting for every Icon size in my project.
My component
function Section(props) {
const classes = useStyles();
const { title, listInfo, icon, gridSize } = props;
return (
<List>
<ListItem>
<ListItemIcon >{icon}</ListItemIcon> //here icon bigger
<ListItemText primary={title} />
</ListItem>
<Divider variant="middle" />
<Grid container>
{listInfo.map((item, index) => {
return (
<Grid item xs={gridSize}>
<ListItem key={index}>
<ListItemIcon>
<Brightness1Icon /> //here icon smaller
</ListItemIcon>
<ListItemText
primary={item.primaryText}
secondary={item.secondaryText}
/>
</ListItem>
</Grid>
);
})}
</Grid>
</List>
);
}
By specifying name: 'MuiSvgIcon' in your makeStyles call, you are causing Material-UI to override the global MuiSvgIcon-root class. If you use the name option in makeStyles, you should never give it a Mui name since these are treated differently and intended for use within the library code.
Below is one way to customize the icon size:
const BiggerListItemIcon = withStyles({
root: {
"& .MuiSvgIcon-root": { fontSize: "2em" }
}
})(ListItemIcon);
This can then be used as in the following example:
import React from "react";
import { makeStyles, withStyles } from "#material-ui/core/styles";
import List from "#material-ui/core/List";
import ListItem from "#material-ui/core/ListItem";
import ListItemIcon from "#material-ui/core/ListItemIcon";
import ListItemText from "#material-ui/core/ListItemText";
import InboxIcon from "#material-ui/icons/Inbox";
import DraftsIcon from "#material-ui/icons/Drafts";
const useStyles = makeStyles(theme => ({
root: {
width: "100%",
maxWidth: 360,
backgroundColor: theme.palette.background.paper
}
}));
const BiggerListItemIcon = withStyles({
root: {
"& .MuiSvgIcon-root": { fontSize: "2em" }
}
})(ListItemIcon);
export default function SimpleList() {
const classes = useStyles();
return (
<div className={classes.root}>
<List component="nav" aria-label="main mailbox folders">
<ListItem button>
<ListItemIcon>
<InboxIcon />
</ListItemIcon>
<ListItemText primary="Inbox" />
</ListItem>
<ListItem button>
<BiggerListItemIcon>
<DraftsIcon />
</BiggerListItemIcon>
<ListItemText primary="Drafts" />
</ListItem>
</List>
</div>
);
}
There are many ways to do styling with material-ui, I won't say this is the best way, but personally it is my own favorite way
import { styled } from "#material-ui";
const Section = () => {
return (
...
<SmallerListItemIcon>
<Brightness1Icon />
</SmallerListItemIcon>
...
)
}
const SmallerListItemIcon = styled(ListItemIcon)({
fontSize: "<your size here>"
});

When I am on a dynamic route, can't go back to the previous route

So I have a route that displays the users, each user is clickable and leads to the user details route that is dynamic. When I am on the details route, if I press the layout button to go back to the list nothing happens.
I've tried create a const what uses window.location.reload(true) and pass it in the onClick but this doesn't work
users.js
import React from "react"
import { BrowserRouter as Router,Switch, Route} from "react-router-dom"
import Layout from "../components/layout"
import User from "../components/users"
import MainComponentWrapper from "../components/mainComponentWrapper"
import UserDetails from "../components/userDetails"
const userDetailsWrapper = props => {
const url = "http://localhost:5000/user/" + props.match.params.cn
return (
<MainComponentWrapper url={url}>
<UserDetails />
</MainComponentWrapper>
)
}
const userWrapper = props => {
const url = "http://localhost:5000/user"
return (
<MainComponentWrapper url={url}>
<User />
</MainComponentWrapper>
)
}
const IndexPage = () => (
<div>
<Router >
<Layout>
<Switch>
<Route exact path="/users" component={userWrapper}/>
<Route exact path="/users/:cn" component={userDetailsWrapper} />
</Switch>
</Layout>
</Router>
</div>
)
export default IndexPage
Layout.jsx
import PropTypes from "prop-types"
import React from "react"
import { makeStyles } from "#material-ui/core/styles"
import Drawer from "#material-ui/core/Drawer"
import CssBaseline from "#material-ui/core/CssBaseline"
import List from "#material-ui/core/List"
import Divider from "#material-ui/core/Divider"
import ListItem from "#material-ui/core/ListItem"
import ListItemIcon from "#material-ui/core/ListItemIcon"
import ListItemText from "#material-ui/core/ListItemText"
import ExitToApp from "#material-ui/icons/ExitToApp"
import PeopleIcon from "#material-ui/icons/People"
import ListIcon from "#material-ui/icons/List"
import ComputerIcon from "#material-ui/icons/Computer"
import { navigate } from "gatsby"
const drawerWidth = 240
const useStyles = makeStyles(theme => ({
root: {
display: "flex",
},
appBar: {
zIndex: theme.zIndex.drawer + 1,
},
drawer: {
width: drawerWidth,
flexShrink: 0,
},
drawerPaper: {
width: drawerWidth,
},
content: {
flexGrow: 1,
padding: theme.spacing(3),
},
toolbar: theme.mixins.toolbar,
}))
function Layout({ children }) {
const classes = useStyles()
const handleRefresh = event => {
window.location.replace("/");
}
const handleLogout = event => {
localStorage.removeItem("access_token")
window.location.replace("/")
}
return (
<div className={classes.root}>
<CssBaseline />
<Drawer
className={classes.drawer}
variant="permanent"
classes={{
paper: classes.drawerPaper,
}}
>
<div className={classes.toolbar} />
<List>
<ListItem button onClick={(handleRefresh) => navigate("/users")}>
<ListItemIcon>
<PeopleIcon />
</ListItemIcon>
<ListItemText primary={"Users"} />
</ListItem>
<ListItem button onClick={() => navigate("/machines")}>
<ListItemIcon>
<ComputerIcon />
</ListItemIcon>
<ListItemText primary={"Machines"} />
</ListItem>
<ListItem button onClick={() => navigate("/audits")}>
<ListItemIcon>
<ListIcon />
</ListItemIcon>
<ListItemText primary={"Audit"} />
</ListItem>
</List>
<Divider />
<List>
<ListItem button onClick={handleLogout}>
<ListItemIcon>
<ExitToApp />
</ListItemIcon>
<ListItemText primary={"Logout"} />
</ListItem>
</List>
</Drawer>
<main className={classes.content}>
<div className={classes.toolbar} />
{children}
</main>
</div>
)
}
Layout.propTypes = {
children: PropTypes.node.isRequired,
}
export default Layout

Resources