Options panels refactoring (#196)
* Refactor library options to match chapter options using shared component * Disable some eslint rules * Cleanup SourceOptions layout to use same components as other panels
This commit is contained in:
@@ -6,22 +6,21 @@
|
||||
* file, You can obtain one at https://mozilla.org/MPL/2.0/.
|
||||
*/
|
||||
|
||||
import React from 'react';
|
||||
import FilterListIcon from '@mui/icons-material/FilterList';
|
||||
import {
|
||||
Drawer, Button, Fab,
|
||||
} from '@mui/material';
|
||||
import { Button, Fab, Stack } from '@mui/material';
|
||||
import { Box } from '@mui/system';
|
||||
import SelectFilter from './filters/SelectFilter';
|
||||
import OptionsPanel from 'components/molecules/OptionsPanel';
|
||||
import React from 'react';
|
||||
import CheckBoxFilter from './filters/CheckBoxFilter';
|
||||
import HeaderFilter from './filters/HeaderFilter';
|
||||
import SeperatorFilter from './filters/SeparatorFilter';
|
||||
import SelectFilter from './filters/SelectFilter';
|
||||
import SortFilter from './filters/SortFilter';
|
||||
import TextFilter from './filters/TextFilter';
|
||||
import TriStateFilter from './filters/TriStateFilter';
|
||||
// this can only cycle once, so should be fine
|
||||
// eslint-disable-next-line import/no-cycle
|
||||
import GroupFilter from './filters/GroupFilter';
|
||||
import SeperatorFilter from './filters/SeparatorFilter';
|
||||
|
||||
interface IFilters {
|
||||
sourceFilter: ISourceFilters[]
|
||||
@@ -46,7 +45,7 @@ export function Options({
|
||||
update,
|
||||
}: IFilters) {
|
||||
return (
|
||||
<Box key={`filters ${group}`}>
|
||||
<Stack key={`filters ${group}`}>
|
||||
{ sourceFilter.map((e: ISourceFilters, index) => {
|
||||
let checkif = update.find((el: {
|
||||
group: number | undefined; position: number;
|
||||
@@ -145,7 +144,7 @@ export function Options({
|
||||
return (<Box key={`${e.filter.name}null`} />);
|
||||
}
|
||||
})}
|
||||
</Box>
|
||||
</Stack>
|
||||
);
|
||||
}
|
||||
|
||||
@@ -182,17 +181,11 @@ export default function SourceOptions({
|
||||
Filter
|
||||
</Fab>
|
||||
|
||||
<Drawer
|
||||
anchor="bottom"
|
||||
<OptionsPanel
|
||||
open={FilterOptions}
|
||||
onClose={() => setFilterOptions(false)}
|
||||
PaperProps={{
|
||||
style: {
|
||||
maxWidth: 600, padding: '1em', marginLeft: 'auto', marginRight: 'auto',
|
||||
},
|
||||
}}
|
||||
>
|
||||
<Box sx={{ display: 'flex' }}>
|
||||
<Box sx={{ display: 'flex', p: 2, pb: 0 }}>
|
||||
<Button
|
||||
onClick={handleReset}
|
||||
>
|
||||
@@ -206,13 +199,20 @@ export default function SourceOptions({
|
||||
Submit
|
||||
</Button>
|
||||
</Box>
|
||||
<Options
|
||||
sourceFilter={sourceFilter}
|
||||
updateFilterValue={updateFilterValue}
|
||||
group={undefined}
|
||||
update={update}
|
||||
/>
|
||||
</Drawer>
|
||||
<Box
|
||||
sx={{
|
||||
pb: 2,
|
||||
mx: 2,
|
||||
}}
|
||||
>
|
||||
<Options
|
||||
sourceFilter={sourceFilter}
|
||||
updateFilterValue={updateFilterValue}
|
||||
group={undefined}
|
||||
update={update}
|
||||
/>
|
||||
</Box>
|
||||
</OptionsPanel>
|
||||
</>
|
||||
);
|
||||
}
|
||||
|
||||
@@ -5,9 +5,8 @@
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at https://mozilla.org/MPL/2.0/.
|
||||
*/
|
||||
import CheckboxInput from 'components/atoms/CheckboxInput';
|
||||
import React from 'react';
|
||||
import { Box } from '@mui/system';
|
||||
import { Checkbox, FormControlLabel } from '@mui/material';
|
||||
|
||||
interface Props {
|
||||
state: boolean
|
||||
@@ -18,7 +17,7 @@ interface Props {
|
||||
update: any
|
||||
}
|
||||
|
||||
export default function CheckBoxFilter(props: Props) {
|
||||
const CheckBoxFilter: React.FC<Props> = (props: Props) => {
|
||||
const {
|
||||
state,
|
||||
name,
|
||||
@@ -39,20 +38,10 @@ export default function CheckBoxFilter(props: Props) {
|
||||
|
||||
if (state !== undefined) {
|
||||
return (
|
||||
<Box sx={{ display: 'flex', flexDirection: 'column', minWidth: 120 }}>
|
||||
<FormControlLabel
|
||||
key={name}
|
||||
control={(
|
||||
<Checkbox
|
||||
name={name}
|
||||
checked={val}
|
||||
onChange={handleChange}
|
||||
/>
|
||||
)}
|
||||
label={name}
|
||||
/>
|
||||
</Box>
|
||||
<CheckboxInput label={name} checked={val} onChange={handleChange} />
|
||||
);
|
||||
}
|
||||
return (<></>);
|
||||
}
|
||||
return null;
|
||||
};
|
||||
|
||||
export default CheckBoxFilter;
|
||||
|
||||
@@ -5,11 +5,12 @@
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at https://mozilla.org/MPL/2.0/.
|
||||
*/
|
||||
import {
|
||||
Collapse, List, ListItemButton, ListItemText,
|
||||
} from '@mui/material';
|
||||
import React from 'react';
|
||||
import { ExpandLess, ExpandMore } from '@mui/icons-material';
|
||||
import {
|
||||
Collapse, ListItemButton, ListItemText, Stack,
|
||||
} from '@mui/material';
|
||||
import { Box } from '@mui/system';
|
||||
import React from 'react';
|
||||
// eslint-disable-next-line import/no-cycle
|
||||
import { Options } from '../SourceOptions';
|
||||
|
||||
@@ -21,7 +22,7 @@ interface Props {
|
||||
update: any
|
||||
}
|
||||
|
||||
export default function GroupFilter(props: Props) {
|
||||
const GroupFilter: React.FC<Props> = (props: Props) => {
|
||||
const {
|
||||
state,
|
||||
name,
|
||||
@@ -32,26 +33,25 @@ export default function GroupFilter(props: Props) {
|
||||
|
||||
const [open, setOpen] = React.useState(false);
|
||||
|
||||
const handleClick = () => {
|
||||
setOpen(!open);
|
||||
};
|
||||
|
||||
return (
|
||||
<>
|
||||
<ListItemButton onClick={handleClick}>
|
||||
<Box sx={{ mx: -2 }}>
|
||||
<ListItemButton onClick={() => setOpen(!open)}>
|
||||
<ListItemText primary={name} />
|
||||
{open ? <ExpandLess /> : <ExpandMore />}
|
||||
</ListItemButton>
|
||||
<Collapse in={open}>
|
||||
<List disablePadding>
|
||||
{/* Container is moved outside 2, so content has to go inside 4 */}
|
||||
<Stack sx={{ mx: 4 }}>
|
||||
<Options
|
||||
sourceFilter={state}
|
||||
group={position}
|
||||
updateFilterValue={updateFilterValue}
|
||||
update={update}
|
||||
/>
|
||||
</List>
|
||||
</Stack>
|
||||
</Collapse>
|
||||
</>
|
||||
</Box>
|
||||
);
|
||||
}
|
||||
};
|
||||
|
||||
export default GroupFilter;
|
||||
|
||||
@@ -6,14 +6,13 @@
|
||||
* file, You can obtain one at https://mozilla.org/MPL/2.0/.
|
||||
*/
|
||||
|
||||
import { Typography } from '@mui/material';
|
||||
import React from 'react';
|
||||
import { Box } from '@mui/system';
|
||||
|
||||
interface Props {
|
||||
name: string
|
||||
}
|
||||
|
||||
export default function HeaderFilter(props: Props) {
|
||||
const { name } = props;
|
||||
return (<Box key={name}>{name}</Box>);
|
||||
}
|
||||
const HeaderFilter: React.FC<Props> = ({ name }) => (<Typography key={name} sx={{ mt: 2 }} variant="subtitle2">{name}</Typography>);
|
||||
|
||||
export default HeaderFilter;
|
||||
|
||||
@@ -7,7 +7,6 @@
|
||||
*/
|
||||
|
||||
import React from 'react';
|
||||
import { Box } from '@mui/system';
|
||||
import InputLabel from '@mui/material/InputLabel';
|
||||
import FormControl from '@mui/material/FormControl';
|
||||
import MenuItem from '@mui/material/MenuItem';
|
||||
@@ -61,26 +60,22 @@ function hasSelect(
|
||||
</MenuItem>
|
||||
));
|
||||
return (
|
||||
<Box key={name} sx={{ display: 'flex', flexDirection: 'column', minWidth: 120 }}>
|
||||
<FormControl fullWidth>
|
||||
<InputLabel sx={{ margin: '10px 0 10px 0' }}>
|
||||
{name}
|
||||
</InputLabel>
|
||||
<Select
|
||||
name={name}
|
||||
value={values[val].displayname}
|
||||
label={name}
|
||||
onChange={handleChange}
|
||||
autoWidth
|
||||
sx={{ margin: '10px 0 10px 0' }}
|
||||
>
|
||||
{rett}
|
||||
</Select>
|
||||
</FormControl>
|
||||
</Box>
|
||||
<FormControl sx={{ my: 1 }} variant="standard">
|
||||
<InputLabel>
|
||||
{name}
|
||||
</InputLabel>
|
||||
<Select
|
||||
name={name}
|
||||
value={values[val].displayname}
|
||||
label={name}
|
||||
onChange={handleChange}
|
||||
>
|
||||
{rett}
|
||||
</Select>
|
||||
</FormControl>
|
||||
);
|
||||
}
|
||||
return (<></>);
|
||||
return null;
|
||||
}
|
||||
|
||||
function noSelect(
|
||||
@@ -106,29 +101,25 @@ function noSelect(
|
||||
|
||||
const rett = values.map((value: string) => (<MenuItem key={`${name} ${value}`} value={value}>{value}</MenuItem>));
|
||||
return (
|
||||
<Box key={name} sx={{ display: 'flex', flexDirection: 'column', minWidth: 120 }}>
|
||||
<FormControl fullWidth>
|
||||
<InputLabel sx={{ margin: '10px 0 10px 0' }}>
|
||||
{name}
|
||||
</InputLabel>
|
||||
<Select
|
||||
name={name}
|
||||
value={values[val]}
|
||||
label={name}
|
||||
onChange={handleChange}
|
||||
autoWidth
|
||||
sx={{ margin: '10px 0 10px 0' }}
|
||||
>
|
||||
{rett}
|
||||
</Select>
|
||||
</FormControl>
|
||||
</Box>
|
||||
<FormControl sx={{ my: 1 }} variant="standard">
|
||||
<InputLabel>
|
||||
{name}
|
||||
</InputLabel>
|
||||
<Select
|
||||
name={name}
|
||||
value={values[val]}
|
||||
label={name}
|
||||
onChange={handleChange}
|
||||
>
|
||||
{rett}
|
||||
</Select>
|
||||
</FormControl>
|
||||
);
|
||||
}
|
||||
return (<></>);
|
||||
return null;
|
||||
}
|
||||
|
||||
export default function SelectFilter({
|
||||
const SelectFilter: React.FC<Props> = ({
|
||||
values,
|
||||
name,
|
||||
state,
|
||||
@@ -137,7 +128,7 @@ export default function SelectFilter({
|
||||
updateFilterValue,
|
||||
update,
|
||||
group,
|
||||
}: Props) {
|
||||
}) => {
|
||||
if (selected === undefined) {
|
||||
return noSelect(
|
||||
values,
|
||||
@@ -159,4 +150,6 @@ export default function SelectFilter({
|
||||
update,
|
||||
group,
|
||||
);
|
||||
}
|
||||
};
|
||||
|
||||
export default SelectFilter;
|
||||
|
||||
@@ -5,14 +5,13 @@
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at https://mozilla.org/MPL/2.0/.
|
||||
*/
|
||||
import { Divider } from '@mui/material';
|
||||
import React from 'react';
|
||||
import { Box } from '@mui/system';
|
||||
|
||||
interface Props {
|
||||
name: string
|
||||
}
|
||||
|
||||
export default function SeperatorFilter(props: Props) {
|
||||
const { name } = props;
|
||||
return (<Box key={name}>{name}</Box>);
|
||||
}
|
||||
const SeparatorFilter: React.FC<Props> = ({ name }) => (<Divider key={name} sx={{ my: 1 }} textAlign="center">{name}</Divider>);
|
||||
|
||||
export default SeparatorFilter;
|
||||
|
||||
@@ -5,18 +5,13 @@
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at https://mozilla.org/MPL/2.0/.
|
||||
*/
|
||||
import React from 'react';
|
||||
import { Box } from '@mui/system';
|
||||
import FormControl from '@mui/material/FormControl';
|
||||
import {
|
||||
Collapse,
|
||||
List,
|
||||
ListItem,
|
||||
ListItemButton, ListItemIcon, ListItemText,
|
||||
} from '@mui/material';
|
||||
import ArrowDownwardIcon from '@mui/icons-material/ArrowDownward';
|
||||
import ArrowUpwardIcon from '@mui/icons-material/ArrowUpward';
|
||||
import { ExpandLess, ExpandMore } from '@mui/icons-material';
|
||||
import {
|
||||
Collapse, ListItemButton, ListItemText, Stack,
|
||||
} from '@mui/material';
|
||||
import { Box } from '@mui/system';
|
||||
import SortRadioInput from 'components/atoms/SortRadioInput';
|
||||
import React from 'react';
|
||||
|
||||
interface Props {
|
||||
values: any
|
||||
@@ -28,7 +23,7 @@ interface Props {
|
||||
update: any
|
||||
}
|
||||
|
||||
export default function SortFilter(props: Props) {
|
||||
const SortFilter: React.FC<Props> = (props: Props) => {
|
||||
const {
|
||||
values,
|
||||
name,
|
||||
@@ -47,8 +42,7 @@ export default function SortFilter(props: Props) {
|
||||
};
|
||||
|
||||
if (values) {
|
||||
const handleChange = (event:
|
||||
React.MouseEvent<HTMLDivElement, MouseEvent>, index: number) => {
|
||||
const handleChange = (index: number) => {
|
||||
const tmp = val;
|
||||
if (tmp.index === index) {
|
||||
tmp.ascending = !tmp.ascending;
|
||||
@@ -63,42 +57,29 @@ export default function SortFilter(props: Props) {
|
||||
updateFilterValue([...upd, { position, state: JSON.stringify(tmp), group }]);
|
||||
};
|
||||
|
||||
const ret = (
|
||||
<FormControl fullWidth>
|
||||
return (
|
||||
<Box sx={{ mx: -2 }}>
|
||||
<ListItemButton onClick={handleClick}>
|
||||
<ListItemText primary={name} />
|
||||
{open ? <ExpandLess /> : <ExpandMore />}
|
||||
</ListItemButton>
|
||||
<Collapse in={open}>
|
||||
<List>
|
||||
{values.map((value: string, index: number) => {
|
||||
let icon;
|
||||
if (val.index === index) {
|
||||
icon = val.ascending ? (<ArrowUpwardIcon color="primary" />)
|
||||
: (<ArrowDownwardIcon color="primary" />);
|
||||
}
|
||||
return (
|
||||
<ListItem disablePadding key={`${name} ${value}`}>
|
||||
<ListItemButton
|
||||
onClick={(event) => handleChange(event, index)}
|
||||
>
|
||||
<ListItemIcon>
|
||||
{icon}
|
||||
</ListItemIcon>
|
||||
<ListItemText primary={value} />
|
||||
</ListItemButton>
|
||||
</ListItem>
|
||||
);
|
||||
})}
|
||||
</List>
|
||||
<Stack sx={{ mx: 4 }}>
|
||||
{values.map((value: string, index: number) => (
|
||||
<SortRadioInput
|
||||
key={`${name} ${value}`}
|
||||
label={value}
|
||||
checked={val.index === index}
|
||||
sortDescending={!val.ascending}
|
||||
onClick={() => handleChange(index)}
|
||||
/>
|
||||
))}
|
||||
</Stack>
|
||||
</Collapse>
|
||||
</FormControl>
|
||||
);
|
||||
return (
|
||||
<Box key={name} sx={{ display: 'flex', flexDirection: 'column', minWidth: 120 }}>
|
||||
{ret}
|
||||
</Box>
|
||||
);
|
||||
}
|
||||
return (<></>);
|
||||
}
|
||||
return null;
|
||||
};
|
||||
|
||||
export default SortFilter;
|
||||
|
||||
@@ -5,14 +5,11 @@
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at https://mozilla.org/MPL/2.0/.
|
||||
*/
|
||||
import React from 'react';
|
||||
import { Box } from '@mui/system';
|
||||
import {
|
||||
Input,
|
||||
InputLabel,
|
||||
FormControl,
|
||||
} from '@mui/material';
|
||||
import SearchIcon from '@mui/icons-material/Search';
|
||||
import {
|
||||
FormControl, Input, InputAdornment, InputLabel,
|
||||
} from '@mui/material';
|
||||
import React from 'react';
|
||||
|
||||
interface Props {
|
||||
state: string
|
||||
@@ -23,7 +20,7 @@ interface Props {
|
||||
update: any
|
||||
}
|
||||
|
||||
export default function TextFilter(props: Props) {
|
||||
const TextFilter: React.FC<Props> = (props) => {
|
||||
const {
|
||||
state,
|
||||
name,
|
||||
@@ -51,27 +48,24 @@ export default function TextFilter(props: Props) {
|
||||
|
||||
if (state !== undefined) {
|
||||
return (
|
||||
<Box key={`${name}`} sx={{ display: 'flex', flexDirection: 'row', minWidth: 120 }}>
|
||||
<>
|
||||
<SearchIcon
|
||||
sx={{
|
||||
margin: 'auto',
|
||||
}}
|
||||
/>
|
||||
<FormControl fullWidth>
|
||||
<InputLabel sx={{ margin: '10px 0 10px 0' }}>
|
||||
{name}
|
||||
</InputLabel>
|
||||
<Input
|
||||
name={name}
|
||||
value={Search || ''}
|
||||
onChange={handleChange}
|
||||
sx={{ margin: '10px 0 10px 0' }}
|
||||
/>
|
||||
</FormControl>
|
||||
</>
|
||||
</Box>
|
||||
<FormControl sx={{ my: 1 }} variant="standard">
|
||||
<InputLabel>
|
||||
{name}
|
||||
</InputLabel>
|
||||
<Input
|
||||
name={name}
|
||||
value={Search || ''}
|
||||
onChange={handleChange}
|
||||
endAdornment={(
|
||||
<InputAdornment position="end">
|
||||
<SearchIcon />
|
||||
</InputAdornment>
|
||||
)}
|
||||
/>
|
||||
</FormControl>
|
||||
);
|
||||
}
|
||||
return (<></>);
|
||||
}
|
||||
};
|
||||
|
||||
export default TextFilter;
|
||||
|
||||
@@ -5,10 +5,8 @@
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at https://mozilla.org/MPL/2.0/.
|
||||
*/
|
||||
import ThreeStateCheckboxInput from 'components/atoms/ThreeStateCheckboxInput';
|
||||
import React from 'react';
|
||||
import { Box } from '@mui/system';
|
||||
import { FormControlLabel } from '@mui/material';
|
||||
import ThreeStateCheckbox from 'components/util/ThreeStateCheckbox';
|
||||
|
||||
interface Props {
|
||||
state: number
|
||||
@@ -19,7 +17,7 @@ interface Props {
|
||||
update: any
|
||||
}
|
||||
|
||||
export default function TriStateFilter(props: Props) {
|
||||
const TriStateFilter: React.FC<Props> = (props) => {
|
||||
const {
|
||||
state,
|
||||
name,
|
||||
@@ -28,48 +26,32 @@ export default function TriStateFilter(props: Props) {
|
||||
updateFilterValue,
|
||||
update,
|
||||
} = props;
|
||||
const [val, setval] = React.useState({
|
||||
[name]: state,
|
||||
});
|
||||
const [val, setval] = React.useState<number>(Number(state));
|
||||
|
||||
const handleChange = (checked: boolean | null | undefined) => {
|
||||
const tmp = val;
|
||||
if (checked !== undefined) {
|
||||
tmp[name] = checked ? 1 : 2;
|
||||
} else {
|
||||
delete tmp[name];
|
||||
}
|
||||
setval({
|
||||
...tmp,
|
||||
});
|
||||
// eslint-disable-next-line no-nested-ternary
|
||||
const newState = checked === undefined ? 0 : checked ? 1 : 2;
|
||||
setval(newState);
|
||||
const upd = update.filter((e: {
|
||||
position: number; group: number | undefined;
|
||||
}) => !(position === e.position && group === e.group));
|
||||
updateFilterValue([...upd, {
|
||||
position,
|
||||
state: (tmp[name] === undefined ? 0 : tmp[name]).toString(),
|
||||
state: newState.toString(),
|
||||
group,
|
||||
}]);
|
||||
};
|
||||
|
||||
if (state !== undefined) {
|
||||
let check;
|
||||
if (val[name] !== 0) {
|
||||
check = val[name] === 1;
|
||||
} else {
|
||||
check = undefined;
|
||||
}
|
||||
return (
|
||||
<Box sx={{ marginLeft: 3 }}>
|
||||
<FormControlLabel
|
||||
key={name}
|
||||
control={(
|
||||
<ThreeStateCheckbox name="Unread" checked={check} onChange={(checked) => handleChange(checked)} />
|
||||
)}
|
||||
label={name}
|
||||
/>
|
||||
</Box>
|
||||
<ThreeStateCheckboxInput
|
||||
label={name}
|
||||
checked={[undefined, true, false][val]}
|
||||
onChange={(checked) => handleChange(checked)}
|
||||
/>
|
||||
);
|
||||
}
|
||||
return (<></>);
|
||||
}
|
||||
};
|
||||
|
||||
export default TriStateFilter;
|
||||
|
||||
Reference in New Issue
Block a user