mirror of
https://github.com/Unleash/unleash.git
synced 2025-07-17 13:46:47 +02:00
refactor: split filter configuration with filter visibility state (#5563)
This PR splits the filter configuration with filter visibility state. This will simplify adding different filter types in future, for example date filters.
This commit is contained in:
parent
38d02e1a85
commit
e89ebf358e
@ -2,7 +2,7 @@ import React, { useState } from 'react';
|
|||||||
import Button from '@mui/material/Button';
|
import Button from '@mui/material/Button';
|
||||||
import Menu from '@mui/material/Menu';
|
import Menu from '@mui/material/Menu';
|
||||||
import MenuItem from '@mui/material/MenuItem';
|
import MenuItem from '@mui/material/MenuItem';
|
||||||
import { IFilterItem } from './FeatureToggleFilters';
|
import { IFilterVisibility, IFilterItem } from './FeatureToggleFilters';
|
||||||
import { Box, styled } from '@mui/material';
|
import { Box, styled } from '@mui/material';
|
||||||
import { Add } from '@mui/icons-material';
|
import { Add } from '@mui/icons-material';
|
||||||
|
|
||||||
@ -11,13 +11,13 @@ const StyledButton = styled(Button)(({ theme }) => ({
|
|||||||
padding: theme.spacing(1.25),
|
padding: theme.spacing(1.25),
|
||||||
}));
|
}));
|
||||||
interface IAddFilterButtonProps {
|
interface IAddFilterButtonProps {
|
||||||
availableFilters: IFilterItem[];
|
visibleFilters: IFilterVisibility;
|
||||||
setAvailableFilters: (filters: IFilterItem[]) => void;
|
setVisibleFilters: (filters: IFilterVisibility) => void;
|
||||||
}
|
}
|
||||||
|
|
||||||
const AddFilterButton = ({
|
const AddFilterButton = ({
|
||||||
availableFilters,
|
visibleFilters,
|
||||||
setAvailableFilters,
|
setVisibleFilters,
|
||||||
}: IAddFilterButtonProps) => {
|
}: IAddFilterButtonProps) => {
|
||||||
const [anchorEl, setAnchorEl] = useState<null | HTMLElement>(null);
|
const [anchorEl, setAnchorEl] = useState<null | HTMLElement>(null);
|
||||||
|
|
||||||
@ -29,15 +29,11 @@ const AddFilterButton = ({
|
|||||||
};
|
};
|
||||||
|
|
||||||
const onClick = (label: string) => {
|
const onClick = (label: string) => {
|
||||||
const filters = availableFilters.map((filter) =>
|
const filterVisibility = {
|
||||||
filter.label === label
|
...visibleFilters,
|
||||||
? {
|
[label]: true,
|
||||||
...filter,
|
};
|
||||||
enabled: true,
|
setVisibleFilters(filterVisibility);
|
||||||
}
|
|
||||||
: filter,
|
|
||||||
);
|
|
||||||
setAvailableFilters(filters);
|
|
||||||
handleClose();
|
handleClose();
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -53,16 +49,12 @@ const AddFilterButton = ({
|
|||||||
open={Boolean(anchorEl)}
|
open={Boolean(anchorEl)}
|
||||||
onClose={handleClose}
|
onClose={handleClose}
|
||||||
>
|
>
|
||||||
{availableFilters.map(
|
{Object.entries(visibleFilters).map(([label, enabled]) =>
|
||||||
(filter) =>
|
!enabled ? (
|
||||||
!filter.enabled && (
|
<MenuItem key={label} onClick={() => onClick(label)}>
|
||||||
<MenuItem
|
{label}
|
||||||
key={filter.label}
|
</MenuItem>
|
||||||
onClick={() => onClick(filter.label)}
|
) : null,
|
||||||
>
|
|
||||||
{filter.label}
|
|
||||||
</MenuItem>
|
|
||||||
),
|
|
||||||
)}
|
)}
|
||||||
</Menu>
|
</Menu>
|
||||||
</div>
|
</div>
|
||||||
|
@ -30,11 +30,14 @@ export interface IFilterItem {
|
|||||||
value: string;
|
value: string;
|
||||||
}[];
|
}[];
|
||||||
filterKey: keyof FeatureTogglesListFilters;
|
filterKey: keyof FeatureTogglesListFilters;
|
||||||
enabled?: boolean;
|
|
||||||
singularOperators: [string, ...string[]];
|
singularOperators: [string, ...string[]];
|
||||||
pluralOperators: [string, ...string[]];
|
pluralOperators: [string, ...string[]];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export type IFilterVisibility = {
|
||||||
|
[key: string]: boolean | undefined;
|
||||||
|
};
|
||||||
|
|
||||||
export const FeatureToggleFilters: VFC<IFeatureToggleFiltersProps> = ({
|
export const FeatureToggleFilters: VFC<IFeatureToggleFiltersProps> = ({
|
||||||
state,
|
state,
|
||||||
onChange,
|
onChange,
|
||||||
@ -54,16 +57,14 @@ export const FeatureToggleFilters: VFC<IFeatureToggleFiltersProps> = ({
|
|||||||
];
|
];
|
||||||
|
|
||||||
const [availableFilters, setAvailableFilters] = useState<IFilterItem[]>([]);
|
const [availableFilters, setAvailableFilters] = useState<IFilterItem[]>([]);
|
||||||
const removeFilter = (label: string) => {
|
const [visibleFilters, setVisibleFilters] = useState<IFilterVisibility>({});
|
||||||
const filters = availableFilters.map((filter) =>
|
|
||||||
filter.label === label
|
const hideFilter = (label: string) => {
|
||||||
? {
|
const filterVisibility = {
|
||||||
...filter,
|
...visibleFilters,
|
||||||
enabled: false,
|
[label]: false,
|
||||||
}
|
};
|
||||||
: filter,
|
setVisibleFilters(filterVisibility);
|
||||||
);
|
|
||||||
setAvailableFilters(filters);
|
|
||||||
};
|
};
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
@ -76,14 +77,13 @@ export const FeatureToggleFilters: VFC<IFeatureToggleFiltersProps> = ({
|
|||||||
value: segment.name,
|
value: segment.name,
|
||||||
}));
|
}));
|
||||||
|
|
||||||
const newFilterItems: IFilterItem[] = [
|
const availableFilters: IFilterItem[] = [
|
||||||
{
|
{
|
||||||
label: 'State',
|
label: 'State',
|
||||||
options: stateOptions,
|
options: stateOptions,
|
||||||
filterKey: 'state',
|
filterKey: 'state',
|
||||||
singularOperators: ['IS', 'IS_NOT'],
|
singularOperators: ['IS', 'IS_NOT'],
|
||||||
pluralOperators: ['IS_ANY_OF', 'IS_NONE_OF'],
|
pluralOperators: ['IS_ANY_OF', 'IS_NONE_OF'],
|
||||||
enabled: Boolean(state.state),
|
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
label: 'Project',
|
label: 'Project',
|
||||||
@ -91,7 +91,6 @@ export const FeatureToggleFilters: VFC<IFeatureToggleFiltersProps> = ({
|
|||||||
filterKey: 'project',
|
filterKey: 'project',
|
||||||
singularOperators: ['IS', 'IS_NOT'],
|
singularOperators: ['IS', 'IS_NOT'],
|
||||||
pluralOperators: ['IS_ANY_OF', 'IS_NONE_OF'],
|
pluralOperators: ['IS_ANY_OF', 'IS_NONE_OF'],
|
||||||
enabled: Boolean(state.project),
|
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
label: 'Segment',
|
label: 'Segment',
|
||||||
@ -104,22 +103,30 @@ export const FeatureToggleFilters: VFC<IFeatureToggleFiltersProps> = ({
|
|||||||
'EXCLUDE_IF_ANY_OF',
|
'EXCLUDE_IF_ANY_OF',
|
||||||
'EXCLUDE_ALL',
|
'EXCLUDE_ALL',
|
||||||
],
|
],
|
||||||
enabled: Boolean(state.segment),
|
|
||||||
},
|
},
|
||||||
];
|
];
|
||||||
|
|
||||||
setAvailableFilters(newFilterItems);
|
setAvailableFilters(availableFilters);
|
||||||
}, [
|
}, [JSON.stringify(projects), JSON.stringify(segments)]);
|
||||||
JSON.stringify(projects),
|
|
||||||
JSON.stringify(state),
|
useEffect(() => {
|
||||||
JSON.stringify(segments),
|
const filterVisibility: IFilterVisibility = {
|
||||||
]);
|
State: Boolean(state.state),
|
||||||
|
Project: Boolean(state.project),
|
||||||
|
Segment: Boolean(state.segment),
|
||||||
|
};
|
||||||
|
setVisibleFilters(filterVisibility);
|
||||||
|
}, [JSON.stringify(state)]);
|
||||||
|
|
||||||
|
const hasAvailableFilters = Object.values(visibleFilters).some(
|
||||||
|
(value) => !value,
|
||||||
|
);
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<StyledBox>
|
<StyledBox>
|
||||||
{availableFilters.map(
|
{availableFilters.map(
|
||||||
(filter) =>
|
(filter) =>
|
||||||
filter.enabled && (
|
visibleFilters[filter.label] && (
|
||||||
<FilterItem
|
<FilterItem
|
||||||
key={filter.label}
|
key={filter.label}
|
||||||
label={filter.label}
|
label={filter.label}
|
||||||
@ -130,16 +137,16 @@ export const FeatureToggleFilters: VFC<IFeatureToggleFiltersProps> = ({
|
|||||||
}
|
}
|
||||||
singularOperators={filter.singularOperators}
|
singularOperators={filter.singularOperators}
|
||||||
pluralOperators={filter.pluralOperators}
|
pluralOperators={filter.pluralOperators}
|
||||||
onChipClose={() => removeFilter(filter.label)}
|
onChipClose={() => hideFilter(filter.label)}
|
||||||
/>
|
/>
|
||||||
),
|
),
|
||||||
)}
|
)}
|
||||||
<ConditionallyRender
|
<ConditionallyRender
|
||||||
condition={availableFilters.some((filter) => !filter.enabled)}
|
condition={hasAvailableFilters}
|
||||||
show={
|
show={
|
||||||
<AddFilterButton
|
<AddFilterButton
|
||||||
availableFilters={availableFilters}
|
visibleFilters={visibleFilters}
|
||||||
setAvailableFilters={setAvailableFilters}
|
setVisibleFilters={setVisibleFilters}
|
||||||
/>
|
/>
|
||||||
}
|
}
|
||||||
/>
|
/>
|
||||||
|
Loading…
Reference in New Issue
Block a user