From 5946b37712877beb4643d19a79971f3c95eed868 Mon Sep 17 00:00:00 2001 From: Lucas Bordeau Date: Fri, 2 May 2025 17:28:45 +0200 Subject: [PATCH] Refactored object filter dropdown input state management (#11838) This PR refactors the generic module object dropdown filter input. We have multiple components for each filter type and each one was using selectedFilterState and the applyRecordFilter hook to read and set its value. The main issue was that each component was forced to pass every property of a RecordFilter to applyRecordFilter to only modify the value property, thus creating a lot of unnecessary dependencies and tight coupling between every component and hook that used the record filters. Now we have each component only reading from a new objectFilterDropdownCurrentRecordFilterComponentState, scoped to a ObjectFilterDropdownComponentInstanceContext, thus whether we're in a view bar dropdown, an editable filter chip dropdown or an advanced filter dropdown, we know where to read the filter value from. This component state might even be simplified by only storing the record filter id, thus avoiding having to synchronize this state with its counterpart in currentRecordFilterComponentState, but we should try after the main refactor effort, as those two states aren't in the same instance context. We implement a new applyObjectFilterDropdownFilterValue hook to handle the value setting from an object filter dropdown input component. There's also a new useApplyObjectFilterDropdownOperand for doing the same but for operand. Another important thing that had to be done to keep a synchronous code path was to set the states of each advanced filter row at the advanced filter dropdown onOpen event, using useSetAdvancedFilterDropdownStates. Finally we remove : useApplyRecordFilter, useSelectFilterUsedInDropdown and selectedFilterComponentState which were making all of this zone difficult to work with. Closes https://github.com/twentyhq/core-team-issues/issues/718 Closes https://github.com/twentyhq/core-team-issues/issues/720 --- .../AdvancedFilterDropdownDateInput.tsx | 122 ------------------ .../AdvancedFilterDropdownFilterInput.tsx | 4 +- .../AdvancedFilterDropdownNumberInput.tsx | 40 ++---- .../AdvancedFilterDropdownTextInput.tsx | 18 +-- .../components/AdvancedFilterValueInput.tsx | 17 +++ ...SelectFieldUsedInAdvancedFilterDropdown.ts | 22 +++- ...eSetAdvancedFilterDropdownAllRowsStates.ts | 98 ++++++++++++++ ...rdFilterUsedInAdvancedFilterDropdownRow.ts | 4 +- .../ObjectFilterDropdownBooleanSelect.tsx | 65 ++-------- .../ObjectFilterDropdownCurrencySelect.tsx | 102 ++++----------- .../ObjectFilterDropdownDateInput.tsx | 67 ++++------ ...jectFilterDropdownFilterSelectMenuItem.tsx | 7 - .../ObjectFilterDropdownNumberInput.tsx | 77 ++++------- .../ObjectFilterDropdownOperandSelect.tsx | 72 +---------- .../ObjectFilterDropdownOptionSelect.tsx | 74 ++++------- .../ObjectFilterDropdownRatingInput.tsx | 74 ++++------- .../ObjectFilterDropdownRecordSelect.tsx | 74 ++--------- .../ObjectFilterDropdownSourceSelect.tsx | 112 ++++------------ .../ObjectFilterDropdownSubFieldSelect.tsx | 7 - .../ObjectFilterDropdownTextInput.tsx | 12 +- .../ObjectFilterDropdownTextSearchInput.tsx | 80 ------------ ...useApplyObjectFilterDropdownFilterValue.ts | 9 +- .../useApplyObjectFilterDropdownOperand.ts | 79 ++++++++++++ .../hooks/useEmptyRecordFilter.ts | 15 ++- .../hooks/useResetFilterDropdown.ts | 8 -- .../hooks/useSelectFilterUsedInDropdown.ts | 97 -------------- ...UpsertObjectFilterDropdownCurrentFilter.ts | 6 - .../states/onFilterSelectComponentState.ts | 11 -- .../states/selectedFilterComponentState.ts | 11 -- .../hooks/useApplyRecordFilter.ts | 32 ----- .../useOpenRecordFilterChipFromTableHeader.ts | 9 -- .../components/RelativeDatePickerHeader.tsx | 3 + .../AdvancedFilterDropdownButton.tsx | 9 ++ .../components/ViewBarFilterDropdown.tsx | 14 +- .../useSetEditableFilterChipDropdownStates.ts | 8 -- 35 files changed, 444 insertions(+), 1015 deletions(-) delete mode 100644 packages/twenty-front/src/modules/object-record/advanced-filter/components/AdvancedFilterDropdownDateInput.tsx create mode 100644 packages/twenty-front/src/modules/object-record/advanced-filter/hooks/useSetAdvancedFilterDropdownAllRowsStates.ts delete mode 100644 packages/twenty-front/src/modules/object-record/object-filter-dropdown/components/ObjectFilterDropdownTextSearchInput.tsx create mode 100644 packages/twenty-front/src/modules/object-record/object-filter-dropdown/hooks/useApplyObjectFilterDropdownOperand.ts delete mode 100644 packages/twenty-front/src/modules/object-record/object-filter-dropdown/hooks/useSelectFilterUsedInDropdown.ts delete mode 100644 packages/twenty-front/src/modules/object-record/object-filter-dropdown/states/onFilterSelectComponentState.ts delete mode 100644 packages/twenty-front/src/modules/object-record/object-filter-dropdown/states/selectedFilterComponentState.ts delete mode 100644 packages/twenty-front/src/modules/object-record/record-filter/hooks/useApplyRecordFilter.ts diff --git a/packages/twenty-front/src/modules/object-record/advanced-filter/components/AdvancedFilterDropdownDateInput.tsx b/packages/twenty-front/src/modules/object-record/advanced-filter/components/AdvancedFilterDropdownDateInput.tsx deleted file mode 100644 index 1a3f4005f..000000000 --- a/packages/twenty-front/src/modules/object-record/advanced-filter/components/AdvancedFilterDropdownDateInput.tsx +++ /dev/null @@ -1,122 +0,0 @@ -import { v4 } from 'uuid'; - -import { getFilterTypeFromFieldType } from '@/object-metadata/utils/formatFieldMetadataItemsAsFilterDefinitions'; -import { fieldMetadataItemUsedInDropdownComponentSelector } from '@/object-record/object-filter-dropdown/states/fieldMetadataItemUsedInDropdownComponentSelector'; -import { selectedFilterComponentState } from '@/object-record/object-filter-dropdown/states/selectedFilterComponentState'; -import { selectedOperandInDropdownComponentState } from '@/object-record/object-filter-dropdown/states/selectedOperandInDropdownComponentState'; -import { getRelativeDateDisplayValue } from '@/object-record/object-filter-dropdown/utils/getRelativeDateDisplayValue'; -import { useApplyRecordFilter } from '@/object-record/record-filter/hooks/useApplyRecordFilter'; -import { DateTimePicker } from '@/ui/input/components/internal/date/components/InternalDatePicker'; -import { useRecoilComponentValueV2 } from '@/ui/utilities/state/component-state/hooks/useRecoilComponentValueV2'; -import { ViewFilterOperand } from '@/views/types/ViewFilterOperand'; -import { computeVariableDateViewFilterValue } from '@/views/view-filter-value/utils/computeVariableDateViewFilterValue'; -import { - resolveDateViewFilterValue, - VariableDateViewFilterValueDirection, - VariableDateViewFilterValueUnit, -} from '@/views/view-filter-value/utils/resolveDateViewFilterValue'; -import { useState } from 'react'; -import { isDefined } from 'twenty-shared/utils'; -import { FieldMetadataType } from '~/generated-metadata/graphql'; - -export const AdvancedFilterDropdownDateInput = () => { - const fieldMetadataItemUsedInDropdown = useRecoilComponentValueV2( - fieldMetadataItemUsedInDropdownComponentSelector, - ); - - const selectedOperandInDropdown = useRecoilComponentValueV2( - selectedOperandInDropdownComponentState, - ); - - const selectedFilter = useRecoilComponentValueV2( - selectedFilterComponentState, - ); - - const { applyRecordFilter } = useApplyRecordFilter(); - - const initialFilterValue = selectedFilter - ? resolveDateViewFilterValue(selectedFilter) - : null; - const [internalDate, setInternalDate] = useState( - initialFilterValue instanceof Date ? initialFilterValue : null, - ); - - const isDateTimeInput = - fieldMetadataItemUsedInDropdown?.type === FieldMetadataType.DATE_TIME; - - const handleAbsoluteDateChange = (newDate: Date | null) => { - setInternalDate(newDate); - - if (!fieldMetadataItemUsedInDropdown || !selectedOperandInDropdown) return; - - const newDisplayValue = isDefined(newDate) - ? newDate.toLocaleDateString() - : ''; - - applyRecordFilter({ - id: selectedFilter?.id ? selectedFilter.id : v4(), - fieldMetadataId: fieldMetadataItemUsedInDropdown.id, - value: newDate?.toISOString() ?? '', - operand: selectedOperandInDropdown, - displayValue: newDisplayValue, - recordFilterGroupId: selectedFilter?.recordFilterGroupId, - positionInRecordFilterGroup: selectedFilter?.positionInRecordFilterGroup, - type: getFilterTypeFromFieldType(fieldMetadataItemUsedInDropdown.type), - label: fieldMetadataItemUsedInDropdown.label, - }); - }; - - const handleRelativeDateChange = ( - relativeDate: { - direction: VariableDateViewFilterValueDirection; - amount?: number; - unit: VariableDateViewFilterValueUnit; - } | null, - ) => { - if (!fieldMetadataItemUsedInDropdown || !selectedOperandInDropdown) return; - - const value = relativeDate - ? computeVariableDateViewFilterValue( - relativeDate.direction, - relativeDate.amount, - relativeDate.unit, - ) - : ''; - - applyRecordFilter({ - id: selectedFilter?.id ? selectedFilter.id : v4(), - fieldMetadataId: fieldMetadataItemUsedInDropdown.id, - value, - operand: selectedOperandInDropdown, - displayValue: getRelativeDateDisplayValue(relativeDate), - recordFilterGroupId: selectedFilter?.recordFilterGroupId, - positionInRecordFilterGroup: selectedFilter?.positionInRecordFilterGroup, - type: getFilterTypeFromFieldType(fieldMetadataItemUsedInDropdown.type), - label: fieldMetadataItemUsedInDropdown.label, - }); - }; - - const isRelativeOperand = - selectedOperandInDropdown === ViewFilterOperand.IsRelative; - - const resolvedValue = selectedFilter - ? resolveDateViewFilterValue(selectedFilter) - : null; - - const relativeDate = - resolvedValue && !(resolvedValue instanceof Date) - ? resolvedValue - : undefined; - - return ( - - ); -}; diff --git a/packages/twenty-front/src/modules/object-record/advanced-filter/components/AdvancedFilterDropdownFilterInput.tsx b/packages/twenty-front/src/modules/object-record/advanced-filter/components/AdvancedFilterDropdownFilterInput.tsx index 9c2de5a91..7afb23afb 100644 --- a/packages/twenty-front/src/modules/object-record/advanced-filter/components/AdvancedFilterDropdownFilterInput.tsx +++ b/packages/twenty-front/src/modules/object-record/advanced-filter/components/AdvancedFilterDropdownFilterInput.tsx @@ -5,9 +5,9 @@ import { ObjectFilterDropdownSearchInput } from '@/object-record/object-filter-d import { ObjectFilterDropdownSourceSelect } from '@/object-record/object-filter-dropdown/components/ObjectFilterDropdownSourceSelect'; import { DropdownMenuSeparator } from '@/ui/layout/dropdown/components/DropdownMenuSeparator'; -import { AdvancedFilterDropdownDateInput } from '@/object-record/advanced-filter/components/AdvancedFilterDropdownDateInput'; import { ObjectFilterDropdownBooleanSelect } from '@/object-record/object-filter-dropdown/components/ObjectFilterDropdownBooleanSelect'; import { ObjectFilterDropdownCurrencySelect } from '@/object-record/object-filter-dropdown/components/ObjectFilterDropdownCurrencySelect'; +import { ObjectFilterDropdownDateInput } from '@/object-record/object-filter-dropdown/components/ObjectFilterDropdownDateInput'; import { ObjectFilterDropdownTextInput } from '@/object-record/object-filter-dropdown/components/ObjectFilterDropdownTextInput'; import { DATE_FILTER_TYPES } from '@/object-record/object-filter-dropdown/constants/DateFilterTypes'; import { subFieldNameUsedInDropdownComponentState } from '@/object-record/object-filter-dropdown/states/subFieldNameUsedInDropdownComponentState'; @@ -41,7 +41,7 @@ export const AdvancedFilterDropdownFilterInput = ({ <> {filterType === 'RATING' && } {DATE_FILTER_TYPES.includes(filterType) && ( - + )} {filterType === 'RELATION' && ( <> diff --git a/packages/twenty-front/src/modules/object-record/advanced-filter/components/AdvancedFilterDropdownNumberInput.tsx b/packages/twenty-front/src/modules/object-record/advanced-filter/components/AdvancedFilterDropdownNumberInput.tsx index e8cf61cae..d20eade9c 100644 --- a/packages/twenty-front/src/modules/object-record/advanced-filter/components/AdvancedFilterDropdownNumberInput.tsx +++ b/packages/twenty-front/src/modules/object-record/advanced-filter/components/AdvancedFilterDropdownNumberInput.tsx @@ -1,13 +1,9 @@ -import { useState } from 'react'; - -import { getFilterTypeFromFieldType } from '@/object-metadata/utils/formatFieldMetadataItemsAsFilterDefinitions'; +import { useApplyObjectFilterDropdownFilterValue } from '@/object-record/object-filter-dropdown/hooks/useApplyObjectFilterDropdownFilterValue'; +import { useObjectFilterDropdownFilterValue } from '@/object-record/object-filter-dropdown/hooks/useObjectFilterDropdownFilterValue'; import { fieldMetadataItemUsedInDropdownComponentSelector } from '@/object-record/object-filter-dropdown/states/fieldMetadataItemUsedInDropdownComponentSelector'; -import { selectedFilterComponentState } from '@/object-record/object-filter-dropdown/states/selectedFilterComponentState'; import { selectedOperandInDropdownComponentState } from '@/object-record/object-filter-dropdown/states/selectedOperandInDropdownComponentState'; -import { useApplyRecordFilter } from '@/object-record/record-filter/hooks/useApplyRecordFilter'; import { TextInputV2 } from '@/ui/input/components/TextInputV2'; import { useRecoilComponentValueV2 } from '@/ui/utilities/state/component-state/hooks/useRecoilComponentValueV2'; -import { v4 } from 'uuid'; export const AdvancedFilterDropdownNumberInput = () => { const selectedOperandInDropdown = useRecoilComponentValueV2( @@ -18,34 +14,14 @@ export const AdvancedFilterDropdownNumberInput = () => { fieldMetadataItemUsedInDropdownComponentSelector, ); - const selectedFilter = useRecoilComponentValueV2( - selectedFilterComponentState, - ); + const { objectFilterDropdownFilterValue } = + useObjectFilterDropdownFilterValue(); - const { applyRecordFilter } = useApplyRecordFilter(); - - const [inputValue, setInputValue] = useState( - () => selectedFilter?.value || '', - ); + const { applyObjectFilterDropdownFilterValue } = + useApplyObjectFilterDropdownFilterValue(); const handleChange = (newValue: string) => { - if (!fieldMetadataItemUsedInDropdown || !selectedOperandInDropdown) { - return; - } - - setInputValue(newValue); - - applyRecordFilter({ - id: selectedFilter?.id ? selectedFilter.id : v4(), - fieldMetadataId: fieldMetadataItemUsedInDropdown?.id ?? '', - value: newValue, - operand: selectedOperandInDropdown, - displayValue: newValue, - type: getFilterTypeFromFieldType(fieldMetadataItemUsedInDropdown.type), - label: fieldMetadataItemUsedInDropdown.label, - recordFilterGroupId: selectedFilter?.recordFilterGroupId, - positionInRecordFilterGroup: selectedFilter?.positionInRecordFilterGroup, - }); + applyObjectFilterDropdownFilterValue(newValue); }; if (!selectedOperandInDropdown || !fieldMetadataItemUsedInDropdown) { @@ -54,7 +30,7 @@ export const AdvancedFilterDropdownNumberInput = () => { return ( { - const { applyRecordFilter } = useApplyRecordFilter(); + const { applyObjectFilterDropdownFilterValue } = + useApplyObjectFilterDropdownFilterValue(); const handleChange = (newValue: string) => { - applyRecordFilter({ - id: recordFilter.id, - fieldMetadataId: recordFilter.fieldMetadataId, - value: newValue, - operand: recordFilter.operand, - displayValue: newValue, - type: recordFilter.type, - label: recordFilter.label, - recordFilterGroupId: recordFilter.recordFilterGroupId, - positionInRecordFilterGroup: recordFilter.positionInRecordFilterGroup, - subFieldName: recordFilter.subFieldName, - }); + applyObjectFilterDropdownFilterValue(newValue); }; return ( diff --git a/packages/twenty-front/src/modules/object-record/advanced-filter/components/AdvancedFilterValueInput.tsx b/packages/twenty-front/src/modules/object-record/advanced-filter/components/AdvancedFilterValueInput.tsx index bd482bfab..9327afb69 100644 --- a/packages/twenty-front/src/modules/object-record/advanced-filter/components/AdvancedFilterValueInput.tsx +++ b/packages/twenty-front/src/modules/object-record/advanced-filter/components/AdvancedFilterValueInput.tsx @@ -4,6 +4,8 @@ import { AdvancedFilterValueInputDropdownButtonClickableSelect } from '@/object- import { DEFAULT_ADVANCED_FILTER_DROPDOWN_OFFSET } from '@/object-record/advanced-filter/constants/DefaultAdvancedFilterDropdownOffset'; import { NUMBER_FILTER_TYPES } from '@/object-record/object-filter-dropdown/constants/NumberFilterTypes'; import { TEXT_FILTER_TYPES } from '@/object-record/object-filter-dropdown/constants/TextFilterTypes'; +import { fieldMetadataItemIdUsedInDropdownComponentState } from '@/object-record/object-filter-dropdown/states/fieldMetadataItemIdUsedInDropdownComponentState'; +import { objectFilterDropdownCurrentRecordFilterComponentState } from '@/object-record/object-filter-dropdown/states/objectFilterDropdownCurrentRecordFilterComponentState'; import { objectFilterDropdownSearchInputComponentState } from '@/object-record/object-filter-dropdown/states/objectFilterDropdownSearchInputComponentState'; import { configurableViewFilterOperands } from '@/object-record/object-filter-dropdown/utils/configurableViewFilterOperands'; import { isExpectedSubFieldName } from '@/object-record/object-filter-dropdown/utils/isExpectedSubFieldName'; @@ -44,6 +46,15 @@ export const AdvancedFilterValueInput = ({ objectFilterDropdownSearchInputComponentState, ); + const setFieldMetadataItemIdUsedInDropdown = useSetRecoilComponentStateV2( + fieldMetadataItemIdUsedInDropdownComponentState, + ); + + const setObjectFilterDropdownCurrentRecordFilter = + useSetRecoilComponentStateV2( + objectFilterDropdownCurrentRecordFilterComponentState, + ); + const operandHasNoInput = recordFilter && !configurableViewFilterOperands.has(recordFilter.operand); @@ -55,6 +66,11 @@ export const AdvancedFilterValueInput = ({ setObjectFilterDropdownSearchInput(''); }; + const handleFilterValueDropdownOpen = () => { + setObjectFilterDropdownCurrentRecordFilter(recordFilter); + setFieldMetadataItemIdUsedInDropdown(recordFilter.fieldMetadataId); + }; + const filterType = recordFilter.type; const dropdownContentOffset = @@ -98,6 +114,7 @@ export const AdvancedFilterValueInput = ({ dropdownPlacement="bottom-start" dropdownWidth={280} onClose={handleFilterValueDropdownClose} + onOpen={handleFilterValueDropdownOpen} /> )} diff --git a/packages/twenty-front/src/modules/object-record/advanced-filter/hooks/useSelectFieldUsedInAdvancedFilterDropdown.ts b/packages/twenty-front/src/modules/object-record/advanced-filter/hooks/useSelectFieldUsedInAdvancedFilterDropdown.ts index 4c97d3312..a913d88b9 100644 --- a/packages/twenty-front/src/modules/object-record/advanced-filter/hooks/useSelectFieldUsedInAdvancedFilterDropdown.ts +++ b/packages/twenty-front/src/modules/object-record/advanced-filter/hooks/useSelectFieldUsedInAdvancedFilterDropdown.ts @@ -1,12 +1,14 @@ import { useGetFieldMetadataItemById } from '@/object-metadata/hooks/useGetFieldMetadataItemById'; import { getFilterTypeFromFieldType } from '@/object-metadata/utils/formatFieldMetadataItemsAsFilterDefinitions'; import { fieldMetadataItemIdUsedInDropdownComponentState } from '@/object-record/object-filter-dropdown/states/fieldMetadataItemIdUsedInDropdownComponentState'; +import { objectFilterDropdownCurrentRecordFilterComponentState } from '@/object-record/object-filter-dropdown/states/objectFilterDropdownCurrentRecordFilterComponentState'; import { objectFilterDropdownSearchInputComponentState } from '@/object-record/object-filter-dropdown/states/objectFilterDropdownSearchInputComponentState'; import { selectedOperandInDropdownComponentState } from '@/object-record/object-filter-dropdown/states/selectedOperandInDropdownComponentState'; import { subFieldNameUsedInDropdownComponentState } from '@/object-record/object-filter-dropdown/states/subFieldNameUsedInDropdownComponentState'; import { getInitialFilterValue } from '@/object-record/object-filter-dropdown/utils/getInitialFilterValue'; -import { useApplyRecordFilter } from '@/object-record/record-filter/hooks/useApplyRecordFilter'; +import { useUpsertRecordFilter } from '@/object-record/record-filter/hooks/useUpsertRecordFilter'; import { currentRecordFiltersComponentState } from '@/object-record/record-filter/states/currentRecordFiltersComponentState'; +import { RecordFilter } from '@/object-record/record-filter/types/RecordFilter'; import { getRecordFilterOperands } from '@/object-record/record-filter/utils/getRecordFilterOperands'; import { SingleRecordPickerHotkeyScope } from '@/object-record/record-picker/single-record-picker/types/SingleRecordPickerHotkeyScope'; @@ -40,14 +42,19 @@ export const useSelectFieldUsedInAdvancedFilterDropdown = () => { const setHotkeyScope = useSetHotkeyScope(); - const { applyRecordFilter } = useApplyRecordFilter(); - const { getFieldMetadataItemById } = useGetFieldMetadataItemById(); const setSubFieldNameUsedInDropdown = useSetRecoilComponentStateV2( subFieldNameUsedInDropdownComponentState, ); + const setObjectFilterDropdownCurrentRecordFilter = + useSetRecoilComponentStateV2( + objectFilterDropdownCurrentRecordFilterComponentState, + ); + + const { upsertRecordFilter } = useUpsertRecordFilter(); + const selectFieldUsedInAdvancedFilterDropdown = ({ fieldMetadataItemId, recordFilterId, @@ -86,7 +93,7 @@ export const useSelectFieldUsedInAdvancedFilterDropdown = () => { (recordFilter) => recordFilter.id === recordFilterId, ); - applyRecordFilter({ + const newAdvancedFilter = { id: recordFilterId, fieldMetadataId: fieldMetadataItem.id, displayValue, @@ -97,12 +104,15 @@ export const useSelectFieldUsedInAdvancedFilterDropdown = () => { existingRecordFilter?.positionInRecordFilterGroup, type: filterType, label: fieldMetadataItem.label, - subFieldName: subFieldName ?? null, - }); + subFieldName, + } satisfies RecordFilter; setSubFieldNameUsedInDropdown(subFieldName); setObjectFilterDropdownSearchInput(''); + + setObjectFilterDropdownCurrentRecordFilter(newAdvancedFilter); + upsertRecordFilter(newAdvancedFilter); }; return { diff --git a/packages/twenty-front/src/modules/object-record/advanced-filter/hooks/useSetAdvancedFilterDropdownAllRowsStates.ts b/packages/twenty-front/src/modules/object-record/advanced-filter/hooks/useSetAdvancedFilterDropdownAllRowsStates.ts new file mode 100644 index 000000000..cd0ca0865 --- /dev/null +++ b/packages/twenty-front/src/modules/object-record/advanced-filter/hooks/useSetAdvancedFilterDropdownAllRowsStates.ts @@ -0,0 +1,98 @@ +import { rootLevelRecordFilterGroupComponentSelector } from '@/object-record/advanced-filter/states/rootLevelRecordFilterGroupComponentSelector'; +import { getAdvancedFilterObjectFilterDropdownComponentInstanceId } from '@/object-record/advanced-filter/utils/getAdvancedFilterObjectFilterDropdownComponentInstanceId'; +import { fieldMetadataItemIdUsedInDropdownComponentState } from '@/object-record/object-filter-dropdown/states/fieldMetadataItemIdUsedInDropdownComponentState'; +import { objectFilterDropdownCurrentRecordFilterComponentState } from '@/object-record/object-filter-dropdown/states/objectFilterDropdownCurrentRecordFilterComponentState'; +import { currentRecordFilterGroupsComponentState } from '@/object-record/record-filter-group/states/currentRecordFilterGroupsComponentState'; +import { currentRecordFiltersComponentState } from '@/object-record/record-filter/states/currentRecordFiltersComponentState'; +import { useRecoilComponentValueV2 } from '@/ui/utilities/state/component-state/hooks/useRecoilComponentValueV2'; +import { useRecoilCallback } from 'recoil'; + +export const useSetAdvancedFilterDropdownStates = () => { + const rootLevelRecordFilterGroup = useRecoilComponentValueV2( + rootLevelRecordFilterGroupComponentSelector, + ); + + const currentRecordFilters = useRecoilComponentValueV2( + currentRecordFiltersComponentState, + ); + + const currentRecordFilterGroups = useRecoilComponentValueV2( + currentRecordFilterGroupsComponentState, + ); + + const setAdvancedFilterDropdownStates = useRecoilCallback( + ({ set }) => + () => { + const rootLevelRecordFilters = currentRecordFilters.filter( + (recordFilter) => + recordFilter.recordFilterGroupId === rootLevelRecordFilterGroup?.id, + ); + + for (const rootLevelRecordFilter of rootLevelRecordFilters) { + set( + objectFilterDropdownCurrentRecordFilterComponentState.atomFamily({ + instanceId: + getAdvancedFilterObjectFilterDropdownComponentInstanceId( + rootLevelRecordFilter.id, + ), + }), + rootLevelRecordFilter, + ); + + set( + fieldMetadataItemIdUsedInDropdownComponentState.atomFamily({ + instanceId: + getAdvancedFilterObjectFilterDropdownComponentInstanceId( + rootLevelRecordFilter.id, + ), + }), + rootLevelRecordFilter.fieldMetadataId, + ); + } + + const childRecordFilterGroups = currentRecordFilterGroups.filter( + (currentRecordGroupToFilter) => + currentRecordGroupToFilter.parentRecordFilterGroupId === + rootLevelRecordFilterGroup?.id, + ); + + for (const childRecordFilterGroup of childRecordFilterGroups) { + const recordFiltersInThisGroup = currentRecordFilters.filter( + (recordFilter) => + recordFilter.recordFilterGroupId === childRecordFilterGroup.id, + ); + + for (const recordFilterInThisGroup of recordFiltersInThisGroup) { + set( + objectFilterDropdownCurrentRecordFilterComponentState.atomFamily({ + instanceId: + getAdvancedFilterObjectFilterDropdownComponentInstanceId( + recordFilterInThisGroup.id, + ), + }), + recordFilterInThisGroup, + ); + + set( + fieldMetadataItemIdUsedInDropdownComponentState.atomFamily({ + instanceId: + getAdvancedFilterObjectFilterDropdownComponentInstanceId( + recordFilterInThisGroup.id, + ), + }), + recordFilterInThisGroup.fieldMetadataId, + ); + } + } + }, + [ + currentRecordFilterGroups, + currentRecordFilters, + rootLevelRecordFilterGroup, + ], + ); + + return { + setAdvancedFilterDropdownStates, + }; +}; diff --git a/packages/twenty-front/src/modules/object-record/advanced-filter/hooks/useSetRecordFilterUsedInAdvancedFilterDropdownRow.ts b/packages/twenty-front/src/modules/object-record/advanced-filter/hooks/useSetRecordFilterUsedInAdvancedFilterDropdownRow.ts index f9a00b8fd..3eddb61cd 100644 --- a/packages/twenty-front/src/modules/object-record/advanced-filter/hooks/useSetRecordFilterUsedInAdvancedFilterDropdownRow.ts +++ b/packages/twenty-front/src/modules/object-record/advanced-filter/hooks/useSetRecordFilterUsedInAdvancedFilterDropdownRow.ts @@ -1,6 +1,6 @@ import { getAdvancedFilterObjectFilterDropdownComponentInstanceId } from '@/object-record/advanced-filter/utils/getAdvancedFilterObjectFilterDropdownComponentInstanceId'; import { fieldMetadataItemIdUsedInDropdownComponentState } from '@/object-record/object-filter-dropdown/states/fieldMetadataItemIdUsedInDropdownComponentState'; -import { selectedFilterComponentState } from '@/object-record/object-filter-dropdown/states/selectedFilterComponentState'; +import { objectFilterDropdownCurrentRecordFilterComponentState } from '@/object-record/object-filter-dropdown/states/objectFilterDropdownCurrentRecordFilterComponentState'; import { selectedOperandInDropdownComponentState } from '@/object-record/object-filter-dropdown/states/selectedOperandInDropdownComponentState'; import { RecordFilter } from '@/object-record/record-filter/types/RecordFilter'; import { useRecoilCallback } from 'recoil'; @@ -31,7 +31,7 @@ export const useSetRecordFilterUsedInAdvancedFilterDropdownRow = () => { ); set( - selectedFilterComponentState.atomFamily({ + objectFilterDropdownCurrentRecordFilterComponentState.atomFamily({ instanceId: advancedFilterRowObjectFilterDropdownComponentInstanceId, }), 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 f17f0a66e..168a7be92 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 @@ -1,20 +1,13 @@ import { useTheme } from '@emotion/react'; import styled from '@emotion/styled'; -import { useEffect, useState } from 'react'; -import { v4 } from 'uuid'; -import { getFilterTypeFromFieldType } from '@/object-metadata/utils/formatFieldMetadataItemsAsFilterDefinitions'; -import { fieldMetadataItemUsedInDropdownComponentSelector } from '@/object-record/object-filter-dropdown/states/fieldMetadataItemUsedInDropdownComponentSelector'; -import { selectedFilterComponentState } from '@/object-record/object-filter-dropdown/states/selectedFilterComponentState'; -import { selectedOperandInDropdownComponentState } from '@/object-record/object-filter-dropdown/states/selectedOperandInDropdownComponentState'; -import { useApplyRecordFilter } from '@/object-record/record-filter/hooks/useApplyRecordFilter'; +import { useApplyObjectFilterDropdownFilterValue } from '@/object-record/object-filter-dropdown/hooks/useApplyObjectFilterDropdownFilterValue'; +import { useObjectFilterDropdownFilterValue } from '@/object-record/object-filter-dropdown/hooks/useObjectFilterDropdownFilterValue'; import { SingleRecordPickerHotkeyScope } from '@/object-record/record-picker/single-record-picker/types/SingleRecordPickerHotkeyScope'; import { BooleanDisplay } from '@/ui/field/display/components/BooleanDisplay'; import { DropdownMenuItemsContainer } from '@/ui/layout/dropdown/components/DropdownMenuItemsContainer'; import { useDropdown } from '@/ui/layout/dropdown/hooks/useDropdown'; import { SelectableList } from '@/ui/layout/selectable-list/components/SelectableList'; -import { useRecoilComponentValueV2 } from '@/ui/utilities/state/component-state/hooks/useRecoilComponentValueV2'; -import { isDefined } from 'twenty-shared/utils'; import { IconCheck } from 'twenty-ui/display'; const StyledBooleanSelectContainer = styled.div<{ selected?: boolean }>` @@ -40,52 +33,20 @@ export const ObjectFilterDropdownBooleanSelect = () => { const theme = useTheme(); const options = [true, false]; - const fieldMetadataItemUsedInDropdown = useRecoilComponentValueV2( - fieldMetadataItemUsedInDropdownComponentSelector, - ); + const { objectFilterDropdownFilterValue } = + useObjectFilterDropdownFilterValue(); - const selectedOperandInDropdown = useRecoilComponentValueV2( - selectedOperandInDropdownComponentState, - ); - - const selectedFilter = useRecoilComponentValueV2( - selectedFilterComponentState, - ); - - const { applyRecordFilter } = useApplyRecordFilter(); + const { applyObjectFilterDropdownFilterValue } = + useApplyObjectFilterDropdownFilterValue(); const { closeDropdown } = useDropdown(); - const [selectedValue, setSelectedValue] = useState( - selectedFilter?.value === 'true', - ); + const handleOptionSelect = (newValue: boolean) => { + applyObjectFilterDropdownFilterValue( + newValue.toString(), + newValue ? 'True' : 'False', + ); - useEffect(() => { - setSelectedValue(selectedFilter?.value === 'true'); - }, [selectedFilter?.value]); - - const handleOptionSelect = (value: boolean) => { - if ( - !isDefined(fieldMetadataItemUsedInDropdown) || - !isDefined(selectedOperandInDropdown) - ) { - return; - } - - applyRecordFilter({ - id: selectedFilter?.id ?? v4(), - operand: selectedOperandInDropdown, - displayValue: value ? 'True' : 'False', - fieldMetadataId: fieldMetadataItemUsedInDropdown.id, - value: value.toString(), - recordFilterGroupId: selectedFilter?.recordFilterGroupId, - positionInRecordFilterGroup: selectedFilter?.positionInRecordFilterGroup, - type: getFilterTypeFromFieldType(fieldMetadataItemUsedInDropdown.type), - label: fieldMetadataItemUsedInDropdown.label, - subFieldName: selectedFilter?.subFieldName, - }); - - setSelectedValue(value); closeDropdown(); }; @@ -100,10 +61,10 @@ export const ObjectFilterDropdownBooleanSelect = () => { handleOptionSelect(option)} - selected={selectedValue === option} + selected={objectFilterDropdownFilterValue === option.toString()} > - {selectedFilter?.value === option.toString() && ( + {objectFilterDropdownFilterValue === option.toString() && ( diff --git a/packages/twenty-front/src/modules/object-record/object-filter-dropdown/components/ObjectFilterDropdownCurrencySelect.tsx b/packages/twenty-front/src/modules/object-record/object-filter-dropdown/components/ObjectFilterDropdownCurrencySelect.tsx index 0893eead3..d10f7fcfa 100644 --- a/packages/twenty-front/src/modules/object-record/object-filter-dropdown/components/ObjectFilterDropdownCurrencySelect.tsx +++ b/packages/twenty-front/src/modules/object-record/object-filter-dropdown/components/ObjectFilterDropdownCurrencySelect.tsx @@ -1,12 +1,7 @@ -import { getFilterTypeFromFieldType } from '@/object-metadata/utils/formatFieldMetadataItemsAsFilterDefinitions'; +import { useApplyObjectFilterDropdownFilterValue } from '@/object-record/object-filter-dropdown/hooks/useApplyObjectFilterDropdownFilterValue'; import { fieldMetadataItemUsedInDropdownComponentSelector } from '@/object-record/object-filter-dropdown/states/fieldMetadataItemUsedInDropdownComponentSelector'; -import { objectFilterDropdownSelectedRecordIdsComponentState } from '@/object-record/object-filter-dropdown/states/objectFilterDropdownSelectedRecordIdsComponentState'; -import { selectedFilterComponentState } from '@/object-record/object-filter-dropdown/states/selectedFilterComponentState'; -import { selectedOperandInDropdownComponentState } from '@/object-record/object-filter-dropdown/states/selectedOperandInDropdownComponentState'; +import { objectFilterDropdownCurrentRecordFilterComponentState } from '@/object-record/object-filter-dropdown/states/objectFilterDropdownCurrentRecordFilterComponentState'; import { turnCurrencyIntoSelectableItem } from '@/object-record/object-filter-dropdown/utils/turnCurrencyIntoSelectableItem'; -import { useApplyRecordFilter } from '@/object-record/record-filter/hooks/useApplyRecordFilter'; -import { currentRecordFiltersComponentState } from '@/object-record/record-filter/states/currentRecordFiltersComponentState'; -import { findDuplicateRecordFilterInNonAdvancedRecordFilters } from '@/object-record/record-filter/utils/findDuplicateRecordFilterInNonAdvancedRecordFilters'; import { StyledMultipleSelectDropdownAvatarChip } from '@/object-record/select/components/StyledMultipleSelectDropdownAvatarChip'; import { SelectableItem } from '@/object-record/select/types/SelectableItem'; import { CURRENCIES } from '@/settings/data-model/constants/Currencies'; @@ -14,70 +9,55 @@ import { DropdownMenuItemsContainer } from '@/ui/layout/dropdown/components/Drop import { DropdownMenuSearchInput } from '@/ui/layout/dropdown/components/DropdownMenuSearchInput'; import { DropdownMenuSeparator } from '@/ui/layout/dropdown/components/DropdownMenuSeparator'; import { useRecoilComponentValueV2 } from '@/ui/utilities/state/component-state/hooks/useRecoilComponentValueV2'; -import { useSetRecoilComponentStateV2 } from '@/ui/utilities/state/component-state/hooks/useSetRecoilComponentStateV2'; -import { ViewFilterOperand } from '@/views/types/ViewFilterOperand'; import { useLingui } from '@lingui/react/macro'; +import { isNonEmptyString } from '@sniptt/guards'; import { ChangeEvent, useState } from 'react'; import { isDefined } from 'twenty-shared/utils'; import { MenuItem, MenuItemMultiSelectAvatar } from 'twenty-ui/navigation'; -import { v4 } from 'uuid'; export const EMPTY_FILTER_VALUE = '[]'; export const MAX_ITEMS_TO_DISPLAY = 3; type ObjectFilterDropdownCurrencySelectProps = { - viewComponentId?: string; dropdownWidth?: number; }; export const ObjectFilterDropdownCurrencySelect = ({ - viewComponentId, dropdownWidth, }: ObjectFilterDropdownCurrencySelectProps) => { const [searchText, setSearchText] = useState(''); - const selectedFilter = useRecoilComponentValueV2( - selectedFilterComponentState, + const objectFilterDropdownCurrentRecordFilter = useRecoilComponentValueV2( + objectFilterDropdownCurrentRecordFilterComponentState, ); - const setObjectFilterDropdownSelectedRecordIds = useSetRecoilComponentStateV2( - objectFilterDropdownSelectedRecordIdsComponentState, - selectedFilter?.id, - ); - - const objectFilterDropdownSelectedRecordIds = useRecoilComponentValueV2( - objectFilterDropdownSelectedRecordIdsComponentState, - selectedFilter?.id, - ); - - const selectedOperandInDropdown = useRecoilComponentValueV2( - selectedOperandInDropdownComponentState, - ); + const { applyObjectFilterDropdownFilterValue } = + useApplyObjectFilterDropdownFilterValue(); const fieldMetadataItemUsedInFilterDropdown = useRecoilComponentValueV2( fieldMetadataItemUsedInDropdownComponentSelector, ); - const { applyRecordFilter } = useApplyRecordFilter(viewComponentId); - const currenciesAsSelectableItems = CURRENCIES.map( turnCurrencyIntoSelectableItem, ); + const selectedCurrencies = isNonEmptyString( + objectFilterDropdownCurrentRecordFilter?.value, + ) + ? (JSON.parse(objectFilterDropdownCurrentRecordFilter.value) as string[]) // TODO: replace by a safe parse + : []; + const filteredSelectableItems = currenciesAsSelectableItems.filter( (selectableItem) => selectableItem.name.toLowerCase().includes(searchText.toLowerCase()) && - !objectFilterDropdownSelectedRecordIds.includes(selectableItem.id), + !selectedCurrencies.includes(selectableItem.id), ); const filteredSelectedItems = currenciesAsSelectableItems.filter( (selectableItem) => selectableItem.name.toLowerCase().includes(searchText.toLowerCase()) && - objectFilterDropdownSelectedRecordIds.includes(selectableItem.id), - ); - - const currentRecordFilters = useRecoilComponentValueV2( - currentRecordFiltersComponentState, + selectedCurrencies.includes(selectableItem.id), ); const handleMultipleItemSelectChange = ( @@ -85,10 +65,8 @@ export const ObjectFilterDropdownCurrencySelect = ({ newSelectedValue: boolean, ) => { const newSelectedItemIds = newSelectedValue - ? [...objectFilterDropdownSelectedRecordIds, itemToSelect.id] - : objectFilterDropdownSelectedRecordIds.filter( - (id) => id !== itemToSelect.id, - ); + ? [...selectedCurrencies, itemToSelect.id] + : selectedCurrencies.filter((id) => id !== itemToSelect.id); if (!isDefined(fieldMetadataItemUsedInFilterDropdown)) { throw new Error( @@ -96,8 +74,6 @@ export const ObjectFilterDropdownCurrencySelect = ({ ); } - setObjectFilterDropdownSelectedRecordIds(newSelectedItemIds); - const selectedItemNames = currenciesAsSelectableItems .filter((option) => newSelectedItemIds.includes(option.id)) .map((option) => option.name); @@ -107,46 +83,12 @@ export const ObjectFilterDropdownCurrencySelect = ({ ? `${selectedItemNames.length} currencies` : selectedItemNames.join(', '); - if ( - isDefined(fieldMetadataItemUsedInFilterDropdown) && - isDefined(selectedOperandInDropdown) - ) { - const newFilterValue = - newSelectedItemIds.length > 0 - ? JSON.stringify(newSelectedItemIds) - : EMPTY_FILTER_VALUE; + const newFilterValue = + newSelectedItemIds.length > 0 + ? JSON.stringify(newSelectedItemIds) + : EMPTY_FILTER_VALUE; - const duplicateFilterInCurrentRecordFilters = - findDuplicateRecordFilterInNonAdvancedRecordFilters({ - recordFilters: currentRecordFilters, - fieldMetadataItemId: fieldMetadataItemUsedInFilterDropdown.id, - subFieldName: 'currencyCode', - }); - - const filterIsAlreadyInCurrentRecordFilters = isDefined( - duplicateFilterInCurrentRecordFilters, - ); - - const filterId = filterIsAlreadyInCurrentRecordFilters - ? duplicateFilterInCurrentRecordFilters?.id - : v4(); - - applyRecordFilter({ - id: selectedFilter?.id ? selectedFilter.id : filterId, - type: getFilterTypeFromFieldType( - fieldMetadataItemUsedInFilterDropdown.type, - ), - label: fieldMetadataItemUsedInFilterDropdown.label, - operand: selectedOperandInDropdown || ViewFilterOperand.Is, - displayValue: filterDisplayValue, - fieldMetadataId: fieldMetadataItemUsedInFilterDropdown.id, - value: newFilterValue, - recordFilterGroupId: selectedFilter?.recordFilterGroupId, - subFieldName: 'currencyCode', - positionInRecordFilterGroup: - selectedFilter?.positionInRecordFilterGroup, - }); - } + applyObjectFilterDropdownFilterValue(newFilterValue, filterDisplayValue); }; const showNoResult = 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 9d0ebc99e..921164ccd 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,11 +1,8 @@ -import { v4 } from 'uuid'; - -import { getFilterTypeFromFieldType } from '@/object-metadata/utils/formatFieldMetadataItemsAsFilterDefinitions'; +import { useApplyObjectFilterDropdownFilterValue } from '@/object-record/object-filter-dropdown/hooks/useApplyObjectFilterDropdownFilterValue'; import { fieldMetadataItemUsedInDropdownComponentSelector } from '@/object-record/object-filter-dropdown/states/fieldMetadataItemUsedInDropdownComponentSelector'; -import { selectedFilterComponentState } from '@/object-record/object-filter-dropdown/states/selectedFilterComponentState'; +import { objectFilterDropdownCurrentRecordFilterComponentState } from '@/object-record/object-filter-dropdown/states/objectFilterDropdownCurrentRecordFilterComponentState'; import { selectedOperandInDropdownComponentState } from '@/object-record/object-filter-dropdown/states/selectedOperandInDropdownComponentState'; import { getRelativeDateDisplayValue } from '@/object-record/object-filter-dropdown/utils/getRelativeDateDisplayValue'; -import { useApplyRecordFilter } from '@/object-record/record-filter/hooks/useApplyRecordFilter'; import { DateTimePicker } from '@/ui/input/components/internal/date/components/InternalDatePicker'; import { useRecoilComponentValueV2 } from '@/ui/utilities/state/component-state/hooks/useRecoilComponentValueV2'; import { ViewFilterOperand } from '@/views/types/ViewFilterOperand'; @@ -28,15 +25,17 @@ export const ObjectFilterDropdownDateInput = () => { selectedOperandInDropdownComponentState, ); - const selectedFilter = useRecoilComponentValueV2( - selectedFilterComponentState, + const objectFilterDropdownCurrentRecordFilter = useRecoilComponentValueV2( + objectFilterDropdownCurrentRecordFilterComponentState, ); - const { applyRecordFilter } = useApplyRecordFilter(); + const { applyObjectFilterDropdownFilterValue } = + useApplyObjectFilterDropdownFilterValue(); - const initialFilterValue = selectedFilter - ? resolveDateViewFilterValue(selectedFilter) + const initialFilterValue = isDefined(objectFilterDropdownCurrentRecordFilter) + ? resolveDateViewFilterValue(objectFilterDropdownCurrentRecordFilter) : null; + const [internalDate, setInternalDate] = useState( initialFilterValue instanceof Date ? initialFilterValue : null, ); @@ -47,24 +46,14 @@ export const ObjectFilterDropdownDateInput = () => { const handleAbsoluteDateChange = (newDate: Date | null) => { setInternalDate(newDate); - if (!fieldMetadataItemUsedInDropdown || !selectedOperandInDropdown) return; + const newFilterValue = newDate?.toISOString() ?? ''; + const newDisplayValue = isDefined(newDate) + ? isDateTimeInput + ? newDate.toLocaleString() + : newDate.toLocaleDateString() + : ''; - applyRecordFilter({ - id: selectedFilter?.id ? selectedFilter.id : v4(), - fieldMetadataId: fieldMetadataItemUsedInDropdown.id, - value: newDate?.toISOString() ?? '', - operand: selectedOperandInDropdown, - displayValue: isDefined(newDate) - ? isDateTimeInput - ? newDate.toLocaleString() - : newDate.toLocaleDateString() - : '', - recordFilterGroupId: selectedFilter?.recordFilterGroupId, - positionInRecordFilterGroup: selectedFilter?.positionInRecordFilterGroup, - type: getFilterTypeFromFieldType(fieldMetadataItemUsedInDropdown.type), - label: fieldMetadataItemUsedInDropdown.label, - subFieldName: selectedFilter?.subFieldName, - }); + applyObjectFilterDropdownFilterValue(newFilterValue, newDisplayValue); }; const handleRelativeDateChange = ( @@ -74,9 +63,7 @@ export const ObjectFilterDropdownDateInput = () => { unit: VariableDateViewFilterValueUnit; } | null, ) => { - if (!fieldMetadataItemUsedInDropdown || !selectedOperandInDropdown) return; - - const value = relativeDate + const newFilterValue = relativeDate ? computeVariableDateViewFilterValue( relativeDate.direction, relativeDate.amount, @@ -84,24 +71,18 @@ export const ObjectFilterDropdownDateInput = () => { ) : ''; - applyRecordFilter({ - id: selectedFilter?.id ? selectedFilter.id : v4(), - fieldMetadataId: fieldMetadataItemUsedInDropdown.id, - value, - operand: selectedOperandInDropdown, - displayValue: getRelativeDateDisplayValue(relativeDate), - recordFilterGroupId: selectedFilter?.recordFilterGroupId, - positionInRecordFilterGroup: selectedFilter?.positionInRecordFilterGroup, - type: getFilterTypeFromFieldType(fieldMetadataItemUsedInDropdown.type), - label: fieldMetadataItemUsedInDropdown.label, - }); + const newDisplayValue = relativeDate + ? getRelativeDateDisplayValue(relativeDate) + : ''; + + applyObjectFilterDropdownFilterValue(newFilterValue, newDisplayValue); }; const isRelativeOperand = selectedOperandInDropdown === ViewFilterOperand.IsRelative; - const resolvedValue = selectedFilter - ? resolveDateViewFilterValue(selectedFilter) + const resolvedValue = objectFilterDropdownCurrentRecordFilter + ? resolveDateViewFilterValue(objectFilterDropdownCurrentRecordFilter) : null; const relativeDate = 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 55159cc69..ddb73212d 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 @@ -9,7 +9,6 @@ import { FieldMetadataItem } from '@/object-metadata/types/FieldMetadataItem'; import { getFilterTypeFromFieldType } from '@/object-metadata/utils/formatFieldMetadataItemsAsFilterDefinitions'; import { FILTER_FIELD_LIST_ID } from '@/object-record/object-filter-dropdown/constants/FilterFieldListId'; import { objectFilterDropdownCurrentRecordFilterComponentState } from '@/object-record/object-filter-dropdown/states/objectFilterDropdownCurrentRecordFilterComponentState'; -import { selectedFilterComponentState } from '@/object-record/object-filter-dropdown/states/selectedFilterComponentState'; import { isCompositeFieldType } from '@/object-record/object-filter-dropdown/utils/isCompositeFieldType'; import { currentRecordFiltersComponentState } from '@/object-record/record-filter/states/currentRecordFiltersComponentState'; import { findDuplicateRecordFilterInNonAdvancedRecordFilters } from '@/object-record/record-filter/utils/findDuplicateRecordFilterInNonAdvancedRecordFilters'; @@ -68,10 +67,6 @@ export const ObjectFilterDropdownFilterSelectMenuItem = ({ currentRecordFiltersComponentState, ); - const setSelectedFilter = useSetRecoilComponentStateV2( - selectedFilterComponentState, - ); - const setObjectFilterDropdownCurrentRecordFilter = useSetRecoilComponentStateV2( objectFilterDropdownCurrentRecordFilterComponentState, @@ -103,8 +98,6 @@ export const ObjectFilterDropdownFilterSelectMenuItem = ({ ); if (filterIsAlreadyInCurrentRecordFilters) { - setSelectedFilter(duplicateFilterInCurrentRecordFilters); - setObjectFilterDropdownCurrentRecordFilter( duplicateFilterInCurrentRecordFilters, ); 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 3f69de42e..a0a81b8b5 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 @@ -1,41 +1,25 @@ import { ChangeEvent, useCallback, useState } from 'react'; -import { v4 } from 'uuid'; -import { getFilterTypeFromFieldType } from '@/object-metadata/utils/formatFieldMetadataItemsAsFilterDefinitions'; +import { useApplyObjectFilterDropdownFilterValue } from '@/object-record/object-filter-dropdown/hooks/useApplyObjectFilterDropdownFilterValue'; +import { useObjectFilterDropdownFilterValue } from '@/object-record/object-filter-dropdown/hooks/useObjectFilterDropdownFilterValue'; import { fieldMetadataItemUsedInDropdownComponentSelector } from '@/object-record/object-filter-dropdown/states/fieldMetadataItemUsedInDropdownComponentSelector'; -import { selectedFilterComponentState } from '@/object-record/object-filter-dropdown/states/selectedFilterComponentState'; -import { selectedOperandInDropdownComponentState } from '@/object-record/object-filter-dropdown/states/selectedOperandInDropdownComponentState'; -import { subFieldNameUsedInDropdownComponentState } from '@/object-record/object-filter-dropdown/states/subFieldNameUsedInDropdownComponentState'; -import { useApplyRecordFilter } from '@/object-record/record-filter/hooks/useApplyRecordFilter'; import { DropdownMenuInput } from '@/ui/layout/dropdown/components/DropdownMenuInput'; import { DropdownMenuItemsContainer } from '@/ui/layout/dropdown/components/DropdownMenuItemsContainer'; import { useRecoilComponentValueV2 } from '@/ui/utilities/state/component-state/hooks/useRecoilComponentValueV2'; export const ObjectFilterDropdownNumberInput = () => { - const selectedOperandInDropdown = useRecoilComponentValueV2( - selectedOperandInDropdownComponentState, - ); - const fieldMetadataItemUsedInDropdown = useRecoilComponentValueV2( fieldMetadataItemUsedInDropdownComponentSelector, ); - const selectedFilter = useRecoilComponentValueV2( - selectedFilterComponentState, - ); + const { objectFilterDropdownFilterValue } = + useObjectFilterDropdownFilterValue(); - const subFieldNameUsedInDropdown = useRecoilComponentValueV2( - subFieldNameUsedInDropdownComponentState, - ); - - const { applyRecordFilter } = useApplyRecordFilter(); + const { applyObjectFilterDropdownFilterValue } = + useApplyObjectFilterDropdownFilterValue(); const [hasFocused, setHasFocused] = useState(false); - const [inputValue, setInputValue] = useState( - () => selectedFilter?.value || '', - ); - const handleInputRef = useCallback( (node: HTMLInputElement | null) => { if (Boolean(node) && !hasFocused) { @@ -47,39 +31,22 @@ export const ObjectFilterDropdownNumberInput = () => { [hasFocused], ); + const handleInputChange = (event: ChangeEvent) => { + const newValue = event.target.value; + + applyObjectFilterDropdownFilterValue(newValue); + }; + return ( - fieldMetadataItemUsedInDropdown && - selectedOperandInDropdown && ( - - ) => { - const newValue = event.target.value; - - setInputValue(newValue); - - applyRecordFilter({ - id: selectedFilter?.id ? selectedFilter.id : v4(), - fieldMetadataId: fieldMetadataItemUsedInDropdown?.id ?? '', - value: newValue, - operand: selectedOperandInDropdown, - displayValue: newValue, - type: getFilterTypeFromFieldType( - fieldMetadataItemUsedInDropdown.type, - ), - label: fieldMetadataItemUsedInDropdown.label, - recordFilterGroupId: selectedFilter?.recordFilterGroupId, - positionInRecordFilterGroup: - selectedFilter?.positionInRecordFilterGroup, - subFieldName: subFieldNameUsedInDropdown, - }); - }} - /> - - ) + + + ); }; 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 c2ee9f99a..28c2a20de 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,22 +1,16 @@ -import { v4 } from 'uuid'; - import { getFilterTypeFromFieldType } from '@/object-metadata/utils/formatFieldMetadataItemsAsFilterDefinitions'; +import { useApplyObjectFilterDropdownOperand } from '@/object-record/object-filter-dropdown/hooks/useApplyObjectFilterDropdownOperand'; import { fieldMetadataItemUsedInDropdownComponentSelector } from '@/object-record/object-filter-dropdown/states/fieldMetadataItemUsedInDropdownComponentSelector'; -import { selectedFilterComponentState } from '@/object-record/object-filter-dropdown/states/selectedFilterComponentState'; -import { selectedOperandInDropdownComponentState } from '@/object-record/object-filter-dropdown/states/selectedOperandInDropdownComponentState'; import { subFieldNameUsedInDropdownComponentState } from '@/object-record/object-filter-dropdown/states/subFieldNameUsedInDropdownComponentState'; -import { getInitialFilterValue } from '@/object-record/object-filter-dropdown/utils/getInitialFilterValue'; -import { useApplyRecordFilter } from '@/object-record/record-filter/hooks/useApplyRecordFilter'; import { getRecordFilterOperands } from '@/object-record/record-filter/utils/getRecordFilterOperands'; import { DropdownMenuItemsContainer } from '@/ui/layout/dropdown/components/DropdownMenuItemsContainer'; import { useDropdown } from '@/ui/layout/dropdown/hooks/useDropdown'; import { useRecoilComponentValueV2 } from '@/ui/utilities/state/component-state/hooks/useRecoilComponentValueV2'; -import { useSetRecoilComponentStateV2 } from '@/ui/utilities/state/component-state/hooks/useSetRecoilComponentStateV2'; import { ViewFilterOperand } from '@/views/types/ViewFilterOperand'; import styled from '@emotion/styled'; import { isDefined } from 'twenty-shared/utils'; -import { getOperandLabel } from '../utils/getOperandLabel'; import { MenuItem } from 'twenty-ui/navigation'; +import { getOperandLabel } from '../utils/getOperandLabel'; const StyledDropdownMenuItemsContainer = styled(DropdownMenuItemsContainer)` background-color: ${({ theme }) => theme.background.primary}; @@ -28,19 +22,12 @@ export const ObjectFilterDropdownOperandSelect = () => { fieldMetadataItemUsedInDropdownComponentSelector, ); - const setSelectedOperandInDropdown = useSetRecoilComponentStateV2( - selectedOperandInDropdownComponentState, - ); - - const selectedFilter = useRecoilComponentValueV2( - selectedFilterComponentState, - ); - const subFieldNameUsedInDropdown = useRecoilComponentValueV2( subFieldNameUsedInDropdownComponentState, ); - const { applyRecordFilter } = useApplyRecordFilter(); + const { applyObjectFilterDropdownOperand } = + useApplyObjectFilterDropdownOperand(); const { closeDropdown } = useDropdown(); @@ -54,56 +41,7 @@ export const ObjectFilterDropdownOperandSelect = () => { : []; const handleOperandChange = (newOperand: ViewFilterOperand) => { - const isValuelessOperand = [ - ViewFilterOperand.IsEmpty, - ViewFilterOperand.IsNotEmpty, - ViewFilterOperand.IsInPast, - ViewFilterOperand.IsInFuture, - ViewFilterOperand.IsToday, - ].includes(newOperand); - - setSelectedOperandInDropdown(newOperand); - - if (isValuelessOperand && isDefined(fieldMetadataItemUsedInDropdown)) { - applyRecordFilter({ - id: selectedFilter?.id ? selectedFilter.id : v4(), - fieldMetadataId: fieldMetadataItemUsedInDropdown.id, - displayValue: '', - operand: newOperand, - value: '', - type: getFilterTypeFromFieldType(fieldMetadataItemUsedInDropdown.type), - label: fieldMetadataItemUsedInDropdown.label, - subFieldName: subFieldNameUsedInDropdown, - }); - return; - } - - if ( - isDefined(fieldMetadataItemUsedInDropdown) && - isDefined(selectedFilter) - ) { - const filterType = getFilterTypeFromFieldType( - fieldMetadataItemUsedInDropdown.type, - ); - - const { value, displayValue } = getInitialFilterValue( - filterType, - newOperand, - selectedFilter.value, - selectedFilter.displayValue, - ); - - applyRecordFilter({ - id: selectedFilter.id ? selectedFilter.id : v4(), - fieldMetadataId: selectedFilter.fieldMetadataId, - displayValue, - operand: newOperand, - value, - type: filterType, - label: fieldMetadataItemUsedInDropdown.label, - subFieldName: subFieldNameUsedInDropdown, - }); - } + applyObjectFilterDropdownOperand(newOperand); }; return ( 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 4c2318d39..755f5ebe4 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 @@ -1,6 +1,5 @@ -import { useEffect, useState } from 'react'; +import { useEffect, useMemo, useState } from 'react'; import { Key } from 'ts-key-enum'; -import { v4 } from 'uuid'; import { FieldMetadataItemOption } from '@/object-metadata/types/FieldMetadataItem'; import { useOptionsForSelect } from '@/object-record/object-filter-dropdown/hooks/useOptionsForSelect'; @@ -10,19 +9,17 @@ import { SelectableList } from '@/ui/layout/selectable-list/components/Selectabl import { useSelectableList } from '@/ui/layout/selectable-list/hooks/useSelectableList'; -import { getFilterTypeFromFieldType } from '@/object-metadata/utils/formatFieldMetadataItemsAsFilterDefinitions'; +import { useApplyObjectFilterDropdownFilterValue } from '@/object-record/object-filter-dropdown/hooks/useApplyObjectFilterDropdownFilterValue'; import { ObjectFilterDropdownComponentInstanceContext } from '@/object-record/object-filter-dropdown/states/contexts/ObjectFilterDropdownComponentInstanceContext'; import { fieldMetadataItemUsedInDropdownComponentSelector } from '@/object-record/object-filter-dropdown/states/fieldMetadataItemUsedInDropdownComponentSelector'; +import { objectFilterDropdownCurrentRecordFilterComponentState } from '@/object-record/object-filter-dropdown/states/objectFilterDropdownCurrentRecordFilterComponentState'; import { objectFilterDropdownSearchInputComponentState } from '@/object-record/object-filter-dropdown/states/objectFilterDropdownSearchInputComponentState'; -import { objectFilterDropdownSelectedOptionValuesComponentState } from '@/object-record/object-filter-dropdown/states/objectFilterDropdownSelectedOptionValuesComponentState'; -import { selectedFilterComponentState } from '@/object-record/object-filter-dropdown/states/selectedFilterComponentState'; -import { selectedOperandInDropdownComponentState } from '@/object-record/object-filter-dropdown/states/selectedOperandInDropdownComponentState'; -import { useApplyRecordFilter } from '@/object-record/record-filter/hooks/useApplyRecordFilter'; import { SingleRecordPickerHotkeyScope } from '@/object-record/record-picker/single-record-picker/types/SingleRecordPickerHotkeyScope'; import { selectedItemIdComponentState } from '@/ui/layout/selectable-list/states/selectedItemIdComponentState'; import { useScopedHotkeys } from '@/ui/utilities/hotkey/hooks/useScopedHotkeys'; import { useAvailableComponentInstanceIdOrThrow } from '@/ui/utilities/state/component-state/hooks/useAvailableComponentInstanceIdOrThrow'; import { useRecoilComponentValueV2 } from '@/ui/utilities/state/component-state/hooks/useRecoilComponentValueV2'; +import { isNonEmptyString } from '@sniptt/guards'; import { isDefined } from 'twenty-shared/utils'; import { MenuItem, MenuItemMultiSelect } from 'twenty-ui/navigation'; @@ -38,27 +35,30 @@ export const ObjectFilterDropdownOptionSelect = () => { fieldMetadataItemUsedInDropdownComponentSelector, ); - const objectFilterDropdownSelectedOptionValues = useRecoilComponentValueV2( - objectFilterDropdownSelectedOptionValuesComponentState, - ); - - const selectedFilter = useRecoilComponentValueV2( - selectedFilterComponentState, - ); - const objectFilterDropdownSearchInput = useRecoilComponentValueV2( objectFilterDropdownSearchInputComponentState, ); - const selectedOperandInDropdown = useRecoilComponentValueV2( - selectedOperandInDropdownComponentState, - ); - const componentInstanceId = useAvailableComponentInstanceIdOrThrow( ObjectFilterDropdownComponentInstanceContext, ); - const { applyRecordFilter } = useApplyRecordFilter(); + const objectFilterDropdownCurrentRecordFilter = useRecoilComponentValueV2( + objectFilterDropdownCurrentRecordFilterComponentState, + ); + + const { applyObjectFilterDropdownFilterValue } = + useApplyObjectFilterDropdownFilterValue(); + + const selectedOptions = useMemo( + () => + isNonEmptyString(objectFilterDropdownCurrentRecordFilter?.value) + ? (JSON.parse( + objectFilterDropdownCurrentRecordFilter.value, + ) as string[]) // TODO: replace by a safe parse + : [], + [objectFilterDropdownCurrentRecordFilter?.value], + ); const { closeDropdown } = useDropdown(); @@ -80,9 +80,7 @@ export const ObjectFilterDropdownOptionSelect = () => { useEffect(() => { if (isDefined(selectOptions)) { const options = selectOptions.map((option) => { - const isSelected = - objectFilterDropdownSelectedOptionValues?.includes(option.value) ?? - false; + const isSelected = selectedOptions?.includes(option.value) ?? false; return { ...option, @@ -92,7 +90,7 @@ export const ObjectFilterDropdownOptionSelect = () => { setSelectableOptions(options); } - }, [objectFilterDropdownSelectedOptionValues, selectOptions]); + }, [selectedOptions, selectOptions]); useScopedHotkeys( [Key.Escape], @@ -127,29 +125,13 @@ export const ObjectFilterDropdownOptionSelect = () => { ? `${selectedOptions.length} options` : selectedOptions.map((option) => option.label).join(', '); - if ( - isDefined(fieldMetadataItemUsedInDropdown) && - isDefined(selectedOperandInDropdown) - ) { - const newFilterValue = - selectedOptions.length > 0 - ? JSON.stringify(selectedOptions.map((option) => option.value)) - : EMPTY_FILTER_VALUE; + const newFilterValue = + selectedOptions.length > 0 + ? JSON.stringify(selectedOptions.map((option) => option.value)) + : EMPTY_FILTER_VALUE; + + applyObjectFilterDropdownFilterValue(newFilterValue, filterDisplayValue); - applyRecordFilter({ - id: selectedFilter?.id ? selectedFilter.id : v4(), - type: getFilterTypeFromFieldType(fieldMetadataItemUsedInDropdown.type), - label: fieldMetadataItemUsedInDropdown.label, - operand: selectedOperandInDropdown, - displayValue: filterDisplayValue, - fieldMetadataId: fieldMetadataItemUsedInDropdown.id, - value: newFilterValue, - recordFilterGroupId: selectedFilter?.recordFilterGroupId, - positionInRecordFilterGroup: - selectedFilter?.positionInRecordFilterGroup, - subFieldName: selectedFilter?.subFieldName, - }); - } resetSelectedItem(); }; 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 85590df54..7378eb993 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,15 +1,9 @@ -import { v4 } from 'uuid'; - -import { selectedOperandInDropdownComponentState } from '@/object-record/object-filter-dropdown/states/selectedOperandInDropdownComponentState'; import { RATING_VALUES } from '@/object-record/record-field/meta-types/constants/RatingValues'; import { FieldRatingValue } from '@/object-record/record-field/types/FieldMetadata'; -import { useApplyRecordFilter } from '@/object-record/record-filter/hooks/useApplyRecordFilter'; import { RatingInput } from '@/ui/field/input/components/RatingInput'; -import { useRecoilComponentValueV2 } from '@/ui/utilities/state/component-state/hooks/useRecoilComponentValueV2'; -import { getFilterTypeFromFieldType } from '@/object-metadata/utils/formatFieldMetadataItemsAsFilterDefinitions'; -import { fieldMetadataItemUsedInDropdownComponentSelector } from '@/object-record/object-filter-dropdown/states/fieldMetadataItemUsedInDropdownComponentSelector'; -import { selectedFilterComponentState } from '@/object-record/object-filter-dropdown/states/selectedFilterComponentState'; +import { useApplyObjectFilterDropdownFilterValue } from '@/object-record/object-filter-dropdown/hooks/useApplyObjectFilterDropdownFilterValue'; +import { useObjectFilterDropdownFilterValue } from '@/object-record/object-filter-dropdown/hooks/useObjectFilterDropdownFilterValue'; import styled from '@emotion/styled'; const StyledRatingInputContainer = styled.div` @@ -35,53 +29,37 @@ export const convertLessThanRatingToArrayOfRatingValues = ( }; export const convertRatingToRatingValue = (rating: number) => { - return `RATING_${rating}`; + return `RATING_${rating}` as FieldRatingValue; }; export const ObjectFilterDropdownRatingInput = () => { - const selectedOperandInDropdown = useRecoilComponentValueV2( - selectedOperandInDropdownComponentState, - ); + const { applyObjectFilterDropdownFilterValue } = + useApplyObjectFilterDropdownFilterValue(); - const fieldMetadataItemUsedInDropdown = useRecoilComponentValueV2( - fieldMetadataItemUsedInDropdownComponentSelector, - ); + const { objectFilterDropdownFilterValue } = + useObjectFilterDropdownFilterValue(); - const selectedFilter = useRecoilComponentValueV2( - selectedFilterComponentState, - ); + const handleInputChange = (newRatingValue: FieldRatingValue) => { + if (!newRatingValue) { + return; + } - const { applyRecordFilter } = useApplyRecordFilter(); + const ratingValueConverted = + convertFieldRatingValueToNumber(newRatingValue); + + applyObjectFilterDropdownFilterValue(ratingValueConverted); + }; + + const currentFilterValueConvertedToRatingValue = convertRatingToRatingValue( + Number(objectFilterDropdownFilterValue), + ); return ( - fieldMetadataItemUsedInDropdown && - selectedOperandInDropdown && ( - - { - if (!newValue) { - return; - } - - applyRecordFilter?.({ - id: selectedFilter?.id ? selectedFilter.id : v4(), - fieldMetadataId: fieldMetadataItemUsedInDropdown.id, - value: convertFieldRatingValueToNumber(newValue), - operand: selectedOperandInDropdown, - displayValue: convertFieldRatingValueToNumber(newValue), - recordFilterGroupId: selectedFilter?.recordFilterGroupId, - positionInRecordFilterGroup: - selectedFilter?.positionInRecordFilterGroup, - type: getFilterTypeFromFieldType( - fieldMetadataItemUsedInDropdown.type, - ), - label: fieldMetadataItemUsedInDropdown.label, - subFieldName: selectedFilter?.subFieldName, - }); - }} - /> - - ) + + + ); }; 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 85f419456..14baaa92d 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 @@ -1,17 +1,13 @@ import { useObjectMetadataItem } from '@/object-metadata/hooks/useObjectMetadataItem'; -import { - getFilterTypeFromFieldType, - getRelationObjectMetadataNameSingular, -} from '@/object-metadata/utils/formatFieldMetadataItemsAsFilterDefinitions'; +import { getRelationObjectMetadataNameSingular } from '@/object-metadata/utils/formatFieldMetadataItemsAsFilterDefinitions'; 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 { useApplyObjectFilterDropdownFilterValue } from '@/object-record/object-filter-dropdown/hooks/useApplyObjectFilterDropdownFilterValue'; +import { useObjectFilterDropdownFilterValue } from '@/object-record/object-filter-dropdown/hooks/useObjectFilterDropdownFilterValue'; import { fieldMetadataItemUsedInDropdownComponentSelector } from '@/object-record/object-filter-dropdown/states/fieldMetadataItemUsedInDropdownComponentSelector'; import { objectFilterDropdownSearchInputComponentState } from '@/object-record/object-filter-dropdown/states/objectFilterDropdownSearchInputComponentState'; -import { selectedFilterComponentState } from '@/object-record/object-filter-dropdown/states/selectedFilterComponentState'; import { selectedOperandInDropdownComponentState } from '@/object-record/object-filter-dropdown/states/selectedOperandInDropdownComponentState'; -import { useApplyRecordFilter } from '@/object-record/record-filter/hooks/useApplyRecordFilter'; import { currentRecordFiltersComponentState } from '@/object-record/record-filter/states/currentRecordFiltersComponentState'; -import { findDuplicateRecordFilterInNonAdvancedRecordFilters } from '@/object-record/record-filter/utils/findDuplicateRecordFilterInNonAdvancedRecordFilters'; import { SingleRecordPickerHotkeyScope } from '@/object-record/record-picker/single-record-picker/types/SingleRecordPickerHotkeyScope'; import { MultipleSelectDropdown } from '@/object-record/select/components/MultipleSelectDropdown'; import { useRecordsForSelect } from '@/object-record/select/hooks/useRecordsForSelect'; @@ -23,7 +19,6 @@ import { jsonRelationFilterValueSchema } from '@/views/view-filter-value/validat import { simpleRelationFilterValueSchema } from '@/views/view-filter-value/validation-schemas/simpleRelationFilterValueSchema'; import { isDefined } from 'twenty-shared/utils'; import { IconUserCircle } from 'twenty-ui/display'; -import { v4 } from 'uuid'; export const EMPTY_FILTER_VALUE: string = JSON.stringify({ isCurrentWorkspaceMemberSelected: false, @@ -33,26 +28,26 @@ export const EMPTY_FILTER_VALUE: string = JSON.stringify({ export const MAX_RECORDS_TO_DISPLAY = 3; type ObjectFilterDropdownRecordSelectProps = { - viewComponentId?: string; recordFilterId?: string; }; export const ObjectFilterDropdownRecordSelect = ({ - viewComponentId, recordFilterId, }: ObjectFilterDropdownRecordSelectProps) => { const fieldMetadataItemUsedInFilterDropdown = useRecoilComponentValueV2( fieldMetadataItemUsedInDropdownComponentSelector, ); + const { objectFilterDropdownFilterValue } = + useObjectFilterDropdownFilterValue(); + + const { applyObjectFilterDropdownFilterValue } = + useApplyObjectFilterDropdownFilterValue(); + const selectedOperandInDropdown = useRecoilComponentValueV2( selectedOperandInDropdownComponentState, ); - const selectedFilter = useRecoilComponentValueV2( - selectedFilterComponentState, - ); - const objectFilterDropdownSearchInput = useRecoilComponentValueV2( objectFilterDropdownSearchInputComponentState, ); @@ -61,16 +56,14 @@ export const ObjectFilterDropdownRecordSelect = ({ currentRecordFiltersComponentState, ); - const { applyRecordFilter } = useApplyRecordFilter(viewComponentId); - const { isCurrentWorkspaceMemberSelected } = jsonRelationFilterValueSchema .catch({ isCurrentWorkspaceMemberSelected: false, selectedRecordIds: simpleRelationFilterValueSchema.parse( - selectedFilter?.value, + objectFilterDropdownFilterValue, ), }) - .parse(selectedFilter?.value); + .parse(objectFilterDropdownFilterValue); if (!isDefined(fieldMetadataItemUsedInFilterDropdown)) { throw new Error('fieldMetadataItemUsedInFilterDropdown is not defined'); @@ -210,50 +203,7 @@ export const ObjectFilterDropdownRecordSelect = ({ } satisfies RelationFilterValue) : ''; - const duplicateFilterInCurrentRecordFilters = - findDuplicateRecordFilterInNonAdvancedRecordFilters({ - recordFilters: currentRecordFilters, - fieldMetadataItemId: fieldMetadataItemUsedInFilterDropdown.id, - }); - - const filterIsAlreadyInCurrentRecordFilters = isDefined( - duplicateFilterInCurrentRecordFilters, - ); - - if (filterIsAlreadyInCurrentRecordFilters && !isDefined(recordFilterId)) { - applyRecordFilter({ - id: duplicateFilterInCurrentRecordFilters.id, - type: getFilterTypeFromFieldType( - fieldMetadataItemUsedInFilterDropdown.type, - ), - label: fieldMetadataItemUsedInFilterDropdown.label, - operand: selectedOperandInDropdown, - displayValue: filterDisplayValue, - fieldMetadataId: fieldMetadataItemUsedInFilterDropdown.id, - value: newFilterValue, - recordFilterGroupId: - duplicateFilterInCurrentRecordFilters.recordFilterGroupId, - positionInRecordFilterGroup: - duplicateFilterInCurrentRecordFilters.positionInRecordFilterGroup, - subFieldName: duplicateFilterInCurrentRecordFilters.subFieldName, - }); - } else { - applyRecordFilter({ - id: selectedFilter?.id ? selectedFilter.id : v4(), - type: getFilterTypeFromFieldType( - fieldMetadataItemUsedInFilterDropdown.type, - ), - label: fieldMetadataItemUsedInFilterDropdown.label, - operand: selectedOperandInDropdown, - displayValue: filterDisplayValue, - fieldMetadataId: fieldMetadataItemUsedInFilterDropdown.id, - value: newFilterValue, - recordFilterGroupId: selectedFilter?.recordFilterGroupId, - positionInRecordFilterGroup: - selectedFilter?.positionInRecordFilterGroup, - subFieldName: selectedFilter?.subFieldName, - }); - } + applyObjectFilterDropdownFilterValue(newFilterValue, filterDisplayValue); } }; 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 a710e1907..85bf0578c 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 @@ -1,68 +1,44 @@ -import { getFilterTypeFromFieldType } from '@/object-metadata/utils/formatFieldMetadataItemsAsFilterDefinitions'; +import { useApplyObjectFilterDropdownFilterValue } from '@/object-record/object-filter-dropdown/hooks/useApplyObjectFilterDropdownFilterValue'; import { fieldMetadataItemUsedInDropdownComponentSelector } from '@/object-record/object-filter-dropdown/states/fieldMetadataItemUsedInDropdownComponentSelector'; +import { objectFilterDropdownCurrentRecordFilterComponentState } from '@/object-record/object-filter-dropdown/states/objectFilterDropdownCurrentRecordFilterComponentState'; import { objectFilterDropdownSearchInputComponentState } from '@/object-record/object-filter-dropdown/states/objectFilterDropdownSearchInputComponentState'; -import { objectFilterDropdownSelectedRecordIdsComponentState } from '@/object-record/object-filter-dropdown/states/objectFilterDropdownSelectedRecordIdsComponentState'; -import { selectedFilterComponentState } from '@/object-record/object-filter-dropdown/states/selectedFilterComponentState'; -import { selectedOperandInDropdownComponentState } from '@/object-record/object-filter-dropdown/states/selectedOperandInDropdownComponentState'; import { getActorSourceMultiSelectOptions } from '@/object-record/object-filter-dropdown/utils/getActorSourceMultiSelectOptions'; -import { useApplyRecordFilter } from '@/object-record/record-filter/hooks/useApplyRecordFilter'; -import { currentRecordFiltersComponentState } from '@/object-record/record-filter/states/currentRecordFiltersComponentState'; -import { findDuplicateRecordFilterInNonAdvancedRecordFilters } from '@/object-record/record-filter/utils/findDuplicateRecordFilterInNonAdvancedRecordFilters'; import { SingleRecordPickerHotkeyScope } from '@/object-record/record-picker/single-record-picker/types/SingleRecordPickerHotkeyScope'; import { MultipleSelectDropdown } from '@/object-record/select/components/MultipleSelectDropdown'; import { SelectableItem } from '@/object-record/select/types/SelectableItem'; import { useRecoilComponentValueV2 } from '@/ui/utilities/state/component-state/hooks/useRecoilComponentValueV2'; -import { useSetRecoilComponentStateV2 } from '@/ui/utilities/state/component-state/hooks/useSetRecoilComponentStateV2'; -import { ViewFilterOperand } from '@/views/types/ViewFilterOperand'; +import { isNonEmptyString } from '@sniptt/guards'; import { isDefined } from 'twenty-shared/utils'; -import { v4 } from 'uuid'; export const EMPTY_FILTER_VALUE = '[]'; export const MAX_ITEMS_TO_DISPLAY = 3; -type ObjectFilterDropdownSourceSelectProps = { - viewComponentId?: string; -}; - -export const ObjectFilterDropdownSourceSelect = ({ - viewComponentId, -}: ObjectFilterDropdownSourceSelectProps) => { +export const ObjectFilterDropdownSourceSelect = () => { const objectFilterDropdownSearchInput = useRecoilComponentValueV2( objectFilterDropdownSearchInputComponentState, ); - const setObjectFilterDropdownSelectedRecordIds = useSetRecoilComponentStateV2( - objectFilterDropdownSelectedRecordIdsComponentState, - ); - - const objectFilterDropdownSelectedRecordIds = useRecoilComponentValueV2( - objectFilterDropdownSelectedRecordIdsComponentState, - ); - - const selectedFilter = useRecoilComponentValueV2( - selectedFilterComponentState, - ); - - const selectedOperandInDropdown = useRecoilComponentValueV2( - selectedOperandInDropdownComponentState, - ); - const fieldMetadataItemUsedInFilterDropdown = useRecoilComponentValueV2( fieldMetadataItemUsedInDropdownComponentSelector, ); - const { applyRecordFilter } = useApplyRecordFilter(viewComponentId); - - const sourceTypes = getActorSourceMultiSelectOptions( - objectFilterDropdownSelectedRecordIds, + const objectFilterDropdownCurrentRecordFilter = useRecoilComponentValueV2( + objectFilterDropdownCurrentRecordFilterComponentState, ); + const { applyObjectFilterDropdownFilterValue } = + useApplyObjectFilterDropdownFilterValue(); + + const selectedSources = isNonEmptyString( + objectFilterDropdownCurrentRecordFilter?.value, + ) + ? (JSON.parse(objectFilterDropdownCurrentRecordFilter.value) as string[]) // TODO: replace by a safe parse + : []; + + const sourceTypes = getActorSourceMultiSelectOptions(selectedSources); + const filteredSelectedItems = sourceTypes.filter((option) => - objectFilterDropdownSelectedRecordIds.includes(option.id), - ); - - const currentRecordFilters = useRecoilComponentValueV2( - currentRecordFiltersComponentState, + selectedSources.includes(option.id), ); const handleMultipleItemSelectChange = ( @@ -70,10 +46,8 @@ export const ObjectFilterDropdownSourceSelect = ({ newSelectedValue: boolean, ) => { const newSelectedItemIds = newSelectedValue - ? [...objectFilterDropdownSelectedRecordIds, itemToSelect.id] - : objectFilterDropdownSelectedRecordIds.filter( - (id) => id !== itemToSelect.id, - ); + ? [...selectedSources, itemToSelect.id] + : selectedSources.filter((id) => id !== itemToSelect.id); if (!isDefined(fieldMetadataItemUsedInFilterDropdown)) { throw new Error( @@ -81,8 +55,6 @@ export const ObjectFilterDropdownSourceSelect = ({ ); } - setObjectFilterDropdownSelectedRecordIds(newSelectedItemIds); - const selectedItemNames = sourceTypes .filter((option) => newSelectedItemIds.includes(option.id)) .map((option) => option.name); @@ -92,46 +64,12 @@ export const ObjectFilterDropdownSourceSelect = ({ ? `${selectedItemNames.length} source types` : selectedItemNames.join(', '); - if ( - isDefined(fieldMetadataItemUsedInFilterDropdown) && - isDefined(selectedOperandInDropdown) - ) { - const newFilterValue = - newSelectedItemIds.length > 0 - ? JSON.stringify(newSelectedItemIds) - : EMPTY_FILTER_VALUE; + const newFilterValue = + newSelectedItemIds.length > 0 + ? JSON.stringify(newSelectedItemIds) + : EMPTY_FILTER_VALUE; - const duplicateFilterInCurrentRecordFilters = - findDuplicateRecordFilterInNonAdvancedRecordFilters({ - recordFilters: currentRecordFilters, - fieldMetadataItemId: fieldMetadataItemUsedInFilterDropdown.id, - subFieldName: 'source', - }); - - const filterIsAlreadyInCurrentRecordFilters = isDefined( - duplicateFilterInCurrentRecordFilters, - ); - - const filterId = filterIsAlreadyInCurrentRecordFilters - ? duplicateFilterInCurrentRecordFilters?.id - : v4(); - - applyRecordFilter({ - id: selectedFilter?.id ? selectedFilter.id : filterId, - type: getFilterTypeFromFieldType( - fieldMetadataItemUsedInFilterDropdown.type, - ), - label: fieldMetadataItemUsedInFilterDropdown.label, - operand: selectedOperandInDropdown || ViewFilterOperand.Is, - displayValue: filterDisplayValue, - fieldMetadataId: fieldMetadataItemUsedInFilterDropdown.id, - value: newFilterValue, - recordFilterGroupId: selectedFilter?.recordFilterGroupId, - subFieldName: 'source', - positionInRecordFilterGroup: - selectedFilter?.positionInRecordFilterGroup, - }); - } + applyObjectFilterDropdownFilterValue(newFilterValue, filterDisplayValue); }; return ( diff --git a/packages/twenty-front/src/modules/object-record/object-filter-dropdown/components/ObjectFilterDropdownSubFieldSelect.tsx b/packages/twenty-front/src/modules/object-record/object-filter-dropdown/components/ObjectFilterDropdownSubFieldSelect.tsx index efedcdbe1..e6eff0d30 100644 --- a/packages/twenty-front/src/modules/object-record/object-filter-dropdown/components/ObjectFilterDropdownSubFieldSelect.tsx +++ b/packages/twenty-front/src/modules/object-record/object-filter-dropdown/components/ObjectFilterDropdownSubFieldSelect.tsx @@ -9,7 +9,6 @@ import { objectFilterDropdownFilterIsSelectedComponentState } from '@/object-rec import { objectFilterDropdownIsSelectingCompositeFieldComponentState } from '@/object-record/object-filter-dropdown/states/objectFilterDropdownIsSelectingCompositeFieldComponentState'; import { objectFilterDropdownSearchInputComponentState } from '@/object-record/object-filter-dropdown/states/objectFilterDropdownSearchInputComponentState'; import { objectFilterDropdownSubMenuFieldTypeComponentState } from '@/object-record/object-filter-dropdown/states/objectFilterDropdownSubMenuFieldTypeComponentState'; -import { selectedFilterComponentState } from '@/object-record/object-filter-dropdown/states/selectedFilterComponentState'; import { selectedOperandInDropdownComponentState } from '@/object-record/object-filter-dropdown/states/selectedOperandInDropdownComponentState'; import { subFieldNameUsedInDropdownComponentState } from '@/object-record/object-filter-dropdown/states/subFieldNameUsedInDropdownComponentState'; import { FiltersHotkeyScope } from '@/object-record/object-filter-dropdown/types/FiltersHotkeyScope'; @@ -81,10 +80,6 @@ export const ObjectFilterDropdownSubFieldSelect = () => { currentRecordFiltersComponentState, ); - const setSelectedFilter = useSetRecoilComponentStateV2( - selectedFilterComponentState, - ); - const setObjectFilterDropdownCurrentRecordFilter = useSetRecoilComponentStateV2( objectFilterDropdownCurrentRecordFilterComponentState, @@ -125,8 +120,6 @@ export const ObjectFilterDropdownSubFieldSelect = () => { ); if (filterIsAlreadyInCurrentRecordFilters) { - setSelectedFilter(duplicateFilterInCurrentRecordFilters); - setObjectFilterDropdownCurrentRecordFilter( duplicateFilterInCurrentRecordFilters, ); diff --git a/packages/twenty-front/src/modules/object-record/object-filter-dropdown/components/ObjectFilterDropdownTextInput.tsx b/packages/twenty-front/src/modules/object-record/object-filter-dropdown/components/ObjectFilterDropdownTextInput.tsx index 1629318e3..4c39c6892 100644 --- a/packages/twenty-front/src/modules/object-record/object-filter-dropdown/components/ObjectFilterDropdownTextInput.tsx +++ b/packages/twenty-front/src/modules/object-record/object-filter-dropdown/components/ObjectFilterDropdownTextInput.tsx @@ -31,6 +31,12 @@ export const ObjectFilterDropdownTextInput = () => { [hasFocused], ); + const handleInputChange = (event: ChangeEvent) => { + const newValue = event.target.value; + + applyObjectFilterDropdownFilterValue(newValue); + }; + return ( { autoFocus type="text" placeholder={fieldMetadataItemUsedInDropdown?.label} - onChange={(event: ChangeEvent) => { - const newValue = event.target.value; - - applyObjectFilterDropdownFilterValue(newValue); - }} + onChange={handleInputChange} /> ); 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 deleted file mode 100644 index 46871720c..000000000 --- a/packages/twenty-front/src/modules/object-record/object-filter-dropdown/components/ObjectFilterDropdownTextSearchInput.tsx +++ /dev/null @@ -1,80 +0,0 @@ -import { ChangeEvent, useCallback, useState } from 'react'; - -import { getFilterTypeFromFieldType } from '@/object-metadata/utils/formatFieldMetadataItemsAsFilterDefinitions'; -import { fieldMetadataItemUsedInDropdownComponentSelector } from '@/object-record/object-filter-dropdown/states/fieldMetadataItemUsedInDropdownComponentSelector'; -import { objectFilterDropdownSearchInputComponentState } from '@/object-record/object-filter-dropdown/states/objectFilterDropdownSearchInputComponentState'; -import { selectedFilterComponentState } from '@/object-record/object-filter-dropdown/states/selectedFilterComponentState'; -import { selectedOperandInDropdownComponentState } from '@/object-record/object-filter-dropdown/states/selectedOperandInDropdownComponentState'; -import { useApplyRecordFilter } from '@/object-record/record-filter/hooks/useApplyRecordFilter'; -import { DropdownMenuSearchInput } from '@/ui/layout/dropdown/components/DropdownMenuSearchInput'; -import { useRecoilComponentValueV2 } from '@/ui/utilities/state/component-state/hooks/useRecoilComponentValueV2'; -import { useSetRecoilComponentStateV2 } from '@/ui/utilities/state/component-state/hooks/useSetRecoilComponentStateV2'; -import { v4 } from 'uuid'; - -export const ObjectFilterDropdownTextSearchInput = () => { - const [hasFocused, setHasFocused] = useState(false); - - const fieldMetadataItemUsedInDropdown = useRecoilComponentValueV2( - fieldMetadataItemUsedInDropdownComponentSelector, - ); - - const selectedOperandInDropdown = useRecoilComponentValueV2( - selectedOperandInDropdownComponentState, - ); - - const objectFilterDropdownSearchInput = useRecoilComponentValueV2( - objectFilterDropdownSearchInputComponentState, - ); - - const selectedFilter = useRecoilComponentValueV2( - selectedFilterComponentState, - ); - - const setObjectFilterDropdownSearchInput = useSetRecoilComponentStateV2( - objectFilterDropdownSearchInputComponentState, - ); - - const { applyRecordFilter } = useApplyRecordFilter(); - - const handleInputRef = useCallback( - (node: HTMLInputElement | null) => { - if (Boolean(node) && !hasFocused) { - node?.focus(); - node?.select(); - setHasFocused(true); - } - }, - [hasFocused], - ); - return ( - fieldMetadataItemUsedInDropdown && - selectedOperandInDropdown && ( - ) => { - setObjectFilterDropdownSearchInput(event.target.value); - - applyRecordFilter({ - id: selectedFilter?.id ?? v4(), - fieldMetadataId: fieldMetadataItemUsedInDropdown.id, - value: event.target.value, - operand: selectedOperandInDropdown, - displayValue: event.target.value, - recordFilterGroupId: selectedFilter?.recordFilterGroupId, - type: getFilterTypeFromFieldType( - fieldMetadataItemUsedInDropdown.type, - ), - label: fieldMetadataItemUsedInDropdown.label, - positionInRecordFilterGroup: - selectedFilter?.positionInRecordFilterGroup, - subFieldName: selectedFilter?.subFieldName, - }); - }} - /> - ) - ); -}; diff --git a/packages/twenty-front/src/modules/object-record/object-filter-dropdown/hooks/useApplyObjectFilterDropdownFilterValue.ts b/packages/twenty-front/src/modules/object-record/object-filter-dropdown/hooks/useApplyObjectFilterDropdownFilterValue.ts index 69f83a828..c94d6a961 100644 --- a/packages/twenty-front/src/modules/object-record/object-filter-dropdown/hooks/useApplyObjectFilterDropdownFilterValue.ts +++ b/packages/twenty-front/src/modules/object-record/object-filter-dropdown/hooks/useApplyObjectFilterDropdownFilterValue.ts @@ -25,7 +25,10 @@ export const useApplyObjectFilterDropdownFilterValue = () => { const { upsertObjectFilterDropdownCurrentFilter } = useUpsertObjectFilterDropdownCurrentFilter(); - const applyObjectFilterDropdownFilterValue = (newFilterValue: string) => { + const applyObjectFilterDropdownFilterValue = ( + newFilterValue: string, + newDisplayValue?: string, + ) => { if (objectFilterDropdownFilterNotYetCreated) { if (!isDefined(fieldMetadataItemUsedInDropdown)) { throw new Error( @@ -41,7 +44,7 @@ export const useApplyObjectFilterDropdownFilterValue = () => { const newCurrentRecordFilter = { ...newRecordFilterFromObjectFilterDropdownStates, value: newFilterValue, - displayValue: newFilterValue, + displayValue: newDisplayValue ?? newFilterValue, } satisfies RecordFilter; upsertObjectFilterDropdownCurrentFilter(newCurrentRecordFilter); @@ -49,7 +52,7 @@ export const useApplyObjectFilterDropdownFilterValue = () => { const newCurrentRecordFilter = { ...objectFilterDropdownCurrentRecordFilter, value: newFilterValue, - displayValue: newFilterValue, + displayValue: newDisplayValue ?? newFilterValue, } satisfies RecordFilter; upsertObjectFilterDropdownCurrentFilter(newCurrentRecordFilter); diff --git a/packages/twenty-front/src/modules/object-record/object-filter-dropdown/hooks/useApplyObjectFilterDropdownOperand.ts b/packages/twenty-front/src/modules/object-record/object-filter-dropdown/hooks/useApplyObjectFilterDropdownOperand.ts new file mode 100644 index 000000000..98601c32e --- /dev/null +++ b/packages/twenty-front/src/modules/object-record/object-filter-dropdown/hooks/useApplyObjectFilterDropdownOperand.ts @@ -0,0 +1,79 @@ +import { useUpsertObjectFilterDropdownCurrentFilter } from '@/object-record/object-filter-dropdown/hooks/useUpsertObjectFilterDropdownCurrentFilter'; +import { fieldMetadataItemUsedInDropdownComponentSelector } from '@/object-record/object-filter-dropdown/states/fieldMetadataItemUsedInDropdownComponentSelector'; +import { objectFilterDropdownCurrentRecordFilterComponentState } from '@/object-record/object-filter-dropdown/states/objectFilterDropdownCurrentRecordFilterComponentState'; +import { selectedOperandInDropdownComponentState } from '@/object-record/object-filter-dropdown/states/selectedOperandInDropdownComponentState'; +import { useCreateEmptyRecordFilterFromFieldMetadataItem } from '@/object-record/record-filter/hooks/useCreateEmptyRecordFilterFromFieldMetadataItem'; +import { RecordFilter } from '@/object-record/record-filter/types/RecordFilter'; +import { RecordFilterOperand } from '@/object-record/record-filter/types/RecordFilterOperand'; +import { useRecoilComponentValueV2 } from '@/ui/utilities/state/component-state/hooks/useRecoilComponentValueV2'; +import { useSetRecoilComponentStateV2 } from '@/ui/utilities/state/component-state/hooks/useSetRecoilComponentStateV2'; +import { isDefined } from 'twenty-shared/utils'; + +export const useApplyObjectFilterDropdownOperand = () => { + const objectFilterDropdownCurrentRecordFilter = useRecoilComponentValueV2( + objectFilterDropdownCurrentRecordFilterComponentState, + ); + + const setSelectedOperandInDropdown = useSetRecoilComponentStateV2( + selectedOperandInDropdownComponentState, + ); + + const objectFilterDropdownFilterIsCreated = isDefined( + objectFilterDropdownCurrentRecordFilter, + ); + + const fieldMetadataItemUsedInDropdown = useRecoilComponentValueV2( + fieldMetadataItemUsedInDropdownComponentSelector, + ); + + const { upsertObjectFilterDropdownCurrentFilter } = + useUpsertObjectFilterDropdownCurrentFilter(); + + const { createEmptyRecordFilterFromFieldMetadataItem } = + useCreateEmptyRecordFilterFromFieldMetadataItem(); + + const applyObjectFilterDropdownOperand = ( + newOperand: RecordFilterOperand, + ) => { + const isValuelessOperand = [ + RecordFilterOperand.IsEmpty, + RecordFilterOperand.IsNotEmpty, + RecordFilterOperand.IsInPast, + RecordFilterOperand.IsInFuture, + RecordFilterOperand.IsToday, + ].includes(newOperand); + + if (objectFilterDropdownFilterIsCreated) { + const newCurrentRecordFilter = { + ...objectFilterDropdownCurrentRecordFilter, + operand: newOperand, + } satisfies RecordFilter; + + upsertObjectFilterDropdownCurrentFilter(newCurrentRecordFilter); + } else if (isValuelessOperand) { + if (!isDefined(fieldMetadataItemUsedInDropdown)) { + throw new Error( + 'FieldMetadataItemUsedInDropdown is not defined, cannot create empty record filter, this should not happen', + ); + } + + const { newRecordFilter: emptyRecordFilter } = + createEmptyRecordFilterFromFieldMetadataItem( + fieldMetadataItemUsedInDropdown, + ); + + const recordFilterToCreate = { + ...emptyRecordFilter, + operand: newOperand, + } satisfies RecordFilter; + + upsertObjectFilterDropdownCurrentFilter(recordFilterToCreate); + } + + setSelectedOperandInDropdown(newOperand); + }; + + return { + applyObjectFilterDropdownOperand, + }; +}; diff --git a/packages/twenty-front/src/modules/object-record/object-filter-dropdown/hooks/useEmptyRecordFilter.ts b/packages/twenty-front/src/modules/object-record/object-filter-dropdown/hooks/useEmptyRecordFilter.ts index 93e70009c..f1094fa70 100644 --- a/packages/twenty-front/src/modules/object-record/object-filter-dropdown/hooks/useEmptyRecordFilter.ts +++ b/packages/twenty-front/src/modules/object-record/object-filter-dropdown/hooks/useEmptyRecordFilter.ts @@ -1,6 +1,6 @@ +import { objectFilterDropdownCurrentRecordFilterComponentState } from '@/object-record/object-filter-dropdown/states/objectFilterDropdownCurrentRecordFilterComponentState'; import { objectFilterDropdownSearchInputComponentState } from '@/object-record/object-filter-dropdown/states/objectFilterDropdownSearchInputComponentState'; import { objectFilterDropdownSelectedRecordIdsComponentState } from '@/object-record/object-filter-dropdown/states/objectFilterDropdownSelectedRecordIdsComponentState'; -import { selectedFilterComponentState } from '@/object-record/object-filter-dropdown/states/selectedFilterComponentState'; import { useRecoilComponentCallbackStateV2 } from '@/ui/utilities/state/component-state/hooks/useRecoilComponentCallbackStateV2'; import { useRecoilCallback } from 'recoil'; @@ -17,22 +17,23 @@ export const useEmptyRecordFilter = (componentInstanceId?: string) => { componentInstanceId, ); - const selectedFilterCallbackState = useRecoilComponentCallbackStateV2( - selectedFilterComponentState, - componentInstanceId, - ); + const objectFilterDropdownCurrentRecordFilter = + useRecoilComponentCallbackStateV2( + objectFilterDropdownCurrentRecordFilterComponentState, + componentInstanceId, + ); const emptyRecordFilter = useRecoilCallback( ({ set }) => () => { set(objectFilterDropdownSearchInputCallbackState, ''); set(objectFilterDropdownSelectedRecordIdsCallbackState, []); - set(selectedFilterCallbackState, undefined); + set(objectFilterDropdownCurrentRecordFilter, undefined); }, [ objectFilterDropdownSearchInputCallbackState, objectFilterDropdownSelectedRecordIdsCallbackState, - selectedFilterCallbackState, + objectFilterDropdownCurrentRecordFilter, ], ); diff --git a/packages/twenty-front/src/modules/object-record/object-filter-dropdown/hooks/useResetFilterDropdown.ts b/packages/twenty-front/src/modules/object-record/object-filter-dropdown/hooks/useResetFilterDropdown.ts index 5c239d59e..280fc3f4b 100644 --- a/packages/twenty-front/src/modules/object-record/object-filter-dropdown/hooks/useResetFilterDropdown.ts +++ b/packages/twenty-front/src/modules/object-record/object-filter-dropdown/hooks/useResetFilterDropdown.ts @@ -4,7 +4,6 @@ import { objectFilterDropdownFilterIsSelectedComponentState } from '@/object-rec import { objectFilterDropdownIsSelectingCompositeFieldComponentState } from '@/object-record/object-filter-dropdown/states/objectFilterDropdownIsSelectingCompositeFieldComponentState'; import { objectFilterDropdownSearchInputComponentState } from '@/object-record/object-filter-dropdown/states/objectFilterDropdownSearchInputComponentState'; import { objectFilterDropdownSelectedRecordIdsComponentState } from '@/object-record/object-filter-dropdown/states/objectFilterDropdownSelectedRecordIdsComponentState'; -import { selectedFilterComponentState } from '@/object-record/object-filter-dropdown/states/selectedFilterComponentState'; import { selectedOperandInDropdownComponentState } from '@/object-record/object-filter-dropdown/states/selectedOperandInDropdownComponentState'; import { useRecoilComponentCallbackStateV2 } from '@/ui/utilities/state/component-state/hooks/useRecoilComponentCallbackStateV2'; import { useRecoilCallback } from 'recoil'; @@ -28,11 +27,6 @@ export const useResetFilterDropdown = (componentInstanceId?: string) => { componentInstanceId, ); - const selectedFilterCallbackState = useRecoilComponentCallbackStateV2( - selectedFilterComponentState, - componentInstanceId, - ); - const selectedOperandInDropdownCallbackState = useRecoilComponentCallbackStateV2( selectedOperandInDropdownComponentState, @@ -62,7 +56,6 @@ export const useResetFilterDropdown = (componentInstanceId?: string) => { () => { set(objectFilterDropdownSearchInputCallbackState, ''); set(objectFilterDropdownSelectedRecordIdsCallbackState, []); - set(selectedFilterCallbackState, undefined); set(selectedOperandInDropdownCallbackState, null); set(objectFilterDropdownFilterIsSelectedCallbackState, false); set(objectFilterDropdownIsSelectingCompositeFieldCallbackState, false); @@ -72,7 +65,6 @@ export const useResetFilterDropdown = (componentInstanceId?: string) => { [ objectFilterDropdownSearchInputCallbackState, objectFilterDropdownSelectedRecordIdsCallbackState, - selectedFilterCallbackState, selectedOperandInDropdownCallbackState, objectFilterDropdownFilterIsSelectedCallbackState, objectFilterDropdownIsSelectingCompositeFieldCallbackState, diff --git a/packages/twenty-front/src/modules/object-record/object-filter-dropdown/hooks/useSelectFilterUsedInDropdown.ts b/packages/twenty-front/src/modules/object-record/object-filter-dropdown/hooks/useSelectFilterUsedInDropdown.ts deleted file mode 100644 index a7c8ed06f..000000000 --- a/packages/twenty-front/src/modules/object-record/object-filter-dropdown/hooks/useSelectFilterUsedInDropdown.ts +++ /dev/null @@ -1,97 +0,0 @@ -import { useGetFieldMetadataItemById } from '@/object-metadata/hooks/useGetFieldMetadataItemById'; -import { getFilterTypeFromFieldType } from '@/object-metadata/utils/formatFieldMetadataItemsAsFilterDefinitions'; -import { fieldMetadataItemIdUsedInDropdownComponentState } from '@/object-record/object-filter-dropdown/states/fieldMetadataItemIdUsedInDropdownComponentState'; -import { objectFilterDropdownSearchInputComponentState } from '@/object-record/object-filter-dropdown/states/objectFilterDropdownSearchInputComponentState'; -import { selectedOperandInDropdownComponentState } from '@/object-record/object-filter-dropdown/states/selectedOperandInDropdownComponentState'; -import { getInitialFilterValue } from '@/object-record/object-filter-dropdown/utils/getInitialFilterValue'; -import { useApplyRecordFilter } from '@/object-record/record-filter/hooks/useApplyRecordFilter'; -import { getRecordFilterOperands } from '@/object-record/record-filter/utils/getRecordFilterOperands'; -import { SingleRecordPickerHotkeyScope } from '@/object-record/record-picker/single-record-picker/types/SingleRecordPickerHotkeyScope'; - -import { getDefaultSubFieldNameForCompositeFilterableFieldType } from '@/object-record/record-filter/utils/getDefaultSubFieldNameForCompositeFilterableFieldType'; -import { useSetHotkeyScope } from '@/ui/utilities/hotkey/hooks/useSetHotkeyScope'; -import { useSetRecoilComponentStateV2 } from '@/ui/utilities/state/component-state/hooks/useSetRecoilComponentStateV2'; -import { isDefined } from 'twenty-shared/utils'; -import { v4 } from 'uuid'; - -type SelectFilterParams = { - fieldMetadataItemId: string; -}; - -export const useSelectFilterUsedInDropdown = (componentInstanceId?: string) => { - const setSelectedOperandInDropdown = useSetRecoilComponentStateV2( - selectedOperandInDropdownComponentState, - componentInstanceId, - ); - - const setFieldMetadataItemIdUsedInDropdown = useSetRecoilComponentStateV2( - fieldMetadataItemIdUsedInDropdownComponentState, - componentInstanceId, - ); - - const setObjectFilterDropdownSearchInput = useSetRecoilComponentStateV2( - objectFilterDropdownSearchInputComponentState, - componentInstanceId, - ); - - const setHotkeyScope = useSetHotkeyScope(); - - const { applyRecordFilter } = useApplyRecordFilter(componentInstanceId); - - const { getFieldMetadataItemById } = useGetFieldMetadataItemById(); - - const selectFilterUsedInDropdown = ({ - fieldMetadataItemId, - }: SelectFilterParams) => { - setFieldMetadataItemIdUsedInDropdown(fieldMetadataItemId); - - const fieldMetadataItem = getFieldMetadataItemById(fieldMetadataItemId); - - if (!isDefined(fieldMetadataItem)) { - return; - } - - if ( - fieldMetadataItem.type === 'RELATION' || - fieldMetadataItem.type === 'SELECT' - ) { - setHotkeyScope(SingleRecordPickerHotkeyScope.SingleRecordPicker); - } - - const filterType = getFilterTypeFromFieldType(fieldMetadataItem.type); - - const defaultSubFieldName = - getDefaultSubFieldNameForCompositeFilterableFieldType(filterType); - - const firstOperand = getRecordFilterOperands({ - filterType, - subFieldName: defaultSubFieldName, - })[0]; - - setSelectedOperandInDropdown(firstOperand); - - const { value, displayValue } = getInitialFilterValue( - filterType, - firstOperand, - ); - - if (value !== '') { - applyRecordFilter({ - id: v4(), - fieldMetadataId: fieldMetadataItem.id, - displayValue, - operand: firstOperand, - value, - type: filterType, - label: fieldMetadataItem.label, - subFieldName: defaultSubFieldName, - }); - } - - setObjectFilterDropdownSearchInput(''); - }; - - return { - selectFilterUsedInDropdown, - }; -}; diff --git a/packages/twenty-front/src/modules/object-record/object-filter-dropdown/hooks/useUpsertObjectFilterDropdownCurrentFilter.ts b/packages/twenty-front/src/modules/object-record/object-filter-dropdown/hooks/useUpsertObjectFilterDropdownCurrentFilter.ts index 52a45b438..e3009382f 100644 --- a/packages/twenty-front/src/modules/object-record/object-filter-dropdown/hooks/useUpsertObjectFilterDropdownCurrentFilter.ts +++ b/packages/twenty-front/src/modules/object-record/object-filter-dropdown/hooks/useUpsertObjectFilterDropdownCurrentFilter.ts @@ -1,5 +1,4 @@ import { objectFilterDropdownCurrentRecordFilterComponentState } from '@/object-record/object-filter-dropdown/states/objectFilterDropdownCurrentRecordFilterComponentState'; -import { selectedFilterComponentState } from '@/object-record/object-filter-dropdown/states/selectedFilterComponentState'; import { useUpsertRecordFilter } from '@/object-record/record-filter/hooks/useUpsertRecordFilter'; import { RecordFilter } from '@/object-record/record-filter/types/RecordFilter'; import { useSetRecoilComponentStateV2 } from '@/ui/utilities/state/component-state/hooks/useSetRecoilComponentStateV2'; @@ -10,10 +9,6 @@ export const useUpsertObjectFilterDropdownCurrentFilter = () => { objectFilterDropdownCurrentRecordFilterComponentState, ); - const setSelectedFilter = useSetRecoilComponentStateV2( - selectedFilterComponentState, - ); - const { upsertRecordFilter } = useUpsertRecordFilter(); const upsertObjectFilterDropdownCurrentFilter = ( @@ -22,7 +17,6 @@ export const useUpsertObjectFilterDropdownCurrentFilter = () => { upsertRecordFilter(recordFilterToUpsert); setObjectFilterDropdownCurrentRecordFilter(recordFilterToUpsert); - setSelectedFilter(recordFilterToUpsert); }; return { diff --git a/packages/twenty-front/src/modules/object-record/object-filter-dropdown/states/onFilterSelectComponentState.ts b/packages/twenty-front/src/modules/object-record/object-filter-dropdown/states/onFilterSelectComponentState.ts deleted file mode 100644 index 9511acc13..000000000 --- a/packages/twenty-front/src/modules/object-record/object-filter-dropdown/states/onFilterSelectComponentState.ts +++ /dev/null @@ -1,11 +0,0 @@ -import { ObjectFilterDropdownComponentInstanceContext } from '@/object-record/object-filter-dropdown/states/contexts/ObjectFilterDropdownComponentInstanceContext'; -import { createComponentStateV2 } from '@/ui/utilities/state/component-state/utils/createComponentStateV2'; -import { RecordFilter } from '../../record-filter/types/RecordFilter'; - -export const onFilterSelectComponentState = createComponentStateV2< - ((filter: RecordFilter | null) => void) | undefined ->({ - key: 'onFilterSelectComponentState', - defaultValue: undefined, - componentInstanceContext: ObjectFilterDropdownComponentInstanceContext, -}); diff --git a/packages/twenty-front/src/modules/object-record/object-filter-dropdown/states/selectedFilterComponentState.ts b/packages/twenty-front/src/modules/object-record/object-filter-dropdown/states/selectedFilterComponentState.ts deleted file mode 100644 index f1d207d45..000000000 --- a/packages/twenty-front/src/modules/object-record/object-filter-dropdown/states/selectedFilterComponentState.ts +++ /dev/null @@ -1,11 +0,0 @@ -import { ObjectFilterDropdownComponentInstanceContext } from '@/object-record/object-filter-dropdown/states/contexts/ObjectFilterDropdownComponentInstanceContext'; -import { createComponentStateV2 } from '@/ui/utilities/state/component-state/utils/createComponentStateV2'; -import { RecordFilter } from '../../record-filter/types/RecordFilter'; - -export const selectedFilterComponentState = createComponentStateV2< - RecordFilter | undefined | null ->({ - key: 'selectedFilterComponentState', - defaultValue: undefined, - componentInstanceContext: ObjectFilterDropdownComponentInstanceContext, -}); diff --git a/packages/twenty-front/src/modules/object-record/record-filter/hooks/useApplyRecordFilter.ts b/packages/twenty-front/src/modules/object-record/record-filter/hooks/useApplyRecordFilter.ts deleted file mode 100644 index 5fabc9cbf..000000000 --- a/packages/twenty-front/src/modules/object-record/record-filter/hooks/useApplyRecordFilter.ts +++ /dev/null @@ -1,32 +0,0 @@ -import { selectedFilterComponentState } from '@/object-record/object-filter-dropdown/states/selectedFilterComponentState'; -import { useUpsertRecordFilter } from '@/object-record/record-filter/hooks/useUpsertRecordFilter'; -import { RecordFilter } from '@/object-record/record-filter/types/RecordFilter'; -import { useRecoilComponentCallbackStateV2 } from '@/ui/utilities/state/component-state/hooks/useRecoilComponentCallbackStateV2'; - -import { useRecoilCallback } from 'recoil'; -import { isDefined } from 'twenty-shared/utils'; - -export const useApplyRecordFilter = (componentInstanceId?: string) => { - const selectedFilterCallbackState = useRecoilComponentCallbackStateV2( - selectedFilterComponentState, - componentInstanceId, - ); - - const { upsertRecordFilter } = useUpsertRecordFilter(); - - const applyRecordFilter = useRecoilCallback( - ({ set }) => - (filter: RecordFilter | null) => { - set(selectedFilterCallbackState, filter); - - if (isDefined(filter)) { - upsertRecordFilter(filter); - } - }, - [selectedFilterCallbackState, upsertRecordFilter], - ); - - return { - applyRecordFilter, - }; -}; diff --git a/packages/twenty-front/src/modules/object-record/record-table/record-table-header/hooks/useOpenRecordFilterChipFromTableHeader.ts b/packages/twenty-front/src/modules/object-record/record-table/record-table-header/hooks/useOpenRecordFilterChipFromTableHeader.ts index 9aef27c50..c888d755e 100644 --- a/packages/twenty-front/src/modules/object-record/record-table/record-table-header/hooks/useOpenRecordFilterChipFromTableHeader.ts +++ b/packages/twenty-front/src/modules/object-record/record-table/record-table-header/hooks/useOpenRecordFilterChipFromTableHeader.ts @@ -1,23 +1,16 @@ -import { useSelectFilterUsedInDropdown } from '@/object-record/object-filter-dropdown/hooks/useSelectFilterUsedInDropdown'; import { useCreateEmptyRecordFilterFromFieldMetadataItem } from '@/object-record/record-filter/hooks/useCreateEmptyRecordFilterFromFieldMetadataItem'; import { useFilterableFieldMetadataItemsInRecordIndexContext } from '@/object-record/record-filter/hooks/useFilterableFieldMetadataItemsInRecordIndexContext'; import { useUpsertRecordFilter } from '@/object-record/record-filter/hooks/useUpsertRecordFilter'; import { currentRecordFiltersComponentState } from '@/object-record/record-filter/states/currentRecordFiltersComponentState'; -import { useRecordIndexContextOrThrow } from '@/object-record/record-index/contexts/RecordIndexContext'; import { useOpenDropdownFromOutside } from '@/ui/layout/dropdown/hooks/useOpenDropdownFromOutside'; import { useRecoilComponentValueV2 } from '@/ui/utilities/state/component-state/hooks/useRecoilComponentValueV2'; import { useSetEditableFilterChipDropdownStates } from '@/views/hooks/useSetEditableFilterChipDropdownStates'; import { isDefined } from 'twenty-shared/utils'; export const useOpenRecordFilterChipFromTableHeader = () => { - const { recordIndexId } = useRecordIndexContextOrThrow(); - const { filterableFieldMetadataItems } = useFilterableFieldMetadataItemsInRecordIndexContext(); - const { selectFilterUsedInDropdown } = - useSelectFilterUsedInDropdown(recordIndexId); - const currentRecordFilters = useRecoilComponentValueV2( currentRecordFiltersComponentState, ); @@ -60,8 +53,6 @@ export const useOpenRecordFilterChipFromTableHeader = () => { upsertRecordFilter(newRecordFilter); - selectFilterUsedInDropdown({ fieldMetadataItemId }); - setEditableFilterChipDropdownStates(newRecordFilter); openDropdownFromOutside(newRecordFilter.id); }; diff --git a/packages/twenty-front/src/modules/ui/input/components/internal/date/components/RelativeDatePickerHeader.tsx b/packages/twenty-front/src/modules/ui/input/components/internal/date/components/RelativeDatePickerHeader.tsx index 70643934d..0c7a15744 100644 --- a/packages/twenty-front/src/modules/ui/input/components/internal/date/components/RelativeDatePickerHeader.tsx +++ b/packages/twenty-front/src/modules/ui/input/components/internal/date/components/RelativeDatePickerHeader.tsx @@ -69,8 +69,10 @@ export const RelativeDatePickerHeader = ( }); }} options={RELATIVE_DATE_DIRECTION_SELECT_OPTIONS} + fullWidth /> { const amountString = text.replace(/[^0-9]|^0+/g, ''); @@ -106,6 +108,7 @@ export const RelativeDatePickerHeader = ( }); }} options={unitSelectOptions} + fullWidth /> ); diff --git a/packages/twenty-front/src/modules/views/components/AdvancedFilterDropdownButton.tsx b/packages/twenty-front/src/modules/views/components/AdvancedFilterDropdownButton.tsx index da51bc55c..d01ac7204 100644 --- a/packages/twenty-front/src/modules/views/components/AdvancedFilterDropdownButton.tsx +++ b/packages/twenty-front/src/modules/views/components/AdvancedFilterDropdownButton.tsx @@ -1,6 +1,7 @@ import { Dropdown } from '@/ui/layout/dropdown/components/Dropdown'; import { AdvancedFilterRootRecordFilterGroup } from '@/object-record/advanced-filter/components/AdvancedFilterRootRecordFilterGroup'; +import { useSetAdvancedFilterDropdownStates } from '@/object-record/advanced-filter/hooks/useSetAdvancedFilterDropdownAllRowsStates'; import { rootLevelRecordFilterGroupComponentSelector } from '@/object-record/advanced-filter/states/rootLevelRecordFilterGroupComponentSelector'; import { useRecoilComponentValueV2 } from '@/ui/utilities/state/component-state/hooks/useRecoilComponentValueV2'; import { AdvancedFilterChip } from '@/views/components/AdvancedFilterChip'; @@ -12,6 +13,13 @@ export const AdvancedFilterDropdownButton = () => { rootLevelRecordFilterGroupComponentSelector, ); + const { setAdvancedFilterDropdownStates } = + useSetAdvancedFilterDropdownStates(); + + const handleOpenAdvancedFilterDropdown = () => { + setAdvancedFilterDropdownStates(); + }; + if (!isDefined(rootLevelRecordFilterGroup)) { return null; } @@ -25,6 +33,7 @@ export const AdvancedFilterDropdownButton = () => { dropdownOffset={{ y: 8, x: 0 }} dropdownPlacement="bottom-start" dropdownWidth="100%" + onOpen={handleOpenAdvancedFilterDropdown} /> ); }; diff --git a/packages/twenty-front/src/modules/views/components/ViewBarFilterDropdown.tsx b/packages/twenty-front/src/modules/views/components/ViewBarFilterDropdown.tsx index 3c13dc749..450417761 100644 --- a/packages/twenty-front/src/modules/views/components/ViewBarFilterDropdown.tsx +++ b/packages/twenty-front/src/modules/views/components/ViewBarFilterDropdown.tsx @@ -3,7 +3,7 @@ import { Dropdown } from '@/ui/layout/dropdown/components/Dropdown'; import { HotkeyScope } from '@/ui/utilities/hotkey/types/HotkeyScope'; import { VIEW_BAR_FILTER_DROPDOWN_ID } from '@/views/constants/ViewBarFilterDropdownId'; -import { selectedFilterComponentState } from '@/object-record/object-filter-dropdown/states/selectedFilterComponentState'; +import { objectFilterDropdownCurrentRecordFilterComponentState } from '@/object-record/object-filter-dropdown/states/objectFilterDropdownCurrentRecordFilterComponentState'; import { useRemoveRecordFilter } from '@/object-record/record-filter/hooks/useRemoveRecordFilter'; import { isRecordFilterConsideredEmpty } from '@/object-record/record-filter/utils/isRecordFilterConsideredEmpty'; import { useRecoilComponentValueV2 } from '@/ui/utilities/state/component-state/hooks/useRecoilComponentValueV2'; @@ -22,17 +22,19 @@ export const ViewBarFilterDropdown = ({ const { removeRecordFilter } = useRemoveRecordFilter(); - const selectedFilter = useRecoilComponentValueV2( - selectedFilterComponentState, + const objectFilterDropdownCurrentRecordFilter = useRecoilComponentValueV2( + objectFilterDropdownCurrentRecordFilterComponentState, ); const handleDropdownClickOutside = () => { const recordFilterIsEmpty = - isDefined(selectedFilter) && - isRecordFilterConsideredEmpty(selectedFilter); + isDefined(objectFilterDropdownCurrentRecordFilter) && + isRecordFilterConsideredEmpty(objectFilterDropdownCurrentRecordFilter); if (recordFilterIsEmpty) { - removeRecordFilter({ recordFilterId: selectedFilter.id }); + removeRecordFilter({ + recordFilterId: objectFilterDropdownCurrentRecordFilter.id, + }); } }; diff --git a/packages/twenty-front/src/modules/views/hooks/useSetEditableFilterChipDropdownStates.ts b/packages/twenty-front/src/modules/views/hooks/useSetEditableFilterChipDropdownStates.ts index 8427b7813..bc8cd0376 100644 --- a/packages/twenty-front/src/modules/views/hooks/useSetEditableFilterChipDropdownStates.ts +++ b/packages/twenty-front/src/modules/views/hooks/useSetEditableFilterChipDropdownStates.ts @@ -2,7 +2,6 @@ import { fieldMetadataItemIdUsedInDropdownComponentState } from '@/object-record import { objectFilterDropdownCurrentRecordFilterComponentState } from '@/object-record/object-filter-dropdown/states/objectFilterDropdownCurrentRecordFilterComponentState'; import { objectFilterDropdownSelectedOptionValuesComponentState } from '@/object-record/object-filter-dropdown/states/objectFilterDropdownSelectedOptionValuesComponentState'; import { objectFilterDropdownSelectedRecordIdsComponentState } from '@/object-record/object-filter-dropdown/states/objectFilterDropdownSelectedRecordIdsComponentState'; -import { selectedFilterComponentState } from '@/object-record/object-filter-dropdown/states/selectedFilterComponentState'; import { selectedOperandInDropdownComponentState } from '@/object-record/object-filter-dropdown/states/selectedOperandInDropdownComponentState'; import { subFieldNameUsedInDropdownComponentState } from '@/object-record/object-filter-dropdown/states/subFieldNameUsedInDropdownComponentState'; import { useFilterableFieldMetadataItemsInRecordIndexContext } from '@/object-record/record-filter/hooks/useFilterableFieldMetadataItemsInRecordIndexContext'; @@ -42,13 +41,6 @@ export const useSetEditableFilterChipDropdownStates = () => { recordFilter.operand, ); - set( - selectedFilterComponentState.atomFamily({ - instanceId: recordFilter.id, - }), - recordFilter, - ); - set( objectFilterDropdownCurrentRecordFilterComponentState.atomFamily({ instanceId: recordFilter.id,