Skip to content

Commit 22e06bf

Browse files
committed
#3909 Reworking filtering in Gantt chart page
1 parent 1a9aa1d commit 22e06bf

2 files changed

Lines changed: 145 additions & 120 deletions

File tree

src/frontend/src/pages/GanttPage/ProjectGanttChart/GanttChartFilters.tsx

Lines changed: 135 additions & 120 deletions
Original file line numberDiff line numberDiff line change
@@ -3,71 +3,86 @@
33
* See the LICENSE file in the repository root folder for details.
44
*/
55

6-
import { Box, Checkbox, Chip, IconButton, Typography, useTheme } from '@mui/material';
7-
import UnfoldMoreIcon from '@mui/icons-material/UnfoldMore';
8-
import UnfoldLessIcon from '@mui/icons-material/UnfoldLess';
9-
import RestartAltIcon from '@mui/icons-material/RestartAlt';
10-
import { ChangeEvent } from 'react';
6+
import {
7+
Box,
8+
Checkbox,
9+
Typography,
10+
useTheme,
11+
Accordion,
12+
AccordionSummary,
13+
AccordionDetails,
14+
FormControlLabel,
15+
IconButton
16+
} from '@mui/material';
17+
import ExpandMoreIcon from '@mui/icons-material/ExpandMore';
18+
import CloseIcon from '@mui/icons-material/Close';
19+
import { ChangeEvent, useState } from 'react';
1120

12-
const FilterChipButton = ({
13-
buttonText,
14-
onChange,
15-
defaultChecked,
16-
checked
21+
const FilterCheckboxes = ({
22+
handlers
1723
}: {
18-
buttonText: string;
19-
onChange: (event: ChangeEvent<HTMLInputElement>) => void;
20-
defaultChecked: boolean;
21-
checked: boolean;
22-
}) => {
23-
const theme = useTheme();
24-
25-
return (
26-
<Checkbox
27-
onChange={onChange}
28-
sx={{
29-
'&:hover': {
30-
backgroundColor: 'transparent'
24+
handlers: { filterLabel: string; handler: (event: ChangeEvent<HTMLInputElement>) => void; defaultChecked: boolean }[];
25+
}) => (
26+
<Box display="flex" flexDirection="column">
27+
{handlers.map((handler) => (
28+
<FormControlLabel
29+
key={handler.filterLabel}
30+
slotProps={{ typography: { fontSize: '14px' } }}
31+
control={
32+
<Checkbox
33+
size="small"
34+
onChange={handler.handler}
35+
defaultChecked={handler.defaultChecked}
36+
sx={{ padding: '2px 7px' }}
37+
/>
3138
}
32-
}}
33-
icon={<Chip label={buttonText} sx={{ borderRadius: '20px', paddingX: 1 }} />}
34-
checkedIcon={
35-
<Chip label={buttonText} sx={{ borderRadius: '20px', paddingX: 1, backgroundColor: theme.palette.primary.main }} />
36-
}
37-
defaultChecked={defaultChecked}
38-
checked={checked}
39-
/>
40-
);
41-
};
39+
label={handler.filterLabel}
40+
/>
41+
))}
42+
</Box>
43+
);
4244

43-
const FilterRow = ({
45+
const FilterAccordion = ({
4446
label,
45-
buttons
47+
children,
48+
expanded,
49+
onChange
4650
}: {
4751
label: string;
48-
buttons: { filterLabel: string; handler: (event: ChangeEvent<HTMLInputElement>) => void; defaultChecked: boolean }[];
52+
children: React.ReactNode;
53+
expanded: boolean;
54+
onChange: () => void;
4955
}) => {
50-
const checkedMap: { [filterLabel: string]: boolean } = {};
56+
const theme = useTheme();
5157

52-
buttons.forEach((button) => {
53-
checkedMap[button.filterLabel] = button.defaultChecked;
54-
});
5558
return (
56-
<Box width={label === 'Team' ? '60%' : undefined}>
57-
<Typography variant="h6" component="label" textAlign="right">
58-
{label}
59-
</Typography>
60-
<Box display={'flex'} flexDirection={label === 'Team' ? undefined : 'column'} flexWrap={'wrap'}>
61-
{buttons.map((button) => (
62-
<FilterChipButton
63-
buttonText={button.filterLabel}
64-
onChange={button.handler}
65-
defaultChecked={button.defaultChecked}
66-
checked={checkedMap[button.filterLabel]}
67-
/>
68-
))}
69-
</Box>
70-
</Box>
59+
<Accordion
60+
disableGutters
61+
elevation={0}
62+
expanded={expanded}
63+
onChange={onChange}
64+
sx={{
65+
backgroundColor: 'transparent',
66+
'&:before': { display: 'none' }
67+
}}
68+
>
69+
<AccordionSummary
70+
expandIcon={<ExpandMoreIcon sx={{ color: theme.palette.text.secondary }} />}
71+
sx={{
72+
minHeight: '36px',
73+
px: 0,
74+
flexDirection: 'row-reverse',
75+
gap: 1,
76+
'& .MuiAccordionSummary-expandIconWrapper': { marginRight: 0, marginLeft: 0 },
77+
'& .MuiAccordionSummary-content': { margin: '6px 0' }
78+
}}
79+
>
80+
<Typography variant="h6" fontWeight="normal" color="text.primary">
81+
{label}
82+
</Typography>
83+
</AccordionSummary>
84+
<AccordionDetails sx={{ padding: '0 0 0 36px' }}>{children}</AccordionDetails>
85+
</Accordion>
7186
);
7287
};
7388

@@ -92,88 +107,88 @@ interface GanttChartFiltersProps {
92107
resetHandler: () => void;
93108
collapseHandler: () => void;
94109
expandHandler: () => void;
110+
onClose: () => void;
95111
}
96112

97113
const GanttChartFilters = ({
98114
carHandlers,
99115
teamTypeHandlers,
100116
teamHandlers,
101-
overdueHandler,
102-
hideTasksHandler,
103117
resetHandler,
104-
collapseHandler,
105-
expandHandler
118+
onClose
106119
}: GanttChartFiltersProps) => {
107-
const FilterButtons = () => {
108-
return (
109-
<Box display={'flex'} flexDirection={'column'} alignItems={'center'} mt={-1} mb={1}>
110-
<IconButton onClick={expandHandler}>
111-
<UnfoldMoreIcon sx={{ color: '#ef4345' }} />
112-
</IconButton>
113-
<Typography fontSize={'10px'} sx={{ color: '#ef4345' }}>
114-
Expand
115-
</Typography>
116-
<IconButton onClick={collapseHandler}>
117-
<UnfoldLessIcon sx={{ color: '#ef4345' }} />
118-
</IconButton>
119-
<Typography fontSize={'10px'} sx={{ color: '#ef4345' }}>
120-
Collapse
120+
const theme = useTheme();
121+
122+
const [expanded, setExpanded] = useState({
123+
car: true,
124+
division: true,
125+
team: true
126+
});
127+
128+
const [resetKey, setResetKey] = useState(0);
129+
130+
const handleReset = () => {
131+
setResetKey((prev) => prev + 1);
132+
resetHandler();
133+
};
134+
135+
const toggle = (section: keyof typeof expanded) => {
136+
setExpanded((prev) => ({ ...prev, [section]: !prev[section] }));
137+
};
138+
139+
return (
140+
<Box
141+
display="flex"
142+
flexDirection="column"
143+
sx={{ padding: 2, width: '20rem', backgroundColor: theme.palette.background.paper, borderRadius: 1 }}
144+
>
145+
<Box display="flex" flexDirection="row" justifyContent="space-between" alignItems="center" sx={{ mb: 0.5 }}>
146+
<Typography variant="h5" fontWeight="normal" color="text.primary">
147+
Filters
121148
</Typography>
122-
<IconButton onClick={resetHandler}>
123-
<RestartAltIcon sx={{ color: '#ef4345' }} />
149+
<IconButton size="small" onClick={onClose}>
150+
<CloseIcon fontSize="small" />
124151
</IconButton>
125-
<Typography fontSize={'10px'} sx={{ color: '#ef4345' }}>
152+
</Box>
153+
154+
<Box display="flex" flexDirection="row" alignItems="center" gap={0.5} sx={{ mb: -0.5 }}>
155+
<Typography
156+
fontSize="14px"
157+
sx={{ color: theme.palette.primary.main, cursor: 'pointer', '&:hover': { textDecoration: 'underline' } }}
158+
onClick={handleReset}
159+
>
126160
Reset
127161
</Typography>
128-
<Checkbox
129-
onChange={overdueHandler[0].handler}
130-
sx={{
131-
'&:hover': {
132-
backgroundColor: 'transparent'
133-
},
134-
color: '#ef4345'
135-
}}
136-
defaultChecked={overdueHandler[0].defaultChecked}
137-
checked={overdueHandler[0].defaultChecked}
138-
/>
139-
<Typography fontSize={'10px'} sx={{ color: '#ef4345' }}>
140-
Overdue
162+
<Typography sx={{ color: '#ffffff', lineHeight: 2.75, fontSize: '0.5rem' }}></Typography>
163+
<Typography
164+
fontSize="13px"
165+
sx={{ color: theme.palette.primary.main, cursor: 'pointer', '&:hover': { textDecoration: 'underline' } }}
166+
onClick={() => setExpanded({ car: true, division: true, team: true })}
167+
>
168+
Expand All
141169
</Typography>
142-
<Checkbox
143-
onChange={hideTasksHandler[0].handler}
144-
sx={{
145-
'&:hover': {
146-
backgroundColor: 'transparent'
147-
},
148-
color: '#ef4345'
149-
}}
150-
defaultChecked={hideTasksHandler[0].defaultChecked}
151-
checked={hideTasksHandler[0].defaultChecked}
152-
/>
153-
<Typography fontSize={'10px'} sx={{ color: '#ef4345' }}>
154-
Hide Tasks
170+
<Typography sx={{ color: '#ffffff', lineHeight: 2.75, fontSize: '0.5rem' }}></Typography>
171+
<Typography
172+
fontSize="13px"
173+
sx={{ color: theme.palette.primary.main, cursor: 'pointer', '&:hover': { textDecoration: 'underline' } }}
174+
onClick={() => setExpanded({ car: false, division: false, team: false })}
175+
>
176+
Collapse All
155177
</Typography>
156178
</Box>
157-
);
158-
};
159179

160-
return (
161-
<Box
162-
display={'flex'}
163-
sx={{
164-
justifyContent: 'start',
165-
alignItems: 'start',
166-
paddingLeft: 2,
167-
paddingTop: 2,
168-
maxWidth: '45rem'
169-
}}
170-
>
171-
<FilterRow label="Car" buttons={carHandlers} />
172-
<FilterRow label="Subteam" buttons={teamTypeHandlers} />
173-
<FilterRow label="Team" buttons={teamHandlers} />
174-
<FilterButtons />
180+
<FilterAccordion label="Car" expanded={expanded.car} onChange={() => toggle('car')}>
181+
<FilterCheckboxes key={`car-${resetKey}`} handlers={carHandlers} />
182+
</FilterAccordion>
183+
184+
<FilterAccordion label="Division" expanded={expanded.division} onChange={() => toggle('division')}>
185+
<FilterCheckboxes key={`division-${resetKey}`} handlers={teamTypeHandlers} />
186+
</FilterAccordion>
187+
188+
<FilterAccordion label="Team" expanded={expanded.team} onChange={() => toggle('team')}>
189+
<FilterCheckboxes key={`team-${resetKey}`} handlers={teamHandlers} />
190+
</FilterAccordion>
175191
</Box>
176192
);
177193
};
178-
179194
export default GanttChartFilters;

src/frontend/src/pages/GanttPage/ProjectGanttChart/GanttChartFiltersButton.tsx

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@ import { ChangeEvent, useState } from 'react';
22
import { IconButton, Popover } from '@mui/material';
33
import GanttChartFilters from './GanttChartFilters';
44
import { Tune } from '@mui/icons-material';
5+
import { useTheme } from '@mui/material';
56

67
interface GanttChartFiltersButtonProps {
78
carHandlers: { filterLabel: string; handler: (event: ChangeEvent<HTMLInputElement>) => void; defaultChecked: boolean }[];
@@ -64,6 +65,14 @@ const GanttChartFiltersButton = ({
6465
horizontal: 'right'
6566
}}
6667
sx={{ maxWidth: '100rem' }}
68+
slotProps={{
69+
paper: {
70+
sx: {
71+
backgroundColor: useTheme().palette.background.paper,
72+
borderRadius: 2
73+
}
74+
}
75+
}}
6776
>
6877
<GanttChartFilters
6978
carHandlers={carHandlers}
@@ -74,6 +83,7 @@ const GanttChartFiltersButton = ({
7483
resetHandler={resetHandler}
7584
collapseHandler={collapseHandler}
7685
expandHandler={expandHandler}
86+
onClose={handleFilterClose}
7787
/>
7888
</Popover>
7989
</>

0 commit comments

Comments
 (0)