Fix/close filter by enter (#16643)

Fixes #16636 

Added useCloseDropdown() hook and set onEnter prop to
onEnter={closeDropDown()} using dropdownID

EDIT from @charlesBochet after refactoring:
- ObjectDropdownFilters are used in 3 places: Main Filter menu,
EditableChip, AdvancedFilters
- deprecate vectorSearch in view filter area, we are not using them, we
are doing a anyField filter now. While refactoring the points below, I
did not want to maintain vectorSearch as it was not used anymore
- stop confusing the dropdownId (which is an id to interact with a
specific dropdown) and componentInstanceIds (which is used to scope
component states) for EditableFilter case
- I haven't fixed the confusion for MainFilter case
- It was already handled for AdvancedFilter case

---------

Co-authored-by: Charles Bochet <charles@twenty.com>
Co-authored-by: Lucas Bordeau <bordeau.lucas@gmail.com>
This commit is contained in:
Manikanth Martha
2025-12-18 19:55:56 +05:30
committed by GitHub
parent 52cf3775b3
commit 4bdd866a20
58 changed files with 183 additions and 537 deletions
@@ -49,12 +49,8 @@ export const AdvancedFilterDropdownFilterInput = ({
<AdvancedFilterDropdownTextInput recordFilter={recordFilter} />
))}
{filterType === 'RATING' && <ObjectFilterDropdownRatingInput />}
{filterType === 'DATE_TIME' && (
<ObjectFilterDropdownDateTimeInput instanceId={filterDropdownId} />
)}
{filterType === 'DATE' && (
<ObjectFilterDropdownDateInput instanceId={filterDropdownId} />
)}
{filterType === 'DATE_TIME' && <ObjectFilterDropdownDateTimeInput />}
{filterType === 'DATE' && <ObjectFilterDropdownDateInput />}
{filterType === 'RELATION' && (
<DropdownContent widthInPixels={GenericDropdownContentWidth.ExtraLarge}>
<ObjectFilterDropdownSearchInput />
@@ -69,7 +65,7 @@ export const AdvancedFilterDropdownFilterInput = ({
(isActorSourceCompositeFilter ? (
<ObjectFilterDropdownSourceSelect dropdownId={filterDropdownId} />
) : (
<ObjectFilterDropdownTextInput />
<ObjectFilterDropdownTextInput filterDropdownId={filterDropdownId} />
))}
{['SELECT', 'MULTI_SELECT'].includes(filterType) && (
<DropdownContent widthInPixels={GenericDropdownContentWidth.ExtraLarge}>
@@ -21,13 +21,7 @@ import {
import { dateLocaleState } from '~/localization/states/dateLocaleState';
import { formatDateString } from '~/utils/string/formatDateString';
type ObjectFilterDropdownDateInputProps = {
instanceId: string;
};
export const ObjectFilterDropdownDateInput = ({
instanceId,
}: ObjectFilterDropdownDateInputProps) => {
export const ObjectFilterDropdownDateInput = () => {
const { dateFormat, timeZone } = useContext(UserContext);
const dateLocale = useRecoilValue(dateLocaleState);
const currentWorkspaceMember = useRecoilValue(currentWorkspaceMemberState);
@@ -112,7 +106,7 @@ export const ObjectFilterDropdownDateInput = ({
return (
<DatePicker
instanceId={instanceId}
instanceId={`object-filter-dropdown-date-input`}
relativeDate={relativeDate}
isRelative={isRelativeOperand}
date={plainDateValue ?? null}
@@ -21,13 +21,7 @@ import {
import { dateLocaleState } from '~/localization/states/dateLocaleState';
import { formatDateTimeString } from '~/utils/string/formatDateTimeString';
type ObjectFilterDropdownDateTimeInputProps = {
instanceId: string;
};
export const ObjectFilterDropdownDateTimeInput = ({
instanceId,
}: ObjectFilterDropdownDateTimeInputProps) => {
export const ObjectFilterDropdownDateTimeInput = () => {
const { dateFormat, timeFormat, timeZone } = useContext(UserContext);
const dateLocale = useRecoilValue(dateLocaleState);
const currentWorkspaceMember = useRecoilValue(currentWorkspaceMemberState);
@@ -115,7 +109,7 @@ export const ObjectFilterDropdownDateTimeInput = ({
return (
<DateTimePicker
instanceId={instanceId}
instanceId={`object-filter-dropdown-date-time-input`}
relativeDate={relativeDate}
isRelative={isRelativeOperand}
date={internalDate}
@@ -12,7 +12,6 @@ import { ObjectFilterDropdownBooleanSelect } from '@/object-record/object-filter
import { ObjectFilterDropdownDateTimeInput } from '@/object-record/object-filter-dropdown/components/ObjectFilterDropdownDateTimeInput';
import { ObjectFilterDropdownInnerSelectOperandDropdown } from '@/object-record/object-filter-dropdown/components/ObjectFilterDropdownInnerSelectOperandDropdown';
import { ObjectFilterDropdownTextInput } from '@/object-record/object-filter-dropdown/components/ObjectFilterDropdownTextInput';
import { ObjectFilterDropdownVectorSearchInput } from '@/object-record/object-filter-dropdown/components/ObjectFilterDropdownVectorSearchInput';
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 { fieldMetadataItemUsedInDropdownComponentSelector } from '@/object-record/object-filter-dropdown/states/fieldMetadataItemUsedInDropdownComponentSelector';
@@ -31,12 +30,10 @@ export const ObjectFilterDropdownFilterInput = ({
}: ObjectFilterDropdownFilterInputProps) => {
const fieldMetadataItemUsedInDropdown = useRecoilComponentValue(
fieldMetadataItemUsedInDropdownComponentSelector,
filterDropdownId,
);
const selectedOperandInDropdown = useRecoilComponentValue(
selectedOperandInDropdownComponentState,
filterDropdownId,
);
const isOperandWithFilterValue =
@@ -54,13 +51,6 @@ export const ObjectFilterDropdownFilterInput = ({
ViewFilterOperand.IS_RELATIVE,
].includes(selectedOperandInDropdown);
const isVectorSearchFilter =
selectedOperandInDropdown === ViewFilterOperand.VECTOR_SEARCH;
if (isVectorSearchFilter && isDefined(filterDropdownId)) {
return <ObjectFilterDropdownVectorSearchInput />;
}
if (!isDefined(fieldMetadataItemUsedInDropdown)) {
return null;
}
@@ -82,7 +72,7 @@ export const ObjectFilterDropdownFilterInput = ({
<>
<ObjectFilterDropdownInnerSelectOperandDropdown />
<DropdownMenuSeparator />
<ObjectFilterDropdownDateInput instanceId={filterDropdownId} />
<ObjectFilterDropdownDateInput />
</>
);
} else if (filterType === 'DATE_TIME') {
@@ -90,7 +80,7 @@ export const ObjectFilterDropdownFilterInput = ({
<>
<ObjectFilterDropdownInnerSelectOperandDropdown />
<DropdownMenuSeparator />
<ObjectFilterDropdownDateTimeInput instanceId={filterDropdownId} />
<ObjectFilterDropdownDateTimeInput />
</>
);
} else {
@@ -99,10 +89,12 @@ export const ObjectFilterDropdownFilterInput = ({
<ObjectFilterDropdownInnerSelectOperandDropdown />
<DropdownMenuSeparator />
{TEXT_FILTER_TYPES.includes(filterType) && (
<ObjectFilterDropdownTextInput />
<ObjectFilterDropdownTextInput filterDropdownId={filterDropdownId} />
)}
{NUMBER_FILTER_TYPES.includes(filterType) && (
<ObjectFilterDropdownNumberInput />
<ObjectFilterDropdownNumberInput
filterDropdownId={filterDropdownId}
/>
)}
{filterType === 'RATING' && <ObjectFilterDropdownRatingInput />}
{filterType === 'RELATION' && (
@@ -115,9 +107,17 @@ export const ObjectFilterDropdownFilterInput = ({
/>
</>
)}
{filterType === 'ACTOR' && <ObjectFilterDropdownTextInput />}
{filterType === 'ADDRESS' && <ObjectFilterDropdownTextInput />}
{filterType === 'CURRENCY' && <ObjectFilterDropdownNumberInput />}
{filterType === 'ACTOR' && (
<ObjectFilterDropdownTextInput filterDropdownId={filterDropdownId} />
)}
{filterType === 'ADDRESS' && (
<ObjectFilterDropdownTextInput filterDropdownId={filterDropdownId} />
)}
{filterType === 'CURRENCY' && (
<ObjectFilterDropdownNumberInput
filterDropdownId={filterDropdownId}
/>
)}
{['SELECT', 'MULTI_SELECT'].includes(filterType) && (
<>
<ObjectFilterDropdownSearchInput />
@@ -1,28 +1,20 @@
import { fieldMetadataItemUsedInDropdownComponentSelector } from '@/object-record/object-filter-dropdown/states/fieldMetadataItemUsedInDropdownComponentSelector';
import { selectedOperandInDropdownComponentState } from '@/object-record/object-filter-dropdown/states/selectedOperandInDropdownComponentState';
import { DropdownMenuHeader } from '@/ui/layout/dropdown/components/DropdownMenuHeader/DropdownMenuHeader';
import { DropdownMenuHeaderLeftComponent } from '@/ui/layout/dropdown/components/DropdownMenuHeader/internal/DropdownMenuHeaderLeftComponent';
import { DropdownComponentInstanceContext } from '@/ui/layout/dropdown/contexts/DropdownComponentInstanceContext';
import { useCloseDropdown } from '@/ui/layout/dropdown/hooks/useCloseDropdown';
import { useRecoilComponentValue } from '@/ui/utilities/state/component-state/hooks/useRecoilComponentValue';
import { ViewBarFilterDropdownFilterInputMenuHeader } from '@/views/components/ViewBarFilterDropdownFilterInputMenuHeader';
import { VIEW_BAR_FILTER_DROPDOWN_ID } from '@/views/constants/ViewBarFilterDropdownId';
import { useLingui } from '@lingui/react/macro';
import { ViewBarFilterDropdownIds } from '@/views/constants/ViewBarFilterDropdownIds';
import { useContext } from 'react';
import { ViewFilterOperand } from 'twenty-shared/types';
import { IconX } from 'twenty-ui/display';
// TODO: we shouldn't guess in which parent we are, this should be splitted in two components, one for each case
export const ObjectFilterDropdownFilterInputHeader = () => {
const { t } = useLingui();
const fieldMetadataItemUsedInDropdown = useRecoilComponentValue(
fieldMetadataItemUsedInDropdownComponentSelector,
);
const selectedOperandInDropdown = useRecoilComponentValue(
selectedOperandInDropdownComponentState,
);
const { closeDropdown } = useCloseDropdown();
const dropdownInstanceId = useContext(
@@ -30,10 +22,7 @@ export const ObjectFilterDropdownFilterInputHeader = () => {
)?.instanceId;
const isInViewBarFilterDropdown =
dropdownInstanceId === VIEW_BAR_FILTER_DROPDOWN_ID;
const isVectorSearchFilter =
selectedOperandInDropdown === ViewFilterOperand.VECTOR_SEARCH;
dropdownInstanceId === ViewBarFilterDropdownIds.MAIN;
if (isInViewBarFilterDropdown) {
return <ViewBarFilterDropdownFilterInputMenuHeader />;
@@ -47,9 +36,7 @@ export const ObjectFilterDropdownFilterInputHeader = () => {
/>
}
>
{isVectorSearchFilter
? t`Search`
: fieldMetadataItemUsedInDropdown?.label}
{fieldMetadataItemUsedInDropdown?.label}
</DropdownMenuHeader>
);
}
@@ -5,9 +5,16 @@ import { useObjectFilterDropdownFilterValue } from '@/object-record/object-filte
import { fieldMetadataItemUsedInDropdownComponentSelector } from '@/object-record/object-filter-dropdown/states/fieldMetadataItemUsedInDropdownComponentSelector';
import { DropdownMenuInput } from '@/ui/layout/dropdown/components/DropdownMenuInput';
import { DropdownMenuItemsContainer } from '@/ui/layout/dropdown/components/DropdownMenuItemsContainer';
import { useCloseDropdown } from '@/ui/layout/dropdown/hooks/useCloseDropdown';
import { useRecoilComponentValue } from '@/ui/utilities/state/component-state/hooks/useRecoilComponentValue';
export const ObjectFilterDropdownNumberInput = () => {
type ObjectFilterDropdownNumberInputProps = {
filterDropdownId: string;
};
export const ObjectFilterDropdownNumberInput = ({
filterDropdownId,
}: ObjectFilterDropdownNumberInputProps) => {
const fieldMetadataItemUsedInDropdown = useRecoilComponentValue(
fieldMetadataItemUsedInDropdownComponentSelector,
);
@@ -18,6 +25,8 @@ export const ObjectFilterDropdownNumberInput = () => {
const { applyObjectFilterDropdownFilterValue } =
useApplyObjectFilterDropdownFilterValue();
const { closeDropdown } = useCloseDropdown();
const [hasFocused, setHasFocused] = useState(false);
const handleInputRef = useCallback(
@@ -40,13 +49,14 @@ export const ObjectFilterDropdownNumberInput = () => {
return (
<DropdownMenuItemsContainer>
<DropdownMenuInput
instanceId="object-filter-dropdown-number-input"
instanceId={filterDropdownId}
ref={handleInputRef}
value={objectFilterDropdownFilterValue}
autoFocus
type="number"
placeholder={fieldMetadataItemUsedInDropdown?.label}
onChange={handleInputChange}
onEnter={() => closeDropdown(filterDropdownId)}
/>
</DropdownMenuItemsContainer>
);
@@ -5,9 +5,16 @@ import { useObjectFilterDropdownFilterValue } from '@/object-record/object-filte
import { fieldMetadataItemUsedInDropdownComponentSelector } from '@/object-record/object-filter-dropdown/states/fieldMetadataItemUsedInDropdownComponentSelector';
import { DropdownMenuInput } from '@/ui/layout/dropdown/components/DropdownMenuInput';
import { DropdownMenuItemsContainer } from '@/ui/layout/dropdown/components/DropdownMenuItemsContainer';
import { useCloseDropdown } from '@/ui/layout/dropdown/hooks/useCloseDropdown';
import { useRecoilComponentValue } from '@/ui/utilities/state/component-state/hooks/useRecoilComponentValue';
export const ObjectFilterDropdownTextInput = () => {
type ObjectFilterDropdownTextInputProps = {
filterDropdownId: string;
};
export const ObjectFilterDropdownTextInput = ({
filterDropdownId,
}: ObjectFilterDropdownTextInputProps) => {
const fieldMetadataItemUsedInDropdown = useRecoilComponentValue(
fieldMetadataItemUsedInDropdownComponentSelector,
);
@@ -18,6 +25,8 @@ export const ObjectFilterDropdownTextInput = () => {
const { applyObjectFilterDropdownFilterValue } =
useApplyObjectFilterDropdownFilterValue();
const { closeDropdown } = useCloseDropdown();
const [hasFocused, setHasFocused] = useState(false);
const handleInputRef = useCallback(
@@ -40,13 +49,16 @@ export const ObjectFilterDropdownTextInput = () => {
return (
<DropdownMenuItemsContainer>
<DropdownMenuInput
instanceId="object-filter-dropdown-text-input"
instanceId={filterDropdownId}
ref={handleInputRef}
value={objectFilterDropdownFilterValue ?? ''}
autoFocus
type="text"
placeholder={fieldMetadataItemUsedInDropdown?.label}
onChange={handleInputChange}
onEnter={() => {
closeDropdown(filterDropdownId);
}}
/>
</DropdownMenuItemsContainer>
);
@@ -1,38 +0,0 @@
import { DropdownMenuSearchInput } from '@/ui/layout/dropdown/components/DropdownMenuSearchInput';
import { useRecoilComponentState } from '@/ui/utilities/state/component-state/hooks/useRecoilComponentState';
import { useVectorSearchFilterActions } from '@/views/hooks/useVectorSearchFilterActions';
import { vectorSearchInputComponentState } from '@/views/states/vectorSearchInputComponentState';
import { useLingui } from '@lingui/react/macro';
import { useDebouncedCallback } from 'use-debounce';
export const ObjectFilterDropdownVectorSearchInput = () => {
const { t } = useLingui();
const [vectorSearchInputValue, setVectorSearchInputValue] =
useRecoilComponentState(vectorSearchInputComponentState);
const { applyVectorSearchFilter } = useVectorSearchFilterActions();
const debouncedApplyVectorSearchFilter = useDebouncedCallback(
(value: string) => {
applyVectorSearchFilter(value);
},
500,
);
const handleSearchChange = (e: React.ChangeEvent<HTMLInputElement>) => {
const inputValue = e.target.value;
setVectorSearchInputValue(inputValue);
debouncedApplyVectorSearchFilter(inputValue);
};
return (
<DropdownMenuSearchInput
autoFocus
type="text"
value={vectorSearchInputValue}
placeholder={t`Search`}
onChange={handleSearchChange}
/>
);
};
@@ -17,7 +17,7 @@ import { RecordCalendarMonth } from '@/object-record/record-calendar/month/compo
import { currentRecordFieldsComponentState } from '@/object-record/record-field/states/currentRecordFieldsComponentState';
import { type RecordField } from '@/object-record/record-field/types/RecordField';
import { useRecordIndexFieldMetadataDerivedStates } from '@/object-record/record-index/hooks/useRecordIndexFieldMetadataDerivedStates';
import { VIEW_BAR_FILTER_DROPDOWN_ID } from '@/views/constants/ViewBarFilterDropdownId';
import { ViewBarFilterDropdownIds } from '@/views/constants/ViewBarFilterDropdownIds';
import { coreViewsState } from '@/views/states/coreViewState';
import { useSetRecoilState } from 'recoil';
import { ComponentDecorator, RouterDecorator } from 'twenty-ui/testing';
@@ -101,7 +101,7 @@ const meta: Meta<typeof RecordCalendarMonth> = {
componentInstanceId={instanceId}
>
<ObjectFilterDropdownComponentInstanceContext.Provider
value={{ instanceId: VIEW_BAR_FILTER_DROPDOWN_ID }}
value={{ instanceId: ViewBarFilterDropdownIds.MAIN }}
>
<RecordTableComponentInstanceContext.Provider
value={{
@@ -5,19 +5,18 @@ import {
MultiItemBaseInput,
type MultiItemBaseInputProps,
} from '@/object-record/record-field/ui/meta-types/input/components/MultiItemBaseInput';
import { MULTI_ITEM_FIELD_INPUT_DROPDOWN_ID_PREFIX } from '@/object-record/record-field/ui/meta-types/input/constants/MultiItemFieldInputDropdownClickOutsideId';
import { RecordFieldComponentInstanceContext } from '@/object-record/record-field/ui/states/contexts/RecordFieldComponentInstanceContext';
import { type PhoneRecord } from '@/object-record/record-field/ui/types/FieldMetadata';
import { PHONE_COUNTRY_CODE_PICKER_DROPDOWN_ID } from '@/ui/input/components/internal/phone/constants/PhoneCountryCodePickerDropdownId';
import { DropdownContent } from '@/ui/layout/dropdown/components/DropdownContent';
import { DropdownMenuItemsContainer } from '@/ui/layout/dropdown/components/DropdownMenuItemsContainer';
import { DropdownMenuSeparator } from '@/ui/layout/dropdown/components/DropdownMenuSeparator';
import { activeDropdownFocusIdState } from '@/ui/layout/dropdown/states/activeDropdownFocusIdState';
import { currentFocusedItemSelector } from '@/ui/utilities/focus/states/currentFocusedItemSelector';
import { FocusComponentType } from '@/ui/utilities/focus/types/FocusComponentType';
import { useHotkeysOnFocusedElement } from '@/ui/utilities/hotkey/hooks/useHotkeysOnFocusedElement';
import { useListenClickOutside } from '@/ui/utilities/pointer-event/hooks/useListenClickOutside';
import { useAvailableComponentInstanceIdOrThrow } from '@/ui/utilities/state/component-state/hooks/useAvailableComponentInstanceIdOrThrow';
import { useRecoilValue } from 'recoil';
import { CustomError, isDefined } from 'twenty-shared/utils';
import { CustomError } from 'twenty-shared/utils';
import { IconCheck, IconPlus } from 'twenty-ui/display';
import { LightIconButton } from 'twenty-ui/input';
import { MenuItem } from 'twenty-ui/navigation';
@@ -73,17 +72,14 @@ export const MultiItemFieldInput = <T,>({
RecordFieldComponentInstanceContext,
);
const activeDropdownFocusId = useRecoilValue(activeDropdownFocusIdState);
const currentFocusedItem = useRecoilValue(currentFocusedItemSelector);
useListenClickOutside({
refs: [containerRef],
callback: (event) => {
if (
(isDefined(activeDropdownFocusId) &&
activeDropdownFocusId.startsWith(
MULTI_ITEM_FIELD_INPUT_DROPDOWN_ID_PREFIX,
)) ||
activeDropdownFocusId === PHONE_COUNTRY_CODE_PICKER_DROPDOWN_ID
currentFocusedItem?.componentInstance.componentType !==
FocusComponentType.OPENED_FIELD_INPUT
) {
return;
}
@@ -2,9 +2,6 @@ import { AdvancedFilterContext } from '@/object-record/advanced-filter/states/co
import { currentRecordFiltersComponentState } from '@/object-record/record-filter/states/currentRecordFiltersComponentState';
import { useRecoilComponentCallbackState } from '@/ui/utilities/state/component-state/hooks/useRecoilComponentCallbackState';
import { getSnapshotValue } from '@/ui/utilities/state/utils/getSnapshotValue';
import { VIEW_BAR_FILTER_DROPDOWN_ID } from '@/views/constants/ViewBarFilterDropdownId';
import { vectorSearchInputComponentState } from '@/views/states/vectorSearchInputComponentState';
import { isVectorSearchFilter } from '@/views/utils/isVectorSearchFilter';
import { useContext } from 'react';
import { useRecoilCallback } from 'recoil';
import { isDefined } from 'twenty-shared/utils';
@@ -32,15 +29,6 @@ export const useRemoveRecordFilter = () => {
return;
}
if (isVectorSearchFilter(filterToRemove)) {
set(
vectorSearchInputComponentState.atomFamily({
instanceId: VIEW_BAR_FILTER_DROPDOWN_ID,
}),
'',
);
}
set(currentRecordFiltersCallbackState, (currentRecordFilters) => {
const newCurrentRecordFilters = [...currentRecordFilters];
@@ -4,6 +4,7 @@ import { useUpsertRecordFilter } from '@/object-record/record-filter/hooks/useUp
import { currentRecordFiltersComponentState } from '@/object-record/record-filter/states/currentRecordFiltersComponentState';
import { useOpenDropdown } from '@/ui/layout/dropdown/hooks/useOpenDropdown';
import { useRecoilComponentValue } from '@/ui/utilities/state/component-state/hooks/useRecoilComponentValue';
import { getEditableChipDropdownId } from '@/views/editable-chip/utils/getEditableChipDropdownId';
import { useSetEditableFilterChipDropdownStates } from '@/views/hooks/useSetEditableFilterChipDropdownStates';
import { isDefined } from 'twenty-shared/utils';
@@ -46,8 +47,9 @@ export const useOpenRecordFilterChipFromTableHeader = () => {
if (isDefined(existingNonAdvancedRecordFilter)) {
setEditableFilterChipDropdownStates(existingNonAdvancedRecordFilter);
openDropdown({
dropdownComponentInstanceIdFromProps:
existingNonAdvancedRecordFilter.id,
dropdownComponentInstanceIdFromProps: getEditableChipDropdownId({
recordFilterId: existingNonAdvancedRecordFilter.id,
}),
});
return;
}
@@ -59,7 +61,11 @@ export const useOpenRecordFilterChipFromTableHeader = () => {
upsertRecordFilter(newRecordFilter);
setEditableFilterChipDropdownStates(newRecordFilter);
openDropdown({ dropdownComponentInstanceIdFromProps: newRecordFilter.id });
openDropdown({
dropdownComponentInstanceIdFromProps: getEditableChipDropdownId({
recordFilterId: newRecordFilter.id,
}),
});
};
return { openRecordFilterChipFromTableHeader };
@@ -1,4 +1,4 @@
import { SEARCH_VECTOR_FIELD_NAME } from '@/views/constants/ViewFieldConstants';
import { SEARCH_VECTOR_FIELD_NAME } from '@/object-record/constants/SearchVectorFieldName';
export const isSystemSearchVectorField = (fieldName: string): boolean => {
return fieldName === SEARCH_VECTOR_FIELD_NAME;
@@ -12,7 +12,7 @@ import { getAllRecordFilterDescendantsOfRecordFilterGroup } from '@/object-recor
import { useCloseDropdown } from '@/ui/layout/dropdown/hooks/useCloseDropdown';
import { useRecoilComponentValue } from '@/ui/utilities/state/component-state/hooks/useRecoilComponentValue';
import { SortOrFilterChip } from '@/views/components/SortOrFilterChip';
import { ADVANCED_FILTER_DROPDOWN_ID } from '@/views/constants/AdvancedFilterDropdownId';
import { ViewBarFilterDropdownIds } from '@/views/constants/ViewBarFilterDropdownIds';
import { plural } from '@lingui/core/macro';
import { useMemo } from 'react';
import { isDefined } from 'twenty-shared/utils';
@@ -49,7 +49,7 @@ export const AdvancedFilterChip = () => {
});
const handleRemoveClick = () => {
closeDropdown(ADVANCED_FILTER_DROPDOWN_ID);
closeDropdown(ViewBarFilterDropdownIds.ADVANCED);
const viewFilterGroupIds = currentRecordFilterGroups.map(
(recordFilterGroup) => recordFilterGroup.id,
@@ -109,7 +109,7 @@ export const AdvancedFilterChip = () => {
return (
<SortOrFilterChip
testId={ADVANCED_FILTER_DROPDOWN_ID}
testId={ViewBarFilterDropdownIds.ADVANCED}
labelKey={chipLabel}
labelValue=""
Icon={IconFilter}
@@ -4,8 +4,8 @@ import { AdvancedFilterRootRecordFilterGroup } from '@/object-record/advanced-fi
import { useSetAdvancedFilterDropdownStates } from '@/object-record/advanced-filter/hooks/useSetAdvancedFilterDropdownAllRowsStates';
import { rootLevelRecordFilterGroupComponentSelector } from '@/object-record/advanced-filter/states/rootLevelRecordFilterGroupComponentSelector';
import { useRecoilComponentValue } from '@/ui/utilities/state/component-state/hooks/useRecoilComponentValue';
import { AdvancedFilterChip } from '@/views/components/AdvancedFilterChip';
import { ADVANCED_FILTER_DROPDOWN_ID } from '@/views/constants/AdvancedFilterDropdownId';
import { AdvancedFilterChip } from '@/views/advanced-filter-chip/components/AdvancedFilterChip';
import { ViewBarFilterDropdownIds } from '@/views/constants/ViewBarFilterDropdownIds';
import { isDefined } from 'twenty-shared/utils';
export const AdvancedFilterDropdownButton = () => {
@@ -26,7 +26,7 @@ export const AdvancedFilterDropdownButton = () => {
return (
<Dropdown
dropdownId={ADVANCED_FILTER_DROPDOWN_ID}
dropdownId={ViewBarFilterDropdownIds.ADVANCED}
clickableComponent={<AdvancedFilterChip />}
dropdownComponents={<AdvancedFilterRootRecordFilterGroup />}
dropdownOffset={{ y: 8, x: 0 }}
@@ -2,7 +2,7 @@ import { anyFieldFilterValueComponentState } from '@/object-record/record-filter
import { useCloseDropdown } from '@/ui/layout/dropdown/hooks/useCloseDropdown';
import { useRecoilComponentState } from '@/ui/utilities/state/component-state/hooks/useRecoilComponentState';
import { SortOrFilterChip } from '@/views/components/SortOrFilterChip';
import { ADVANCED_FILTER_DROPDOWN_ID } from '@/views/constants/AdvancedFilterDropdownId';
import { ViewBarFilterDropdownIds } from '@/views/constants/ViewBarFilterDropdownIds';
import { useLingui } from '@lingui/react/macro';
import { IconFilter } from 'twenty-ui/display';
@@ -22,7 +22,7 @@ export const AnyFieldSearchChip = () => {
return (
<SortOrFilterChip
testId={ADVANCED_FILTER_DROPDOWN_ID}
testId={ViewBarFilterDropdownIds.ADVANCED}
labelKey={t`Any field`}
labelValue={`: ${anyFieldFilterValue}`}
Icon={IconFilter}
@@ -20,7 +20,7 @@ import { ViewBarRecordFieldEffect } from '@/views/components/ViewBarRecordFieldE
import { ViewBarRecordFilterEffect } from '@/views/components/ViewBarRecordFilterEffect';
import { ViewBarRecordFilterGroupEffect } from '@/views/components/ViewBarRecordFilterGroupEffect';
import { ViewBarRecordSortEffect } from '@/views/components/ViewBarRecordSortEffect';
import { VIEW_BAR_FILTER_DROPDOWN_ID } from '@/views/constants/ViewBarFilterDropdownId';
import { ViewBarFilterDropdownIds } from '@/views/constants/ViewBarFilterDropdownIds';
import { UpdateViewButtonGroup } from './UpdateViewButtonGroup';
import { ViewBarDetails } from './ViewBarDetails';
@@ -63,7 +63,7 @@ export const ViewBar = ({
rightComponent={
<>
<ObjectFilterDropdownComponentInstanceContext.Provider
value={{ instanceId: VIEW_BAR_FILTER_DROPDOWN_ID }}
value={{ instanceId: ViewBarFilterDropdownIds.MAIN }}
>
<ViewBarFilterDropdown />
</ObjectFilterDropdownComponentInstanceContext.Provider>
@@ -5,10 +5,9 @@ import { useObjectNameSingularFromPlural } from '@/object-metadata/hooks/useObje
import { ObjectFilterDropdownComponentInstanceContext } from '@/object-record/object-filter-dropdown/states/contexts/ObjectFilterDropdownComponentInstanceContext';
import { useHandleToggleTrashColumnFilter } from '@/object-record/record-index/hooks/useHandleToggleTrashColumnFilter';
import { useRecoilComponentValue } from '@/ui/utilities/state/component-state/hooks/useRecoilComponentValue';
import { AdvancedFilterDropdownButton } from '@/views/components/AdvancedFilterDropdownButton';
import { EditableFilterDropdownButton } from '@/views/components/EditableFilterDropdownButton';
import { EditableSortChip } from '@/views/components/EditableSortChip';
import { AdvancedFilterDropdownButton } from '@/views/advanced-filter-chip/components/AdvancedFilterDropdownButton';
import { ViewBarDetailsAddFilterButton } from '@/views/components/ViewBarDetailsAddFilterButton';
import { EditableSortChip } from '@/views/editable-chip/components/EditableSortChip';
import { currentRecordFiltersComponentState } from '@/object-record/record-filter/states/currentRecordFiltersComponentState';
import { currentRecordSortsComponentState } from '@/object-record/record-sort/states/currentRecordSortsComponentState';
@@ -25,6 +24,8 @@ import { isDropdownOpenComponentState } from '@/ui/layout/dropdown/states/isDrop
import { ScrollWrapper } from '@/ui/utilities/scroll/components/ScrollWrapper';
import { AnyFieldSearchDropdownButton } from '@/views/components/AnyFieldSearchDropdownButton';
import { ANY_FIELD_SEARCH_DROPDOWN_ID } from '@/views/constants/AnyFieldSearchDropdownId';
import { EditableFilterDropdownButton } from '@/views/editable-chip/components/EditableFilterDropdownButton';
import { getEditableChipObjectFilterDropdownComponentInstanceId } from '@/views/editable-chip/utils/getEditableChipObjectFilterDropdownComponentInstanceId';
import { useHasFiltersInQueryParams } from '@/views/hooks/internal/useHasFiltersInQueryParams';
import { useApplyCurrentViewAnyFieldFilterToAnyFieldFilter } from '@/views/hooks/useApplyCurrentViewAnyFieldFilterToAnyFieldFilter';
import { useApplyCurrentViewFilterGroupsToCurrentRecordFilterGroups } from '@/views/hooks/useApplyCurrentViewFilterGroupsToCurrentRecordFilterGroups';
@@ -253,7 +254,12 @@ export const ViewBarDetails = ({
{recordFilters.map((recordFilter) => (
<ObjectFilterDropdownComponentInstanceContext.Provider
key={recordFilter.id}
value={{ instanceId: recordFilter.id }}
value={{
instanceId:
getEditableChipObjectFilterDropdownComponentInstanceId({
recordFilterId: recordFilter.id,
}),
}}
>
<EditableFilterDropdownButton recordFilter={recordFilter} />
</ObjectFilterDropdownComponentInstanceContext.Provider>
@@ -1,4 +1,4 @@
import { VIEW_BAR_FILTER_DROPDOWN_ID } from '@/views/constants/ViewBarFilterDropdownId';
import { ViewBarFilterDropdownIds } from '@/views/constants/ViewBarFilterDropdownIds';
import { useResetFilterDropdown } from '@/object-record/object-filter-dropdown/hooks/useResetFilterDropdown';
import { useToggleDropdown } from '@/ui/layout/dropdown/hooks/useToggleDropdown';
@@ -10,13 +10,13 @@ export const ViewBarDetailsAddFilterButton = () => {
const { toggleDropdown } = useToggleDropdown();
const { resetFilterDropdown } = useResetFilterDropdown(
VIEW_BAR_FILTER_DROPDOWN_ID,
ViewBarFilterDropdownIds.MAIN,
);
const handleClick = () => {
resetFilterDropdown();
toggleDropdown({
dropdownComponentInstanceIdFromProps: VIEW_BAR_FILTER_DROPDOWN_ID,
dropdownComponentInstanceIdFromProps: ViewBarFilterDropdownIds.MAIN,
});
};
@@ -1,13 +1,13 @@
import { StyledHeaderDropdownButton } from '@/ui/layout/dropdown/components/StyledHeaderDropdownButton';
import { isDropdownOpenComponentState } from '@/ui/layout/dropdown/states/isDropdownOpenComponentState';
import { useRecoilComponentValue } from '@/ui/utilities/state/component-state/hooks/useRecoilComponentValue';
import { VIEW_BAR_FILTER_DROPDOWN_ID } from '@/views/constants/ViewBarFilterDropdownId';
import { ViewBarFilterDropdownIds } from '@/views/constants/ViewBarFilterDropdownIds';
import { Trans } from '@lingui/react/macro';
export const ViewBarFilterButton = () => {
const isDropdownOpen = useRecoilComponentValue(
isDropdownOpenComponentState,
VIEW_BAR_FILTER_DROPDOWN_ID,
ViewBarFilterDropdownIds.MAIN,
);
return (
@@ -1,28 +1,23 @@
import { useResetFilterDropdown } from '@/object-record/object-filter-dropdown/hooks/useResetFilterDropdown';
import { Dropdown } from '@/ui/layout/dropdown/components/Dropdown';
import { VIEW_BAR_FILTER_DROPDOWN_ID } from '@/views/constants/ViewBarFilterDropdownId';
import { useVectorSearchFilterActions } from '@/views/hooks/useVectorSearchFilterActions';
import { ViewBarFilterDropdownIds } from '@/views/constants/ViewBarFilterDropdownIds';
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 { useRecoilComponentValue } from '@/ui/utilities/state/component-state/hooks/useRecoilComponentValue';
import { ViewBarFilterDropdownContent } from '@/views/components/ViewBarFilterDropdownContent';
import { useClearVectorSearchInput } from '@/views/hooks/useClearVectorSearchInput';
import { isDefined } from 'twenty-shared/utils';
import { ViewBarFilterButton } from './ViewBarFilterButton';
export const ViewBarFilterDropdown = () => {
const { resetFilterDropdown } = useResetFilterDropdown();
const { removeEmptyVectorSearchFilter } = useVectorSearchFilterActions();
const { removeRecordFilter } = useRemoveRecordFilter();
const objectFilterDropdownCurrentRecordFilter = useRecoilComponentValue(
objectFilterDropdownCurrentRecordFilterComponentState,
);
const { clearVectorSearchInput } = useClearVectorSearchInput();
const handleDropdownClickOutside = () => {
const recordFilterIsEmpty =
isDefined(objectFilterDropdownCurrentRecordFilter) &&
@@ -33,14 +28,10 @@ export const ViewBarFilterDropdown = () => {
recordFilterId: objectFilterDropdownCurrentRecordFilter.id,
});
}
removeEmptyVectorSearchFilter();
};
const handleDropdownClose = () => {
resetFilterDropdown();
removeEmptyVectorSearchFilter();
clearVectorSearchInput();
};
const handleDropdownOpen = () => {
@@ -49,7 +40,7 @@ export const ViewBarFilterDropdown = () => {
return (
<Dropdown
dropdownId={VIEW_BAR_FILTER_DROPDOWN_ID}
dropdownId={ViewBarFilterDropdownIds.MAIN}
onClose={handleDropdownClose}
onOpen={handleDropdownOpen}
clickableComponent={<ViewBarFilterButton />}
@@ -7,14 +7,13 @@ import { SelectableListItem } from '@/ui/layout/selectable-list/components/Selec
import { isSelectedItemIdComponentFamilySelector } from '@/ui/layout/selectable-list/states/selectors/isSelectedItemIdComponentFamilySelector';
import { useRecoilComponentFamilyValue } from '@/ui/utilities/state/component-state/hooks/useRecoilComponentFamilyValue';
import { VIEW_BAR_FILTER_BOTTOM_MENU_ITEM_IDS } from '@/views/constants/ViewBarFilterBottomMenuItemIds';
import { VIEW_BAR_FILTER_DROPDOWN_ID } from '@/views/constants/ViewBarFilterDropdownId';
import { useSetRecordFilterUsedInAdvancedFilterDropdownRow } from '@/object-record/advanced-filter/hooks/useSetRecordFilterUsedInAdvancedFilterDropdownRow';
import { useCreateEmptyRecordFilterFromFieldMetadataItem } from '@/object-record/record-filter/hooks/useCreateEmptyRecordFilterFromFieldMetadataItem';
import { useCloseDropdown } from '@/ui/layout/dropdown/hooks/useCloseDropdown';
import { useOpenDropdown } from '@/ui/layout/dropdown/hooks/useOpenDropdown';
import { useRecoilComponentValue } from '@/ui/utilities/state/component-state/hooks/useRecoilComponentValue';
import { ADVANCED_FILTER_DROPDOWN_ID } from '@/views/constants/AdvancedFilterDropdownId';
import { ViewBarFilterDropdownIds } from '@/views/constants/ViewBarFilterDropdownIds';
import { useGetCurrentViewOnly } from '@/views/hooks/useGetCurrentViewOnly';
import styled from '@emotion/styled';
import { useLingui } from '@lingui/react/macro';
@@ -115,9 +114,9 @@ export const ViewBarFilterDropdownAdvancedFilterButton = () => {
setRecordFilterUsedInAdvancedFilterDropdownRow(newRecordFilter);
}
closeObjectFilterDropdown(VIEW_BAR_FILTER_DROPDOWN_ID);
closeObjectFilterDropdown(ViewBarFilterDropdownIds.MAIN);
openAdvancedFilterDropdown({
dropdownComponentInstanceIdFromProps: ADVANCED_FILTER_DROPDOWN_ID,
dropdownComponentInstanceIdFromProps: ViewBarFilterDropdownIds.ADVANCED,
});
};
@@ -1,42 +1,28 @@
import { objectFilterDropdownAnyFieldSearchIsSelectedComponentState } from '@/object-record/object-filter-dropdown/states/objectFilterDropdownAnyFieldSearchIsSelectedComponentState';
import { objectFilterDropdownFilterIsSelectedComponentState } from '@/object-record/object-filter-dropdown/states/objectFilterDropdownFilterIsSelectedComponentState';
import { selectedOperandInDropdownComponentState } from '@/object-record/object-filter-dropdown/states/selectedOperandInDropdownComponentState';
import { useRecoilComponentState } from '@/ui/utilities/state/component-state/hooks/useRecoilComponentState';
import { useRecoilComponentValue } from '@/ui/utilities/state/component-state/hooks/useRecoilComponentValue';
import { ViewBarFilterDropdownAnyFieldSearchInput } from '@/views/components/ViewBarFilterDropdownAnyFieldSearchInput';
import { ViewBarFilterDropdownFieldSelectMenu } from '@/views/components/ViewBarFilterDropdownFieldSelectMenu';
import { ViewBarFilterDropdownFilterInput } from '@/views/components/ViewBarFilterDropdownFilterInput';
import { ViewBarFilterDropdownVectorSearchInput } from '@/views/components/ViewBarFilterDropdownVectorSearchInput';
import { VIEW_BAR_FILTER_DROPDOWN_ID } from '@/views/constants/ViewBarFilterDropdownId';
import { ViewFilterOperand } from 'twenty-shared/types';
import { ViewBarFilterDropdownIds } from '@/views/constants/ViewBarFilterDropdownIds';
export const ViewBarFilterDropdownContent = () => {
const [objectFilterDropdownFilterIsSelected] = useRecoilComponentState(
objectFilterDropdownFilterIsSelectedComponentState,
VIEW_BAR_FILTER_DROPDOWN_ID,
ViewBarFilterDropdownIds.MAIN,
);
const objectFilterDropdownAnyFieldSearchIsSelected = useRecoilComponentValue(
objectFilterDropdownAnyFieldSearchIsSelectedComponentState,
);
const selectedOperandInDropdown = useRecoilComponentValue(
selectedOperandInDropdownComponentState,
);
const isVectorSearchFilter =
selectedOperandInDropdown === ViewFilterOperand.VECTOR_SEARCH;
const isAnyFieldSearchFilter = objectFilterDropdownAnyFieldSearchIsSelected;
if (isAnyFieldSearchFilter) {
return <ViewBarFilterDropdownAnyFieldSearchInput />;
}
if (isVectorSearchFilter) {
return <ViewBarFilterDropdownVectorSearchInput />;
}
const shouldShowFilterInput = objectFilterDropdownFilterIsSelected;
return (
@@ -21,7 +21,7 @@ import { DropdownMenuHeaderLeftComponent } from '@/ui/layout/dropdown/components
import { GenericDropdownContentWidth } from '@/ui/layout/dropdown/constants/GenericDropdownContentWidth';
import { useCloseDropdown } from '@/ui/layout/dropdown/hooks/useCloseDropdown';
import { VIEW_BAR_FILTER_BOTTOM_MENU_ITEM_IDS } from '@/views/constants/ViewBarFilterBottomMenuItemIds';
import { VIEW_BAR_FILTER_DROPDOWN_ID } from '@/views/constants/ViewBarFilterDropdownId';
import { ViewBarFilterDropdownIds } from '@/views/constants/ViewBarFilterDropdownIds';
import { useLingui } from '@lingui/react/macro';
import { IconX } from 'twenty-ui/display';
@@ -110,7 +110,7 @@ export const ViewBarFilterDropdownFieldSelectMenu = () => {
<SelectableList
selectableItemIdArray={selectableFieldMetadataItemIds}
selectableListInstanceId={FILTER_FIELD_LIST_ID}
focusId={VIEW_BAR_FILTER_DROPDOWN_ID}
focusId={ViewBarFilterDropdownIds.MAIN}
>
{shouldShowVisibleFields && (
<>
@@ -1,7 +1,7 @@
import { ObjectFilterDropdownContentWrapper } from '@/object-record/object-filter-dropdown/components/ObjectFilterDropdownContentWrapper';
import { ObjectFilterDropdownFilterInput } from '@/object-record/object-filter-dropdown/components/ObjectFilterDropdownFilterInput';
import { ViewBarFilterDropdownFilterInputMenuHeader } from '@/views/components/ViewBarFilterDropdownFilterInputMenuHeader';
import { VIEW_BAR_FILTER_DROPDOWN_ID } from '@/views/constants/ViewBarFilterDropdownId';
import { ViewBarFilterDropdownIds } from '@/views/constants/ViewBarFilterDropdownIds';
type ViewBarFilterDropdownFilterInputProps = {
recordFilterId?: string;
@@ -14,7 +14,7 @@ export const ViewBarFilterDropdownFilterInput = ({
<ObjectFilterDropdownContentWrapper>
<ViewBarFilterDropdownFilterInputMenuHeader />
<ObjectFilterDropdownFilterInput
filterDropdownId={VIEW_BAR_FILTER_DROPDOWN_ID}
filterDropdownId={ViewBarFilterDropdownIds.MAIN}
recordFilterId={recordFilterId}
/>
</ObjectFilterDropdownContentWrapper>
@@ -1,35 +1,19 @@
import { useResetFilterDropdown } from '@/object-record/object-filter-dropdown/hooks/useResetFilterDropdown';
import { fieldMetadataItemUsedInDropdownComponentSelector } from '@/object-record/object-filter-dropdown/states/fieldMetadataItemUsedInDropdownComponentSelector';
import { selectedOperandInDropdownComponentState } from '@/object-record/object-filter-dropdown/states/selectedOperandInDropdownComponentState';
import { DropdownMenuHeader } from '@/ui/layout/dropdown/components/DropdownMenuHeader/DropdownMenuHeader';
import { DropdownMenuHeaderLeftComponent } from '@/ui/layout/dropdown/components/DropdownMenuHeader/internal/DropdownMenuHeaderLeftComponent';
import { useRecoilComponentValue } from '@/ui/utilities/state/component-state/hooks/useRecoilComponentValue';
import { useClearVectorSearchInput } from '@/views/hooks/useClearVectorSearchInput';
import { useLingui } from '@lingui/react/macro';
import { ViewFilterOperand } from 'twenty-shared/types';
import { IconChevronLeft } from 'twenty-ui/display';
export const ViewBarFilterDropdownFilterInputMenuHeader = () => {
const { t } = useLingui();
const fieldMetadataItemUsedInDropdown = useRecoilComponentValue(
fieldMetadataItemUsedInDropdownComponentSelector,
);
const selectedOperandInDropdown = useRecoilComponentValue(
selectedOperandInDropdownComponentState,
);
const isVectorSearchFilter =
selectedOperandInDropdown === ViewFilterOperand.VECTOR_SEARCH;
const { clearVectorSearchInput } = useClearVectorSearchInput();
const { resetFilterDropdown } = useResetFilterDropdown();
const handleBackButtonClick = () => {
resetFilterDropdown();
clearVectorSearchInput();
};
return (
@@ -41,9 +25,7 @@ export const ViewBarFilterDropdownFilterInputMenuHeader = () => {
/>
}
>
{isVectorSearchFilter
? t`Search`
: fieldMetadataItemUsedInDropdown?.label}
{fieldMetadataItemUsedInDropdown?.label}
</DropdownMenuHeader>
);
};
@@ -1,75 +0,0 @@
import { SelectableListItem } from '@/ui/layout/selectable-list/components/SelectableListItem';
import { isSelectedItemIdComponentFamilySelector } from '@/ui/layout/selectable-list/states/selectors/isSelectedItemIdComponentFamilySelector';
import { useRecoilComponentFamilyValue } from '@/ui/utilities/state/component-state/hooks/useRecoilComponentFamilyValue';
import { useRecoilComponentState } from '@/ui/utilities/state/component-state/hooks/useRecoilComponentState';
import { useRecoilComponentValue } from '@/ui/utilities/state/component-state/hooks/useRecoilComponentValue';
import styled from '@emotion/styled';
import { useLingui } from '@lingui/react/macro';
import { IconSearch } from 'twenty-ui/display';
import { MenuItem } from 'twenty-ui/navigation';
import { VIEW_BAR_FILTER_BOTTOM_MENU_ITEM_IDS } from '@/views/constants/ViewBarFilterBottomMenuItemIds';
import { objectFilterDropdownSearchInputComponentState } from '@/object-record/object-filter-dropdown/states/objectFilterDropdownSearchInputComponentState';
import { useOpenVectorSearchFilter } from '@/views/hooks/useOpenVectorSearchFilter';
import { useSetVectorSearchInputValueFromExistingFilter } from '@/views/hooks/useSetVectorSearchInputValueFromExistingFilter';
import { useVectorSearchFilterActions } from '@/views/hooks/useVectorSearchFilterActions';
import { vectorSearchInputComponentState } from '@/views/states/vectorSearchInputComponentState';
const StyledSearchText = styled.span`
color: ${({ theme }) => theme.font.color.light};
margin-left: ${({ theme }) => theme.spacing(1)};
`;
export const ViewBarFilterDropdownVectorSearchButton = () => {
const { t } = useLingui();
const [, setVectorSearchInputValue] = useRecoilComponentState(
vectorSearchInputComponentState,
);
const { setVectorSearchInputValueFromExistingFilter } =
useSetVectorSearchInputValueFromExistingFilter();
const objectFilterDropdownSearchInput = useRecoilComponentValue(
objectFilterDropdownSearchInputComponentState,
);
const { applyVectorSearchFilter } = useVectorSearchFilterActions();
const { openVectorSearchFilter } = useOpenVectorSearchFilter();
const isSelected = useRecoilComponentFamilyValue(
isSelectedItemIdComponentFamilySelector,
VIEW_BAR_FILTER_BOTTOM_MENU_ITEM_IDS.SEARCH,
);
const handleSearchClick = () => {
openVectorSearchFilter();
if (objectFilterDropdownSearchInput.length > 0) {
setVectorSearchInputValue(objectFilterDropdownSearchInput);
applyVectorSearchFilter(objectFilterDropdownSearchInput);
} else {
setVectorSearchInputValueFromExistingFilter();
}
};
return (
<SelectableListItem
itemId={VIEW_BAR_FILTER_BOTTOM_MENU_ITEM_IDS.SEARCH}
onEnter={handleSearchClick}
>
<MenuItem
focused={isSelected}
onClick={handleSearchClick}
LeftIcon={IconSearch}
text={
<>
{t`Search`}
{objectFilterDropdownSearchInput && (
<StyledSearchText>{t`· ${objectFilterDropdownSearchInput}`}</StyledSearchText>
)}
</>
}
/>
</SelectableListItem>
);
};
@@ -1,13 +0,0 @@
import { ObjectFilterDropdownVectorSearchInput } from '@/object-record/object-filter-dropdown/components/ObjectFilterDropdownVectorSearchInput';
import { DropdownContent } from '@/ui/layout/dropdown/components/DropdownContent';
import { GenericDropdownContentWidth } from '@/ui/layout/dropdown/constants/GenericDropdownContentWidth';
import { ViewBarFilterDropdownFilterInputMenuHeader } from '@/views/components/ViewBarFilterDropdownFilterInputMenuHeader';
export const ViewBarFilterDropdownVectorSearchInput = () => {
return (
<DropdownContent widthInPixels={GenericDropdownContentWidth.ExtraLarge}>
<ViewBarFilterDropdownFilterInputMenuHeader />
<ObjectFilterDropdownVectorSearchInput />
</DropdownContent>
);
};
@@ -16,7 +16,7 @@ import { RecordComponentInstanceContextsWrapper } from '@/object-record/componen
import { currentRecordFieldsComponentState } from '@/object-record/record-field/states/currentRecordFieldsComponentState';
import { type RecordField } from '@/object-record/record-field/types/RecordField';
import { useRecordIndexFieldMetadataDerivedStates } from '@/object-record/record-index/hooks/useRecordIndexFieldMetadataDerivedStates';
import { VIEW_BAR_FILTER_DROPDOWN_ID } from '@/views/constants/ViewBarFilterDropdownId';
import { ViewBarFilterDropdownIds } from '@/views/constants/ViewBarFilterDropdownIds';
import { coreViewsState } from '@/views/states/coreViewState';
import { within } from '@storybook/test';
import { useSetRecoilState } from 'recoil';
@@ -104,7 +104,7 @@ const meta: Meta<typeof ViewBarFilterDropdown> = {
componentInstanceId={instanceId}
>
<ObjectFilterDropdownComponentInstanceContext.Provider
value={{ instanceId: VIEW_BAR_FILTER_DROPDOWN_ID }}
value={{ instanceId: ViewBarFilterDropdownIds.MAIN }}
>
<RecordTableComponentInstanceContext.Provider
value={{
@@ -1 +0,0 @@
export const ADVANCED_FILTER_DROPDOWN_ID = 'advanced-filter';
@@ -1 +0,0 @@
export const VIEW_BAR_FILTER_DROPDOWN_ID = 'view-bar-filter-dropdown';
@@ -0,0 +1,5 @@
export enum ViewBarFilterDropdownIds {
MAIN = 'view-bar-main-filter-dropdown-id',
ADVANCED = 'view-bar-advanced-filter-dropdown-id',
// We also have editable chip dropdown, in this case use the getEditableChipDropdownId
}
@@ -1,6 +1,7 @@
import { ObjectFilterDropdownContentWrapper } from '@/object-record/object-filter-dropdown/components/ObjectFilterDropdownContentWrapper';
import { ObjectFilterDropdownFilterInput } from '@/object-record/object-filter-dropdown/components/ObjectFilterDropdownFilterInput';
import { EditableFilterChipDropdownMenuHeader } from '@/views/components/EditableFilterChipDropdownMenuHeader';
import { EditableFilterChipDropdownMenuHeader } from '@/views/editable-chip/components/EditableFilterChipDropdownMenuHeader';
import { getEditableChipDropdownId } from '@/views/editable-chip/utils/getEditableChipDropdownId';
type EditableFilterChipDropdownContentProps = {
recordFilterId: string;
@@ -13,7 +14,7 @@ export const EditableFilterChipDropdownContent = ({
<ObjectFilterDropdownContentWrapper>
<EditableFilterChipDropdownMenuHeader />
<ObjectFilterDropdownFilterInput
filterDropdownId={recordFilterId}
filterDropdownId={getEditableChipDropdownId({ recordFilterId })}
recordFilterId={recordFilterId}
/>
</ObjectFilterDropdownContentWrapper>
@@ -1,27 +1,15 @@
import { fieldMetadataItemUsedInDropdownComponentSelector } from '@/object-record/object-filter-dropdown/states/fieldMetadataItemUsedInDropdownComponentSelector';
import { selectedOperandInDropdownComponentState } from '@/object-record/object-filter-dropdown/states/selectedOperandInDropdownComponentState';
import { DropdownMenuHeader } from '@/ui/layout/dropdown/components/DropdownMenuHeader/DropdownMenuHeader';
import { DropdownMenuHeaderLeftComponent } from '@/ui/layout/dropdown/components/DropdownMenuHeader/internal/DropdownMenuHeaderLeftComponent';
import { useCloseDropdown } from '@/ui/layout/dropdown/hooks/useCloseDropdown';
import { useRecoilComponentValue } from '@/ui/utilities/state/component-state/hooks/useRecoilComponentValue';
import { useLingui } from '@lingui/react/macro';
import { ViewFilterOperand } from 'twenty-shared/types';
import { IconX } from 'twenty-ui/display';
export const EditableFilterChipDropdownMenuHeader = () => {
const { t } = useLingui();
const fieldMetadataItemUsedInDropdown = useRecoilComponentValue(
fieldMetadataItemUsedInDropdownComponentSelector,
);
const selectedOperandInDropdown = useRecoilComponentValue(
selectedOperandInDropdownComponentState,
);
const isVectorSearchFilter =
selectedOperandInDropdown === ViewFilterOperand.VECTOR_SEARCH;
const { closeDropdown } = useCloseDropdown();
const handleBackButtonClick = () => {
@@ -37,9 +25,7 @@ export const EditableFilterChipDropdownMenuHeader = () => {
/>
}
>
{isVectorSearchFilter
? t`Search`
: fieldMetadataItemUsedInDropdown?.label}
{fieldMetadataItemUsedInDropdown?.label}
</DropdownMenuHeader>
);
};
@@ -2,14 +2,14 @@ import { useCallback } from 'react';
import { type RecordFilter } from '@/object-record/record-filter/types/RecordFilter';
import { Dropdown } from '@/ui/layout/dropdown/components/Dropdown';
import { EditableFilterChip } from '@/views/components/EditableFilterChip';
import { EditableFilterChip } from '@/views/editable-chip/components/EditableFilterChip';
import { useRemoveRecordFilter } from '@/object-record/record-filter/hooks/useRemoveRecordFilter';
import { isRecordFilterConsideredEmpty } from '@/object-record/record-filter/utils/isRecordFilterConsideredEmpty';
import { useCloseDropdown } from '@/ui/layout/dropdown/hooks/useCloseDropdown';
import { EditableFilterChipDropdownContent } from '@/views/components/EditableFilterChipDropdownContent';
import { EditableRelationFilterChip } from '@/views/components/EditableRelationFilterChip';
import { useClearVectorSearchInput } from '@/views/hooks/useClearVectorSearchInput';
import { EditableFilterChipDropdownContent } from '@/views/editable-chip/components/EditableFilterChipDropdownContent';
import { EditableRelationFilterChip } from '@/views/editable-chip/components/EditableRelationFilterChip';
import { getEditableChipDropdownId } from '@/views/editable-chip/utils/getEditableChipDropdownId';
import { useSetEditableFilterChipDropdownStates } from '@/views/hooks/useSetEditableFilterChipDropdownStates';
type EditableFilterDropdownButtonProps = {
@@ -19,29 +19,25 @@ type EditableFilterDropdownButtonProps = {
export const EditableFilterDropdownButton = ({
recordFilter,
}: EditableFilterDropdownButtonProps) => {
const dropdownId = recordFilter.id;
const { closeDropdown } = useCloseDropdown();
const { removeRecordFilter } = useRemoveRecordFilter();
const handleRemove = () => {
closeDropdown(dropdownId);
closeDropdown(
getEditableChipDropdownId({ recordFilterId: recordFilter.id }),
);
removeRecordFilter({ recordFilterId: recordFilter.id });
};
const { clearVectorSearchInput } = useClearVectorSearchInput();
const onFilterDropdownClose = useCallback(() => {
const recordFilterIsEmpty = isRecordFilterConsideredEmpty(recordFilter);
if (recordFilterIsEmpty) {
removeRecordFilter({ recordFilterId: recordFilter.id });
}
clearVectorSearchInput();
}, [recordFilter, removeRecordFilter, clearVectorSearchInput]);
}, [recordFilter, removeRecordFilter]);
const { setEditableFilterChipDropdownStates } =
useSetEditableFilterChipDropdownStates();
@@ -53,7 +49,9 @@ export const EditableFilterDropdownButton = ({
return (
<>
<Dropdown
dropdownId={recordFilter.id}
dropdownId={getEditableChipDropdownId({
recordFilterId: recordFilter.id,
})}
clickableComponent={
recordFilter.type === 'RELATION' ? (
<EditableRelationFilterChip
@@ -0,0 +1,9 @@
type GetEditableChipDropdownIdProps = {
recordFilterId: string;
};
export const getEditableChipDropdownId = ({
recordFilterId,
}: GetEditableChipDropdownIdProps) => {
return `editable-chip-dropdown-${recordFilterId}`;
};
@@ -0,0 +1,9 @@
type GetEditableChipObjectFilterDropdownComponentInstanceIdProps = {
recordFilterId: string;
};
export const getEditableChipObjectFilterDropdownComponentInstanceId = ({
recordFilterId,
}: GetEditableChipObjectFilterDropdownComponentInstanceIdProps) => {
return `editable-filter-${recordFilterId}`;
};
@@ -17,7 +17,7 @@ import { getRecordFilterOperands } from '@/object-record/record-filter/utils/get
import { FocusComponentType } from '@/ui/utilities/focus/types/FocusComponentType';
import { useRecoilComponentValue } from '@/ui/utilities/state/component-state/hooks/useRecoilComponentValue';
import { useSetRecoilComponentState } from '@/ui/utilities/state/component-state/hooks/useSetRecoilComponentState';
import { VIEW_BAR_FILTER_DROPDOWN_ID } from '@/views/constants/ViewBarFilterDropdownId';
import { ViewBarFilterDropdownIds } from '@/views/constants/ViewBarFilterDropdownIds';
import { getFilterTypeFromFieldType } from 'twenty-shared/utils';
import { getMockPersonObjectMetadataItem } from '~/testing/mock-data/people';
import { generatedMockObjectMetadataItems } from '~/testing/utils/generatedMockObjectMetadataItems';
@@ -165,7 +165,7 @@ describe('useInitializeFilterOnFieldMetadataItemFromViewBarFilterDropdown', () =
expect(result.current.objectFilterDropdownFilterIsSelected).toBe(true);
expect(result.current.selectedOperandInDropdown).toBe(defaultOperand);
expect(mockPushFocusItemToFocusStack).toHaveBeenCalledWith({
focusId: VIEW_BAR_FILTER_DROPDOWN_ID,
focusId: ViewBarFilterDropdownIds.MAIN,
component: {
type: FocusComponentType.DROPDOWN,
instanceId: personCompanyFieldMetadataItemMock.id,
@@ -1,16 +0,0 @@
import { useSetRecoilComponentState } from '@/ui/utilities/state/component-state/hooks/useSetRecoilComponentState';
import { vectorSearchInputComponentState } from '@/views/states/vectorSearchInputComponentState';
export const useClearVectorSearchInput = () => {
const setVectorSearchInputValue = useSetRecoilComponentState(
vectorSearchInputComponentState,
);
const clearVectorSearchInput = () => {
setVectorSearchInputValue('');
};
return {
clearVectorSearchInput,
};
};
@@ -13,7 +13,7 @@ import { getRecordFilterOperands } from '@/object-record/record-filter/utils/get
import { usePushFocusItemToFocusStack } from '@/ui/utilities/focus/hooks/usePushFocusItemToFocusStack';
import { FocusComponentType } from '@/ui/utilities/focus/types/FocusComponentType';
import { useRecoilComponentCallbackState } from '@/ui/utilities/state/component-state/hooks/useRecoilComponentCallbackState';
import { VIEW_BAR_FILTER_DROPDOWN_ID } from '@/views/constants/ViewBarFilterDropdownId';
import { ViewBarFilterDropdownIds } from '@/views/constants/ViewBarFilterDropdownIds';
import { useRecoilCallback } from 'recoil';
import { getFilterTypeFromFieldType, isDefined } from 'twenty-shared/utils';
@@ -68,7 +68,7 @@ export const useInitializeFilterOnFieldMetadataItemFromViewBarFilterDropdown =
if (filterType === 'RELATION' || filterType === 'SELECT') {
pushFocusItemToFocusStack({
focusId: VIEW_BAR_FILTER_DROPDOWN_ID,
focusId: ViewBarFilterDropdownIds.MAIN,
component: {
type: FocusComponentType.DROPDOWN,
instanceId: fieldMetadataItem.id,
@@ -1,7 +1,7 @@
import { useRecordIndexContextOrThrow } from '@/object-record/record-index/contexts/RecordIndexContext';
import { type CoreViewFilter } from '~/generated/graphql';
import { type ViewFilter } from '../types/ViewFilter';
import { getFilterableFieldsWithVectorSearch } from '../utils/getFilterableFieldsWithVectorSearch';
import { getFilterableFields } from '../utils/getFilterableFields';
import { mapViewFiltersToFilters } from '../utils/mapViewFiltersToFilters';
export const useMapViewFiltersToFilters = () => {
@@ -11,7 +11,7 @@ export const useMapViewFiltersToFilters = () => {
viewFilters: ViewFilter[] | CoreViewFilter[],
) => {
const filterableFieldMetadataItems =
getFilterableFieldsWithVectorSearch(objectMetadataItem);
getFilterableFields(objectMetadataItem);
return mapViewFiltersToFilters(viewFilters, filterableFieldMetadataItems);
};
@@ -1,25 +0,0 @@
import { objectFilterDropdownFilterIsSelectedComponentState } from '@/object-record/object-filter-dropdown/states/objectFilterDropdownFilterIsSelectedComponentState';
import { selectedOperandInDropdownComponentState } from '@/object-record/object-filter-dropdown/states/selectedOperandInDropdownComponentState';
import { useSetRecoilComponentState } from '@/ui/utilities/state/component-state/hooks/useSetRecoilComponentState';
import { ViewFilterOperand } from 'twenty-shared/types';
export const useOpenVectorSearchFilter = (filterDropdownId?: string) => {
const setSelectedOperandInDropdown = useSetRecoilComponentState(
selectedOperandInDropdownComponentState,
filterDropdownId,
);
const setObjectFilterDropdownFilterIsSelected = useSetRecoilComponentState(
objectFilterDropdownFilterIsSelectedComponentState,
filterDropdownId,
);
const openVectorSearchFilter = () => {
setObjectFilterDropdownFilterIsSelected(true);
setSelectedOperandInDropdown(ViewFilterOperand.VECTOR_SEARCH);
};
return {
openVectorSearchFilter,
};
};
@@ -6,7 +6,7 @@ import { currentRecordSortsComponentState } from '@/object-record/record-sort/st
import { getRecordIndexIdFromObjectNamePluralAndViewId } from '@/object-record/utils/getRecordIndexIdFromObjectNamePluralAndViewId';
import { coreViewsByObjectMetadataIdFamilySelector } from '@/views/states/selectors/coreViewsByObjectMetadataIdFamilySelector';
import { convertCoreViewToView } from '@/views/utils/convertCoreViewToView';
import { getFilterableFieldsWithVectorSearch } from '@/views/utils/getFilterableFieldsWithVectorSearch';
import { getFilterableFields } from '@/views/utils/getFilterableFields';
import { mapViewFieldToRecordField } from '@/views/utils/mapViewFieldToRecordField';
import { mapViewFiltersToFilters } from '@/views/utils/mapViewFiltersToFilters';
@@ -117,7 +117,7 @@ export const useRefreshCoreViewsByObjectMetadataId = () => {
}),
mapViewFiltersToFilters(
view.viewFilters,
getFilterableFieldsWithVectorSearch(objectMetadataItem),
getFilterableFields(objectMetadataItem),
),
);
}
@@ -4,9 +4,7 @@ import { selectedOperandInDropdownComponentState } from '@/object-record/object-
import { subFieldNameUsedInDropdownComponentState } from '@/object-record/object-filter-dropdown/states/subFieldNameUsedInDropdownComponentState';
import { useFilterableFieldMetadataItemsInRecordIndexContext } from '@/object-record/record-filter/hooks/useFilterableFieldMetadataItemsInRecordIndexContext';
import { type RecordFilter } from '@/object-record/record-filter/types/RecordFilter';
import { useVectorSearchFieldInRecordIndexContextOrThrow } from '@/views/hooks/useVectorSearchFieldInRecordIndexContextOrThrow';
import { vectorSearchInputComponentState } from '@/views/states/vectorSearchInputComponentState';
import { isVectorSearchFilter } from '@/views/utils/isVectorSearchFilter';
import { getEditableChipObjectFilterDropdownComponentInstanceId } from '@/views/editable-chip/utils/getEditableChipObjectFilterDropdownComponentInstanceId';
import { useRecoilCallback } from 'recoil';
import { isDefined } from 'twenty-shared/utils';
@@ -14,26 +12,10 @@ export const useSetEditableFilterChipDropdownStates = () => {
const { filterableFieldMetadataItems } =
useFilterableFieldMetadataItemsInRecordIndexContext();
const { vectorSearchField } =
useVectorSearchFieldInRecordIndexContextOrThrow();
const setEditableFilterChipDropdownStates = useRecoilCallback(
({ set }) =>
(recordFilter: RecordFilter) => {
const filterableFieldsWithVector = vectorSearchField
? filterableFieldMetadataItems.concat(vectorSearchField)
: filterableFieldMetadataItems;
if (isVectorSearchFilter(recordFilter)) {
set(
vectorSearchInputComponentState.atomFamily({
instanceId: recordFilter.id,
}),
recordFilter.value,
);
}
const fieldMetadataItem = filterableFieldsWithVector.find(
const fieldMetadataItem = filterableFieldMetadataItems.find(
(fieldMetadataItem) =>
fieldMetadataItem.id === recordFilter.fieldMetadataId,
);
@@ -41,7 +23,10 @@ export const useSetEditableFilterChipDropdownStates = () => {
if (isDefined(fieldMetadataItem)) {
set(
fieldMetadataItemIdUsedInDropdownComponentState.atomFamily({
instanceId: recordFilter.id,
instanceId:
getEditableChipObjectFilterDropdownComponentInstanceId({
recordFilterId: recordFilter.id,
}),
}),
fieldMetadataItem.id,
);
@@ -49,26 +34,32 @@ export const useSetEditableFilterChipDropdownStates = () => {
set(
selectedOperandInDropdownComponentState.atomFamily({
instanceId: recordFilter.id,
instanceId: getEditableChipObjectFilterDropdownComponentInstanceId({
recordFilterId: recordFilter.id,
}),
}),
recordFilter.operand,
);
set(
objectFilterDropdownCurrentRecordFilterComponentState.atomFamily({
instanceId: recordFilter.id,
instanceId: getEditableChipObjectFilterDropdownComponentInstanceId({
recordFilterId: recordFilter.id,
}),
}),
recordFilter,
);
set(
subFieldNameUsedInDropdownComponentState.atomFamily({
instanceId: recordFilter.id,
instanceId: getEditableChipObjectFilterDropdownComponentInstanceId({
recordFilterId: recordFilter.id,
}),
}),
recordFilter.subFieldName,
);
},
[filterableFieldMetadataItems, vectorSearchField],
[filterableFieldMetadataItems],
);
return {
@@ -1,21 +0,0 @@
import { useRecoilComponentState } from '@/ui/utilities/state/component-state/hooks/useRecoilComponentState';
import { vectorSearchInputComponentState } from '@/views/states/vectorSearchInputComponentState';
import { isDefined } from 'twenty-shared/utils';
import { useVectorSearchFilterState } from './useVectorSearchFilterState';
export const useSetVectorSearchInputValueFromExistingFilter = () => {
const [, setVectorSearchInputValue] = useRecoilComponentState(
vectorSearchInputComponentState,
);
const { getExistingVectorSearchFilter } = useVectorSearchFilterState();
const setVectorSearchInputValueFromExistingFilter = () => {
const existingVectorSearchFilter = getExistingVectorSearchFilter();
if (isDefined(existingVectorSearchFilter)) {
setVectorSearchInputValue(existingVectorSearchFilter.value);
}
};
return { setVectorSearchInputValueFromExistingFilter };
};
@@ -1,13 +0,0 @@
import { useRecordIndexContextOrThrow } from '@/object-record/record-index/contexts/RecordIndexContext';
import { SEARCH_VECTOR_FIELD_NAME } from '../constants/ViewFieldConstants';
export const useVectorSearchFieldInRecordIndexContextOrThrow = () => {
const { objectMetadataItem } = useRecordIndexContextOrThrow();
const vectorSearchField = objectMetadataItem.fields.find(
(field) =>
field.type === 'TS_VECTOR' && field.name === SEARCH_VECTOR_FIELD_NAME,
);
return { vectorSearchField };
};
@@ -1,55 +0,0 @@
import { useRemoveRecordFilter } from '@/object-record/record-filter/hooks/useRemoveRecordFilter';
import { useUpsertRecordFilter } from '@/object-record/record-filter/hooks/useUpsertRecordFilter';
import { isRecordFilterConsideredEmpty } from '@/object-record/record-filter/utils/isRecordFilterConsideredEmpty';
import { useVectorSearchFieldInRecordIndexContextOrThrow } from '@/views/hooks/useVectorSearchFieldInRecordIndexContextOrThrow';
import { t } from '@lingui/core/macro';
import { ViewFilterOperand } from 'twenty-shared/types';
import { getFilterTypeFromFieldType, isDefined } from 'twenty-shared/utils';
import { v4 } from 'uuid';
import { useVectorSearchFilterState } from './useVectorSearchFilterState';
export const useVectorSearchFilterActions = () => {
const { vectorSearchField } =
useVectorSearchFieldInRecordIndexContextOrThrow();
const { getExistingVectorSearchFilter } = useVectorSearchFilterState();
const { upsertRecordFilter } = useUpsertRecordFilter();
const { removeRecordFilter } = useRemoveRecordFilter();
const applyVectorSearchFilter = (value: string) => {
if (!vectorSearchField) {
return;
}
const existingVectorSearchFilter = getExistingVectorSearchFilter();
const vectorSearchRecordFilter = {
id: existingVectorSearchFilter?.id ?? v4(),
fieldMetadataId: vectorSearchField.id,
value: value,
displayValue: value,
operand: ViewFilterOperand.VECTOR_SEARCH,
type: getFilterTypeFromFieldType(vectorSearchField.type),
label: t`Search`,
};
upsertRecordFilter(vectorSearchRecordFilter);
};
const removeEmptyVectorSearchFilter = () => {
const vectorSearchFilter = getExistingVectorSearchFilter();
if (
isDefined(vectorSearchFilter) &&
isRecordFilterConsideredEmpty(vectorSearchFilter)
) {
removeRecordFilter({
recordFilterId: vectorSearchFilter.id,
});
}
};
return {
applyVectorSearchFilter,
removeEmptyVectorSearchFilter,
};
};
@@ -1,17 +0,0 @@
import { currentRecordFiltersComponentState } from '@/object-record/record-filter/states/currentRecordFiltersComponentState';
import { useRecoilComponentValue } from '@/ui/utilities/state/component-state/hooks/useRecoilComponentValue';
import { isVectorSearchFilter } from '@/views/utils/isVectorSearchFilter';
export const useVectorSearchFilterState = () => {
const currentRecordFilters = useRecoilComponentValue(
currentRecordFiltersComponentState,
);
const getExistingVectorSearchFilter = () => {
return currentRecordFilters.find(isVectorSearchFilter);
};
return {
getExistingVectorSearchFilter,
};
};
@@ -1,8 +0,0 @@
import { ObjectFilterDropdownComponentInstanceContext } from '@/object-record/object-filter-dropdown/states/contexts/ObjectFilterDropdownComponentInstanceContext';
import { createComponentState } from '@/ui/utilities/state/component-state/utils/createComponentState';
export const vectorSearchInputComponentState = createComponentState<string>({
key: 'vectorSearchInputComponentState',
defaultValue: '',
componentInstanceContext: ObjectFilterDropdownComponentInstanceContext,
});
@@ -0,0 +1,10 @@
import { type ObjectMetadataItem } from '@/object-metadata/types/ObjectMetadataItem';
import { getFilterFilterableFieldMetadataItems } from '@/object-metadata/utils/getFilterFilterableFieldMetadataItems';
export const getFilterableFields = (objectMetadataItem: ObjectMetadataItem) => {
return [
...objectMetadataItem.fields.filter(
getFilterFilterableFieldMetadataItems({ isJsonFilterEnabled: true }),
),
];
};
@@ -1,19 +0,0 @@
import { type ObjectMetadataItem } from '@/object-metadata/types/ObjectMetadataItem';
import { getFilterFilterableFieldMetadataItems } from '@/object-metadata/utils/getFilterFilterableFieldMetadataItems';
import { SEARCH_VECTOR_FIELD_NAME } from '../constants/ViewFieldConstants';
export const getFilterableFieldsWithVectorSearch = (
objectMetadataItem: ObjectMetadataItem,
) => {
const vectorSearchField = objectMetadataItem.fields.find(
(field) =>
field.type === 'TS_VECTOR' && field.name === SEARCH_VECTOR_FIELD_NAME,
);
return [
...objectMetadataItem.fields.filter(
getFilterFilterableFieldMetadataItems({ isJsonFilterEnabled: true }),
),
...(vectorSearchField ? [vectorSearchField] : []),
];
};
@@ -1,6 +0,0 @@
import { type RecordFilter } from '@/object-record/record-filter/types/RecordFilter';
import { ViewFilterOperand } from 'twenty-shared/types';
export const isVectorSearchFilter = (filter: RecordFilter) => {
return filter.operand === ViewFilterOperand.VECTOR_SEARCH;
};
@@ -14,5 +14,4 @@ export enum ViewFilterOperandDeprecated {
IsInPast = 'isInPast',
IsInFuture = 'isInFuture',
IsToday = 'isToday',
VectorSearch = 'search',
}
@@ -19,7 +19,6 @@ const operandMapping: Record<string, ViewFilterOperand> = {
[ViewFilterOperandDeprecated.IsInPast]: ViewFilterOperand.IS_IN_PAST,
[ViewFilterOperandDeprecated.IsInFuture]: ViewFilterOperand.IS_IN_FUTURE,
[ViewFilterOperandDeprecated.IsToday]: ViewFilterOperand.IS_TODAY,
[ViewFilterOperandDeprecated.VectorSearch]: ViewFilterOperand.VECTOR_SEARCH,
[ViewFilterOperand.IS]: ViewFilterOperand.IS,
[ViewFilterOperand.IS_NOT_NULL]: ViewFilterOperand.IS_NOT_NULL,
[ViewFilterOperand.IS_NOT]: ViewFilterOperand.IS_NOT,