diff --git a/packages/twenty-front/src/modules/object-record/advanced-filter/components/AdvancedFilterRecordFilterGroupOptionsDropdown.tsx b/packages/twenty-front/src/modules/object-record/advanced-filter/components/AdvancedFilterRecordFilterGroupOptionsDropdown.tsx index 18f924161..337f4d3ca 100644 --- a/packages/twenty-front/src/modules/object-record/advanced-filter/components/AdvancedFilterRecordFilterGroupOptionsDropdown.tsx +++ b/packages/twenty-front/src/modules/object-record/advanced-filter/components/AdvancedFilterRecordFilterGroupOptionsDropdown.tsx @@ -4,6 +4,7 @@ import { useRemoveRecordFilter } from '@/object-record/record-filter/hooks/useRe import { Dropdown } from '@/ui/layout/dropdown/components/Dropdown'; import { DropdownMenuItemsContainer } from '@/ui/layout/dropdown/components/DropdownMenuItemsContainer'; +import { useDropdown } from '@/ui/layout/dropdown/hooks/useDropdown'; import { IconButton, IconDotsVertical, MenuItem } from 'twenty-ui'; type AdvancedFilterRecordFilterGroupOptionsDropdownProps = { @@ -15,6 +16,8 @@ export const AdvancedFilterRecordFilterGroupOptionsDropdown = ({ }: AdvancedFilterRecordFilterGroupOptionsDropdownProps) => { const dropdownId = `advanced-filter-record-filter-group-options-${recordFilterGroupId}`; + const { closeDropdown } = useDropdown(dropdownId); + const { removeRecordFilter } = useRemoveRecordFilter(); const { removeRecordFilterGroup } = useRemoveRecordFilterGroup(); @@ -28,6 +31,8 @@ export const AdvancedFilterRecordFilterGroupOptionsDropdown = ({ } removeRecordFilterGroup(recordFilterGroupId); + + closeDropdown(); }; return ( diff --git a/packages/twenty-front/src/modules/object-record/advanced-filter/components/AdvancedFilterRecordFilterOptionsDropdown.tsx b/packages/twenty-front/src/modules/object-record/advanced-filter/components/AdvancedFilterRecordFilterOptionsDropdown.tsx index 8b4c2ff2b..bbec255b8 100644 --- a/packages/twenty-front/src/modules/object-record/advanced-filter/components/AdvancedFilterRecordFilterOptionsDropdown.tsx +++ b/packages/twenty-front/src/modules/object-record/advanced-filter/components/AdvancedFilterRecordFilterOptionsDropdown.tsx @@ -6,6 +6,7 @@ import { currentRecordFiltersComponentState } from '@/object-record/record-filte import { Dropdown } from '@/ui/layout/dropdown/components/Dropdown'; 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 { isDefined } from 'twenty-shared'; import { IconButton, IconDotsVertical, MenuItem } from 'twenty-ui'; @@ -19,6 +20,8 @@ export const AdvancedFilterRecordFilterOptionsDropdown = ({ }: AdvancedFilterRecordFilterOptionsDropdownProps) => { const dropdownId = `advanced-filter-record-filter-options-${recordFilterId}`; + const { closeDropdown } = useDropdown(dropdownId); + const { removeRecordFilter } = useRemoveRecordFilter(); const { removeRecordFilterGroup } = useRemoveRecordFilterGroup(); @@ -36,7 +39,7 @@ export const AdvancedFilterRecordFilterOptionsDropdown = ({ }); const handleRemove = async () => { - removeRecordFilter({ recordFilterId: recordFilterId }); + closeDropdown(); if (isDefined(currentRecordFilter?.recordFilterGroupId)) { const isOnlyViewFilterInGroup = @@ -46,6 +49,8 @@ export const AdvancedFilterRecordFilterOptionsDropdown = ({ removeRecordFilterGroup(currentRecordFilter.recordFilterGroupId); } } + + removeRecordFilter({ recordFilterId: recordFilterId }); }; return ( diff --git a/packages/twenty-front/src/modules/object-record/object-filter-dropdown/components/ObjectFilterDropdownFilterInput.tsx b/packages/twenty-front/src/modules/object-record/object-filter-dropdown/components/ObjectFilterDropdownFilterInput.tsx index 3121c2dd6..c2ce2765f 100644 --- a/packages/twenty-front/src/modules/object-record/object-filter-dropdown/components/ObjectFilterDropdownFilterInput.tsx +++ b/packages/twenty-front/src/modules/object-record/object-filter-dropdown/components/ObjectFilterDropdownFilterInput.tsx @@ -5,13 +5,13 @@ import { ObjectFilterDropdownRatingInput } from '@/object-record/object-filter-d import { ObjectFilterDropdownRecordSelect } from '@/object-record/object-filter-dropdown/components/ObjectFilterDropdownRecordSelect'; import { ObjectFilterDropdownSearchInput } from '@/object-record/object-filter-dropdown/components/ObjectFilterDropdownSearchInput'; import { ObjectFilterDropdownSourceSelect } from '@/object-record/object-filter-dropdown/components/ObjectFilterDropdownSourceSelect'; -import { ObjectFilterDropdownTextSearchInput } from '@/object-record/object-filter-dropdown/components/ObjectFilterDropdownTextSearchInput'; import { DropdownMenuSeparator } from '@/ui/layout/dropdown/components/DropdownMenuSeparator'; import { ViewFilterOperand } from '@/views/types/ViewFilterOperand'; import { isDefined } from 'twenty-shared'; import { getFilterTypeFromFieldType } from '@/object-metadata/utils/formatFieldMetadataItemsAsFilterDefinitions'; import { ObjectFilterDropdownBooleanSelect } from '@/object-record/object-filter-dropdown/components/ObjectFilterDropdownBooleanSelect'; +import { ObjectFilterDropdownTextInput } from '@/object-record/object-filter-dropdown/components/ObjectFilterDropdownTextInput'; import { DATE_FILTER_TYPES } from '@/object-record/object-filter-dropdown/constants/DateFilterTypes'; import { NUMBER_FILTER_TYPES } from '@/object-record/object-filter-dropdown/constants/NumberFilterTypes'; import { TEXT_FILTER_TYPES } from '@/object-record/object-filter-dropdown/constants/TextFilterTypes'; @@ -75,9 +75,7 @@ export const ObjectFilterDropdownFilterInput = ({ {isConfigurable && selectedOperandInDropdown && ( <> {TEXT_FILTER_TYPES.includes(filterType) && - !isActorSourceCompositeFilter && ( - - )} + !isActorSourceCompositeFilter && } {NUMBER_FILTER_TYPES.includes(filterType) && ( )} diff --git a/packages/twenty-front/src/modules/object-record/object-filter-dropdown/components/ObjectFilterDropdownFilterSelect.tsx b/packages/twenty-front/src/modules/object-record/object-filter-dropdown/components/ObjectFilterDropdownFilterSelect.tsx index 9d575494e..8e2b4ef69 100644 --- a/packages/twenty-front/src/modules/object-record/object-filter-dropdown/components/ObjectFilterDropdownFilterSelect.tsx +++ b/packages/twenty-front/src/modules/object-record/object-filter-dropdown/components/ObjectFilterDropdownFilterSelect.tsx @@ -27,6 +27,7 @@ import { advancedFilterViewFilterIdComponentState } from '@/object-record/object import { fieldMetadataItemIdUsedInDropdownComponentState } from '@/object-record/object-filter-dropdown/states/fieldMetadataItemIdUsedInDropdownComponentState'; import { FiltersHotkeyScope } from '@/object-record/object-filter-dropdown/types/FiltersHotkeyScope'; import { useFilterableFieldMetadataItemsInRecordIndexContext } from '@/object-record/record-filter/hooks/useFilterableFieldMetadataItemsInRecordIndexContext'; +import { useRecoilComponentStateV2 } from '@/ui/utilities/state/component-state/hooks/useRecoilComponentStateV2'; import { useGetCurrentViewOnly } from '@/views/hooks/useGetCurrentViewOnly'; import { useLingui } from '@lingui/react/macro'; @@ -65,17 +66,12 @@ export const ObjectFilterDropdownFilterSelect = ({ }: ObjectFilterDropdownFilterSelectProps) => { const { recordIndexId } = useRecordIndexContextOrThrow(); - const setObjectFilterDropdownSearchInput = useSetRecoilComponentStateV2( - objectFilterDropdownSearchInputComponentState, - ); - const advancedFilterViewFilterId = useRecoilComponentValueV2( advancedFilterViewFilterIdComponentState, ); - const objectFilterDropdownSearchInput = useRecoilComponentValueV2( - objectFilterDropdownSearchInputComponentState, - ); + const [objectFilterDropdownSearchInput, setObjectFilterDropdownSearchInput] = + useRecoilComponentStateV2(objectFilterDropdownSearchInputComponentState); const { closeAdvancedFilterDropdown } = useAdvancedFilterDropdown( advancedFilterViewFilterId, 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 new file mode 100644 index 000000000..e22856d88 --- /dev/null +++ b/packages/twenty-front/src/modules/object-record/object-filter-dropdown/components/ObjectFilterDropdownTextInput.tsx @@ -0,0 +1,74 @@ +import { ChangeEvent, useCallback, 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 { DropdownMenuInput } from '@/ui/layout/dropdown/components/DropdownMenuInput'; +import { useRecoilComponentValueV2 } from '@/ui/utilities/state/component-state/hooks/useRecoilComponentValueV2'; + +export const ObjectFilterDropdownTextInput = () => { + const selectedOperandInDropdown = useRecoilComponentValueV2( + selectedOperandInDropdownComponentState, + ); + + const fieldMetadataItemUsedInDropdown = useRecoilComponentValueV2( + fieldMetadataItemUsedInDropdownComponentSelector, + ); + + const selectedFilter = useRecoilComponentValueV2( + selectedFilterComponentState, + ); + + const { applyRecordFilter } = useApplyRecordFilter(); + + const [hasFocused, setHasFocused] = useState(false); + + const [inputValue, setInputValue] = useState( + () => selectedFilter?.value || '', + ); + + const handleInputRef = useCallback( + (node: HTMLInputElement | null) => { + if (Boolean(node) && !hasFocused) { + node?.focus(); + node?.select(); + setHasFocused(true); + } + }, + [hasFocused], + ); + + 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, + }); + }} + /> + ) + ); +}; diff --git a/packages/twenty-front/src/modules/views/components/UpdateViewButtonGroup.tsx b/packages/twenty-front/src/modules/views/components/UpdateViewButtonGroup.tsx index ac539dd96..6df4d6c35 100644 --- a/packages/twenty-front/src/modules/views/components/UpdateViewButtonGroup.tsx +++ b/packages/twenty-front/src/modules/views/components/UpdateViewButtonGroup.tsx @@ -2,6 +2,7 @@ import styled from '@emotion/styled'; import { Button, ButtonGroup, + IconButton, IconChevronDown, IconPlus, MenuItem, @@ -32,9 +33,7 @@ const StyledContainer = styled.div` margin-right: ${({ theme }) => theme.spacing(2)}; position: relative; `; -const StyledButton = styled(Button)` - padding: ${({ theme }) => theme.spacing(1)}; -`; + export type UpdateViewButtonGroupProps = { hotkeyScope: HotkeyScope; }; @@ -116,7 +115,7 @@ export const UpdateViewButtonGroup = ({ dropdownId={UPDATE_VIEW_BUTTON_DROPDOWN_ID} dropdownHotkeyScope={hotkeyScope} clickableComponent={ -