| // Licensed to the Software Freedom Conservancy (SFC) under one |
| // or more contributor license agreements. See the NOTICE file |
| // distributed with this work for additional information |
| // regarding copyright ownership. The SFC licenses this file |
| // to you under the Apache License, Version 2.0 (the |
| // "License"); you may not use this file except in compliance |
| // with the License. You may obtain a copy of the License at |
| // |
| // http://www.apache.org/licenses/LICENSE-2.0 |
| // |
| // Unless required by applicable law or agreed to in writing, |
| // software distributed under the License is distributed on an |
| // "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY |
| // KIND, either express or implied. See the License for the |
| // specific language governing permissions and limitations |
| // under the License. |
| |
| import Divider from '@mui/material/Divider' |
| import MuiDrawer from '@mui/material/Drawer' |
| import IconButton from '@mui/material/IconButton' |
| import List from '@mui/material/List' |
| import ListItem from '@mui/material/ListItem' |
| import ListItemIcon from '@mui/material/ListItemIcon' |
| import ListItemText from '@mui/material/ListItemText' |
| import { ChevronLeft as ChevronLeftIcon } from '@mui/icons-material' |
| import { Dashboard as DashboardIcon } from '@mui/icons-material' |
| import { Assessment as AssessmentIcon } from '@mui/icons-material' |
| import { Help as HelpIcon } from '@mui/icons-material' |
| import React from 'react' |
| import { Box, Typography } from '@mui/material' |
| import { useLocation } from 'react-router-dom' |
| import OverallConcurrency from './OverallConcurrency' |
| import { CSSObject, styled, Theme } from '@mui/material/styles' |
| |
| const drawerWidth = 240 |
| |
| function ListItemLink (props): JSX.Element { |
| return <ListItem button component='a' {...props} /> |
| } |
| |
| 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 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) |
| }) |
| }) |
| ) |
| |
| function NavBarBottom (props): JSX.Element { |
| const { |
| sessionQueueSize, |
| sessionCount, |
| maxSession, |
| nodeCount |
| } = props |
| const location = useLocation() |
| // Not showing the overall status when the user is on the Overview |
| // page and there is only one node, because polling is not happening |
| // at the same time, and it could be confusing for the user. So, |
| // displaying it when there is more than one node, or when the user is |
| // on a different page and there is at least one node registered. |
| const showOverallConcurrency = |
| nodeCount > 1 || (location.pathname !== '/' && nodeCount > 0) |
| |
| return ( |
| <div> |
| <Box p={3} m={1}> |
| <Typography |
| align='center' |
| gutterBottom |
| variant='h4' |
| > |
| Queue size: {sessionQueueSize} |
| </Typography> |
| </Box> |
| {showOverallConcurrency && ( |
| <OverallConcurrency |
| sessionCount={sessionCount} |
| maxSession={maxSession} |
| /> |
| )} |
| </div> |
| ) |
| } |
| |
| function NavBar (props) { |
| const { |
| open, |
| maxSession, |
| sessionCount, |
| nodeCount, |
| sessionQueueSize |
| } = props |
| |
| return ( |
| <Drawer |
| variant='permanent' |
| open={open} |
| > |
| <Box |
| display='flex' |
| alignItems='center' |
| justifyContent='flex-end' |
| sx={{ bgcolor: 'primary.main' }} |
| marginTop={2} |
| > |
| <IconButton color='secondary' size='large'> |
| <ChevronLeftIcon /> |
| </IconButton> |
| </Box> |
| <Divider /> |
| <List> |
| <div> |
| <ListItemLink href='#'> |
| <ListItemIcon> |
| <DashboardIcon /> |
| </ListItemIcon> |
| <ListItemText primary='Overview' /> |
| </ListItemLink> |
| <ListItemLink href='#/sessions'> |
| <ListItemIcon> |
| <AssessmentIcon /> |
| </ListItemIcon> |
| <ListItemText primary='Sessions' /> |
| </ListItemLink> |
| <ListItemLink href='#/help'> |
| <ListItemIcon> |
| <HelpIcon /> |
| </ListItemIcon> |
| <ListItemText primary='Help' /> |
| </ListItemLink> |
| </div> |
| </List> |
| <Box flexGrow={1} /> |
| {open && ( |
| <NavBarBottom |
| sessionQueueSize={sessionQueueSize} |
| sessionCount={sessionCount} |
| maxSession={maxSession} |
| nodeCount={nodeCount} |
| /> |
| )} |
| </Drawer> |
| ) |
| } |
| |
| export default NavBar |