1
0
mirror of https://github.com/Unleash/unleash.git synced 2025-05-08 01:15:49 +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:
Jaanus Sellin 2023-12-07 11:59:35 +02:00 committed by GitHub
parent 38d02e1a85
commit e89ebf358e
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
2 changed files with 49 additions and 50 deletions

View File

@ -2,7 +2,7 @@ import React, { useState } from 'react';
import Button from '@mui/material/Button';
import Menu from '@mui/material/Menu';
import MenuItem from '@mui/material/MenuItem';
import { IFilterItem } from './FeatureToggleFilters';
import { IFilterVisibility, IFilterItem } from './FeatureToggleFilters';
import { Box, styled } from '@mui/material';
import { Add } from '@mui/icons-material';
@ -11,13 +11,13 @@ const StyledButton = styled(Button)(({ theme }) => ({
padding: theme.spacing(1.25),
}));
interface IAddFilterButtonProps {
availableFilters: IFilterItem[];
setAvailableFilters: (filters: IFilterItem[]) => void;
visibleFilters: IFilterVisibility;
setVisibleFilters: (filters: IFilterVisibility) => void;
}
const AddFilterButton = ({
availableFilters,
setAvailableFilters,
visibleFilters,
setVisibleFilters,
}: IAddFilterButtonProps) => {
const [anchorEl, setAnchorEl] = useState<null | HTMLElement>(null);
@ -29,15 +29,11 @@ const AddFilterButton = ({
};
const onClick = (label: string) => {
const filters = availableFilters.map((filter) =>
filter.label === label
? {
...filter,
enabled: true,
}
: filter,
);
setAvailableFilters(filters);
const filterVisibility = {
...visibleFilters,
[label]: true,
};
setVisibleFilters(filterVisibility);
handleClose();
};
@ -53,16 +49,12 @@ const AddFilterButton = ({
open={Boolean(anchorEl)}
onClose={handleClose}
>
{availableFilters.map(
(filter) =>
!filter.enabled && (
<MenuItem
key={filter.label}
onClick={() => onClick(filter.label)}
>
{filter.label}
</MenuItem>
),
{Object.entries(visibleFilters).map(([label, enabled]) =>
!enabled ? (
<MenuItem key={label} onClick={() => onClick(label)}>
{label}
</MenuItem>
) : null,
)}
</Menu>
</div>

View File

@ -30,11 +30,14 @@ export interface IFilterItem {
value: string;
}[];
filterKey: keyof FeatureTogglesListFilters;
enabled?: boolean;
singularOperators: [string, ...string[]];
pluralOperators: [string, ...string[]];
}
export type IFilterVisibility = {
[key: string]: boolean | undefined;
};
export const FeatureToggleFilters: VFC<IFeatureToggleFiltersProps> = ({
state,
onChange,
@ -54,16 +57,14 @@ export const FeatureToggleFilters: VFC<IFeatureToggleFiltersProps> = ({
];
const [availableFilters, setAvailableFilters] = useState<IFilterItem[]>([]);
const removeFilter = (label: string) => {
const filters = availableFilters.map((filter) =>
filter.label === label
? {
...filter,
enabled: false,
}
: filter,
);
setAvailableFilters(filters);
const [visibleFilters, setVisibleFilters] = useState<IFilterVisibility>({});
const hideFilter = (label: string) => {
const filterVisibility = {
...visibleFilters,
[label]: false,
};
setVisibleFilters(filterVisibility);
};
useEffect(() => {
@ -76,14 +77,13 @@ export const FeatureToggleFilters: VFC<IFeatureToggleFiltersProps> = ({
value: segment.name,
}));
const newFilterItems: IFilterItem[] = [
const availableFilters: IFilterItem[] = [
{
label: 'State',
options: stateOptions,
filterKey: 'state',
singularOperators: ['IS', 'IS_NOT'],
pluralOperators: ['IS_ANY_OF', 'IS_NONE_OF'],
enabled: Boolean(state.state),
},
{
label: 'Project',
@ -91,7 +91,6 @@ export const FeatureToggleFilters: VFC<IFeatureToggleFiltersProps> = ({
filterKey: 'project',
singularOperators: ['IS', 'IS_NOT'],
pluralOperators: ['IS_ANY_OF', 'IS_NONE_OF'],
enabled: Boolean(state.project),
},
{
label: 'Segment',
@ -104,22 +103,30 @@ export const FeatureToggleFilters: VFC<IFeatureToggleFiltersProps> = ({
'EXCLUDE_IF_ANY_OF',
'EXCLUDE_ALL',
],
enabled: Boolean(state.segment),
},
];
setAvailableFilters(newFilterItems);
}, [
JSON.stringify(projects),
JSON.stringify(state),
JSON.stringify(segments),
]);
setAvailableFilters(availableFilters);
}, [JSON.stringify(projects), JSON.stringify(segments)]);
useEffect(() => {
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 (
<StyledBox>
{availableFilters.map(
(filter) =>
filter.enabled && (
visibleFilters[filter.label] && (
<FilterItem
key={filter.label}
label={filter.label}
@ -130,16 +137,16 @@ export const FeatureToggleFilters: VFC<IFeatureToggleFiltersProps> = ({
}
singularOperators={filter.singularOperators}
pluralOperators={filter.pluralOperators}
onChipClose={() => removeFilter(filter.label)}
onChipClose={() => hideFilter(filter.label)}
/>
),
)}
<ConditionallyRender
condition={availableFilters.some((filter) => !filter.enabled)}
condition={hasAvailableFilters}
show={
<AddFilterButton
availableFilters={availableFilters}
setAvailableFilters={setAvailableFilters}
visibleFilters={visibleFilters}
setVisibleFilters={setVisibleFilters}
/>
}
/>