diff --git a/package.json b/package.json index fb5d9396d..ad03762b2 100644 --- a/package.json +++ b/package.json @@ -1,5 +1,5 @@ { - "version": "8.1.13", + "version": "8.1.14", "license": "MIT", "main": "dist/cjs/index.js", "module": "dist/esm/index.js", diff --git a/src/components/data-grid/DataGrid.tsx b/src/components/data-grid/DataGrid.tsx index a49c7e812..df7b0bee2 100755 --- a/src/components/data-grid/DataGrid.tsx +++ b/src/components/data-grid/DataGrid.tsx @@ -56,6 +56,7 @@ import { RowModelType, DataGridColumnValueType, CustomFilterTypes, + Filter, } from './types'; import { useTheme } from '../../providers'; import { defaultFormatSettings } from './defaultFormatSettings'; @@ -572,6 +573,22 @@ export const DataGrid = ({ onFiltering(filterModel); }; + const getSetFilterObject = (values: (string | number | boolean | null)[], filterObject?: Filter) => { + if (filterObject?.customFilterMap) { + return filterObject?.customFilterMap(values); + } + if (filterObject?.byId) { + return { + ids: values, + filterType: CustomFilterTypes.ids, + }; + } + return { + values, + filterType: CustomFilterTypes.set, + }; + }; + const onSetFiltering = useCallback( (columnField: string, type: FilterType, value: FilterValue['value']) => { let currentValues; @@ -589,22 +606,7 @@ export const DataGrid = ({ } const filterObject = filters?.find((filter) => filter.columnField === columnField); - let setFilter; - if (filterObject?.customFilterMap) { - setFilter = filterObject?.customFilterMap(values); - } else if (filterObject?.byId) { - setFilter = { - ids: values, - filterType: CustomFilterTypes.ids, - }; - } else { - setFilter = { - values, - filterType: CustomFilterTypes.set, - }; - } - - filterModel[columnField] = setFilter; + filterModel[columnField] = getSetFilterObject(values, filterObject); onFiltering(filterModel); }, @@ -634,6 +636,26 @@ export const DataGrid = ({ [setSelectedFilterIds, onSetFiltering], ); + const filterOnMultiValues = useCallback( + (columnField: string, values: FilterValue['value'][]) => { + if (!values.length) { + setFilterModel((model) => ({ ...model, [columnField]: undefined })); + return gridApi?.onFilterChanged(); + } + const filterObject = filters?.find((filter) => filter.columnField === columnField); + + filterModel[columnField] = getSetFilterObject(values, filterObject); + + onFiltering(filterModel); + + setSelectedFilterIds((currentIds) => ({ + ...currentIds, + [columnField]: values, + })); + }, + [setSelectedFilterIds, onSetFiltering], + ); + // Date format that is send as part of the query request const getDateFormat = useCallback((date: Date) => new TcDate(date).getDateWithoutTimeAsUTC().toISOString(), []); @@ -772,6 +794,7 @@ export const DataGrid = ({ selectedFilterIds={selectedFilterIds} setSelectedFilterIds={setSelectedFilterIds} filterOnValue={filterOnValue} + filterOnMultiValues={filterOnMultiValues} filterOnDate={filterOnDate} debouncedSearch={debouncedSearch} clearFilterModel={clearFilterModel} diff --git a/src/components/data-grid/defaultTranslations.tsx b/src/components/data-grid/defaultTranslations.tsx index ffdbcb3a7..831ffea20 100755 --- a/src/components/data-grid/defaultTranslations.tsx +++ b/src/components/data-grid/defaultTranslations.tsx @@ -40,6 +40,7 @@ export const defaultTranslations: Translations = { defaultViewTooltip: 'Default view cannot be edited.', lessFilters: 'Less filters', allFilters: 'All filters', + applyFilters: 'Apply filters', showResultsBy: 'Show', paginationPrevious: 'Prev', paginationNext: 'Next', diff --git a/src/components/data-grid/filters/ColumnFilters.tsx b/src/components/data-grid/filters/ColumnFilters.tsx index ee45ceede..2e9cfbf1f 100755 --- a/src/components/data-grid/filters/ColumnFilters.tsx +++ b/src/components/data-grid/filters/ColumnFilters.tsx @@ -12,6 +12,7 @@ import { Button } from '../../button'; import { ButtonKind } from '../../../models'; import { ParagraphSmall } from 'baseui/typography'; import { FixedSizeSelect } from '../../fixed-size-select'; +import { MultiFilter } from './MultiFilter'; const LESS_FILTERS_BUTTON_TEST_ID = 'less-filters-button'; const MORE_FILTERS_BUTTON_TEST_ID = 'more-filters-button'; @@ -25,9 +26,10 @@ export const ColumnFilters = ({ setDates, setSelectedFilterIds, selectedFilterIds, - translations: { search, lessFilters, allFilters, clearFilters }, + translations: { search, lessFilters, allFilters, clearFilters, applyFilters }, datepickerTranslations, filterOnValue, + filterOnMultiValues, filterOnDate, clearFilterModel, showClearFilters, @@ -205,6 +207,9 @@ export const ColumnFilters = ({ const getSelectedFilterIds = (columnField: string) => selectedFilterIds[columnField]?.map(String); + const handleFilterMultiValues = (columnField: string) => (values: FilterValue['value'][]) => + filterOnMultiValues(columnField, values); + const getSelectHasValue = (columnField: string) => Array.isArray(selectedFilterIds[columnField]) ? !!selectedFilterIds[columnField].length @@ -244,24 +249,18 @@ export const ColumnFilters = ({ ), [FilterType.multi]: ( - - } - size={SIZE.compact} - isActive={isSetFilterActive(columnField)} - onClear={() => onSetFilterClear(columnField)} - hasValue={isSetFilterActive(columnField)} - arrows - /> - + valuesLoading={valuesLoading} + title={getSetTitle(columnField, title)} + icon={Icon && } + isFilterActive={isSetFilterActive(columnField)} + onSetFilterClear={() => onSetFilterClear(columnField)} + onApplyFilter={handleFilterMultiValues(columnField)} + applyFiltersLabel={applyFilters} + /> ), [FilterType.multiVirtual]: ( { + const [selectedItems, setSelectedItems] = useState([]); + + const { + theme: { + current: { + sizing: { scale300, scale600 }, + customColors: { light4 }, + }, + }, + } = useTheme(); + + useEffect(() => { + setSelectedItems(values.filter((value) => !!initialSelectedFilterIds?.includes(value.id as string))); + }, [initialSelectedFilterIds]); + + const handleApplyFilter = () => { + onApplyFilter(selectedItems.map((item) => item.id as string)); + }; + + const handleSelectItem = (item: DropdownItem) => { + const filteredSelectedItems = selectedItems.filter(({ id }) => id !== item.id); + if (filteredSelectedItems.length < selectedItems.length) { + setSelectedItems(filteredSelectedItems); + return; + } + setSelectedItems([...selectedItems, item]); + }; + + const preparedValues = values.map((value) => ({ + ...value, + action: () => handleSelectItem(value), + isBold: !!selectedItems.find(({ id }) => id === value.id), + })); + + return ( + id as string)} + searchPlaceholder={searchPlaceholder} + isLoading={valuesLoading} + footer={ + + + + } + > + + + ); +}; diff --git a/src/components/data-grid/filters/types.ts b/src/components/data-grid/filters/types.ts new file mode 100644 index 000000000..d242daaa5 --- /dev/null +++ b/src/components/data-grid/filters/types.ts @@ -0,0 +1,16 @@ +import { ReactNode } from 'react'; +import { DropdownItem } from '../../dropdown'; +import { FilterValue } from '../types'; + +export interface MultiFilterProps { + searchPlaceholder: string; + valuesLoading?: boolean; + values: DropdownItem[]; + icon?: ReactNode; + isFilterActive: boolean; + title: string; + initialSelectedFilterIds: string[]; + applyFiltersLabel: string; + onSetFilterClear: () => void; + onApplyFilter: (selectedItems: FilterValue['value'][]) => void; +} diff --git a/src/components/data-grid/types.ts b/src/components/data-grid/types.ts index 9c38a2e73..707b0322f 100755 --- a/src/components/data-grid/types.ts +++ b/src/components/data-grid/types.ts @@ -173,6 +173,7 @@ export interface Translations { defaultViewTooltip: string; lessFilters: string; allFilters: string; + applyFilters: string; showResultsBy: string; paginationPrevious: string; paginationNext: string; @@ -296,6 +297,7 @@ export interface FiltersProps { selectedFilterIds: SelectedFilterIds; setSelectedFilterIds: Dispatch>; filterOnValue: (columnField: string, value: FilterValue['value'], type: FilterType) => void; + filterOnMultiValues: (columnField: string, values: FilterValue['value'][]) => void; filterOnDate: (columnField: string, selectedDates: Date[]) => void; debouncedSearch?: boolean; clearFilterModel: (columnFilter: string) => void; @@ -317,6 +319,7 @@ export interface ColumnFiltersProps { selectedFilterIds: SelectedFilterIds; setSelectedFilterIds: Dispatch>; filterOnValue: (columnField: string, value: FilterValue['value'], type: FilterType) => void; + filterOnMultiValues: (columnField: string, values: FilterValue['value'][]) => void; filterOnDate: (columnField: string, selectedDates: Date[]) => void; clearFilterModel: (columnFilter: string) => void; showClearFilters?: boolean;