Refactored select filter and select filter definition logic (#9519)

This PR extracts the logic to manage filter and filter definition
setting.

Previously it was ambiguous, we had the same "selectFilter" naming used
for setting filter definition in filter dropdown and for setting the
actual filter value and saving to view filter states.

This is another incremental refactor, which will allow to remove
useFilterDropdown hook.
This commit is contained in:
Lucas Bordeau
2025-01-09 18:54:34 +01:00
committed by GitHub
parent 71a4593ba4
commit 17e2e38812
16 changed files with 138 additions and 72 deletions

View File

@ -4,6 +4,7 @@ import { useEffect, useState } from 'react';
import { useRecoilValue } from 'recoil'; import { useRecoilValue } from 'recoil';
import { v4 } from 'uuid'; import { v4 } from 'uuid';
import { useApplyRecordFilter } from '@/object-record/object-filter-dropdown/hooks/useApplyRecordFilter';
import { useFilterDropdown } from '@/object-record/object-filter-dropdown/hooks/useFilterDropdown'; import { useFilterDropdown } from '@/object-record/object-filter-dropdown/hooks/useFilterDropdown';
import { RelationPickerHotkeyScope } from '@/object-record/relation-picker/types/RelationPickerHotkeyScope'; import { RelationPickerHotkeyScope } from '@/object-record/relation-picker/types/RelationPickerHotkeyScope';
import { BooleanDisplay } from '@/ui/field/display/components/BooleanDisplay'; import { BooleanDisplay } from '@/ui/field/display/components/BooleanDisplay';
@ -40,9 +41,10 @@ export const ObjectFilterDropdownBooleanSelect = () => {
filterDefinitionUsedInDropdownState, filterDefinitionUsedInDropdownState,
selectedOperandInDropdownState, selectedOperandInDropdownState,
selectedFilterState, selectedFilterState,
selectFilter,
} = useFilterDropdown(); } = useFilterDropdown();
const { applyRecordFilter } = useApplyRecordFilter();
const { closeDropdown } = useDropdown(); const { closeDropdown } = useDropdown();
const filterDefinitionUsedInDropdown = useRecoilValue( const filterDefinitionUsedInDropdown = useRecoilValue(
@ -69,7 +71,7 @@ export const ObjectFilterDropdownBooleanSelect = () => {
return; return;
} }
selectFilter({ applyRecordFilter({
id: selectedFilter?.id ?? v4(), id: selectedFilter?.id ?? v4(),
definition: filterDefinitionUsedInDropdown, definition: filterDefinitionUsedInDropdown,
operand: selectedOperandInDropdown, operand: selectedOperandInDropdown,

View File

@ -1,6 +1,7 @@
import { useRecoilValue } from 'recoil'; import { useRecoilValue } from 'recoil';
import { v4 } from 'uuid'; import { v4 } from 'uuid';
import { useApplyRecordFilter } from '@/object-record/object-filter-dropdown/hooks/useApplyRecordFilter';
import { useFilterDropdown } from '@/object-record/object-filter-dropdown/hooks/useFilterDropdown'; import { useFilterDropdown } from '@/object-record/object-filter-dropdown/hooks/useFilterDropdown';
import { Filter } from '@/object-record/object-filter-dropdown/types/Filter'; import { Filter } from '@/object-record/object-filter-dropdown/types/Filter';
import { getRelativeDateDisplayValue } from '@/object-record/object-filter-dropdown/utils/getRelativeDateDisplayValue'; import { getRelativeDateDisplayValue } from '@/object-record/object-filter-dropdown/utils/getRelativeDateDisplayValue';
@ -21,9 +22,10 @@ export const ObjectFilterDropdownDateInput = () => {
filterDefinitionUsedInDropdownState, filterDefinitionUsedInDropdownState,
selectedOperandInDropdownState, selectedOperandInDropdownState,
selectedFilterState, selectedFilterState,
selectFilter,
} = useFilterDropdown(); } = useFilterDropdown();
const { applyRecordFilter } = useApplyRecordFilter();
const filterDefinitionUsedInDropdown = useRecoilValue( const filterDefinitionUsedInDropdown = useRecoilValue(
filterDefinitionUsedInDropdownState, filterDefinitionUsedInDropdownState,
); );
@ -51,7 +53,7 @@ export const ObjectFilterDropdownDateInput = () => {
if (!filterDefinitionUsedInDropdown || !selectedOperandInDropdown) return; if (!filterDefinitionUsedInDropdown || !selectedOperandInDropdown) return;
selectFilter?.({ applyRecordFilter({
id: selectedFilter?.id ? selectedFilter.id : v4(), id: selectedFilter?.id ? selectedFilter.id : v4(),
fieldMetadataId: filterDefinitionUsedInDropdown.fieldMetadataId, fieldMetadataId: filterDefinitionUsedInDropdown.fieldMetadataId,
value: newDate?.toISOString() ?? '', value: newDate?.toISOString() ?? '',
@ -83,7 +85,7 @@ export const ObjectFilterDropdownDateInput = () => {
) )
: ''; : '';
selectFilter?.({ applyRecordFilter({
id: selectedFilter?.id ? selectedFilter.id : v4(), id: selectedFilter?.id ? selectedFilter.id : v4(),
fieldMetadataId: filterDefinitionUsedInDropdown.fieldMetadataId, fieldMetadataId: filterDefinitionUsedInDropdown.fieldMetadataId,
value, value,

View File

@ -7,7 +7,7 @@ import { AdvancedFilterButton } from '@/object-record/object-filter-dropdown/com
import { ObjectFilterDropdownFilterSelectMenuItem } from '@/object-record/object-filter-dropdown/components/ObjectFilterDropdownFilterSelectMenuItem'; import { ObjectFilterDropdownFilterSelectMenuItem } from '@/object-record/object-filter-dropdown/components/ObjectFilterDropdownFilterSelectMenuItem';
import { OBJECT_FILTER_DROPDOWN_ID } from '@/object-record/object-filter-dropdown/constants/ObjectFilterDropdownId'; import { OBJECT_FILTER_DROPDOWN_ID } from '@/object-record/object-filter-dropdown/constants/ObjectFilterDropdownId';
import { useFilterDropdown } from '@/object-record/object-filter-dropdown/hooks/useFilterDropdown'; import { useFilterDropdown } from '@/object-record/object-filter-dropdown/hooks/useFilterDropdown';
import { useSelectFilter } from '@/object-record/object-filter-dropdown/hooks/useSelectFilter'; import { useSelectFilterDefinitionUsedInDropdown } from '@/object-record/object-filter-dropdown/hooks/useSelectFilterDefinitionUsedInDropdown';
import { FiltersHotkeyScope } from '@/object-record/object-filter-dropdown/types/FiltersHotkeyScope'; import { FiltersHotkeyScope } from '@/object-record/object-filter-dropdown/types/FiltersHotkeyScope';
import { useRecordIndexContextOrThrow } from '@/object-record/record-index/contexts/RecordIndexContext'; import { useRecordIndexContextOrThrow } from '@/object-record/record-index/contexts/RecordIndexContext';
import { hiddenTableColumnsComponentSelector } from '@/object-record/record-table/states/selectors/hiddenTableColumnsComponentSelector'; import { hiddenTableColumnsComponentSelector } from '@/object-record/record-table/states/selectors/hiddenTableColumnsComponentSelector';
@ -121,7 +121,8 @@ export const ObjectFilterDropdownFilterSelect = ({
(item) => item.fieldMetadataId, (item) => item.fieldMetadataId,
); );
const { selectFilter } = useSelectFilter(); const { selectFilterDefinitionUsedInDropdown } =
useSelectFilterDefinitionUsedInDropdown();
const { resetSelectedItem } = useSelectableList(OBJECT_FILTER_DROPDOWN_ID); const { resetSelectedItem } = useSelectableList(OBJECT_FILTER_DROPDOWN_ID);
@ -135,7 +136,11 @@ export const ObjectFilterDropdownFilterSelect = ({
} }
resetSelectedItem(); resetSelectedItem();
selectFilter({ filterDefinition: selectedFilterDefinition });
selectFilterDefinitionUsedInDropdown({
filterDefinition: selectedFilterDefinition,
});
closeAdvancedFilterDropdown(); closeAdvancedFilterDropdown();
}; };

View File

@ -1,4 +1,5 @@
import { useAdvancedFilterDropdown } from '@/object-record/advanced-filter/hooks/useAdvancedFilterDropdown'; import { useAdvancedFilterDropdown } from '@/object-record/advanced-filter/hooks/useAdvancedFilterDropdown';
import { useApplyRecordFilter } from '@/object-record/object-filter-dropdown/hooks/useApplyRecordFilter';
import { useFilterDropdown } from '@/object-record/object-filter-dropdown/hooks/useFilterDropdown'; import { useFilterDropdown } from '@/object-record/object-filter-dropdown/hooks/useFilterDropdown';
import { objectFilterDropdownFilterIsSelectedComponentState } from '@/object-record/object-filter-dropdown/states/objectFilterDropdownFilterIsSelectedComponentState'; import { objectFilterDropdownFilterIsSelectedComponentState } from '@/object-record/object-filter-dropdown/states/objectFilterDropdownFilterIsSelectedComponentState';
import { objectFilterDropdownFirstLevelFilterDefinitionComponentState } from '@/object-record/object-filter-dropdown/states/objectFilterDropdownFirstLevelFilterDefinitionComponentState'; import { objectFilterDropdownFirstLevelFilterDefinitionComponentState } from '@/object-record/object-filter-dropdown/states/objectFilterDropdownFirstLevelFilterDefinitionComponentState';
@ -55,11 +56,12 @@ export const ObjectFilterDropdownFilterSelectCompositeFieldSubMenu = () => {
setFilterDefinitionUsedInDropdown, setFilterDefinitionUsedInDropdown,
setSelectedOperandInDropdown, setSelectedOperandInDropdown,
setObjectFilterDropdownSearchInput, setObjectFilterDropdownSearchInput,
selectFilter,
advancedFilterViewFilterIdState, advancedFilterViewFilterIdState,
advancedFilterViewFilterGroupIdState, advancedFilterViewFilterGroupIdState,
} = useFilterDropdown(); } = useFilterDropdown();
const { applyRecordFilter } = useApplyRecordFilter();
const advancedFilterViewFilterId = useRecoilValue( const advancedFilterViewFilterId = useRecoilValue(
advancedFilterViewFilterIdState, advancedFilterViewFilterIdState,
); );
@ -84,7 +86,8 @@ export const ObjectFilterDropdownFilterSelectCompositeFieldSubMenu = () => {
definition.type, definition.type,
operand, operand,
); );
selectFilter({
applyRecordFilter({
id: advancedFilterViewFilterId, id: advancedFilterViewFilterId,
fieldMetadataId: definition.fieldMetadataId, fieldMetadataId: definition.fieldMetadataId,
value, value,

View File

@ -1,7 +1,7 @@
import { useAdvancedFilterDropdown } from '@/object-record/advanced-filter/hooks/useAdvancedFilterDropdown'; import { useAdvancedFilterDropdown } from '@/object-record/advanced-filter/hooks/useAdvancedFilterDropdown';
import { OBJECT_FILTER_DROPDOWN_ID } from '@/object-record/object-filter-dropdown/constants/ObjectFilterDropdownId'; import { OBJECT_FILTER_DROPDOWN_ID } from '@/object-record/object-filter-dropdown/constants/ObjectFilterDropdownId';
import { useFilterDropdown } from '@/object-record/object-filter-dropdown/hooks/useFilterDropdown'; import { useFilterDropdown } from '@/object-record/object-filter-dropdown/hooks/useFilterDropdown';
import { useSelectFilter } from '@/object-record/object-filter-dropdown/hooks/useSelectFilter'; import { useSelectFilterDefinitionUsedInDropdown } from '@/object-record/object-filter-dropdown/hooks/useSelectFilterDefinitionUsedInDropdown';
import { objectFilterDropdownFilterIsSelectedComponentState } from '@/object-record/object-filter-dropdown/states/objectFilterDropdownFilterIsSelectedComponentState'; import { objectFilterDropdownFilterIsSelectedComponentState } from '@/object-record/object-filter-dropdown/states/objectFilterDropdownFilterIsSelectedComponentState';
import { objectFilterDropdownFirstLevelFilterDefinitionComponentState } from '@/object-record/object-filter-dropdown/states/objectFilterDropdownFirstLevelFilterDefinitionComponentState'; import { objectFilterDropdownFirstLevelFilterDefinitionComponentState } from '@/object-record/object-filter-dropdown/states/objectFilterDropdownFirstLevelFilterDefinitionComponentState';
import { objectFilterDropdownIsSelectingCompositeFieldComponentState } from '@/object-record/object-filter-dropdown/states/objectFilterDropdownIsSelectingCompositeFieldComponentState'; import { objectFilterDropdownIsSelectingCompositeFieldComponentState } from '@/object-record/object-filter-dropdown/states/objectFilterDropdownIsSelectingCompositeFieldComponentState';
@ -25,7 +25,8 @@ export type ObjectFilterDropdownFilterSelectMenuItemProps = {
export const ObjectFilterDropdownFilterSelectMenuItem = ({ export const ObjectFilterDropdownFilterSelectMenuItem = ({
filterDefinition, filterDefinition,
}: ObjectFilterDropdownFilterSelectMenuItemProps) => { }: ObjectFilterDropdownFilterSelectMenuItemProps) => {
const { selectFilter } = useSelectFilter(); const { selectFilterDefinitionUsedInDropdown } =
useSelectFilterDefinitionUsedInDropdown();
const [, setObjectFilterDropdownFirstLevelFilterDefinition] = const [, setObjectFilterDropdownFirstLevelFilterDefinition] =
useRecoilComponentStateV2( useRecoilComponentStateV2(
@ -55,12 +56,8 @@ export const ObjectFilterDropdownFilterSelectMenuItem = ({
const isACompositeField = isCompositeField(filterDefinition.type); const isACompositeField = isCompositeField(filterDefinition.type);
const { const { setSelectedOperandInDropdown, advancedFilterViewFilterIdState } =
setFilterDefinitionUsedInDropdown, useFilterDropdown();
setSelectedOperandInDropdown,
setObjectFilterDropdownSearchInput,
advancedFilterViewFilterIdState,
} = useFilterDropdown();
const setHotkeyScope = useSetHotkeyScope(); const setHotkeyScope = useSetHotkeyScope();
@ -72,11 +69,14 @@ export const ObjectFilterDropdownFilterSelectMenuItem = ({
advancedFilterViewFilterId, advancedFilterViewFilterId,
); );
const handleSelectFilter = (availableFilterDefinition: FilterDefinition) => { const handleSelectFilterDefinition = (
availableFilterDefinition: FilterDefinition,
) => {
closeAdvancedFilterDropdown(); closeAdvancedFilterDropdown();
selectFilter({ filterDefinition: availableFilterDefinition });
setFilterDefinitionUsedInDropdown(availableFilterDefinition); selectFilterDefinitionUsedInDropdown({
filterDefinition: availableFilterDefinition,
});
if ( if (
availableFilterDefinition.type === 'RELATION' || availableFilterDefinition.type === 'RELATION' ||
@ -89,8 +89,6 @@ export const ObjectFilterDropdownFilterSelectMenuItem = ({
getOperandsForFilterDefinition(availableFilterDefinition)[0], getOperandsForFilterDefinition(availableFilterDefinition)[0],
); );
setObjectFilterDropdownSearchInput('');
setObjectFilterDropdownFilterIsSelected(true); setObjectFilterDropdownFilterIsSelected(true);
}; };
@ -107,7 +105,7 @@ export const ObjectFilterDropdownFilterSelectMenuItem = ({
setObjectFilterDropdownFirstLevelFilterDefinition(filterDefinition); setObjectFilterDropdownFirstLevelFilterDefinition(filterDefinition);
setObjectFilterDropdownIsSelectingCompositeField(true); setObjectFilterDropdownIsSelectingCompositeField(true);
} else { } else {
handleSelectFilter(filterDefinition); handleSelectFilterDefinition(filterDefinition);
} }
}; };

View File

@ -2,6 +2,7 @@ import { ChangeEvent, useCallback, useState } from 'react';
import { useRecoilValue } from 'recoil'; import { useRecoilValue } from 'recoil';
import { v4 } from 'uuid'; import { v4 } from 'uuid';
import { useApplyRecordFilter } from '@/object-record/object-filter-dropdown/hooks/useApplyRecordFilter';
import { useFilterDropdown } from '@/object-record/object-filter-dropdown/hooks/useFilterDropdown'; import { useFilterDropdown } from '@/object-record/object-filter-dropdown/hooks/useFilterDropdown';
import { DropdownMenuInput } from '@/ui/layout/dropdown/components/DropdownMenuInput'; import { DropdownMenuInput } from '@/ui/layout/dropdown/components/DropdownMenuInput';
@ -10,8 +11,10 @@ export const ObjectFilterDropdownNumberInput = () => {
selectedOperandInDropdownState, selectedOperandInDropdownState,
filterDefinitionUsedInDropdownState, filterDefinitionUsedInDropdownState,
selectedFilterState, selectedFilterState,
selectFilter,
} = useFilterDropdown(); } = useFilterDropdown();
const { applyRecordFilter } = useApplyRecordFilter();
const [hasFocused, setHasFocused] = useState(false); const [hasFocused, setHasFocused] = useState(false);
const filterDefinitionUsedInDropdown = useRecoilValue( const filterDefinitionUsedInDropdown = useRecoilValue(
@ -48,8 +51,10 @@ export const ObjectFilterDropdownNumberInput = () => {
placeholder={filterDefinitionUsedInDropdown.label} placeholder={filterDefinitionUsedInDropdown.label}
onChange={(event: ChangeEvent<HTMLInputElement>) => { onChange={(event: ChangeEvent<HTMLInputElement>) => {
const newValue = event.target.value; const newValue = event.target.value;
setInputValue(newValue); setInputValue(newValue);
selectFilter?.({
applyRecordFilter({
id: selectedFilter?.id ? selectedFilter.id : v4(), id: selectedFilter?.id ? selectedFilter.id : v4(),
fieldMetadataId: filterDefinitionUsedInDropdown.fieldMetadataId, fieldMetadataId: filterDefinitionUsedInDropdown.fieldMetadataId,
value: newValue, value: newValue,

View File

@ -1,6 +1,7 @@
import { useRecoilValue } from 'recoil'; import { useRecoilValue } from 'recoil';
import { v4 } from 'uuid'; import { v4 } from 'uuid';
import { useApplyRecordFilter } from '@/object-record/object-filter-dropdown/hooks/useApplyRecordFilter';
import { useFilterDropdown } from '@/object-record/object-filter-dropdown/hooks/useFilterDropdown'; import { useFilterDropdown } from '@/object-record/object-filter-dropdown/hooks/useFilterDropdown';
import { getInitialFilterValue } from '@/object-record/object-filter-dropdown/utils/getInitialFilterValue'; import { getInitialFilterValue } from '@/object-record/object-filter-dropdown/utils/getInitialFilterValue';
import { DropdownMenuItemsContainer } from '@/ui/layout/dropdown/components/DropdownMenuItemsContainer'; import { DropdownMenuItemsContainer } from '@/ui/layout/dropdown/components/DropdownMenuItemsContainer';
@ -22,9 +23,10 @@ export const ObjectFilterDropdownOperandSelect = () => {
filterDefinitionUsedInDropdownState, filterDefinitionUsedInDropdownState,
setSelectedOperandInDropdown, setSelectedOperandInDropdown,
selectedFilterState, selectedFilterState,
selectFilter,
} = useFilterDropdown(); } = useFilterDropdown();
const { applyRecordFilter } = useApplyRecordFilter();
const { closeDropdown } = useDropdown(); const { closeDropdown } = useDropdown();
const filterDefinitionUsedInDropdown = useRecoilValue( const filterDefinitionUsedInDropdown = useRecoilValue(
@ -49,7 +51,7 @@ export const ObjectFilterDropdownOperandSelect = () => {
setSelectedOperandInDropdown(newOperand); setSelectedOperandInDropdown(newOperand);
if (isValuelessOperand && isDefined(filterDefinitionUsedInDropdown)) { if (isValuelessOperand && isDefined(filterDefinitionUsedInDropdown)) {
selectFilter?.({ applyRecordFilter({
id: v4(), id: v4(),
fieldMetadataId: filterDefinitionUsedInDropdown?.fieldMetadataId ?? '', fieldMetadataId: filterDefinitionUsedInDropdown?.fieldMetadataId ?? '',
displayValue: '', displayValue: '',
@ -71,7 +73,7 @@ export const ObjectFilterDropdownOperandSelect = () => {
selectedFilter.displayValue, selectedFilter.displayValue,
); );
selectFilter?.({ applyRecordFilter({
id: selectedFilter.id ? selectedFilter.id : v4(), id: selectedFilter.id ? selectedFilter.id : v4(),
fieldMetadataId: selectedFilter.fieldMetadataId, fieldMetadataId: selectedFilter.fieldMetadataId,
displayValue, displayValue,

View File

@ -14,6 +14,7 @@ import { SelectableList } from '@/ui/layout/selectable-list/components/Selectabl
import { useSelectableListStates } from '@/ui/layout/selectable-list/hooks/internal/useSelectableListStates'; import { useSelectableListStates } from '@/ui/layout/selectable-list/hooks/internal/useSelectableListStates';
import { useSelectableList } from '@/ui/layout/selectable-list/hooks/useSelectableList'; import { useSelectableList } from '@/ui/layout/selectable-list/hooks/useSelectableList';
import { useApplyRecordFilter } from '@/object-record/object-filter-dropdown/hooks/useApplyRecordFilter';
import { useScopedHotkeys } from '@/ui/utilities/hotkey/hooks/useScopedHotkeys'; import { useScopedHotkeys } from '@/ui/utilities/hotkey/hooks/useScopedHotkeys';
import { MenuItem, MenuItemMultiSelect } from 'twenty-ui'; import { MenuItem, MenuItemMultiSelect } from 'twenty-ui';
import { isDefined } from '~/utils/isDefined'; import { isDefined } from '~/utils/isDefined';
@ -32,9 +33,10 @@ export const ObjectFilterDropdownOptionSelect = () => {
selectedOperandInDropdownState, selectedOperandInDropdownState,
objectFilterDropdownSelectedOptionValuesState, objectFilterDropdownSelectedOptionValuesState,
selectedFilterState, selectedFilterState,
selectFilter,
} = useFilterDropdown(); } = useFilterDropdown();
const { applyRecordFilter } = useApplyRecordFilter();
const { closeDropdown } = useDropdown(); const { closeDropdown } = useDropdown();
const { selectedItemIdState } = useSelectableListStates({ const { selectedItemIdState } = useSelectableListStates({
@ -128,7 +130,7 @@ export const ObjectFilterDropdownOptionSelect = () => {
? JSON.stringify(selectedOptions.map((option) => option.value)) ? JSON.stringify(selectedOptions.map((option) => option.value))
: EMPTY_FILTER_VALUE; : EMPTY_FILTER_VALUE;
selectFilter({ applyRecordFilter({
id: selectedFilter?.id ? selectedFilter.id : v4(), id: selectedFilter?.id ? selectedFilter.id : v4(),
definition: filterDefinitionUsedInDropdown, definition: filterDefinitionUsedInDropdown,
operand: selectedOperandInDropdown, operand: selectedOperandInDropdown,

View File

@ -1,6 +1,7 @@
import { useRecoilValue } from 'recoil'; import { useRecoilValue } from 'recoil';
import { v4 } from 'uuid'; import { v4 } from 'uuid';
import { useApplyRecordFilter } from '@/object-record/object-filter-dropdown/hooks/useApplyRecordFilter';
import { useFilterDropdown } from '@/object-record/object-filter-dropdown/hooks/useFilterDropdown'; import { useFilterDropdown } from '@/object-record/object-filter-dropdown/hooks/useFilterDropdown';
import { RATING_VALUES } from '@/object-record/record-field/meta-types/constants/RatingValues'; import { RATING_VALUES } from '@/object-record/record-field/meta-types/constants/RatingValues';
import { FieldRatingValue } from '@/object-record/record-field/types/FieldMetadata'; import { FieldRatingValue } from '@/object-record/record-field/types/FieldMetadata';
@ -34,7 +35,6 @@ export const ObjectFilterDropdownRatingInput = () => {
selectedOperandInDropdownState, selectedOperandInDropdownState,
filterDefinitionUsedInDropdownState, filterDefinitionUsedInDropdownState,
selectedFilterState, selectedFilterState,
selectFilter,
} = useFilterDropdown(); } = useFilterDropdown();
const filterDefinitionUsedInDropdown = useRecoilValue( const filterDefinitionUsedInDropdown = useRecoilValue(
@ -46,6 +46,8 @@ export const ObjectFilterDropdownRatingInput = () => {
const selectedFilter = useRecoilValue(selectedFilterState); const selectedFilter = useRecoilValue(selectedFilterState);
const { applyRecordFilter } = useApplyRecordFilter();
return ( return (
filterDefinitionUsedInDropdown && filterDefinitionUsedInDropdown &&
selectedOperandInDropdown && ( selectedOperandInDropdown && (
@ -57,7 +59,7 @@ export const ObjectFilterDropdownRatingInput = () => {
return; return;
} }
selectFilter?.({ applyRecordFilter?.({
id: selectedFilter?.id ? selectedFilter.id : v4(), id: selectedFilter?.id ? selectedFilter.id : v4(),
fieldMetadataId: filterDefinitionUsedInDropdown.fieldMetadataId, fieldMetadataId: filterDefinitionUsedInDropdown.fieldMetadataId,
value: convertFieldRatingValueToNumber(newValue), value: convertFieldRatingValueToNumber(newValue),

View File

@ -5,6 +5,7 @@ import { v4 } from 'uuid';
import { useObjectMetadataItem } from '@/object-metadata/hooks/useObjectMetadataItem'; import { useObjectMetadataItem } from '@/object-metadata/hooks/useObjectMetadataItem';
import { ObjectFilterDropdownRecordPinnedItems } from '@/object-record/object-filter-dropdown/components/ObjectFilterDropdownRecordPinnedItems'; 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 { CURRENT_WORKSPACE_MEMBER_SELECTABLE_ITEM_ID } from '@/object-record/object-filter-dropdown/constants/CurrentWorkspaceMemberSelectableItemId';
import { useApplyRecordFilter } from '@/object-record/object-filter-dropdown/hooks/useApplyRecordFilter';
import { useFilterDropdown } from '@/object-record/object-filter-dropdown/hooks/useFilterDropdown'; import { useFilterDropdown } from '@/object-record/object-filter-dropdown/hooks/useFilterDropdown';
import { RelationPickerHotkeyScope } from '@/object-record/relation-picker/types/RelationPickerHotkeyScope'; import { RelationPickerHotkeyScope } from '@/object-record/relation-picker/types/RelationPickerHotkeyScope';
import { MultipleSelectDropdown } from '@/object-record/select/components/MultipleSelectDropdown'; import { MultipleSelectDropdown } from '@/object-record/select/components/MultipleSelectDropdown';
@ -37,9 +38,10 @@ export const ObjectFilterDropdownRecordSelect = ({
selectedOperandInDropdownState, selectedOperandInDropdownState,
selectedFilterState, selectedFilterState,
objectFilterDropdownSelectedRecordIdsState, objectFilterDropdownSelectedRecordIdsState,
selectFilter,
} = useFilterDropdown(); } = useFilterDropdown();
const { applyRecordFilter } = useApplyRecordFilter(viewComponentId);
const { currentViewWithCombinedFiltersAndSorts } = const { currentViewWithCombinedFiltersAndSorts } =
useGetCurrentView(viewComponentId); useGetCurrentView(viewComponentId);
@ -187,7 +189,7 @@ export const ObjectFilterDropdownRecordSelect = ({
const filterId = viewFilter?.id ?? fieldId; const filterId = viewFilter?.id ?? fieldId;
selectFilter({ applyRecordFilter({
id: selectedFilter?.id ? selectedFilter.id : filterId, id: selectedFilter?.id ? selectedFilter.id : filterId,
definition: filterDefinitionUsedInDropdown, definition: filterDefinitionUsedInDropdown,
operand: selectedOperandInDropdown, operand: selectedOperandInDropdown,

View File

@ -2,6 +2,7 @@ import { useState } from 'react';
import { useRecoilValue } from 'recoil'; import { useRecoilValue } from 'recoil';
import { v4 } from 'uuid'; import { v4 } from 'uuid';
import { useApplyRecordFilter } from '@/object-record/object-filter-dropdown/hooks/useApplyRecordFilter';
import { useFilterDropdown } from '@/object-record/object-filter-dropdown/hooks/useFilterDropdown'; import { useFilterDropdown } from '@/object-record/object-filter-dropdown/hooks/useFilterDropdown';
import { getActorSourceMultiSelectOptions } from '@/object-record/object-filter-dropdown/utils/getActorSourceMultiSelectOptions'; import { getActorSourceMultiSelectOptions } from '@/object-record/object-filter-dropdown/utils/getActorSourceMultiSelectOptions';
import { RelationPickerHotkeyScope } from '@/object-record/relation-picker/types/RelationPickerHotkeyScope'; import { RelationPickerHotkeyScope } from '@/object-record/relation-picker/types/RelationPickerHotkeyScope';
@ -29,10 +30,11 @@ export const ObjectFilterDropdownSourceSelect = ({
selectedFilterState, selectedFilterState,
setObjectFilterDropdownSelectedRecordIds, setObjectFilterDropdownSelectedRecordIds,
objectFilterDropdownSelectedRecordIdsState, objectFilterDropdownSelectedRecordIdsState,
selectFilter,
emptyFilterButKeepDefinition, emptyFilterButKeepDefinition,
} = useFilterDropdown(); } = useFilterDropdown();
const { applyRecordFilter } = useApplyRecordFilter(viewComponentId);
const { deleteCombinedViewFilter } = const { deleteCombinedViewFilter } =
useDeleteCombinedViewFilters(viewComponentId); useDeleteCombinedViewFilters(viewComponentId);
@ -108,7 +110,7 @@ export const ObjectFilterDropdownSourceSelect = ({
const filterId = viewFilter?.id ?? fieldId; const filterId = viewFilter?.id ?? fieldId;
selectFilter({ applyRecordFilter({
id: selectedFilter?.id ? selectedFilter.id : filterId, id: selectedFilter?.id ? selectedFilter.id : filterId,
definition: filterDefinitionUsedInDropdown, definition: filterDefinitionUsedInDropdown,
operand: selectedOperandInDropdown || ViewFilterOperand.Is, operand: selectedOperandInDropdown || ViewFilterOperand.Is,

View File

@ -2,6 +2,7 @@ import { ChangeEvent, useCallback, useState } from 'react';
import { useRecoilValue } from 'recoil'; import { useRecoilValue } from 'recoil';
import { v4 } from 'uuid'; import { v4 } from 'uuid';
import { useApplyRecordFilter } from '@/object-record/object-filter-dropdown/hooks/useApplyRecordFilter';
import { useFilterDropdown } from '@/object-record/object-filter-dropdown/hooks/useFilterDropdown'; import { useFilterDropdown } from '@/object-record/object-filter-dropdown/hooks/useFilterDropdown';
import { DropdownMenuSearchInput } from '@/ui/layout/dropdown/components/DropdownMenuSearchInput'; import { DropdownMenuSearchInput } from '@/ui/layout/dropdown/components/DropdownMenuSearchInput';
@ -12,7 +13,6 @@ export const ObjectFilterDropdownTextSearchInput = () => {
objectFilterDropdownSearchInputState, objectFilterDropdownSearchInputState,
setObjectFilterDropdownSearchInput, setObjectFilterDropdownSearchInput,
selectedFilterState, selectedFilterState,
selectFilter,
} = useFilterDropdown(); } = useFilterDropdown();
const [filterId] = useState(v4()); const [filterId] = useState(v4());
@ -29,6 +29,8 @@ export const ObjectFilterDropdownTextSearchInput = () => {
); );
const selectedFilter = useRecoilValue(selectedFilterState); const selectedFilter = useRecoilValue(selectedFilterState);
const { applyRecordFilter } = useApplyRecordFilter();
const handleInputRef = useCallback( const handleInputRef = useCallback(
(node: HTMLInputElement | null) => { (node: HTMLInputElement | null) => {
if (Boolean(node) && !hasFocused) { if (Boolean(node) && !hasFocused) {
@ -51,7 +53,7 @@ export const ObjectFilterDropdownTextSearchInput = () => {
onChange={(event: ChangeEvent<HTMLInputElement>) => { onChange={(event: ChangeEvent<HTMLInputElement>) => {
setObjectFilterDropdownSearchInput(event.target.value); setObjectFilterDropdownSearchInput(event.target.value);
selectFilter?.({ applyRecordFilter({
id: selectedFilter?.id ?? filterId, id: selectedFilter?.id ?? filterId,
fieldMetadataId: filterDefinitionUsedInDropdown.fieldMetadataId, fieldMetadataId: filterDefinitionUsedInDropdown.fieldMetadataId,
value: event.target.value, value: event.target.value,

View File

@ -2,6 +2,7 @@ import { expect } from '@storybook/test';
import { act, renderHook, waitFor } from '@testing-library/react'; import { act, renderHook, waitFor } from '@testing-library/react';
import { RecoilRoot, useRecoilState } from 'recoil'; import { RecoilRoot, useRecoilState } from 'recoil';
import { useApplyRecordFilter } from '@/object-record/object-filter-dropdown/hooks/useApplyRecordFilter';
import { useFilterDropdown } from '@/object-record/object-filter-dropdown/hooks/useFilterDropdown'; import { useFilterDropdown } from '@/object-record/object-filter-dropdown/hooks/useFilterDropdown';
import { useFilterDropdownStates } from '@/object-record/object-filter-dropdown/hooks/useFilterDropdownStates'; import { useFilterDropdownStates } from '@/object-record/object-filter-dropdown/hooks/useFilterDropdownStates';
import { Filter } from '@/object-record/object-filter-dropdown/types/Filter'; import { Filter } from '@/object-record/object-filter-dropdown/types/Filter';
@ -261,19 +262,26 @@ describe('useFilterDropdown', () => {
it('should reset filter', async () => { it('should reset filter', async () => {
const { result } = renderHook(() => { const { result } = renderHook(() => {
const { resetFilter, selectFilter } = useFilterDropdown({ const { resetFilter } = useFilterDropdown({
filterDropdownId, filterDropdownId,
}); });
const { applyRecordFilter } = useApplyRecordFilter(filterDropdownId);
const { selectedFilterState } = useFilterDropdownStates(filterDropdownId); const { selectedFilterState } = useFilterDropdownStates(filterDropdownId);
const [selectedFilter, setSelectedFilter] = const [selectedFilter, setSelectedFilter] =
useRecoilState(selectedFilterState); useRecoilState(selectedFilterState);
return { selectedFilter, setSelectedFilter, selectFilter, resetFilter }; return {
selectedFilter,
setSelectedFilter,
applyRecordFilter,
resetFilter,
};
}, renderHookConfig); }, renderHookConfig);
act(() => { act(() => {
result.current.selectFilter(mockFilter); result.current.applyRecordFilter(mockFilter);
}); });
await waitFor(() => { await waitFor(() => {
@ -291,12 +299,13 @@ describe('useFilterDropdown', () => {
it('should call onFilterSelect when a filter option is set', async () => { it('should call onFilterSelect when a filter option is set', async () => {
const { result } = renderHook(() => { const { result } = renderHook(() => {
const { selectFilter } = useFilterDropdown({ filterDropdownId }); const { applyRecordFilter } = useApplyRecordFilter(filterDropdownId);
const { onFilterSelectState } = useFilterDropdownStates(filterDropdownId); const { onFilterSelectState } = useFilterDropdownStates(filterDropdownId);
const [onFilterSelect, setOnFilterSelect] = const [onFilterSelect, setOnFilterSelect] =
useRecoilState(onFilterSelectState); useRecoilState(onFilterSelectState);
return { onFilterSelect, setOnFilterSelect, selectFilter }; return { onFilterSelect, setOnFilterSelect, applyRecordFilter };
}, renderHookConfig); }, renderHookConfig);
const onFilterSelectMock = jest.fn(); const onFilterSelectMock = jest.fn();
@ -304,7 +313,7 @@ describe('useFilterDropdown', () => {
act(() => { act(() => {
result.current.setOnFilterSelect(onFilterSelectMock); result.current.setOnFilterSelect(onFilterSelectMock);
result.current.selectFilter(mockFilter); result.current.applyRecordFilter(mockFilter);
}); });
await waitFor(() => { await waitFor(() => {

View File

@ -0,0 +1,48 @@
import { onFilterSelectComponentState } from '@/object-record/object-filter-dropdown/states/onFilterSelectComponentState';
import { selectedFilterComponentState } from '@/object-record/object-filter-dropdown/states/selectedFilterComponentState';
import { Filter } from '@/object-record/object-filter-dropdown/types/Filter';
import { getSnapshotValue } from '@/ui/utilities/recoil-scope/utils/getSnapshotValue';
import { useRecoilComponentCallbackStateV2 } from '@/ui/utilities/state/component-state/hooks/useRecoilComponentCallbackStateV2';
import { useUpsertCombinedViewFilters } from '@/views/hooks/useUpsertCombinedViewFilters';
import { useRecoilCallback } from 'recoil';
import { isDefined } from 'twenty-ui';
export const useApplyRecordFilter = (componentInstanceId?: string) => {
const { upsertCombinedViewFilter } = useUpsertCombinedViewFilters();
const selectedFilterCallbackState = useRecoilComponentCallbackStateV2(
selectedFilterComponentState,
componentInstanceId,
);
const onFilterSelectCallbackState = useRecoilComponentCallbackStateV2(
onFilterSelectComponentState,
componentInstanceId,
);
const applyRecordFilter = useRecoilCallback(
({ set, snapshot }) =>
(filter: Filter | null) => {
set(selectedFilterCallbackState, filter);
const onFilterSelect = getSnapshotValue(
snapshot,
onFilterSelectCallbackState,
);
if (isDefined(filter)) {
upsertCombinedViewFilter(filter);
}
onFilterSelect?.(filter);
},
[
selectedFilterCallbackState,
onFilterSelectCallbackState,
upsertCombinedViewFilter,
],
);
return {
applyRecordFilter,
};
};

View File

@ -1,16 +1,12 @@
import { useRecoilCallback, useSetRecoilState } from 'recoil'; import { useRecoilCallback, useSetRecoilState } from 'recoil';
import { useFilterDropdownStates } from '@/object-record/object-filter-dropdown/hooks/useFilterDropdownStates'; import { useFilterDropdownStates } from '@/object-record/object-filter-dropdown/hooks/useFilterDropdownStates';
import { getSnapshotValue } from '@/ui/utilities/recoil-scope/utils/getSnapshotValue';
import { ObjectFilterDropdownComponentInstanceContext } from '@/object-record/object-filter-dropdown/states/contexts/ObjectFilterDropdownComponentInstanceContext'; import { ObjectFilterDropdownComponentInstanceContext } from '@/object-record/object-filter-dropdown/states/contexts/ObjectFilterDropdownComponentInstanceContext';
import { objectFilterDropdownFilterIsSelectedComponentState } from '@/object-record/object-filter-dropdown/states/objectFilterDropdownFilterIsSelectedComponentState'; import { objectFilterDropdownFilterIsSelectedComponentState } from '@/object-record/object-filter-dropdown/states/objectFilterDropdownFilterIsSelectedComponentState';
import { objectFilterDropdownIsSelectingCompositeFieldComponentState } from '@/object-record/object-filter-dropdown/states/objectFilterDropdownIsSelectingCompositeFieldComponentState'; import { objectFilterDropdownIsSelectingCompositeFieldComponentState } from '@/object-record/object-filter-dropdown/states/objectFilterDropdownIsSelectingCompositeFieldComponentState';
import { useAvailableComponentInstanceIdOrThrow } from '@/ui/utilities/state/component-state/hooks/useAvailableComponentInstanceIdOrThrow'; import { useAvailableComponentInstanceIdOrThrow } from '@/ui/utilities/state/component-state/hooks/useAvailableComponentInstanceIdOrThrow';
import { useRecoilComponentCallbackStateV2 } from '@/ui/utilities/state/component-state/hooks/useRecoilComponentCallbackStateV2'; import { useRecoilComponentCallbackStateV2 } from '@/ui/utilities/state/component-state/hooks/useRecoilComponentCallbackStateV2';
import { useUpsertCombinedViewFilters } from '@/views/hooks/useUpsertCombinedViewFilters';
import { isDefined } from 'twenty-ui';
import { Filter } from '../types/Filter';
type UseFilterDropdownProps = { type UseFilterDropdownProps = {
filterDropdownId?: string; filterDropdownId?: string;
@ -34,23 +30,6 @@ export const useFilterDropdown = (props?: UseFilterDropdownProps) => {
advancedFilterViewFilterIdState, advancedFilterViewFilterIdState,
} = useFilterDropdownStates(componentInstanceId); } = useFilterDropdownStates(componentInstanceId);
const { upsertCombinedViewFilter } = useUpsertCombinedViewFilters();
const selectFilter = useRecoilCallback(
({ set, snapshot }) =>
(filter: Filter | null) => {
set(selectedFilterState, filter);
const onFilterSelect = getSnapshotValue(snapshot, onFilterSelectState);
if (isDefined(filter)) {
upsertCombinedViewFilter(filter);
}
onFilterSelect?.(filter);
},
[selectedFilterState, onFilterSelectState, upsertCombinedViewFilter],
);
const emptyFilterButKeepDefinition = useRecoilCallback( const emptyFilterButKeepDefinition = useRecoilCallback(
({ set }) => ({ set }) =>
() => { () => {
@ -129,7 +108,6 @@ export const useFilterDropdown = (props?: UseFilterDropdownProps) => {
return { return {
componentInstanceId, componentInstanceId,
selectFilter,
resetFilter, resetFilter,
setSelectedFilter, setSelectedFilter,
setSelectedOperandInDropdown, setSelectedOperandInDropdown,

View File

@ -1,3 +1,4 @@
import { useApplyRecordFilter } from '@/object-record/object-filter-dropdown/hooks/useApplyRecordFilter';
import { useFilterDropdown } from '@/object-record/object-filter-dropdown/hooks/useFilterDropdown'; import { useFilterDropdown } from '@/object-record/object-filter-dropdown/hooks/useFilterDropdown';
import { FilterDefinition } from '@/object-record/object-filter-dropdown/types/FilterDefinition'; import { FilterDefinition } from '@/object-record/object-filter-dropdown/types/FilterDefinition';
import { getInitialFilterValue } from '@/object-record/object-filter-dropdown/utils/getInitialFilterValue'; import { getInitialFilterValue } from '@/object-record/object-filter-dropdown/utils/getInitialFilterValue';
@ -12,12 +13,11 @@ type SelectFilterParams = {
filterDefinition: FilterDefinition; filterDefinition: FilterDefinition;
}; };
export const useSelectFilter = () => { export const useSelectFilterDefinitionUsedInDropdown = () => {
const { const {
setFilterDefinitionUsedInDropdown, setFilterDefinitionUsedInDropdown,
setSelectedOperandInDropdown, setSelectedOperandInDropdown,
setObjectFilterDropdownSearchInput, setObjectFilterDropdownSearchInput,
selectFilter: filterDropdownSelectFilter,
advancedFilterViewFilterGroupIdState, advancedFilterViewFilterGroupIdState,
advancedFilterViewFilterIdState, advancedFilterViewFilterIdState,
} = useFilterDropdown(); } = useFilterDropdown();
@ -31,7 +31,11 @@ export const useSelectFilter = () => {
const setHotkeyScope = useSetHotkeyScope(); const setHotkeyScope = useSetHotkeyScope();
const selectFilter = ({ filterDefinition }: SelectFilterParams) => { const { applyRecordFilter } = useApplyRecordFilter();
const selectFilterDefinitionUsedInDropdown = ({
filterDefinition,
}: SelectFilterParams) => {
setFilterDefinitionUsedInDropdown(filterDefinition); setFilterDefinitionUsedInDropdown(filterDefinition);
if ( if (
@ -53,7 +57,7 @@ export const useSelectFilter = () => {
const isAdvancedFilter = isDefined(advancedFilterViewFilterId); const isAdvancedFilter = isDefined(advancedFilterViewFilterId);
if (isAdvancedFilter || value !== '') { if (isAdvancedFilter || value !== '') {
filterDropdownSelectFilter({ applyRecordFilter({
id: advancedFilterViewFilterId ?? v4(), id: advancedFilterViewFilterId ?? v4(),
fieldMetadataId: filterDefinition.fieldMetadataId, fieldMetadataId: filterDefinition.fieldMetadataId,
displayValue, displayValue,
@ -68,6 +72,6 @@ export const useSelectFilter = () => {
}; };
return { return {
selectFilter, selectFilterDefinitionUsedInDropdown,
}; };
}; };