Reorganize app pages (#73)

* Update layout and menus

* Add breadcrumbs
Add menu icons
Add ECU drop down

* Implement submenu
Update download progress

* revamped dashboard section - failing app.test.js

* Clean up

Co-authored-by: Drew Taylor <dtaylor@fiskerinc.com>
This commit is contained in:
John Wu
2021-08-10 08:11:06 -07:00
committed by GitHub
parent 0545b54daf
commit e50eb886e6
39 changed files with 4043 additions and 3623 deletions

View File

@@ -1,26 +1,26 @@
import React from "react";
import clsx from "clsx";
import Drawer from "@material-ui/core/Drawer";
import AppBar from "@material-ui/core/AppBar";
import Toolbar from "@material-ui/core/Toolbar";
import Typography from "@material-ui/core/Typography";
import Divider from "@material-ui/core/Divider";
import {
Container,
Drawer,
AppBar,
Toolbar,
Typography,
Divider,
} from "@material-ui/core";
import SideMenu from "./SideMenu";
import useStyles from "../useStyles";
import { useUserContext } from "../Contexts/UserContext";
import { useStatusContext } from "../Contexts/StatusContext";
import { Button, Container } from "@material-ui/core";
import UserMenu from "./UserMenu";
import SiteBreadcrumbs from "../Controls/SiteBreadCrumbs";
import logo from "../../assets/fisker-badge.svg";
export default function MenuDrawer({ children }) {
const classes = useStyles();
const { title } = useStatusContext();
const { signOut, token } = useUserContext();
const onSignOut = () => {
document.location = signOut();
};
const { title, sitePath } = useStatusContext();
const { token } = useUserContext();
return (
<div className={classes.root}>
@@ -31,17 +31,14 @@ export default function MenuDrawer({ children }) {
})}
>
<Toolbar>
<Typography variant="h6" noWrap>
{title}
</Typography>
<div>
<Typography variant="h6" noWrap>
{title}
</Typography>
<SiteBreadcrumbs path={sitePath} className={classes.breadcrumbs} />
</div>
{token !== null && (
<Button
color="inherit"
onClick={onSignOut}
className={classes.rightToolbar}
>
Sign Out
</Button>
<UserMenu color="inherit" className={classes.rightToolbar} />
)}
</Toolbar>
</AppBar>

View File

@@ -4,46 +4,89 @@ import ListItemLink from "../ListItemLink";
import ListItemExternalLink from "../ListItemExternalLink";
import { useUserContext } from "../Contexts/UserContext";
import { Roles, hasRole } from "../../utils/roles";
import HomeIcon from "@material-ui/icons/Home";
import CommuteIcon from "@material-ui/icons/Commute";
import CloudDownloadIcon from "@material-ui/icons/CloudDownload";
import AssessmentIcon from "@material-ui/icons/Assessment";
const menuData = [
{
label: "Home",
to: "/home",
icon: <HomeIcon />,
roles: [],
},
{
label: "Dashboard",
to: "/dashboard",
roles: [Roles.CREATE, Roles.READ],
},
{
label: "Deploy Packages",
label: "Deployments",
to: "/packages",
icon: <CloudDownloadIcon />,
roles: [Roles.CREATE, Roles.READ],
},
{
label: "Create Package",
to: "/package-create",
roles: [Roles.CREATE],
},
{
label: "View Vehicles",
label: "Vehicles",
to: "/vehicles",
icon: <CommuteIcon />,
roles: [Roles.CREATE],
},
{
label: "Datascope",
to: "/datascope",
icon: <AssessmentIcon />,
roles: [Roles.CREATE, Roles.READ],
},
{
label: "Add Vehicle",
to: "/vehicle-add",
roles: [Roles.CREATE],
},
{
label: "Send Command",
to: "/vehicles-command",
roles: [Roles.CREATE],
submenus: [
{
label: "Battery",
to: "/datascope/battery",
},
{
label: "Diagnostics",
url: "https://grafana.fiskerdps.com",
},
],
},
];
export default function SideMenu() {
const MenuItem = ({ item, children }) => {
return (
<li>
{item.to && (
<ListItemLink primary={item.label} to={item.to} icon={item.icon} />
)}
{item.url && (
<ListItemExternalLink
primary={item.label}
url={item.url}
icon={item.icon}
/>
)}
{children}
</li>
);
};
const ExpandableSideMenuItem = ({ item }) => {
/*
const [expanded, setExpanded] = useState(true);
const clickHandler = (e) => {
setExpanded(!expanded);
};
*/
return (
<>
<span>
<MenuItem item={item}></MenuItem>
</span>
<ul style={{ marginLeft: 50 }}>
{item.submenus.map((subitem, index) => (
<MenuItem key={`submenu-${index}`} item={subitem} />
))}
</ul>
</>
);
};
const SideMenu = () => {
const { groups } = useUserContext();
const menu = menuData.reduce((result, item) => {
if (hasRole(item.roles, groups)) {
@@ -55,14 +98,14 @@ export default function SideMenu() {
return (
<List>
{menu.map((item, index) => (
<li key={index}>
{item.to && <ListItemLink primary={item.label} to={item.to} />}
{item.url && (
<ListItemExternalLink primary={item.label} url={item.url} />
)}
</li>
))}
{menu.map((item, index) => {
const key = `menu-${index}`;
if (item.submenus)
return <ExpandableSideMenuItem key={key} item={item} />;
return <MenuItem key={key} item={item} />;
})}
</List>
);
}
};
export default SideMenu;

View File

@@ -0,0 +1,48 @@
import React, { useState } from "react";
import { Button, Fade, Menu, MenuItem } from "@material-ui/core";
import { useUserContext } from "../../Contexts/UserContext";
import { getName } from "../../../utils/jwt";
const UserMenu = (props) => {
const { signOut, token } = useUserContext();
const [anchorEl, setAnchorEl] = useState(null);
const open = Boolean(anchorEl);
const handleClick = (event) => {
setAnchorEl(event.currentTarget);
};
const handleClose = () => {
setAnchorEl(null);
};
const handleSignOut = () => {
document.location = signOut();
};
return (
<div {...props}>
<Button
aria-controls="fade-menu"
aria-haspopup="true"
onClick={handleClick}
color="inherit"
>
{getName(token)}
</Button>
<Menu
id="fade-menu"
anchorEl={anchorEl}
keepMounted
open={open}
onClose={handleClose}
TransitionComponent={Fade}
>
<MenuItem onClick={handleSignOut}>Sign out</MenuItem>
</Menu>
</div>
);
};
export default UserMenu;

View File

@@ -16,6 +16,20 @@ exports[`SideMenu Authenticated 1`] = `
role="button"
tabindex="0"
>
<div
class="MuiListItemIcon-root"
>
<svg
aria-hidden="true"
class="MuiSvgIcon-root"
focusable="false"
viewBox="0 0 24 24"
>
<path
d="M10 20v-6h4v6h5v-8h3L12 3 2 12h3v8z"
/>
</svg>
</div>
<div
class="MuiListItemText-root"
>
@@ -30,28 +44,6 @@ exports[`SideMenu Authenticated 1`] = `
/>
</a>
</li>
<li>
<a
aria-disabled="false"
class="MuiButtonBase-root MuiListItem-root MuiListItem-gutters MuiListItem-button"
href="/dashboard"
role="button"
tabindex="0"
>
<div
class="MuiListItemText-root"
>
<span
class="MuiTypography-root MuiListItemText-primary MuiTypography-body1 MuiTypography-displayBlock"
>
Dashboard
</span>
</div>
<span
class="MuiTouchRipple-root"
/>
</a>
</li>
<li>
<a
aria-disabled="false"
@@ -61,34 +53,26 @@ exports[`SideMenu Authenticated 1`] = `
tabindex="0"
>
<div
class="MuiListItemText-root"
class="MuiListItemIcon-root"
>
<span
class="MuiTypography-root MuiListItemText-primary MuiTypography-body1 MuiTypography-displayBlock"
<svg
aria-hidden="true"
class="MuiSvgIcon-root"
focusable="false"
viewBox="0 0 24 24"
>
Deploy Packages
</span>
<path
d="M19.35 10.04C18.67 6.59 15.64 4 12 4 9.11 4 6.6 5.64 5.35 8.04 2.34 8.36 0 10.91 0 14c0 3.31 2.69 6 6 6h13c2.76 0 5-2.24 5-5 0-2.64-2.05-4.78-4.65-4.96zM17 13l-5 5-5-5h3V9h4v4h3z"
/>
</svg>
</div>
<span
class="MuiTouchRipple-root"
/>
</a>
</li>
<li>
<a
aria-disabled="false"
class="MuiButtonBase-root MuiListItem-root MuiListItem-gutters MuiListItem-button"
href="/package-create"
role="button"
tabindex="0"
>
<div
class="MuiListItemText-root"
>
<span
class="MuiTypography-root MuiListItemText-primary MuiTypography-body1 MuiTypography-displayBlock"
>
Create Package
Deployments
</span>
</div>
<span
@@ -105,34 +89,26 @@ exports[`SideMenu Authenticated 1`] = `
tabindex="0"
>
<div
class="MuiListItemText-root"
class="MuiListItemIcon-root"
>
<span
class="MuiTypography-root MuiListItemText-primary MuiTypography-body1 MuiTypography-displayBlock"
<svg
aria-hidden="true"
class="MuiSvgIcon-root"
focusable="false"
viewBox="0 0 24 24"
>
View Vehicles
</span>
<path
d="M12 4H5C3.34 4 2 5.34 2 7v8c0 1.66 1.34 3 3 3l-1 1v1h1l2-2.03L9 18v-5H4V5.98L13 6v2h2V7c0-1.66-1.34-3-3-3zM5 14c.55 0 1 .45 1 1s-.45 1-1 1-1-.45-1-1 .45-1 1-1zm15.57-4.34c-.14-.4-.52-.66-.97-.66h-7.19c-.46 0-.83.26-.98.66L10 13.77l.01 5.51c0 .38.31.72.69.72h.62c.38 0 .68-.38.68-.76V18h8v1.24c0 .38.31.76.69.76h.61c.38 0 .69-.34.69-.72l.01-1.37v-4.14l-1.43-4.11zm-8.16.34h7.19l1.03 3h-9.25l1.03-3zM12 16c-.55 0-1-.45-1-1s.45-1 1-1 1 .45 1 1-.45 1-1 1zm8 0c-.55 0-1-.45-1-1s.45-1 1-1 1 .45 1 1-.45 1-1 1z"
/>
</svg>
</div>
<span
class="MuiTouchRipple-root"
/>
</a>
</li>
<li>
<a
aria-disabled="false"
class="MuiButtonBase-root MuiListItem-root MuiListItem-gutters MuiListItem-button"
href="/vehicle-add"
role="button"
tabindex="0"
>
<div
class="MuiListItemText-root"
>
<span
class="MuiTypography-root MuiListItemText-primary MuiTypography-body1 MuiTypography-displayBlock"
>
Add Vehicle
Vehicles
</span>
</div>
<span
@@ -140,28 +116,95 @@ exports[`SideMenu Authenticated 1`] = `
/>
</a>
</li>
<li>
<a
aria-disabled="false"
class="MuiButtonBase-root MuiListItem-root MuiListItem-gutters MuiListItem-button"
href="/vehicles-command"
role="button"
tabindex="0"
>
<div
class="MuiListItemText-root"
<span>
<li>
<a
aria-disabled="false"
class="MuiButtonBase-root MuiListItem-root MuiListItem-gutters MuiListItem-button"
href="/datascope"
role="button"
tabindex="0"
>
<span
class="MuiTypography-root MuiListItemText-primary MuiTypography-body1 MuiTypography-displayBlock"
<div
class="MuiListItemIcon-root"
>
Send Command
</span>
</div>
<span
class="MuiTouchRipple-root"
/>
</a>
</li>
<svg
aria-hidden="true"
class="MuiSvgIcon-root"
focusable="false"
viewBox="0 0 24 24"
>
<path
d="M19 3H5c-1.1 0-2 .9-2 2v14c0 1.1.9 2 2 2h14c1.1 0 2-.9 2-2V5c0-1.1-.9-2-2-2zM9 17H7v-7h2v7zm4 0h-2V7h2v10zm4 0h-2v-4h2v4z"
/>
</svg>
</div>
<div
class="MuiListItemText-root"
>
<span
class="MuiTypography-root MuiListItemText-primary MuiTypography-body1 MuiTypography-displayBlock"
>
Datascope
</span>
</div>
<span
class="MuiTouchRipple-root"
/>
</a>
</li>
</span>
<ul
style="margin-left: 50px;"
>
<li>
<a
aria-disabled="false"
class="MuiButtonBase-root MuiListItem-root MuiListItem-gutters MuiListItem-button"
href="/datascope/battery"
role="button"
tabindex="0"
>
<div
class="MuiListItemText-root"
>
<span
class="MuiTypography-root MuiListItemText-primary MuiTypography-body1 MuiTypography-displayBlock"
>
Battery
</span>
</div>
<span
class="MuiTouchRipple-root"
/>
</a>
</li>
<li>
<a
aria-disabled="false"
class="MuiTypography-root MuiLink-root MuiLink-underlineHover MuiButtonBase-root MuiListItem-root MuiListItem-gutters MuiListItem-button MuiTypography-colorPrimary"
href="https://grafana.fiskerdps.com"
rel="noopener"
role="button"
style="text-decoration: inherit;"
tabindex="0"
target="_blank"
>
<div
class="MuiListItemText-root"
>
<span
class="MuiTypography-root MuiListItemText-primary MuiTypography-body1 MuiTypography-displayBlock"
>
Diagnostics
</span>
</div>
<span
class="MuiTouchRipple-root"
/>
</a>
</li>
</ul>
</ul>
</div>
</div>
@@ -183,6 +226,20 @@ exports[`SideMenu Unauthenticated 1`] = `
role="button"
tabindex="0"
>
<div
class="MuiListItemIcon-root"
>
<svg
aria-hidden="true"
class="MuiSvgIcon-root"
focusable="false"
viewBox="0 0 24 24"
>
<path
d="M10 20v-6h4v6h5v-8h3L12 3 2 12h3v8z"
/>
</svg>
</div>
<div
class="MuiListItemText-root"
>