import {Dialog} from '../../ui/overlays/dialog/dialog'; import { BackendFilter, CustomFilterControl, DatePickerFilterControl, FilterBooleanToggleControl, FilterChipFieldControl, FilterControlType, FilterOperator, FilterSelectControl, FilterSelectModelControl, FilterTextInputControl, } from './backend-filter'; import {Trans} from '../../i18n/trans'; import {Key, useState} from 'react'; import {DialogHeader} from '../../ui/overlays/dialog/dialog-header'; import {DialogBody} from '../../ui/overlays/dialog/dialog-body'; import {useBackendFilterUrlParams} from './backend-filter-url-params'; import {useDialogContext} from '../../ui/overlays/dialog/dialog-context'; import {Accordion, AccordionItem} from '../../ui/accordion/accordion'; import {Button} from '../../ui/buttons/button'; import {useForm} from 'react-hook-form'; import {Form} from '../../ui/forms/form'; import {Checkbox} from '../../ui/forms/toggle/checkbox'; import {SelectFilterPanel} from './panels/select-filter-panel'; import {DateRangeFilterPanel} from './panels/date-range-filter-panel'; import {NormalizedModelFilterPanel} from './panels/normalized-model-filter-panel'; import {InputFilterPanel} from './panels/input-filter-panel'; import {BooleanFilterPanel} from './panels/boolean-filter-panel'; import clsx from 'clsx'; import {ChipFieldFilterPanel} from '@common/datatable/filters/panels/chip-field-filter-panel'; export interface FilterItemFormValue { value: T; operator?: FilterOperator; } interface AddFilterDialogProps { filters: BackendFilter[]; } export function AddFilterDialog({filters}: AddFilterDialogProps) { const {decodedFilters} = useBackendFilterUrlParams(filters); const {formId} = useDialogContext(); // expand currently active filters const [expandedFilters, setExpandedFilters] = useState(() => { return decodedFilters.map(f => f.key); }); const clearButton = ( ); const applyButton = ( ); return ( ); } interface FilterListProps { filters: BackendFilter[]; expandedFilters: Key[]; setExpandedFilters: (value: Key[]) => void; } function FilterList({ filters, expandedFilters, setExpandedFilters, }: FilterListProps) { const {decodedFilters, replaceAll} = useBackendFilterUrlParams(filters); // either get value and operator from url params if filter is active, or get defaults from filter config const defaultValues: Record = {}; filters.forEach(filter => { const appliedFilter = decodedFilters.find(f => f.key === filter.key); defaultValues[filter.key] = appliedFilter?.value !== undefined ? // there might be some extra keys set on filter besides // "value" and "operator", so add the whole object to form appliedFilter : { value: filter.control.defaultValue, operator: filter.defaultOperator, }; }); const form = useForm>({defaultValues}); const {formId, close} = useDialogContext(); return (
{ const filterValue = Object.entries(formValue) // remove undefined and non-expanded filters, so "clear" button will correctly remove active filters .filter( ([key, fieldValue]) => expandedFilters.includes(key) && fieldValue !== undefined ) .map(([key, fieldValue]) => ({ key, ...fieldValue, // value and operator from form })); replaceAll(filterValue); close(); }} > {filters.map(filter => ( } key={filter.key} value={filter.key} label={} bodyClassName="max-h-288 overflow-y-auto compact-scrollbar" > {filter.description && (
)}
))}
); } interface ActiveFilterPanelProps { filter: BackendFilter; } export function AddFilterDialogPanel({filter}: ActiveFilterPanelProps) { switch (filter.control.type) { case FilterControlType.Select: return ( } /> ); case FilterControlType.ChipField: return ( } /> ); case FilterControlType.DateRangePicker: return ( } /> ); case FilterControlType.SelectModel: return ( } /> ); case FilterControlType.Input: return ( } /> ); case FilterControlType.BooleanToggle: return ( } /> ); case 'custom': const CustomComponent = filter.control.panel; return ( } /> ); default: return null; } }