From 17e2e38812021a67300b08321e384ec3a938010a Mon Sep 17 00:00:00 2001 From: Lucas Bordeau Date: Thu, 9 Jan 2025 18:54:34 +0100 Subject: [PATCH] Refactored select filter and select filter definition logic (#9519) This PR extracts the logic to manage filter and filter definition setting. Previously it was ambiguous, we had the same "selectFilter" naming used for setting filter definition in filter dropdown and for setting the actual filter value and saving to view filter states. This is another incremental refactor, which will allow to remove useFilterDropdown hook. --- .../ObjectFilterDropdownBooleanSelect.tsx | 6 ++- .../ObjectFilterDropdownDateInput.tsx | 8 ++-- .../ObjectFilterDropdownFilterSelect.tsx | 11 +++-- ...pdownFilterSelectCompositeFieldSubMenu.tsx | 7 ++- ...jectFilterDropdownFilterSelectMenuItem.tsx | 26 +++++----- .../ObjectFilterDropdownNumberInput.tsx | 9 +++- .../ObjectFilterDropdownOperandSelect.tsx | 8 ++-- .../ObjectFilterDropdownOptionSelect.tsx | 6 ++- .../ObjectFilterDropdownRatingInput.tsx | 6 ++- .../ObjectFilterDropdownRecordSelect.tsx | 6 ++- .../ObjectFilterDropdownSourceSelect.tsx | 6 ++- .../ObjectFilterDropdownTextSearchInput.tsx | 6 ++- .../__tests__/useFilterDropdown.test.tsx | 21 +++++--- .../hooks/useApplyRecordFilter.ts | 48 +++++++++++++++++++ .../hooks/useFilterDropdown.ts | 22 --------- ...seSelectFilterDefinitionUsedInDropdown.ts} | 14 ++++-- 16 files changed, 138 insertions(+), 72 deletions(-) create mode 100644 packages/twenty-front/src/modules/object-record/object-filter-dropdown/hooks/useApplyRecordFilter.ts rename packages/twenty-front/src/modules/object-record/object-filter-dropdown/hooks/{useSelectFilter.ts => useSelectFilterDefinitionUsedInDropdown.ts} (85%) diff --git a/packages/twenty-front/src/modules/object-record/object-filter-dropdown/components/ObjectFilterDropdownBooleanSelect.tsx b/packages/twenty-front/src/modules/object-record/object-filter-dropdown/components/ObjectFilterDropdownBooleanSelect.tsx index 9a550ea9d5..e8fa38cbed 100644 --- a/packages/twenty-front/src/modules/object-record/object-filter-dropdown/components/ObjectFilterDropdownBooleanSelect.tsx +++ b/packages/twenty-front/src/modules/object-record/object-filter-dropdown/components/ObjectFilterDropdownBooleanSelect.tsx @@ -4,6 +4,7 @@ import { useEffect, useState } from 'react'; import { useRecoilValue } from 'recoil'; import { v4 } from 'uuid'; +import { useApplyRecordFilter } from '@/object-record/object-filter-dropdown/hooks/useApplyRecordFilter'; import { useFilterDropdown } from '@/object-record/object-filter-dropdown/hooks/useFilterDropdown'; import { RelationPickerHotkeyScope } from '@/object-record/relation-picker/types/RelationPickerHotkeyScope'; import { BooleanDisplay } from '@/ui/field/display/components/BooleanDisplay'; @@ -40,9 +41,10 @@ export const ObjectFilterDropdownBooleanSelect = () => { filterDefinitionUsedInDropdownState, selectedOperandInDropdownState, selectedFilterState, - selectFilter, } = useFilterDropdown(); + const { applyRecordFilter } = useApplyRecordFilter(); + const { closeDropdown } = useDropdown(); const filterDefinitionUsedInDropdown = useRecoilValue( @@ -69,7 +71,7 @@ export const ObjectFilterDropdownBooleanSelect = () => { return; } - selectFilter({ + applyRecordFilter({ id: selectedFilter?.id ?? v4(), definition: filterDefinitionUsedInDropdown, operand: selectedOperandInDropdown, diff --git a/packages/twenty-front/src/modules/object-record/object-filter-dropdown/components/ObjectFilterDropdownDateInput.tsx b/packages/twenty-front/src/modules/object-record/object-filter-dropdown/components/ObjectFilterDropdownDateInput.tsx index 6a90b16f0c..a7a061bdfb 100644 --- a/packages/twenty-front/src/modules/object-record/object-filter-dropdown/components/ObjectFilterDropdownDateInput.tsx +++ b/packages/twenty-front/src/modules/object-record/object-filter-dropdown/components/ObjectFilterDropdownDateInput.tsx @@ -1,6 +1,7 @@ import { useRecoilValue } from 'recoil'; import { v4 } from 'uuid'; +import { useApplyRecordFilter } from '@/object-record/object-filter-dropdown/hooks/useApplyRecordFilter'; import { useFilterDropdown } from '@/object-record/object-filter-dropdown/hooks/useFilterDropdown'; import { Filter } from '@/object-record/object-filter-dropdown/types/Filter'; import { getRelativeDateDisplayValue } from '@/object-record/object-filter-dropdown/utils/getRelativeDateDisplayValue'; @@ -21,9 +22,10 @@ export const ObjectFilterDropdownDateInput = () => { filterDefinitionUsedInDropdownState, selectedOperandInDropdownState, selectedFilterState, - selectFilter, } = useFilterDropdown(); + const { applyRecordFilter } = useApplyRecordFilter(); + const filterDefinitionUsedInDropdown = useRecoilValue( filterDefinitionUsedInDropdownState, ); @@ -51,7 +53,7 @@ export const ObjectFilterDropdownDateInput = () => { if (!filterDefinitionUsedInDropdown || !selectedOperandInDropdown) return; - selectFilter?.({ + applyRecordFilter({ id: selectedFilter?.id ? selectedFilter.id : v4(), fieldMetadataId: filterDefinitionUsedInDropdown.fieldMetadataId, value: newDate?.toISOString() ?? '', @@ -83,7 +85,7 @@ export const ObjectFilterDropdownDateInput = () => { ) : ''; - selectFilter?.({ + applyRecordFilter({ id: selectedFilter?.id ? selectedFilter.id : v4(), fieldMetadataId: filterDefinitionUsedInDropdown.fieldMetadataId, value, diff --git a/packages/twenty-front/src/modules/object-record/object-filter-dropdown/components/ObjectFilterDropdownFilterSelect.tsx b/packages/twenty-front/src/modules/object-record/object-filter-dropdown/components/ObjectFilterDropdownFilterSelect.tsx index 0e465e5722..649032fe0b 100644 --- a/packages/twenty-front/src/modules/object-record/object-filter-dropdown/components/ObjectFilterDropdownFilterSelect.tsx +++ b/packages/twenty-front/src/modules/object-record/object-filter-dropdown/components/ObjectFilterDropdownFilterSelect.tsx @@ -7,7 +7,7 @@ import { AdvancedFilterButton } from '@/object-record/object-filter-dropdown/com import { ObjectFilterDropdownFilterSelectMenuItem } from '@/object-record/object-filter-dropdown/components/ObjectFilterDropdownFilterSelectMenuItem'; import { OBJECT_FILTER_DROPDOWN_ID } from '@/object-record/object-filter-dropdown/constants/ObjectFilterDropdownId'; import { useFilterDropdown } from '@/object-record/object-filter-dropdown/hooks/useFilterDropdown'; -import { useSelectFilter } from '@/object-record/object-filter-dropdown/hooks/useSelectFilter'; +import { useSelectFilterDefinitionUsedInDropdown } from '@/object-record/object-filter-dropdown/hooks/useSelectFilterDefinitionUsedInDropdown'; import { FiltersHotkeyScope } from '@/object-record/object-filter-dropdown/types/FiltersHotkeyScope'; import { useRecordIndexContextOrThrow } from '@/object-record/record-index/contexts/RecordIndexContext'; import { hiddenTableColumnsComponentSelector } from '@/object-record/record-table/states/selectors/hiddenTableColumnsComponentSelector'; @@ -121,7 +121,8 @@ export const ObjectFilterDropdownFilterSelect = ({ (item) => item.fieldMetadataId, ); - const { selectFilter } = useSelectFilter(); + const { selectFilterDefinitionUsedInDropdown } = + useSelectFilterDefinitionUsedInDropdown(); const { resetSelectedItem } = useSelectableList(OBJECT_FILTER_DROPDOWN_ID); @@ -135,7 +136,11 @@ export const ObjectFilterDropdownFilterSelect = ({ } resetSelectedItem(); - selectFilter({ filterDefinition: selectedFilterDefinition }); + + selectFilterDefinitionUsedInDropdown({ + filterDefinition: selectedFilterDefinition, + }); + closeAdvancedFilterDropdown(); }; diff --git a/packages/twenty-front/src/modules/object-record/object-filter-dropdown/components/ObjectFilterDropdownFilterSelectCompositeFieldSubMenu.tsx b/packages/twenty-front/src/modules/object-record/object-filter-dropdown/components/ObjectFilterDropdownFilterSelectCompositeFieldSubMenu.tsx index c364bb90eb..9dbd2d110d 100644 --- a/packages/twenty-front/src/modules/object-record/object-filter-dropdown/components/ObjectFilterDropdownFilterSelectCompositeFieldSubMenu.tsx +++ b/packages/twenty-front/src/modules/object-record/object-filter-dropdown/components/ObjectFilterDropdownFilterSelectCompositeFieldSubMenu.tsx @@ -1,4 +1,5 @@ import { useAdvancedFilterDropdown } from '@/object-record/advanced-filter/hooks/useAdvancedFilterDropdown'; +import { useApplyRecordFilter } from '@/object-record/object-filter-dropdown/hooks/useApplyRecordFilter'; import { useFilterDropdown } from '@/object-record/object-filter-dropdown/hooks/useFilterDropdown'; import { objectFilterDropdownFilterIsSelectedComponentState } from '@/object-record/object-filter-dropdown/states/objectFilterDropdownFilterIsSelectedComponentState'; import { objectFilterDropdownFirstLevelFilterDefinitionComponentState } from '@/object-record/object-filter-dropdown/states/objectFilterDropdownFirstLevelFilterDefinitionComponentState'; @@ -55,11 +56,12 @@ export const ObjectFilterDropdownFilterSelectCompositeFieldSubMenu = () => { setFilterDefinitionUsedInDropdown, setSelectedOperandInDropdown, setObjectFilterDropdownSearchInput, - selectFilter, advancedFilterViewFilterIdState, advancedFilterViewFilterGroupIdState, } = useFilterDropdown(); + const { applyRecordFilter } = useApplyRecordFilter(); + const advancedFilterViewFilterId = useRecoilValue( advancedFilterViewFilterIdState, ); @@ -84,7 +86,8 @@ export const ObjectFilterDropdownFilterSelectCompositeFieldSubMenu = () => { definition.type, operand, ); - selectFilter({ + + applyRecordFilter({ id: advancedFilterViewFilterId, fieldMetadataId: definition.fieldMetadataId, value, diff --git a/packages/twenty-front/src/modules/object-record/object-filter-dropdown/components/ObjectFilterDropdownFilterSelectMenuItem.tsx b/packages/twenty-front/src/modules/object-record/object-filter-dropdown/components/ObjectFilterDropdownFilterSelectMenuItem.tsx index 84f9addb44..d933f2f273 100644 --- a/packages/twenty-front/src/modules/object-record/object-filter-dropdown/components/ObjectFilterDropdownFilterSelectMenuItem.tsx +++ b/packages/twenty-front/src/modules/object-record/object-filter-dropdown/components/ObjectFilterDropdownFilterSelectMenuItem.tsx @@ -1,7 +1,7 @@ import { useAdvancedFilterDropdown } from '@/object-record/advanced-filter/hooks/useAdvancedFilterDropdown'; import { OBJECT_FILTER_DROPDOWN_ID } from '@/object-record/object-filter-dropdown/constants/ObjectFilterDropdownId'; import { useFilterDropdown } from '@/object-record/object-filter-dropdown/hooks/useFilterDropdown'; -import { useSelectFilter } from '@/object-record/object-filter-dropdown/hooks/useSelectFilter'; +import { useSelectFilterDefinitionUsedInDropdown } from '@/object-record/object-filter-dropdown/hooks/useSelectFilterDefinitionUsedInDropdown'; import { objectFilterDropdownFilterIsSelectedComponentState } from '@/object-record/object-filter-dropdown/states/objectFilterDropdownFilterIsSelectedComponentState'; import { objectFilterDropdownFirstLevelFilterDefinitionComponentState } from '@/object-record/object-filter-dropdown/states/objectFilterDropdownFirstLevelFilterDefinitionComponentState'; import { objectFilterDropdownIsSelectingCompositeFieldComponentState } from '@/object-record/object-filter-dropdown/states/objectFilterDropdownIsSelectingCompositeFieldComponentState'; @@ -25,7 +25,8 @@ export type ObjectFilterDropdownFilterSelectMenuItemProps = { export const ObjectFilterDropdownFilterSelectMenuItem = ({ filterDefinition, }: ObjectFilterDropdownFilterSelectMenuItemProps) => { - const { selectFilter } = useSelectFilter(); + const { selectFilterDefinitionUsedInDropdown } = + useSelectFilterDefinitionUsedInDropdown(); const [, setObjectFilterDropdownFirstLevelFilterDefinition] = useRecoilComponentStateV2( @@ -55,12 +56,8 @@ export const ObjectFilterDropdownFilterSelectMenuItem = ({ const isACompositeField = isCompositeField(filterDefinition.type); - const { - setFilterDefinitionUsedInDropdown, - setSelectedOperandInDropdown, - setObjectFilterDropdownSearchInput, - advancedFilterViewFilterIdState, - } = useFilterDropdown(); + const { setSelectedOperandInDropdown, advancedFilterViewFilterIdState } = + useFilterDropdown(); const setHotkeyScope = useSetHotkeyScope(); @@ -72,11 +69,14 @@ export const ObjectFilterDropdownFilterSelectMenuItem = ({ advancedFilterViewFilterId, ); - const handleSelectFilter = (availableFilterDefinition: FilterDefinition) => { + const handleSelectFilterDefinition = ( + availableFilterDefinition: FilterDefinition, + ) => { closeAdvancedFilterDropdown(); - selectFilter({ filterDefinition: availableFilterDefinition }); - setFilterDefinitionUsedInDropdown(availableFilterDefinition); + selectFilterDefinitionUsedInDropdown({ + filterDefinition: availableFilterDefinition, + }); if ( availableFilterDefinition.type === 'RELATION' || @@ -89,8 +89,6 @@ export const ObjectFilterDropdownFilterSelectMenuItem = ({ getOperandsForFilterDefinition(availableFilterDefinition)[0], ); - setObjectFilterDropdownSearchInput(''); - setObjectFilterDropdownFilterIsSelected(true); }; @@ -107,7 +105,7 @@ export const ObjectFilterDropdownFilterSelectMenuItem = ({ setObjectFilterDropdownFirstLevelFilterDefinition(filterDefinition); setObjectFilterDropdownIsSelectingCompositeField(true); } else { - handleSelectFilter(filterDefinition); + handleSelectFilterDefinition(filterDefinition); } }; diff --git a/packages/twenty-front/src/modules/object-record/object-filter-dropdown/components/ObjectFilterDropdownNumberInput.tsx b/packages/twenty-front/src/modules/object-record/object-filter-dropdown/components/ObjectFilterDropdownNumberInput.tsx index 38246cf53d..5222e61569 100644 --- a/packages/twenty-front/src/modules/object-record/object-filter-dropdown/components/ObjectFilterDropdownNumberInput.tsx +++ b/packages/twenty-front/src/modules/object-record/object-filter-dropdown/components/ObjectFilterDropdownNumberInput.tsx @@ -2,6 +2,7 @@ import { ChangeEvent, useCallback, useState } from 'react'; import { useRecoilValue } from 'recoil'; import { v4 } from 'uuid'; +import { useApplyRecordFilter } from '@/object-record/object-filter-dropdown/hooks/useApplyRecordFilter'; import { useFilterDropdown } from '@/object-record/object-filter-dropdown/hooks/useFilterDropdown'; import { DropdownMenuInput } from '@/ui/layout/dropdown/components/DropdownMenuInput'; @@ -10,8 +11,10 @@ export const ObjectFilterDropdownNumberInput = () => { selectedOperandInDropdownState, filterDefinitionUsedInDropdownState, selectedFilterState, - selectFilter, } = useFilterDropdown(); + + const { applyRecordFilter } = useApplyRecordFilter(); + const [hasFocused, setHasFocused] = useState(false); const filterDefinitionUsedInDropdown = useRecoilValue( @@ -48,8 +51,10 @@ export const ObjectFilterDropdownNumberInput = () => { placeholder={filterDefinitionUsedInDropdown.label} onChange={(event: ChangeEvent) => { const newValue = event.target.value; + setInputValue(newValue); - selectFilter?.({ + + applyRecordFilter({ id: selectedFilter?.id ? selectedFilter.id : v4(), fieldMetadataId: filterDefinitionUsedInDropdown.fieldMetadataId, value: newValue, diff --git a/packages/twenty-front/src/modules/object-record/object-filter-dropdown/components/ObjectFilterDropdownOperandSelect.tsx b/packages/twenty-front/src/modules/object-record/object-filter-dropdown/components/ObjectFilterDropdownOperandSelect.tsx index 3dfd6d6203..ba59dc97ea 100644 --- a/packages/twenty-front/src/modules/object-record/object-filter-dropdown/components/ObjectFilterDropdownOperandSelect.tsx +++ b/packages/twenty-front/src/modules/object-record/object-filter-dropdown/components/ObjectFilterDropdownOperandSelect.tsx @@ -1,6 +1,7 @@ import { useRecoilValue } from 'recoil'; import { v4 } from 'uuid'; +import { useApplyRecordFilter } from '@/object-record/object-filter-dropdown/hooks/useApplyRecordFilter'; import { useFilterDropdown } from '@/object-record/object-filter-dropdown/hooks/useFilterDropdown'; import { getInitialFilterValue } from '@/object-record/object-filter-dropdown/utils/getInitialFilterValue'; import { DropdownMenuItemsContainer } from '@/ui/layout/dropdown/components/DropdownMenuItemsContainer'; @@ -22,9 +23,10 @@ export const ObjectFilterDropdownOperandSelect = () => { filterDefinitionUsedInDropdownState, setSelectedOperandInDropdown, selectedFilterState, - selectFilter, } = useFilterDropdown(); + const { applyRecordFilter } = useApplyRecordFilter(); + const { closeDropdown } = useDropdown(); const filterDefinitionUsedInDropdown = useRecoilValue( @@ -49,7 +51,7 @@ export const ObjectFilterDropdownOperandSelect = () => { setSelectedOperandInDropdown(newOperand); if (isValuelessOperand && isDefined(filterDefinitionUsedInDropdown)) { - selectFilter?.({ + applyRecordFilter({ id: v4(), fieldMetadataId: filterDefinitionUsedInDropdown?.fieldMetadataId ?? '', displayValue: '', @@ -71,7 +73,7 @@ export const ObjectFilterDropdownOperandSelect = () => { selectedFilter.displayValue, ); - selectFilter?.({ + applyRecordFilter({ id: selectedFilter.id ? selectedFilter.id : v4(), fieldMetadataId: selectedFilter.fieldMetadataId, displayValue, diff --git a/packages/twenty-front/src/modules/object-record/object-filter-dropdown/components/ObjectFilterDropdownOptionSelect.tsx b/packages/twenty-front/src/modules/object-record/object-filter-dropdown/components/ObjectFilterDropdownOptionSelect.tsx index c409cdf006..0eb8035254 100644 --- a/packages/twenty-front/src/modules/object-record/object-filter-dropdown/components/ObjectFilterDropdownOptionSelect.tsx +++ b/packages/twenty-front/src/modules/object-record/object-filter-dropdown/components/ObjectFilterDropdownOptionSelect.tsx @@ -14,6 +14,7 @@ import { SelectableList } from '@/ui/layout/selectable-list/components/Selectabl import { useSelectableListStates } from '@/ui/layout/selectable-list/hooks/internal/useSelectableListStates'; import { useSelectableList } from '@/ui/layout/selectable-list/hooks/useSelectableList'; +import { useApplyRecordFilter } from '@/object-record/object-filter-dropdown/hooks/useApplyRecordFilter'; import { useScopedHotkeys } from '@/ui/utilities/hotkey/hooks/useScopedHotkeys'; import { MenuItem, MenuItemMultiSelect } from 'twenty-ui'; import { isDefined } from '~/utils/isDefined'; @@ -32,9 +33,10 @@ export const ObjectFilterDropdownOptionSelect = () => { selectedOperandInDropdownState, objectFilterDropdownSelectedOptionValuesState, selectedFilterState, - selectFilter, } = useFilterDropdown(); + const { applyRecordFilter } = useApplyRecordFilter(); + const { closeDropdown } = useDropdown(); const { selectedItemIdState } = useSelectableListStates({ @@ -128,7 +130,7 @@ export const ObjectFilterDropdownOptionSelect = () => { ? JSON.stringify(selectedOptions.map((option) => option.value)) : EMPTY_FILTER_VALUE; - selectFilter({ + applyRecordFilter({ id: selectedFilter?.id ? selectedFilter.id : v4(), definition: filterDefinitionUsedInDropdown, operand: selectedOperandInDropdown, diff --git a/packages/twenty-front/src/modules/object-record/object-filter-dropdown/components/ObjectFilterDropdownRatingInput.tsx b/packages/twenty-front/src/modules/object-record/object-filter-dropdown/components/ObjectFilterDropdownRatingInput.tsx index 95af2de52e..5982797053 100644 --- a/packages/twenty-front/src/modules/object-record/object-filter-dropdown/components/ObjectFilterDropdownRatingInput.tsx +++ b/packages/twenty-front/src/modules/object-record/object-filter-dropdown/components/ObjectFilterDropdownRatingInput.tsx @@ -1,6 +1,7 @@ import { useRecoilValue } from 'recoil'; import { v4 } from 'uuid'; +import { useApplyRecordFilter } from '@/object-record/object-filter-dropdown/hooks/useApplyRecordFilter'; import { useFilterDropdown } from '@/object-record/object-filter-dropdown/hooks/useFilterDropdown'; import { RATING_VALUES } from '@/object-record/record-field/meta-types/constants/RatingValues'; import { FieldRatingValue } from '@/object-record/record-field/types/FieldMetadata'; @@ -34,7 +35,6 @@ export const ObjectFilterDropdownRatingInput = () => { selectedOperandInDropdownState, filterDefinitionUsedInDropdownState, selectedFilterState, - selectFilter, } = useFilterDropdown(); const filterDefinitionUsedInDropdown = useRecoilValue( @@ -46,6 +46,8 @@ export const ObjectFilterDropdownRatingInput = () => { const selectedFilter = useRecoilValue(selectedFilterState); + const { applyRecordFilter } = useApplyRecordFilter(); + return ( filterDefinitionUsedInDropdown && selectedOperandInDropdown && ( @@ -57,7 +59,7 @@ export const ObjectFilterDropdownRatingInput = () => { return; } - selectFilter?.({ + applyRecordFilter?.({ id: selectedFilter?.id ? selectedFilter.id : v4(), fieldMetadataId: filterDefinitionUsedInDropdown.fieldMetadataId, value: convertFieldRatingValueToNumber(newValue), diff --git a/packages/twenty-front/src/modules/object-record/object-filter-dropdown/components/ObjectFilterDropdownRecordSelect.tsx b/packages/twenty-front/src/modules/object-record/object-filter-dropdown/components/ObjectFilterDropdownRecordSelect.tsx index 1bfb234f59..1c5046a30e 100644 --- a/packages/twenty-front/src/modules/object-record/object-filter-dropdown/components/ObjectFilterDropdownRecordSelect.tsx +++ b/packages/twenty-front/src/modules/object-record/object-filter-dropdown/components/ObjectFilterDropdownRecordSelect.tsx @@ -5,6 +5,7 @@ import { v4 } from 'uuid'; import { useObjectMetadataItem } from '@/object-metadata/hooks/useObjectMetadataItem'; import { ObjectFilterDropdownRecordPinnedItems } from '@/object-record/object-filter-dropdown/components/ObjectFilterDropdownRecordPinnedItems'; import { CURRENT_WORKSPACE_MEMBER_SELECTABLE_ITEM_ID } from '@/object-record/object-filter-dropdown/constants/CurrentWorkspaceMemberSelectableItemId'; +import { useApplyRecordFilter } from '@/object-record/object-filter-dropdown/hooks/useApplyRecordFilter'; import { useFilterDropdown } from '@/object-record/object-filter-dropdown/hooks/useFilterDropdown'; import { RelationPickerHotkeyScope } from '@/object-record/relation-picker/types/RelationPickerHotkeyScope'; import { MultipleSelectDropdown } from '@/object-record/select/components/MultipleSelectDropdown'; @@ -37,9 +38,10 @@ export const ObjectFilterDropdownRecordSelect = ({ selectedOperandInDropdownState, selectedFilterState, objectFilterDropdownSelectedRecordIdsState, - selectFilter, } = useFilterDropdown(); + const { applyRecordFilter } = useApplyRecordFilter(viewComponentId); + const { currentViewWithCombinedFiltersAndSorts } = useGetCurrentView(viewComponentId); @@ -187,7 +189,7 @@ export const ObjectFilterDropdownRecordSelect = ({ const filterId = viewFilter?.id ?? fieldId; - selectFilter({ + applyRecordFilter({ id: selectedFilter?.id ? selectedFilter.id : filterId, definition: filterDefinitionUsedInDropdown, operand: selectedOperandInDropdown, diff --git a/packages/twenty-front/src/modules/object-record/object-filter-dropdown/components/ObjectFilterDropdownSourceSelect.tsx b/packages/twenty-front/src/modules/object-record/object-filter-dropdown/components/ObjectFilterDropdownSourceSelect.tsx index cb46def5c7..b0fac7b094 100644 --- a/packages/twenty-front/src/modules/object-record/object-filter-dropdown/components/ObjectFilterDropdownSourceSelect.tsx +++ b/packages/twenty-front/src/modules/object-record/object-filter-dropdown/components/ObjectFilterDropdownSourceSelect.tsx @@ -2,6 +2,7 @@ import { useState } from 'react'; import { useRecoilValue } from 'recoil'; import { v4 } from 'uuid'; +import { useApplyRecordFilter } from '@/object-record/object-filter-dropdown/hooks/useApplyRecordFilter'; import { useFilterDropdown } from '@/object-record/object-filter-dropdown/hooks/useFilterDropdown'; import { getActorSourceMultiSelectOptions } from '@/object-record/object-filter-dropdown/utils/getActorSourceMultiSelectOptions'; import { RelationPickerHotkeyScope } from '@/object-record/relation-picker/types/RelationPickerHotkeyScope'; @@ -29,10 +30,11 @@ export const ObjectFilterDropdownSourceSelect = ({ selectedFilterState, setObjectFilterDropdownSelectedRecordIds, objectFilterDropdownSelectedRecordIdsState, - selectFilter, emptyFilterButKeepDefinition, } = useFilterDropdown(); + const { applyRecordFilter } = useApplyRecordFilter(viewComponentId); + const { deleteCombinedViewFilter } = useDeleteCombinedViewFilters(viewComponentId); @@ -108,7 +110,7 @@ export const ObjectFilterDropdownSourceSelect = ({ const filterId = viewFilter?.id ?? fieldId; - selectFilter({ + applyRecordFilter({ id: selectedFilter?.id ? selectedFilter.id : filterId, definition: filterDefinitionUsedInDropdown, operand: selectedOperandInDropdown || ViewFilterOperand.Is, diff --git a/packages/twenty-front/src/modules/object-record/object-filter-dropdown/components/ObjectFilterDropdownTextSearchInput.tsx b/packages/twenty-front/src/modules/object-record/object-filter-dropdown/components/ObjectFilterDropdownTextSearchInput.tsx index b6508323bb..9f7c13af76 100644 --- a/packages/twenty-front/src/modules/object-record/object-filter-dropdown/components/ObjectFilterDropdownTextSearchInput.tsx +++ b/packages/twenty-front/src/modules/object-record/object-filter-dropdown/components/ObjectFilterDropdownTextSearchInput.tsx @@ -2,6 +2,7 @@ import { ChangeEvent, useCallback, useState } from 'react'; import { useRecoilValue } from 'recoil'; import { v4 } from 'uuid'; +import { useApplyRecordFilter } from '@/object-record/object-filter-dropdown/hooks/useApplyRecordFilter'; import { useFilterDropdown } from '@/object-record/object-filter-dropdown/hooks/useFilterDropdown'; import { DropdownMenuSearchInput } from '@/ui/layout/dropdown/components/DropdownMenuSearchInput'; @@ -12,7 +13,6 @@ export const ObjectFilterDropdownTextSearchInput = () => { objectFilterDropdownSearchInputState, setObjectFilterDropdownSearchInput, selectedFilterState, - selectFilter, } = useFilterDropdown(); const [filterId] = useState(v4()); @@ -29,6 +29,8 @@ export const ObjectFilterDropdownTextSearchInput = () => { ); const selectedFilter = useRecoilValue(selectedFilterState); + const { applyRecordFilter } = useApplyRecordFilter(); + const handleInputRef = useCallback( (node: HTMLInputElement | null) => { if (Boolean(node) && !hasFocused) { @@ -51,7 +53,7 @@ export const ObjectFilterDropdownTextSearchInput = () => { onChange={(event: ChangeEvent) => { setObjectFilterDropdownSearchInput(event.target.value); - selectFilter?.({ + applyRecordFilter({ id: selectedFilter?.id ?? filterId, fieldMetadataId: filterDefinitionUsedInDropdown.fieldMetadataId, value: event.target.value, diff --git a/packages/twenty-front/src/modules/object-record/object-filter-dropdown/hooks/__tests__/useFilterDropdown.test.tsx b/packages/twenty-front/src/modules/object-record/object-filter-dropdown/hooks/__tests__/useFilterDropdown.test.tsx index a3007acdcc..1433c97631 100644 --- a/packages/twenty-front/src/modules/object-record/object-filter-dropdown/hooks/__tests__/useFilterDropdown.test.tsx +++ b/packages/twenty-front/src/modules/object-record/object-filter-dropdown/hooks/__tests__/useFilterDropdown.test.tsx @@ -2,6 +2,7 @@ import { expect } from '@storybook/test'; import { act, renderHook, waitFor } from '@testing-library/react'; import { RecoilRoot, useRecoilState } from 'recoil'; +import { useApplyRecordFilter } from '@/object-record/object-filter-dropdown/hooks/useApplyRecordFilter'; import { useFilterDropdown } from '@/object-record/object-filter-dropdown/hooks/useFilterDropdown'; import { useFilterDropdownStates } from '@/object-record/object-filter-dropdown/hooks/useFilterDropdownStates'; import { Filter } from '@/object-record/object-filter-dropdown/types/Filter'; @@ -261,19 +262,26 @@ describe('useFilterDropdown', () => { it('should reset filter', async () => { const { result } = renderHook(() => { - const { resetFilter, selectFilter } = useFilterDropdown({ + const { resetFilter } = useFilterDropdown({ filterDropdownId, }); + const { applyRecordFilter } = useApplyRecordFilter(filterDropdownId); + const { selectedFilterState } = useFilterDropdownStates(filterDropdownId); const [selectedFilter, setSelectedFilter] = useRecoilState(selectedFilterState); - return { selectedFilter, setSelectedFilter, selectFilter, resetFilter }; + return { + selectedFilter, + setSelectedFilter, + applyRecordFilter, + resetFilter, + }; }, renderHookConfig); act(() => { - result.current.selectFilter(mockFilter); + result.current.applyRecordFilter(mockFilter); }); await waitFor(() => { @@ -291,12 +299,13 @@ describe('useFilterDropdown', () => { it('should call onFilterSelect when a filter option is set', async () => { const { result } = renderHook(() => { - const { selectFilter } = useFilterDropdown({ filterDropdownId }); + const { applyRecordFilter } = useApplyRecordFilter(filterDropdownId); + const { onFilterSelectState } = useFilterDropdownStates(filterDropdownId); const [onFilterSelect, setOnFilterSelect] = useRecoilState(onFilterSelectState); - return { onFilterSelect, setOnFilterSelect, selectFilter }; + return { onFilterSelect, setOnFilterSelect, applyRecordFilter }; }, renderHookConfig); const onFilterSelectMock = jest.fn(); @@ -304,7 +313,7 @@ describe('useFilterDropdown', () => { act(() => { result.current.setOnFilterSelect(onFilterSelectMock); - result.current.selectFilter(mockFilter); + result.current.applyRecordFilter(mockFilter); }); await waitFor(() => { diff --git a/packages/twenty-front/src/modules/object-record/object-filter-dropdown/hooks/useApplyRecordFilter.ts b/packages/twenty-front/src/modules/object-record/object-filter-dropdown/hooks/useApplyRecordFilter.ts new file mode 100644 index 0000000000..cc19f836a5 --- /dev/null +++ b/packages/twenty-front/src/modules/object-record/object-filter-dropdown/hooks/useApplyRecordFilter.ts @@ -0,0 +1,48 @@ +import { onFilterSelectComponentState } from '@/object-record/object-filter-dropdown/states/onFilterSelectComponentState'; +import { selectedFilterComponentState } from '@/object-record/object-filter-dropdown/states/selectedFilterComponentState'; +import { Filter } from '@/object-record/object-filter-dropdown/types/Filter'; +import { getSnapshotValue } from '@/ui/utilities/recoil-scope/utils/getSnapshotValue'; +import { useRecoilComponentCallbackStateV2 } from '@/ui/utilities/state/component-state/hooks/useRecoilComponentCallbackStateV2'; +import { useUpsertCombinedViewFilters } from '@/views/hooks/useUpsertCombinedViewFilters'; +import { useRecoilCallback } from 'recoil'; +import { isDefined } from 'twenty-ui'; + +export const useApplyRecordFilter = (componentInstanceId?: string) => { + const { upsertCombinedViewFilter } = useUpsertCombinedViewFilters(); + const selectedFilterCallbackState = useRecoilComponentCallbackStateV2( + selectedFilterComponentState, + componentInstanceId, + ); + + const onFilterSelectCallbackState = useRecoilComponentCallbackStateV2( + onFilterSelectComponentState, + componentInstanceId, + ); + + const applyRecordFilter = useRecoilCallback( + ({ set, snapshot }) => + (filter: Filter | null) => { + set(selectedFilterCallbackState, filter); + + const onFilterSelect = getSnapshotValue( + snapshot, + onFilterSelectCallbackState, + ); + + if (isDefined(filter)) { + upsertCombinedViewFilter(filter); + } + + onFilterSelect?.(filter); + }, + [ + selectedFilterCallbackState, + onFilterSelectCallbackState, + upsertCombinedViewFilter, + ], + ); + + return { + applyRecordFilter, + }; +}; diff --git a/packages/twenty-front/src/modules/object-record/object-filter-dropdown/hooks/useFilterDropdown.ts b/packages/twenty-front/src/modules/object-record/object-filter-dropdown/hooks/useFilterDropdown.ts index df5acd6765..fe36bb1191 100644 --- a/packages/twenty-front/src/modules/object-record/object-filter-dropdown/hooks/useFilterDropdown.ts +++ b/packages/twenty-front/src/modules/object-record/object-filter-dropdown/hooks/useFilterDropdown.ts @@ -1,16 +1,12 @@ import { useRecoilCallback, useSetRecoilState } from 'recoil'; import { useFilterDropdownStates } from '@/object-record/object-filter-dropdown/hooks/useFilterDropdownStates'; -import { getSnapshotValue } from '@/ui/utilities/recoil-scope/utils/getSnapshotValue'; import { ObjectFilterDropdownComponentInstanceContext } from '@/object-record/object-filter-dropdown/states/contexts/ObjectFilterDropdownComponentInstanceContext'; import { objectFilterDropdownFilterIsSelectedComponentState } from '@/object-record/object-filter-dropdown/states/objectFilterDropdownFilterIsSelectedComponentState'; import { objectFilterDropdownIsSelectingCompositeFieldComponentState } from '@/object-record/object-filter-dropdown/states/objectFilterDropdownIsSelectingCompositeFieldComponentState'; import { useAvailableComponentInstanceIdOrThrow } from '@/ui/utilities/state/component-state/hooks/useAvailableComponentInstanceIdOrThrow'; import { useRecoilComponentCallbackStateV2 } from '@/ui/utilities/state/component-state/hooks/useRecoilComponentCallbackStateV2'; -import { useUpsertCombinedViewFilters } from '@/views/hooks/useUpsertCombinedViewFilters'; -import { isDefined } from 'twenty-ui'; -import { Filter } from '../types/Filter'; type UseFilterDropdownProps = { filterDropdownId?: string; @@ -34,23 +30,6 @@ export const useFilterDropdown = (props?: UseFilterDropdownProps) => { advancedFilterViewFilterIdState, } = useFilterDropdownStates(componentInstanceId); - const { upsertCombinedViewFilter } = useUpsertCombinedViewFilters(); - - const selectFilter = useRecoilCallback( - ({ set, snapshot }) => - (filter: Filter | null) => { - set(selectedFilterState, filter); - const onFilterSelect = getSnapshotValue(snapshot, onFilterSelectState); - - if (isDefined(filter)) { - upsertCombinedViewFilter(filter); - } - - onFilterSelect?.(filter); - }, - [selectedFilterState, onFilterSelectState, upsertCombinedViewFilter], - ); - const emptyFilterButKeepDefinition = useRecoilCallback( ({ set }) => () => { @@ -129,7 +108,6 @@ export const useFilterDropdown = (props?: UseFilterDropdownProps) => { return { componentInstanceId, - selectFilter, resetFilter, setSelectedFilter, setSelectedOperandInDropdown, diff --git a/packages/twenty-front/src/modules/object-record/object-filter-dropdown/hooks/useSelectFilter.ts b/packages/twenty-front/src/modules/object-record/object-filter-dropdown/hooks/useSelectFilterDefinitionUsedInDropdown.ts similarity index 85% rename from packages/twenty-front/src/modules/object-record/object-filter-dropdown/hooks/useSelectFilter.ts rename to packages/twenty-front/src/modules/object-record/object-filter-dropdown/hooks/useSelectFilterDefinitionUsedInDropdown.ts index af287141ea..d919c7b203 100644 --- a/packages/twenty-front/src/modules/object-record/object-filter-dropdown/hooks/useSelectFilter.ts +++ b/packages/twenty-front/src/modules/object-record/object-filter-dropdown/hooks/useSelectFilterDefinitionUsedInDropdown.ts @@ -1,3 +1,4 @@ +import { useApplyRecordFilter } from '@/object-record/object-filter-dropdown/hooks/useApplyRecordFilter'; import { useFilterDropdown } from '@/object-record/object-filter-dropdown/hooks/useFilterDropdown'; import { FilterDefinition } from '@/object-record/object-filter-dropdown/types/FilterDefinition'; import { getInitialFilterValue } from '@/object-record/object-filter-dropdown/utils/getInitialFilterValue'; @@ -12,12 +13,11 @@ type SelectFilterParams = { filterDefinition: FilterDefinition; }; -export const useSelectFilter = () => { +export const useSelectFilterDefinitionUsedInDropdown = () => { const { setFilterDefinitionUsedInDropdown, setSelectedOperandInDropdown, setObjectFilterDropdownSearchInput, - selectFilter: filterDropdownSelectFilter, advancedFilterViewFilterGroupIdState, advancedFilterViewFilterIdState, } = useFilterDropdown(); @@ -31,7 +31,11 @@ export const useSelectFilter = () => { const setHotkeyScope = useSetHotkeyScope(); - const selectFilter = ({ filterDefinition }: SelectFilterParams) => { + const { applyRecordFilter } = useApplyRecordFilter(); + + const selectFilterDefinitionUsedInDropdown = ({ + filterDefinition, + }: SelectFilterParams) => { setFilterDefinitionUsedInDropdown(filterDefinition); if ( @@ -53,7 +57,7 @@ export const useSelectFilter = () => { const isAdvancedFilter = isDefined(advancedFilterViewFilterId); if (isAdvancedFilter || value !== '') { - filterDropdownSelectFilter({ + applyRecordFilter({ id: advancedFilterViewFilterId ?? v4(), fieldMetadataId: filterDefinition.fieldMetadataId, displayValue, @@ -68,6 +72,6 @@ export const useSelectFilter = () => { }; return { - selectFilter, + selectFilterDefinitionUsedInDropdown, }; };