Skip to content

Commit c74f780

Browse files
authored
Merge pull request #3083 from andrewbaldwin44/feature/mobile-friendly
Make the Locust UI Responsive
2 parents 73d60fa + aea2d8f commit c74f780

File tree

7 files changed

+109
-46
lines changed

7 files changed

+109
-46
lines changed

Diff for: locust/webui/src/components/Layout/Navbar/Navbar.tsx

+74-17
Original file line numberDiff line numberDiff line change
@@ -1,30 +1,87 @@
1-
import { AppBar, Box, Container, Link, Toolbar } from '@mui/material';
1+
import { useEffect, useState } from 'react';
2+
import MenuIcon from '@mui/icons-material/Menu';
3+
import { AppBar, Box, Container, Drawer, IconButton, Link, Toolbar, useTheme } from '@mui/material';
24

35
import Logo from 'assets/Logo';
46
import DarkLightToggle from 'components/Layout/Navbar/DarkLightToggle';
57
import SwarmMonitor from 'components/Layout/Navbar/SwarmMonitor';
68
import StateButtons from 'components/StateButtons/StateButtons';
79

810
export default function Navbar() {
11+
const theme = useTheme();
12+
const [drawerOpen, setDrawerOpen] = useState(false);
13+
14+
useEffect(() => {
15+
const handleResize = () => {
16+
if (window.innerWidth >= theme.breakpoints.values.md) {
17+
setDrawerOpen(false);
18+
}
19+
};
20+
21+
window.addEventListener('resize', handleResize);
22+
23+
return () => {
24+
window.removeEventListener('resize', handleResize);
25+
};
26+
}, []);
27+
28+
const toggleDrawer = (open: boolean) => () => {
29+
setDrawerOpen(open);
30+
};
31+
932
return (
10-
<AppBar position='static'>
11-
<Container maxWidth='xl'>
12-
<Toolbar disableGutters sx={{ display: 'flex', justifyContent: 'space-between', columnGap: 2 }}>
13-
<Link
14-
color='inherit'
15-
href='/'
16-
sx={{ display: 'flex', alignItems: 'center' }}
17-
underline='none'
33+
<>
34+
<AppBar position='static'>
35+
<Container maxWidth='xl'>
36+
<Toolbar
37+
disableGutters
38+
sx={{ display: 'flex', justifyContent: 'space-between', columnGap: 2 }}
1839
>
19-
<Logo />
20-
</Link>
21-
<Box sx={{ display: 'flex', columnGap: 6 }}>
22-
<SwarmMonitor />
23-
<StateButtons />
40+
<Link
41+
color='inherit'
42+
href='/'
43+
sx={{ display: 'flex', alignItems: 'center' }}
44+
underline='none'
45+
>
46+
<Logo />
47+
</Link>
48+
<IconButton
49+
aria-label='menu'
50+
color='inherit'
51+
edge='start'
52+
onClick={toggleDrawer(true)}
53+
sx={{ display: { xs: 'block', md: 'none' } }}
54+
>
55+
<MenuIcon />
56+
</IconButton>
57+
58+
<Box sx={{ display: { xs: 'none', md: 'flex' }, columnGap: { md: 2, lg: 6 } }}>
59+
<SwarmMonitor />
60+
<StateButtons />
61+
<DarkLightToggle />
62+
</Box>
63+
</Toolbar>
64+
</Container>
65+
</AppBar>
66+
67+
<Drawer anchor='right' onClose={toggleDrawer(false)} open={drawerOpen}>
68+
<Box
69+
sx={{
70+
display: 'flex',
71+
flexDirection: 'column',
72+
columnGap: { md: 2, lg: 6 },
73+
rowGap: 2,
74+
p: 2,
75+
maxWidth: '100vw',
76+
}}
77+
>
78+
<Box sx={{ display: 'flex', justifyContent: 'flex-end' }}>
2479
<DarkLightToggle />
2580
</Box>
26-
</Toolbar>
27-
</Container>
28-
</AppBar>
81+
<StateButtons />
82+
<SwarmMonitor />
83+
</Box>
84+
</Drawer>
85+
</>
2986
);
3087
}

Diff for: locust/webui/src/components/Layout/Navbar/SwarmMonitor.tsx

+15-12
Original file line numberDiff line numberDiff line change
@@ -20,16 +20,19 @@ function SwarmMonitor({
2020
workerCount,
2121
}: ISwarmMonitor) {
2222
return (
23-
<Box sx={{ display: 'flex', columnGap: 2 }}>
23+
<Box
24+
sx={{ display: 'flex', columnGap: 2, rowGap: 1, flexDirection: { xs: 'column', md: 'row' } }}
25+
>
2426
<Box sx={{ display: 'flex', flexDirection: 'column' }}>
25-
<Typography variant='button'>Host</Typography>
27+
<Typography sx={{ fontWeight: 'bold' }}>Host</Typography>
2628
<Tooltip title={host}>
2729
<Typography
2830
noWrap
2931
sx={{
3032
overflow: 'hidden',
3133
textOverflow: 'ellipsis',
32-
maxWidth: '400px',
34+
35+
maxWidth: { xs: '180px', lg: '400px' },
3336
}}
3437
>
3538
{host}
@@ -38,14 +41,14 @@ function SwarmMonitor({
3841
</Box>
3942
<Divider flexItem orientation='vertical' />
4043
<Box sx={{ display: 'flex', flexDirection: 'column' }}>
41-
<Typography variant='button'>Status</Typography>
44+
<Typography sx={{ fontWeight: 'bold' }}>Status</Typography>
4245
<Typography variant='button'>{state}</Typography>
4346
</Box>
4447
{(state === SWARM_STATE.RUNNING || state === SWARM_STATE.SPAWNING) && (
4548
<>
4649
<Divider flexItem orientation='vertical' />
47-
<Box sx={{ display: 'flex', flexDirection: 'column', alignItems: 'center' }}>
48-
<Typography variant='button'>Users</Typography>
50+
<Box sx={{ display: 'flex', flexDirection: 'column', alignItems: { md: 'center' } }}>
51+
<Typography sx={{ fontWeight: 'bold' }}>Users</Typography>
4952
<Typography noWrap variant='button'>
5053
{userCount}
5154
</Typography>
@@ -55,24 +58,24 @@ function SwarmMonitor({
5558
{isDistributed && (
5659
<>
5760
<Divider flexItem orientation='vertical' />
58-
<Box sx={{ display: 'flex', flexDirection: 'column', alignItems: 'center' }}>
59-
<Typography variant='button'>Workers</Typography>
61+
<Box sx={{ display: 'flex', flexDirection: 'column', alignItems: { md: 'center' } }}>
62+
<Typography sx={{ fontWeight: 'bold' }}>Workers</Typography>
6063
<Typography noWrap variant='button'>
6164
{workerCount}
6265
</Typography>
6366
</Box>
6467
</>
6568
)}
6669
<Divider flexItem orientation='vertical' />
67-
<Box sx={{ display: 'flex', flexDirection: 'column', alignItems: 'center' }}>
68-
<Typography variant='button'>RPS</Typography>
70+
<Box sx={{ display: 'flex', flexDirection: 'column', alignItems: { md: 'center' } }}>
71+
<Typography sx={{ fontWeight: 'bold' }}>RPS</Typography>
6972
<Typography noWrap variant='button'>
7073
{totalRps}
7174
</Typography>
7275
</Box>
7376
<Divider flexItem orientation='vertical' />
74-
<Box sx={{ display: 'flex', flexDirection: 'column', alignItems: 'center' }}>
75-
<Typography variant='button'>Failures</Typography>
77+
<Box sx={{ display: 'flex', flexDirection: 'column', alignItems: { md: 'center' } }}>
78+
<Typography sx={{ fontWeight: 'bold' }}>Failures</Typography>
7679
<Typography noWrap variant='button'>{`${failRatio}%`}</Typography>
7780
</Box>
7881
</Box>

Diff for: locust/webui/src/components/StatsTable/StatsTable.tsx

+9-2
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
1+
import { Box } from '@mui/material';
12
import { connect } from 'react-redux';
23

34
import Table from 'components/Table/Table';
@@ -40,15 +41,21 @@ export function StatsTable({ stats, tableStructure = baseTableStructure }: IStat
4041
useSelectViewColumns(tableStructure);
4142

4243
return (
43-
<>
44+
<Box
45+
sx={{
46+
display: 'flex',
47+
flexDirection: { xs: 'column', lg: 'row-reverse', alignItems: 'flex-start' },
48+
columnGap: 1,
49+
}}
50+
>
4451
<ViewColumnSelector
4552
addColumn={addColumn}
4653
removeColumn={removeColumn}
4754
selectedColumns={selectedColumns}
4855
structure={tableStructure}
4956
/>
5057
<Table<ISwarmStat> hasTotalRow rows={stats} structure={filteredStructure} />
51-
</>
58+
</Box>
5259
);
5360
}
5461

Diff for: locust/webui/src/components/SwarmCharts/SwarmCharts.tsx

+3-7
Original file line numberDiff line numberDiff line change
@@ -45,13 +45,9 @@ const availableSwarmCharts: Omit<ILineChart<ICharts>, 'charts'>[] = [
4545
];
4646

4747
export function SwarmCharts({ charts }: { charts: ICharts }) {
48-
return (
49-
<div>
50-
{availableSwarmCharts.map((lineChartProps, index) => (
51-
<LineChart<ICharts> key={`swarm-chart-${index}`} {...lineChartProps} charts={charts} />
52-
))}
53-
</div>
54-
);
48+
return availableSwarmCharts.map((lineChartProps, index) => (
49+
<LineChart<ICharts> key={`swarm-chart-${index}`} {...lineChartProps} charts={charts} />
50+
));
5551
}
5652

5753
const storeConnector = ({ ui: { charts } }: IRootState) => ({ charts });

Diff for: locust/webui/src/components/Table/Table.tsx

+1-6
Original file line numberDiff line numberDiff line change
@@ -62,12 +62,7 @@ export default function Table<Row extends Record<string, any> = Record<string, s
6262
});
6363

6464
return (
65-
<TableContainer
66-
component={Paper}
67-
sx={{
68-
overflowX: 'visible',
69-
}}
70-
>
65+
<TableContainer component={Paper}>
7166
<MuiTable>
7267
<TableHead
7368
sx={{

Diff for: locust/webui/src/components/Tabs/Tabs.tsx

+6-1
Original file line numberDiff line numberDiff line change
@@ -60,7 +60,12 @@ function Tabs({ currentTabIndexFromQuery, notification, setNotification, setUrl,
6060
return (
6161
<Container maxWidth='xl'>
6262
<Box sx={{ mb: 2 }}>
63-
<MuiTabs onChange={onTabChange} value={currentTabIndex}>
63+
<MuiTabs
64+
onChange={onTabChange}
65+
scrollButtons='auto'
66+
value={currentTabIndex}
67+
variant='scrollable'
68+
>
6469
{tabs.map(({ key: tabKey, title }, index) => (
6570
<MuiTab
6671
key={`tab-${index}`}

Diff for: locust/webui/src/components/ViewColumnSelector/ViewColumnSelector.tsx

+1-1
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,7 @@ function ViewColumnSelector({
2020
const [anchorEl, setAnchorEl] = useState(null as HTMLButtonElement | null);
2121

2222
return (
23-
<Stack direction='row' justifyContent='end' my={2} spacing={1}>
23+
<Stack sx={{ alignSelf: { xs: 'end', lg: 'start' }, my: 2 }}>
2424
<Button onClick={event => setAnchorEl(event.currentTarget)} variant='outlined'>
2525
<ViewColumnIcon />
2626
</Button>

0 commit comments

Comments
 (0)