From 1c1a055c946ac53f6b53b4e61099ed951298c007 Mon Sep 17 00:00:00 2001 From: martmull Date: Thu, 18 Apr 2024 15:46:59 +0200 Subject: [PATCH] Improve multi word filtering (#5034) improve multi word search closes #4212 closes #3386 --- packages/twenty-front/src/App.tsx | 2 +- .../src/modules/auth/hooks/useAuth.ts | 2 +- .../sign-in-up/components/SignInUpForm.tsx | 10 +-- .../hooks/useNavigateAfterSignInUp.ts | 6 +- .../auth/sign-in-up/hooks/useSignInUp.tsx | 4 +- .../auth/sign-in-up/hooks/useSignInUpForm.ts | 4 +- .../sign-in-up/hooks/useSignInWithGoogle.ts | 2 +- .../billing/components/SubscriptionCard.tsx | 2 +- .../command-menu/components/CommandMenu.tsx | 7 +- .../ObjectMetadataItemsProvider.tsx | 2 +- .../hooks/useFieldMetadataItem.ts | 2 +- .../hooks/useObjectMetadataItem.ts | 2 +- .../hooks/useObjectNamePluralFromSingular.ts | 2 +- .../hooks/useObjectNameSingularFromPlural.ts | 2 +- .../formatFieldMetadataItemInput.test.ts | 2 +- .../utils/formatFieldMetadataItemInput.ts | 2 +- .../record-field/components/FieldDisplay.tsx | 2 +- .../record-field/components/FieldInput.tsx | 2 +- .../record-field/hooks/usePersistField.ts | 4 +- .../components/MultiSelectFieldDisplay.tsx | 2 +- .../meta-types/hooks/useMultiSelectField.ts | 16 ++--- .../components/MultiSelectFieldInput.tsx | 2 +- .../types/guards/isFieldAddress.ts | 2 +- .../types/guards/isFieldBoolean.ts | 2 +- .../types/guards/isFieldCurrency.ts | 2 +- .../types/guards/isFieldDateTime.ts | 2 +- .../record-field/types/guards/isFieldEmail.ts | 2 +- .../types/guards/isFieldFullName.ts | 2 +- .../record-field/types/guards/isFieldLink.ts | 2 +- .../types/guards/isFieldMultiSelect.ts | 6 +- .../types/guards/isFieldMultiSelectValue.ts | 4 +- .../types/guards/isFieldNumber.ts | 2 +- .../record-field/types/guards/isFieldPhone.ts | 2 +- .../types/guards/isFieldRawJson.ts | 2 +- .../types/guards/isFieldRelation.ts | 2 +- .../record-field/types/guards/isFieldText.ts | 2 +- .../record-field/types/guards/isFieldUuid.ts | 2 +- .../record-field/utils/isFieldValueEmpty.ts | 4 +- ...turnObjectDropdownFilterIntoQueryFilter.ts | 52 ++++----------- .../hooks/useLoadRecordIndexTable.ts | 2 +- .../RecordIndexOptionsDropdownContent.tsx | 2 +- .../RecordDetailRelationRecordsListItem.tsx | 2 +- .../hooks/useSearchFilterPerMetadataItem.ts | 28 +++----- .../hooks/useFilteredSearchEntityQuery.ts | 35 ++++++---- .../SettingsNavigationDrawerItems.tsx | 2 +- .../developers/constants/ExpirationDates.ts | 2 +- .../developers/utils/format-expiration.ts | 2 +- .../src/pages/auth/ChooseYourPlan.tsx | 6 +- .../src/pages/auth/PasswordReset.tsx | 2 +- .../src/pages/auth/PaymentSuccess.tsx | 4 +- .../src/pages/settings/SettingsBilling.tsx | 8 +-- .../SettingsObjectNewFieldStep2.tsx | 2 +- ...rateILikeFiltersForCompositeFields.test.ts | 64 +++++++++++++++++++ .../generateILikeFiltersForCompositeFields.ts | 24 +++++++ 54 files changed, 212 insertions(+), 146 deletions(-) create mode 100644 packages/twenty-front/src/utils/array/__tests__/generateILikeFiltersForCompositeFields.test.ts create mode 100644 packages/twenty-front/src/utils/array/generateILikeFiltersForCompositeFields.ts diff --git a/packages/twenty-front/src/App.tsx b/packages/twenty-front/src/App.tsx index 9dd101d0a..6c86ccafe 100644 --- a/packages/twenty-front/src/App.tsx +++ b/packages/twenty-front/src/App.tsx @@ -2,7 +2,7 @@ import { Route, Routes, useLocation } from 'react-router-dom'; import { useRecoilValue } from 'recoil'; import { VerifyEffect } from '@/auth/components/VerifyEffect'; -import { billingState } from '@/client-config/states/billingState.ts'; +import { billingState } from '@/client-config/states/billingState'; import { AppPath } from '@/types/AppPath'; import { SettingsPath } from '@/types/SettingsPath'; import { BlankLayout } from '@/ui/layout/page/BlankLayout'; diff --git a/packages/twenty-front/src/modules/auth/hooks/useAuth.ts b/packages/twenty-front/src/modules/auth/hooks/useAuth.ts index 5b1664fc3..392c717a1 100644 --- a/packages/twenty-front/src/modules/auth/hooks/useAuth.ts +++ b/packages/twenty-front/src/modules/auth/hooks/useAuth.ts @@ -11,7 +11,7 @@ import { iconsState } from 'twenty-ui'; import { currentWorkspaceMemberState } from '@/auth/states/currentWorkspaceMemberState'; import { currentWorkspaceState } from '@/auth/states/currentWorkspaceState'; -import { isCurrentUserLoadedState } from '@/auth/states/isCurrentUserLoadingState.ts'; +import { isCurrentUserLoadedState } from '@/auth/states/isCurrentUserLoadingState'; import { isVerifyPendingState } from '@/auth/states/isVerifyPendingState'; import { workspacesState } from '@/auth/states/workspaces'; import { authProvidersState } from '@/client-config/states/authProvidersState'; diff --git a/packages/twenty-front/src/modules/auth/sign-in-up/components/SignInUpForm.tsx b/packages/twenty-front/src/modules/auth/sign-in-up/components/SignInUpForm.tsx index a183ff4be..ae5a08e58 100644 --- a/packages/twenty-front/src/modules/auth/sign-in-up/components/SignInUpForm.tsx +++ b/packages/twenty-front/src/modules/auth/sign-in-up/components/SignInUpForm.tsx @@ -6,11 +6,11 @@ import { motion } from 'framer-motion'; import { useRecoilState } from 'recoil'; import { IconGoogle } from 'twenty-ui'; -import { useHandleResetPassword } from '@/auth/sign-in-up/hooks/useHandleResetPassword.ts'; -import { useSignInUpForm } from '@/auth/sign-in-up/hooks/useSignInUpForm.ts'; -import { useSignInWithGoogle } from '@/auth/sign-in-up/hooks/useSignInWithGoogle.ts'; -import { useWorkspaceFromInviteHash } from '@/auth/sign-in-up/hooks/useWorkspaceFromInviteHash.ts'; -import { authProvidersState } from '@/client-config/states/authProvidersState.ts'; +import { useHandleResetPassword } from '@/auth/sign-in-up/hooks/useHandleResetPassword'; +import { useSignInUpForm } from '@/auth/sign-in-up/hooks/useSignInUpForm'; +import { useSignInWithGoogle } from '@/auth/sign-in-up/hooks/useSignInWithGoogle'; +import { useWorkspaceFromInviteHash } from '@/auth/sign-in-up/hooks/useWorkspaceFromInviteHash'; +import { authProvidersState } from '@/client-config/states/authProvidersState'; import { Loader } from '@/ui/feedback/loader/components/Loader'; import { MainButton } from '@/ui/input/button/components/MainButton'; import { TextInput } from '@/ui/input/components/TextInput'; diff --git a/packages/twenty-front/src/modules/auth/sign-in-up/hooks/useNavigateAfterSignInUp.ts b/packages/twenty-front/src/modules/auth/sign-in-up/hooks/useNavigateAfterSignInUp.ts index ef0e9b6cc..7d4336071 100644 --- a/packages/twenty-front/src/modules/auth/sign-in-up/hooks/useNavigateAfterSignInUp.ts +++ b/packages/twenty-front/src/modules/auth/sign-in-up/hooks/useNavigateAfterSignInUp.ts @@ -2,10 +2,10 @@ import { useCallback } from 'react'; import { useNavigate } from 'react-router-dom'; import { useRecoilValue } from 'recoil'; -import { CurrentWorkspace } from '@/auth/states/currentWorkspaceState.ts'; +import { CurrentWorkspace } from '@/auth/states/currentWorkspaceState'; import { previousUrlState } from '@/auth/states/previousUrlState'; -import { billingState } from '@/client-config/states/billingState.ts'; -import { AppPath } from '@/types/AppPath.ts'; +import { billingState } from '@/client-config/states/billingState'; +import { AppPath } from '@/types/AppPath'; import { WorkspaceMember } from '~/generated/graphql.tsx'; export const useNavigateAfterSignInUp = () => { diff --git a/packages/twenty-front/src/modules/auth/sign-in-up/hooks/useSignInUp.tsx b/packages/twenty-front/src/modules/auth/sign-in-up/hooks/useSignInUp.tsx index 4fa77f3d5..6c4bf6198 100644 --- a/packages/twenty-front/src/modules/auth/sign-in-up/hooks/useSignInUp.tsx +++ b/packages/twenty-front/src/modules/auth/sign-in-up/hooks/useSignInUp.tsx @@ -2,8 +2,8 @@ import { useCallback, useState } from 'react'; import { SubmitHandler, UseFormReturn } from 'react-hook-form'; import { useParams } from 'react-router-dom'; -import { useNavigateAfterSignInUp } from '@/auth/sign-in-up/hooks/useNavigateAfterSignInUp.ts'; -import { Form } from '@/auth/sign-in-up/hooks/useSignInUpForm.ts'; +import { useNavigateAfterSignInUp } from '@/auth/sign-in-up/hooks/useNavigateAfterSignInUp'; +import { Form } from '@/auth/sign-in-up/hooks/useSignInUpForm'; import { AppPath } from '@/types/AppPath'; import { useSnackBar } from '@/ui/feedback/snack-bar-manager/hooks/useSnackBar'; import { useIsMatchingLocation } from '~/hooks/useIsMatchingLocation'; diff --git a/packages/twenty-front/src/modules/auth/sign-in-up/hooks/useSignInUpForm.ts b/packages/twenty-front/src/modules/auth/sign-in-up/hooks/useSignInUpForm.ts index 77a555fa9..f7d4de9b4 100644 --- a/packages/twenty-front/src/modules/auth/sign-in-up/hooks/useSignInUpForm.ts +++ b/packages/twenty-front/src/modules/auth/sign-in-up/hooks/useSignInUpForm.ts @@ -4,8 +4,8 @@ import { zodResolver } from '@hookform/resolvers/zod'; import { useRecoilValue } from 'recoil'; import { z } from 'zod'; -import { PASSWORD_REGEX } from '@/auth/utils/passwordRegex.ts'; -import { isSignInPrefilledState } from '@/client-config/states/isSignInPrefilledState.ts'; +import { PASSWORD_REGEX } from '@/auth/utils/passwordRegex'; +import { isSignInPrefilledState } from '@/client-config/states/isSignInPrefilledState'; const validationSchema = z .object({ diff --git a/packages/twenty-front/src/modules/auth/sign-in-up/hooks/useSignInWithGoogle.ts b/packages/twenty-front/src/modules/auth/sign-in-up/hooks/useSignInWithGoogle.ts index 2bd2b3186..8eb008b6f 100644 --- a/packages/twenty-front/src/modules/auth/sign-in-up/hooks/useSignInWithGoogle.ts +++ b/packages/twenty-front/src/modules/auth/sign-in-up/hooks/useSignInWithGoogle.ts @@ -1,6 +1,6 @@ import { useParams } from 'react-router-dom'; -import { useAuth } from '@/auth/hooks/useAuth.ts'; +import { useAuth } from '@/auth/hooks/useAuth'; export const useSignInWithGoogle = () => { const workspaceInviteHash = useParams().workspaceInviteHash; diff --git a/packages/twenty-front/src/modules/billing/components/SubscriptionCard.tsx b/packages/twenty-front/src/modules/billing/components/SubscriptionCard.tsx index fd323391c..7af7e093b 100644 --- a/packages/twenty-front/src/modules/billing/components/SubscriptionCard.tsx +++ b/packages/twenty-front/src/modules/billing/components/SubscriptionCard.tsx @@ -1,7 +1,7 @@ import styled from '@emotion/styled'; import { SubscriptionCardPrice } from '@/billing/components/SubscriptionCardPrice.tsx'; -import { capitalize } from '~/utils/string/capitalize.ts'; +import { capitalize } from '~/utils/string/capitalize'; type SubscriptionCardProps = { type?: string; diff --git a/packages/twenty-front/src/modules/command-menu/components/CommandMenu.tsx b/packages/twenty-front/src/modules/command-menu/components/CommandMenu.tsx index f44ed37cf..08694d4a9 100644 --- a/packages/twenty-front/src/modules/command-menu/components/CommandMenu.tsx +++ b/packages/twenty-front/src/modules/command-menu/components/CommandMenu.tsx @@ -22,6 +22,7 @@ import { useListenClickOutside } from '@/ui/utilities/pointer-event/hooks/useLis import { useIsMobile } from '@/ui/utilities/responsive/hooks/useIsMobile'; import { ScrollWrapper } from '@/ui/utilities/scroll/components/ScrollWrapper'; import { getLogoUrlFromDomainName } from '~/utils'; +import { generateILikeFiltersForCompositeFields } from '~/utils/array/generateILikeFiltersForCompositeFields'; import { isDefined } from '~/utils/isDefined'; import { useCommandMenu } from '../hooks/useCommandMenu'; @@ -142,8 +143,10 @@ export const CommandMenu = () => { objectNameSingular: CoreObjectNameSingular.Person, filter: commandMenuSearch ? makeOrFilterVariables([ - { name: { firstName: { ilike: `%${commandMenuSearch}%` } } }, - { name: { lastName: { ilike: `%${commandMenuSearch}%` } } }, + ...generateILikeFiltersForCompositeFields(commandMenuSearch, 'name', [ + 'firstName', + 'lastName', + ]), { email: { ilike: `%${commandMenuSearch}%` } }, { phone: { ilike: `%${commandMenuSearch}%` } }, ]) diff --git a/packages/twenty-front/src/modules/object-metadata/components/ObjectMetadataItemsProvider.tsx b/packages/twenty-front/src/modules/object-metadata/components/ObjectMetadataItemsProvider.tsx index 0c3ebdadc..eafc5c884 100644 --- a/packages/twenty-front/src/modules/object-metadata/components/ObjectMetadataItemsProvider.tsx +++ b/packages/twenty-front/src/modules/object-metadata/components/ObjectMetadataItemsProvider.tsx @@ -1,7 +1,7 @@ import React from 'react'; import { useRecoilValue } from 'recoil'; -import { currentWorkspaceMemberState } from '@/auth/states/currentWorkspaceMemberState.ts'; +import { currentWorkspaceMemberState } from '@/auth/states/currentWorkspaceMemberState'; import { ObjectMetadataItemsLoadEffect } from '@/object-metadata/components/ObjectMetadataItemsLoadEffect'; import { objectMetadataItemsState } from '@/object-metadata/states/objectMetadataItemsState'; import { RelationPickerScope } from '@/object-record/relation-picker/scopes/RelationPickerScope'; diff --git a/packages/twenty-front/src/modules/object-metadata/hooks/useFieldMetadataItem.ts b/packages/twenty-front/src/modules/object-metadata/hooks/useFieldMetadataItem.ts index 51c900099..2e07cabb2 100644 --- a/packages/twenty-front/src/modules/object-metadata/hooks/useFieldMetadataItem.ts +++ b/packages/twenty-front/src/modules/object-metadata/hooks/useFieldMetadataItem.ts @@ -1,6 +1,6 @@ import { v4 } from 'uuid'; -import { FieldMetadataOption } from '@/object-metadata/types/FieldMetadataOption.ts'; +import { FieldMetadataOption } from '@/object-metadata/types/FieldMetadataOption'; import { getDefaultValueForBackend } from '@/object-metadata/utils/getDefaultValueForBackend'; import { Field } from '~/generated/graphql'; diff --git a/packages/twenty-front/src/modules/object-metadata/hooks/useObjectMetadataItem.ts b/packages/twenty-front/src/modules/object-metadata/hooks/useObjectMetadataItem.ts index 5c8472a54..4f4f777c1 100644 --- a/packages/twenty-front/src/modules/object-metadata/hooks/useObjectMetadataItem.ts +++ b/packages/twenty-front/src/modules/object-metadata/hooks/useObjectMetadataItem.ts @@ -1,6 +1,6 @@ import { useRecoilValue } from 'recoil'; -import { currentWorkspaceState } from '@/auth/states/currentWorkspaceState.ts'; +import { currentWorkspaceState } from '@/auth/states/currentWorkspaceState'; import { ObjectMetadataItemNotFoundError } from '@/object-metadata/errors/ObjectMetadataNotFoundError'; import { objectMetadataItemFamilySelector } from '@/object-metadata/states/objectMetadataItemFamilySelector'; import { objectMetadataItemsState } from '@/object-metadata/states/objectMetadataItemsState'; diff --git a/packages/twenty-front/src/modules/object-metadata/hooks/useObjectNamePluralFromSingular.ts b/packages/twenty-front/src/modules/object-metadata/hooks/useObjectNamePluralFromSingular.ts index 3cf1c60bb..502bd2938 100644 --- a/packages/twenty-front/src/modules/object-metadata/hooks/useObjectNamePluralFromSingular.ts +++ b/packages/twenty-front/src/modules/object-metadata/hooks/useObjectNamePluralFromSingular.ts @@ -1,6 +1,6 @@ import { useRecoilValue } from 'recoil'; -import { currentWorkspaceState } from '@/auth/states/currentWorkspaceState.ts'; +import { currentWorkspaceState } from '@/auth/states/currentWorkspaceState'; import { objectMetadataItemFamilySelector } from '@/object-metadata/states/objectMetadataItemFamilySelector'; import { getObjectMetadataItemsMock } from '@/object-metadata/utils/getObjectMetadataItemsMock'; import { isDefined } from '~/utils/isDefined'; diff --git a/packages/twenty-front/src/modules/object-metadata/hooks/useObjectNameSingularFromPlural.ts b/packages/twenty-front/src/modules/object-metadata/hooks/useObjectNameSingularFromPlural.ts index 432a3b718..1ec11b9bb 100644 --- a/packages/twenty-front/src/modules/object-metadata/hooks/useObjectNameSingularFromPlural.ts +++ b/packages/twenty-front/src/modules/object-metadata/hooks/useObjectNameSingularFromPlural.ts @@ -1,6 +1,6 @@ import { useRecoilValue } from 'recoil'; -import { currentWorkspaceState } from '@/auth/states/currentWorkspaceState.ts'; +import { currentWorkspaceState } from '@/auth/states/currentWorkspaceState'; import { objectMetadataItemFamilySelector } from '@/object-metadata/states/objectMetadataItemFamilySelector'; import { getObjectMetadataItemsMock } from '@/object-metadata/utils/getObjectMetadataItemsMock'; import { isDefined } from '~/utils/isDefined'; diff --git a/packages/twenty-front/src/modules/object-metadata/utils/__tests__/formatFieldMetadataItemInput.test.ts b/packages/twenty-front/src/modules/object-metadata/utils/__tests__/formatFieldMetadataItemInput.test.ts index a85741c63..59a8f9b5c 100644 --- a/packages/twenty-front/src/modules/object-metadata/utils/__tests__/formatFieldMetadataItemInput.test.ts +++ b/packages/twenty-front/src/modules/object-metadata/utils/__tests__/formatFieldMetadataItemInput.test.ts @@ -1,4 +1,4 @@ -import { FieldMetadataType } from '~/generated-metadata/graphql.ts'; +import { FieldMetadataType } from '~/generated-metadata/graphql'; import { formatFieldMetadataItemInput, diff --git a/packages/twenty-front/src/modules/object-metadata/utils/formatFieldMetadataItemInput.ts b/packages/twenty-front/src/modules/object-metadata/utils/formatFieldMetadataItemInput.ts index 80ba590d6..cf762af5c 100644 --- a/packages/twenty-front/src/modules/object-metadata/utils/formatFieldMetadataItemInput.ts +++ b/packages/twenty-front/src/modules/object-metadata/utils/formatFieldMetadataItemInput.ts @@ -2,7 +2,7 @@ import toCamelCase from 'lodash.camelcase'; import toSnakeCase from 'lodash.snakecase'; import { Field, FieldMetadataType } from '~/generated-metadata/graphql'; -import { isDefined } from '~/utils/isDefined.ts'; +import { isDefined } from '~/utils/isDefined'; import { FieldMetadataOption } from '../types/FieldMetadataOption'; diff --git a/packages/twenty-front/src/modules/object-record/record-field/components/FieldDisplay.tsx b/packages/twenty-front/src/modules/object-record/record-field/components/FieldDisplay.tsx index 68999b4fc..a63a5810a 100644 --- a/packages/twenty-front/src/modules/object-record/record-field/components/FieldDisplay.tsx +++ b/packages/twenty-front/src/modules/object-record/record-field/components/FieldDisplay.tsx @@ -24,7 +24,7 @@ import { isFieldDateTime } from '../types/guards/isFieldDateTime'; import { isFieldEmail } from '../types/guards/isFieldEmail'; import { isFieldFullName } from '../types/guards/isFieldFullName'; import { isFieldLink } from '../types/guards/isFieldLink'; -import { isFieldMultiSelect } from '../types/guards/isFieldMultiSelect.ts'; +import { isFieldMultiSelect } from '../types/guards/isFieldMultiSelect'; import { isFieldNumber } from '../types/guards/isFieldNumber'; import { isFieldPhone } from '../types/guards/isFieldPhone'; import { isFieldRawJson } from '../types/guards/isFieldRawJson'; diff --git a/packages/twenty-front/src/modules/object-record/record-field/components/FieldInput.tsx b/packages/twenty-front/src/modules/object-record/record-field/components/FieldInput.tsx index 841a90f7f..7a751a330 100644 --- a/packages/twenty-front/src/modules/object-record/record-field/components/FieldInput.tsx +++ b/packages/twenty-front/src/modules/object-record/record-field/components/FieldInput.tsx @@ -9,7 +9,7 @@ import { SelectFieldInput } from '@/object-record/record-field/meta-types/input/ import { RecordFieldInputScope } from '@/object-record/record-field/scopes/RecordFieldInputScope'; import { isFieldDate } from '@/object-record/record-field/types/guards/isFieldDate'; import { isFieldFullName } from '@/object-record/record-field/types/guards/isFieldFullName'; -import { isFieldMultiSelect } from '@/object-record/record-field/types/guards/isFieldMultiSelect.ts'; +import { isFieldMultiSelect } from '@/object-record/record-field/types/guards/isFieldMultiSelect'; import { isFieldRawJson } from '@/object-record/record-field/types/guards/isFieldRawJson'; import { isFieldSelect } from '@/object-record/record-field/types/guards/isFieldSelect'; import { getScopeIdFromComponentId } from '@/ui/utilities/recoil-scope/utils/getScopeIdFromComponentId'; diff --git a/packages/twenty-front/src/modules/object-record/record-field/hooks/usePersistField.ts b/packages/twenty-front/src/modules/object-record/record-field/hooks/usePersistField.ts index 2e18b77f0..5368d225e 100644 --- a/packages/twenty-front/src/modules/object-record/record-field/hooks/usePersistField.ts +++ b/packages/twenty-front/src/modules/object-record/record-field/hooks/usePersistField.ts @@ -7,8 +7,8 @@ import { isFieldDate } from '@/object-record/record-field/types/guards/isFieldDa import { isFieldDateValue } from '@/object-record/record-field/types/guards/isFieldDateValue'; import { isFieldFullName } from '@/object-record/record-field/types/guards/isFieldFullName'; import { isFieldFullNameValue } from '@/object-record/record-field/types/guards/isFieldFullNameValue'; -import { isFieldMultiSelect } from '@/object-record/record-field/types/guards/isFieldMultiSelect.ts'; -import { isFieldMultiSelectValue } from '@/object-record/record-field/types/guards/isFieldMultiSelectValue.ts'; +import { isFieldMultiSelect } from '@/object-record/record-field/types/guards/isFieldMultiSelect'; +import { isFieldMultiSelectValue } from '@/object-record/record-field/types/guards/isFieldMultiSelectValue'; import { isFieldRawJson } from '@/object-record/record-field/types/guards/isFieldRawJson'; import { isFieldRawJsonValue } from '@/object-record/record-field/types/guards/isFieldRawJsonValue'; import { isFieldSelect } from '@/object-record/record-field/types/guards/isFieldSelect'; diff --git a/packages/twenty-front/src/modules/object-record/record-field/meta-types/display/components/MultiSelectFieldDisplay.tsx b/packages/twenty-front/src/modules/object-record/record-field/meta-types/display/components/MultiSelectFieldDisplay.tsx index 7f885da43..5cafe5156 100644 --- a/packages/twenty-front/src/modules/object-record/record-field/meta-types/display/components/MultiSelectFieldDisplay.tsx +++ b/packages/twenty-front/src/modules/object-record/record-field/meta-types/display/components/MultiSelectFieldDisplay.tsx @@ -1,6 +1,6 @@ import styled from '@emotion/styled'; -import { useMultiSelectField } from '@/object-record/record-field/meta-types/hooks/useMultiSelectField.ts'; +import { useMultiSelectField } from '@/object-record/record-field/meta-types/hooks/useMultiSelectField'; import { Tag } from '@/ui/display/tag/components/Tag'; const StyledTagContainer = styled.div` diff --git a/packages/twenty-front/src/modules/object-record/record-field/meta-types/hooks/useMultiSelectField.ts b/packages/twenty-front/src/modules/object-record/record-field/meta-types/hooks/useMultiSelectField.ts index 5a4a2eacd..9cd2bed96 100644 --- a/packages/twenty-front/src/modules/object-record/record-field/meta-types/hooks/useMultiSelectField.ts +++ b/packages/twenty-front/src/modules/object-record/record-field/meta-types/hooks/useMultiSelectField.ts @@ -1,14 +1,14 @@ import { useContext } from 'react'; import { useRecoilState, useRecoilValue } from 'recoil'; -import { FieldContext } from '@/object-record/record-field/contexts/FieldContext.ts'; -import { usePersistField } from '@/object-record/record-field/hooks/usePersistField.ts'; -import { useRecordFieldInput } from '@/object-record/record-field/hooks/useRecordFieldInput.ts'; -import { FieldMultiSelectValue } from '@/object-record/record-field/types/FieldMetadata.ts'; -import { assertFieldMetadata } from '@/object-record/record-field/types/guards/assertFieldMetadata.ts'; -import { isFieldMultiSelect } from '@/object-record/record-field/types/guards/isFieldMultiSelect.ts'; -import { isFieldMultiSelectValue } from '@/object-record/record-field/types/guards/isFieldMultiSelectValue.ts'; -import { recordStoreFamilySelector } from '@/object-record/record-store/states/selectors/recordStoreFamilySelector.ts'; +import { FieldContext } from '@/object-record/record-field/contexts/FieldContext'; +import { usePersistField } from '@/object-record/record-field/hooks/usePersistField'; +import { useRecordFieldInput } from '@/object-record/record-field/hooks/useRecordFieldInput'; +import { FieldMultiSelectValue } from '@/object-record/record-field/types/FieldMetadata'; +import { assertFieldMetadata } from '@/object-record/record-field/types/guards/assertFieldMetadata'; +import { isFieldMultiSelect } from '@/object-record/record-field/types/guards/isFieldMultiSelect'; +import { isFieldMultiSelectValue } from '@/object-record/record-field/types/guards/isFieldMultiSelectValue'; +import { recordStoreFamilySelector } from '@/object-record/record-store/states/selectors/recordStoreFamilySelector'; import { FieldMetadataType } from '~/generated/graphql.tsx'; export const useMultiSelectField = () => { diff --git a/packages/twenty-front/src/modules/object-record/record-field/meta-types/input/components/MultiSelectFieldInput.tsx b/packages/twenty-front/src/modules/object-record/record-field/meta-types/input/components/MultiSelectFieldInput.tsx index 864384918..0614ba33b 100644 --- a/packages/twenty-front/src/modules/object-record/record-field/meta-types/input/components/MultiSelectFieldInput.tsx +++ b/packages/twenty-front/src/modules/object-record/record-field/meta-types/input/components/MultiSelectFieldInput.tsx @@ -1,7 +1,7 @@ import { useRef, useState } from 'react'; import styled from '@emotion/styled'; -import { useMultiSelectField } from '@/object-record/record-field/meta-types/hooks/useMultiSelectField.ts'; +import { useMultiSelectField } from '@/object-record/record-field/meta-types/hooks/useMultiSelectField'; import { FieldInputEvent } from '@/object-record/record-field/types/FieldInputEvent'; import { DropdownMenu } from '@/ui/layout/dropdown/components/DropdownMenu'; import { DropdownMenuItemsContainer } from '@/ui/layout/dropdown/components/DropdownMenuItemsContainer'; diff --git a/packages/twenty-front/src/modules/object-record/record-field/types/guards/isFieldAddress.ts b/packages/twenty-front/src/modules/object-record/record-field/types/guards/isFieldAddress.ts index c55280811..6197aa19f 100644 --- a/packages/twenty-front/src/modules/object-record/record-field/types/guards/isFieldAddress.ts +++ b/packages/twenty-front/src/modules/object-record/record-field/types/guards/isFieldAddress.ts @@ -1,4 +1,4 @@ -import { FieldMetadataType } from '~/generated-metadata/graphql.ts'; +import { FieldMetadataType } from '~/generated-metadata/graphql'; import { FieldDefinition } from '../FieldDefinition'; import { FieldAddressMetadata, FieldMetadata } from '../FieldMetadata'; diff --git a/packages/twenty-front/src/modules/object-record/record-field/types/guards/isFieldBoolean.ts b/packages/twenty-front/src/modules/object-record/record-field/types/guards/isFieldBoolean.ts index 69add94d5..4c56293e1 100644 --- a/packages/twenty-front/src/modules/object-record/record-field/types/guards/isFieldBoolean.ts +++ b/packages/twenty-front/src/modules/object-record/record-field/types/guards/isFieldBoolean.ts @@ -1,4 +1,4 @@ -import { FieldMetadataType } from '~/generated-metadata/graphql.ts'; +import { FieldMetadataType } from '~/generated-metadata/graphql'; import { FieldDefinition } from '../FieldDefinition'; import { FieldBooleanMetadata, FieldMetadata } from '../FieldMetadata'; diff --git a/packages/twenty-front/src/modules/object-record/record-field/types/guards/isFieldCurrency.ts b/packages/twenty-front/src/modules/object-record/record-field/types/guards/isFieldCurrency.ts index b6738c0bb..2b9d16a76 100644 --- a/packages/twenty-front/src/modules/object-record/record-field/types/guards/isFieldCurrency.ts +++ b/packages/twenty-front/src/modules/object-record/record-field/types/guards/isFieldCurrency.ts @@ -1,4 +1,4 @@ -import { FieldMetadataType } from '~/generated-metadata/graphql.ts'; +import { FieldMetadataType } from '~/generated-metadata/graphql'; import { FieldDefinition } from '../FieldDefinition'; import { FieldCurrencyMetadata, FieldMetadata } from '../FieldMetadata'; diff --git a/packages/twenty-front/src/modules/object-record/record-field/types/guards/isFieldDateTime.ts b/packages/twenty-front/src/modules/object-record/record-field/types/guards/isFieldDateTime.ts index 15c2a01c5..060424f6d 100644 --- a/packages/twenty-front/src/modules/object-record/record-field/types/guards/isFieldDateTime.ts +++ b/packages/twenty-front/src/modules/object-record/record-field/types/guards/isFieldDateTime.ts @@ -1,4 +1,4 @@ -import { FieldMetadataType } from '~/generated-metadata/graphql.ts'; +import { FieldMetadataType } from '~/generated-metadata/graphql'; import { FieldDefinition } from '../FieldDefinition'; import { FieldDateTimeMetadata, FieldMetadata } from '../FieldMetadata'; diff --git a/packages/twenty-front/src/modules/object-record/record-field/types/guards/isFieldEmail.ts b/packages/twenty-front/src/modules/object-record/record-field/types/guards/isFieldEmail.ts index 265301773..676cca39b 100644 --- a/packages/twenty-front/src/modules/object-record/record-field/types/guards/isFieldEmail.ts +++ b/packages/twenty-front/src/modules/object-record/record-field/types/guards/isFieldEmail.ts @@ -1,4 +1,4 @@ -import { FieldMetadataType } from '~/generated-metadata/graphql.ts'; +import { FieldMetadataType } from '~/generated-metadata/graphql'; import { FieldDefinition } from '../FieldDefinition'; import { FieldEmailMetadata, FieldMetadata } from '../FieldMetadata'; diff --git a/packages/twenty-front/src/modules/object-record/record-field/types/guards/isFieldFullName.ts b/packages/twenty-front/src/modules/object-record/record-field/types/guards/isFieldFullName.ts index a6261d642..0fc6bc0f1 100644 --- a/packages/twenty-front/src/modules/object-record/record-field/types/guards/isFieldFullName.ts +++ b/packages/twenty-front/src/modules/object-record/record-field/types/guards/isFieldFullName.ts @@ -1,4 +1,4 @@ -import { FieldMetadataType } from '~/generated-metadata/graphql.ts'; +import { FieldMetadataType } from '~/generated-metadata/graphql'; import { FieldDefinition } from '../FieldDefinition'; import { FieldFullNameMetadata, FieldMetadata } from '../FieldMetadata'; diff --git a/packages/twenty-front/src/modules/object-record/record-field/types/guards/isFieldLink.ts b/packages/twenty-front/src/modules/object-record/record-field/types/guards/isFieldLink.ts index 526881a8a..6f98150d0 100644 --- a/packages/twenty-front/src/modules/object-record/record-field/types/guards/isFieldLink.ts +++ b/packages/twenty-front/src/modules/object-record/record-field/types/guards/isFieldLink.ts @@ -1,4 +1,4 @@ -import { FieldMetadataType } from '~/generated-metadata/graphql.ts'; +import { FieldMetadataType } from '~/generated-metadata/graphql'; import { FieldDefinition } from '../FieldDefinition'; import { FieldLinkMetadata, FieldMetadata } from '../FieldMetadata'; diff --git a/packages/twenty-front/src/modules/object-record/record-field/types/guards/isFieldMultiSelect.ts b/packages/twenty-front/src/modules/object-record/record-field/types/guards/isFieldMultiSelect.ts index e799738e6..5427fca94 100644 --- a/packages/twenty-front/src/modules/object-record/record-field/types/guards/isFieldMultiSelect.ts +++ b/packages/twenty-front/src/modules/object-record/record-field/types/guards/isFieldMultiSelect.ts @@ -1,9 +1,9 @@ -import { FieldDefinition } from '@/object-record/record-field/types/FieldDefinition.ts'; +import { FieldDefinition } from '@/object-record/record-field/types/FieldDefinition'; import { FieldMetadata, FieldMultiSelectMetadata, -} from '@/object-record/record-field/types/FieldMetadata.ts'; -import { FieldMetadataType } from '~/generated-metadata/graphql.ts'; +} from '@/object-record/record-field/types/FieldMetadata'; +import { FieldMetadataType } from '~/generated-metadata/graphql'; export const isFieldMultiSelect = ( field: Pick, 'type'>, diff --git a/packages/twenty-front/src/modules/object-record/record-field/types/guards/isFieldMultiSelectValue.ts b/packages/twenty-front/src/modules/object-record/record-field/types/guards/isFieldMultiSelectValue.ts index 01d2b47ff..f8c3842b7 100644 --- a/packages/twenty-front/src/modules/object-record/record-field/types/guards/isFieldMultiSelectValue.ts +++ b/packages/twenty-front/src/modules/object-record/record-field/types/guards/isFieldMultiSelectValue.ts @@ -1,5 +1,5 @@ -import { FieldMultiSelectValue } from '@/object-record/record-field/types/FieldMetadata.ts'; -import { multiSelectFieldValueSchema } from '@/object-record/record-field/validation-schemas/multiSelectFieldValueSchema.ts'; +import { FieldMultiSelectValue } from '@/object-record/record-field/types/FieldMetadata'; +import { multiSelectFieldValueSchema } from '@/object-record/record-field/validation-schemas/multiSelectFieldValueSchema'; export const isFieldMultiSelectValue = ( fieldValue: unknown, diff --git a/packages/twenty-front/src/modules/object-record/record-field/types/guards/isFieldNumber.ts b/packages/twenty-front/src/modules/object-record/record-field/types/guards/isFieldNumber.ts index 6b863170a..e5a9bcc63 100644 --- a/packages/twenty-front/src/modules/object-record/record-field/types/guards/isFieldNumber.ts +++ b/packages/twenty-front/src/modules/object-record/record-field/types/guards/isFieldNumber.ts @@ -1,4 +1,4 @@ -import { FieldMetadataType } from '~/generated-metadata/graphql.ts'; +import { FieldMetadataType } from '~/generated-metadata/graphql'; import { FieldDefinition } from '../FieldDefinition'; import { FieldMetadata, FieldNumberMetadata } from '../FieldMetadata'; diff --git a/packages/twenty-front/src/modules/object-record/record-field/types/guards/isFieldPhone.ts b/packages/twenty-front/src/modules/object-record/record-field/types/guards/isFieldPhone.ts index a417d1fb0..98d10e9d2 100644 --- a/packages/twenty-front/src/modules/object-record/record-field/types/guards/isFieldPhone.ts +++ b/packages/twenty-front/src/modules/object-record/record-field/types/guards/isFieldPhone.ts @@ -1,4 +1,4 @@ -import { FieldMetadataType } from '~/generated-metadata/graphql.ts'; +import { FieldMetadataType } from '~/generated-metadata/graphql'; import { FieldDefinition } from '../FieldDefinition'; import { FieldMetadata, FieldPhoneMetadata } from '../FieldMetadata'; diff --git a/packages/twenty-front/src/modules/object-record/record-field/types/guards/isFieldRawJson.ts b/packages/twenty-front/src/modules/object-record/record-field/types/guards/isFieldRawJson.ts index 1cdc93665..18700f181 100644 --- a/packages/twenty-front/src/modules/object-record/record-field/types/guards/isFieldRawJson.ts +++ b/packages/twenty-front/src/modules/object-record/record-field/types/guards/isFieldRawJson.ts @@ -1,4 +1,4 @@ -import { FieldMetadataType } from '~/generated-metadata/graphql.ts'; +import { FieldMetadataType } from '~/generated-metadata/graphql'; import { FieldDefinition } from '../FieldDefinition'; import { FieldMetadata, FieldRawJsonMetadata } from '../FieldMetadata'; diff --git a/packages/twenty-front/src/modules/object-record/record-field/types/guards/isFieldRelation.ts b/packages/twenty-front/src/modules/object-record/record-field/types/guards/isFieldRelation.ts index b64046647..68bc5fd68 100644 --- a/packages/twenty-front/src/modules/object-record/record-field/types/guards/isFieldRelation.ts +++ b/packages/twenty-front/src/modules/object-record/record-field/types/guards/isFieldRelation.ts @@ -1,4 +1,4 @@ -import { FieldMetadataType } from '~/generated-metadata/graphql.ts'; +import { FieldMetadataType } from '~/generated-metadata/graphql'; import { FieldDefinition } from '../FieldDefinition'; import { FieldMetadata, FieldRelationMetadata } from '../FieldMetadata'; diff --git a/packages/twenty-front/src/modules/object-record/record-field/types/guards/isFieldText.ts b/packages/twenty-front/src/modules/object-record/record-field/types/guards/isFieldText.ts index 197c46046..028a9b49b 100644 --- a/packages/twenty-front/src/modules/object-record/record-field/types/guards/isFieldText.ts +++ b/packages/twenty-front/src/modules/object-record/record-field/types/guards/isFieldText.ts @@ -1,4 +1,4 @@ -import { FieldMetadataType } from '~/generated-metadata/graphql.ts'; +import { FieldMetadataType } from '~/generated-metadata/graphql'; import { FieldDefinition } from '../FieldDefinition'; import { FieldMetadata, FieldTextMetadata } from '../FieldMetadata'; diff --git a/packages/twenty-front/src/modules/object-record/record-field/types/guards/isFieldUuid.ts b/packages/twenty-front/src/modules/object-record/record-field/types/guards/isFieldUuid.ts index a8bf679c5..45b6ebc2a 100644 --- a/packages/twenty-front/src/modules/object-record/record-field/types/guards/isFieldUuid.ts +++ b/packages/twenty-front/src/modules/object-record/record-field/types/guards/isFieldUuid.ts @@ -1,4 +1,4 @@ -import { FieldMetadataType } from '~/generated-metadata/graphql.ts'; +import { FieldMetadataType } from '~/generated-metadata/graphql'; import { FieldDefinition } from '../FieldDefinition'; import { FieldMetadata, FieldUuidMetadata } from '../FieldMetadata'; diff --git a/packages/twenty-front/src/modules/object-record/record-field/utils/isFieldValueEmpty.ts b/packages/twenty-front/src/modules/object-record/record-field/utils/isFieldValueEmpty.ts index ded220c98..dd1573212 100644 --- a/packages/twenty-front/src/modules/object-record/record-field/utils/isFieldValueEmpty.ts +++ b/packages/twenty-front/src/modules/object-record/record-field/utils/isFieldValueEmpty.ts @@ -12,8 +12,8 @@ import { isFieldFullName } from '@/object-record/record-field/types/guards/isFie import { isFieldFullNameValue } from '@/object-record/record-field/types/guards/isFieldFullNameValue'; import { isFieldLink } from '@/object-record/record-field/types/guards/isFieldLink'; import { isFieldLinkValue } from '@/object-record/record-field/types/guards/isFieldLinkValue'; -import { isFieldMultiSelect } from '@/object-record/record-field/types/guards/isFieldMultiSelect.ts'; -import { isFieldMultiSelectValue } from '@/object-record/record-field/types/guards/isFieldMultiSelectValue.ts'; +import { isFieldMultiSelect } from '@/object-record/record-field/types/guards/isFieldMultiSelect'; +import { isFieldMultiSelectValue } from '@/object-record/record-field/types/guards/isFieldMultiSelectValue'; import { isFieldNumber } from '@/object-record/record-field/types/guards/isFieldNumber'; import { isFieldRating } from '@/object-record/record-field/types/guards/isFieldRating'; import { isFieldRawJson } from '@/object-record/record-field/types/guards/isFieldRawJson'; diff --git a/packages/twenty-front/src/modules/object-record/record-filter/utils/turnObjectDropdownFilterIntoQueryFilter.ts b/packages/twenty-front/src/modules/object-record/record-filter/utils/turnObjectDropdownFilterIntoQueryFilter.ts index c6974c435..8fce2cf7a 100644 --- a/packages/twenty-front/src/modules/object-record/record-filter/utils/turnObjectDropdownFilterIntoQueryFilter.ts +++ b/packages/twenty-front/src/modules/object-record/record-filter/utils/turnObjectDropdownFilterIntoQueryFilter.ts @@ -5,7 +5,6 @@ import { CurrencyFilter, DateFilter, FloatFilter, - FullNameFilter, ObjectRecordQueryFilter, StringFilter, URLFilter, @@ -14,6 +13,7 @@ import { import { makeAndFilterVariables } from '@/object-record/utils/makeAndFilterVariables'; import { ViewFilterOperand } from '@/views/types/ViewFilterOperand'; import { Field } from '~/generated/graphql'; +import { generateILikeFiltersForCompositeFields } from '~/utils/array/generateILikeFiltersForCompositeFields'; import { isDefined } from '~/utils/isDefined'; import { Filter } from '../../object-filter-dropdown/types/Filter'; @@ -203,50 +203,25 @@ export const turnObjectDropdownFilterIntoQueryFilter = ( ); } break; - case 'FULL_NAME': + case 'FULL_NAME': { + const fullNameFilters = generateILikeFiltersForCompositeFields( + rawUIFilter.value, + correspondingField.name, + ['firstName', 'lastName'], + ); switch (rawUIFilter.operand) { case ViewFilterOperand.Contains: objectRecordFilters.push({ - or: [ - { - [correspondingField.name]: { - firstName: { - ilike: `%${rawUIFilter.value}%`, - }, - } as FullNameFilter, - }, - { - [correspondingField.name]: { - lastName: { - ilike: `%${rawUIFilter.value}%`, - }, - } as FullNameFilter, - }, - ], + or: fullNameFilters, }); break; case ViewFilterOperand.DoesNotContain: objectRecordFilters.push({ - and: [ - { - not: { - [correspondingField.name]: { - firstName: { - ilike: `%${rawUIFilter.value}%`, - }, - } as FullNameFilter, - }, - }, - { - not: { - [correspondingField.name]: { - lastName: { - ilike: `%${rawUIFilter.value}%`, - }, - } as FullNameFilter, - }, - }, - ], + and: fullNameFilters.map((filter) => { + return { + not: filter, + }; + }), }); break; default: @@ -255,6 +230,7 @@ export const turnObjectDropdownFilterIntoQueryFilter = ( ); } break; + } case 'ADDRESS': switch (rawUIFilter.operand) { case ViewFilterOperand.Contains: diff --git a/packages/twenty-front/src/modules/object-record/record-index/hooks/useLoadRecordIndexTable.ts b/packages/twenty-front/src/modules/object-record/record-index/hooks/useLoadRecordIndexTable.ts index 5fd83e306..fe474fbfc 100644 --- a/packages/twenty-front/src/modules/object-record/record-index/hooks/useLoadRecordIndexTable.ts +++ b/packages/twenty-front/src/modules/object-record/record-index/hooks/useLoadRecordIndexTable.ts @@ -1,6 +1,6 @@ import { useRecoilValue, useSetRecoilState } from 'recoil'; -import { currentWorkspaceState } from '@/auth/states/currentWorkspaceState.ts'; +import { currentWorkspaceState } from '@/auth/states/currentWorkspaceState'; import { useObjectMetadataItem } from '@/object-metadata/hooks/useObjectMetadataItem'; import { useFindManyRecords } from '@/object-record/hooks/useFindManyRecords'; import { turnSortsIntoOrderBy } from '@/object-record/object-sort-dropdown/utils/turnSortsIntoOrderBy'; diff --git a/packages/twenty-front/src/modules/object-record/record-index/options/components/RecordIndexOptionsDropdownContent.tsx b/packages/twenty-front/src/modules/object-record/record-index/options/components/RecordIndexOptionsDropdownContent.tsx index dffa9d58e..890c609c6 100644 --- a/packages/twenty-front/src/modules/object-record/record-index/options/components/RecordIndexOptionsDropdownContent.tsx +++ b/packages/twenty-front/src/modules/object-record/record-index/options/components/RecordIndexOptionsDropdownContent.tsx @@ -9,7 +9,7 @@ import { } from 'twenty-ui'; import { RECORD_INDEX_OPTIONS_DROPDOWN_ID } from '@/object-record/record-index/options/constants/RecordIndexOptionsDropdownId'; -import { useExportTableData } from '@/object-record/record-index/options/hooks/useExportTableData.ts'; +import { useExportTableData } from '@/object-record/record-index/options/hooks/useExportTableData'; import { useRecordIndexOptionsForBoard } from '@/object-record/record-index/options/hooks/useRecordIndexOptionsForBoard'; import { useRecordIndexOptionsForTable } from '@/object-record/record-index/options/hooks/useRecordIndexOptionsForTable'; import { TableOptionsHotkeyScope } from '@/object-record/record-table/types/TableOptionsHotkeyScope'; diff --git a/packages/twenty-front/src/modules/object-record/record-show/record-detail-section/components/RecordDetailRelationRecordsListItem.tsx b/packages/twenty-front/src/modules/object-record/record-show/record-detail-section/components/RecordDetailRelationRecordsListItem.tsx index 319073b01..d7d4c7fb7 100644 --- a/packages/twenty-front/src/modules/object-record/record-show/record-detail-section/components/RecordDetailRelationRecordsListItem.tsx +++ b/packages/twenty-front/src/modules/object-record/record-show/record-detail-section/components/RecordDetailRelationRecordsListItem.tsx @@ -14,7 +14,7 @@ import { useObjectMetadataItem } from '@/object-metadata/hooks/useObjectMetadata import { CoreObjectNameSingular } from '@/object-metadata/types/CoreObjectNameSingular'; import { formatFieldMetadataItemAsColumnDefinition } from '@/object-metadata/utils/formatFieldMetadataItemAsColumnDefinition'; import { RecordChip } from '@/object-record/components/RecordChip'; -import { useDeleteOneRecord } from '@/object-record/hooks/useDeleteOneRecord.ts'; +import { useDeleteOneRecord } from '@/object-record/hooks/useDeleteOneRecord'; import { useLazyFindOneRecord } from '@/object-record/hooks/useLazyFindOneRecord'; import { useUpdateOneRecord } from '@/object-record/hooks/useUpdateOneRecord'; import { diff --git a/packages/twenty-front/src/modules/object-record/relation-picker/hooks/useSearchFilterPerMetadataItem.ts b/packages/twenty-front/src/modules/object-record/relation-picker/hooks/useSearchFilterPerMetadataItem.ts index 6a342b92d..40ec48828 100644 --- a/packages/twenty-front/src/modules/object-record/relation-picker/hooks/useSearchFilterPerMetadataItem.ts +++ b/packages/twenty-front/src/modules/object-record/relation-picker/hooks/useSearchFilterPerMetadataItem.ts @@ -5,6 +5,7 @@ import { getLabelIdentifierFieldMetadataItem } from '@/object-metadata/utils/get import { ObjectRecordQueryFilter } from '@/object-record/record-filter/types/ObjectRecordQueryFilter'; import { makeOrFilterVariables } from '@/object-record/utils/makeOrFilterVariables'; import { FieldMetadataType } from '~/generated/graphql'; +import { generateILikeFiltersForCompositeFields } from '~/utils/array/generateILikeFiltersForCompositeFields'; import { isDefined } from '~/utils/isDefined'; export const useSearchFilterPerMetadataItem = ({ @@ -29,25 +30,16 @@ export const useSearchFilterPerMetadataItem = ({ switch (labelIdentifierFieldMetadataItem.type) { case FieldMetadataType.FullName: { if (isNonEmptyString(searchFilterValue)) { - const fullNameFilter = makeOrFilterVariables([ - { - [labelIdentifierFieldMetadataItem.name]: { - firstName: { - ilike: `%${searchFilterValue}%`, - }, - }, - }, - { - [labelIdentifierFieldMetadataItem.name]: { - lastName: { - ilike: `%${searchFilterValue}%`, - }, - }, - }, - ]); + const compositeFilter = makeOrFilterVariables( + generateILikeFiltersForCompositeFields( + searchFilterValue, + labelIdentifierFieldMetadataItem.name, + ['firstName', 'lastName'], + ), + ); - if (isDefined(fullNameFilter)) { - searchFilter = fullNameFilter; + if (isDefined(compositeFilter)) { + searchFilter = compositeFilter; } } break; diff --git a/packages/twenty-front/src/modules/search/hooks/useFilteredSearchEntityQuery.ts b/packages/twenty-front/src/modules/search/hooks/useFilteredSearchEntityQuery.ts index d7beaefce..5d12f9625 100644 --- a/packages/twenty-front/src/modules/search/hooks/useFilteredSearchEntityQuery.ts +++ b/packages/twenty-front/src/modules/search/hooks/useFilteredSearchEntityQuery.ts @@ -4,11 +4,13 @@ import { useMapToObjectRecordIdentifier } from '@/object-metadata/hooks/useMapTo import { OrderBy } from '@/object-metadata/types/OrderBy'; import { DEFAULT_SEARCH_REQUEST_LIMIT } from '@/object-record/constants/DefaultSearchRequestLimit'; import { useFindManyRecords } from '@/object-record/hooks/useFindManyRecords'; +import { ObjectRecordQueryFilter } from '@/object-record/record-filter/types/ObjectRecordQueryFilter'; import { EntitiesForMultipleEntitySelect } from '@/object-record/relation-picker/types/EntitiesForMultipleEntitySelect'; import { EntityForSelect } from '@/object-record/relation-picker/types/EntityForSelect'; import { ObjectRecord } from '@/object-record/types/ObjectRecord'; import { makeAndFilterVariables } from '@/object-record/utils/makeAndFilterVariables'; import { makeOrFilterVariables } from '@/object-record/utils/makeOrFilterVariables'; +import { generateILikeFiltersForCompositeFields } from '~/utils/array/generateILikeFiltersForCompositeFields'; import { isDefined } from '~/utils/isDefined'; type SearchFilter = { fieldNames: string[]; filter: string | number }; @@ -56,28 +58,33 @@ export const useFilteredSearchEntityQuery = ({ return undefined; } - return makeOrFilterVariables( - fieldNames.map((fieldName) => { + const formattedFilters = fieldNames.reduce( + (previousValue: ObjectRecordQueryFilter[], fieldName) => { const [parentFieldName, subFieldName] = fieldName.split('.'); if (isNonEmptyString(subFieldName)) { // Composite field - return { - [parentFieldName]: { - [subFieldName]: { - ilike: `%${filter}%`, - }, - }, - }; + return [ + ...previousValue, + ...generateILikeFiltersForCompositeFields(filter, parentFieldName, [ + subFieldName, + ]), + ]; } - return { - [fieldName]: { - ilike: `%${filter}%`, + return [ + ...previousValue, + { + [fieldName]: { + ilike: `%${filter}%`, + }, }, - }; - }), + ]; + }, + [], ); + + return makeOrFilterVariables(formattedFilters); }); const { diff --git a/packages/twenty-front/src/modules/settings/components/SettingsNavigationDrawerItems.tsx b/packages/twenty-front/src/modules/settings/components/SettingsNavigationDrawerItems.tsx index 68629d078..931b4bd01 100644 --- a/packages/twenty-front/src/modules/settings/components/SettingsNavigationDrawerItems.tsx +++ b/packages/twenty-front/src/modules/settings/components/SettingsNavigationDrawerItems.tsx @@ -17,7 +17,7 @@ import { } from 'twenty-ui'; import { useAuth } from '@/auth/hooks/useAuth'; -import { billingState } from '@/client-config/states/billingState.ts'; +import { billingState } from '@/client-config/states/billingState'; import { SettingsNavigationDrawerItem } from '@/settings/components/SettingsNavigationDrawerItem'; import { AppPath } from '@/types/AppPath'; import { SettingsPath } from '@/types/SettingsPath'; diff --git a/packages/twenty-front/src/modules/settings/developers/constants/ExpirationDates.ts b/packages/twenty-front/src/modules/settings/developers/constants/ExpirationDates.ts index 20c2ea683..f70b95215 100644 --- a/packages/twenty-front/src/modules/settings/developers/constants/ExpirationDates.ts +++ b/packages/twenty-front/src/modules/settings/developers/constants/ExpirationDates.ts @@ -1,4 +1,4 @@ -import { NEVER_EXPIRE_DELTA_IN_YEARS } from '@/settings/developers/constants/NeverExpireDeltaInYears.ts'; +import { NEVER_EXPIRE_DELTA_IN_YEARS } from '@/settings/developers/constants/NeverExpireDeltaInYears'; export const EXPIRATION_DATES: { value: number | null; diff --git a/packages/twenty-front/src/modules/settings/developers/utils/format-expiration.ts b/packages/twenty-front/src/modules/settings/developers/utils/format-expiration.ts index cfcd0b293..6b0b7a3ca 100644 --- a/packages/twenty-front/src/modules/settings/developers/utils/format-expiration.ts +++ b/packages/twenty-front/src/modules/settings/developers/utils/format-expiration.ts @@ -1,7 +1,7 @@ import { isNonEmptyString } from '@sniptt/guards'; import { DateTime } from 'luxon'; -import { NEVER_EXPIRE_DELTA_IN_YEARS } from '@/settings/developers/constants/NeverExpireDeltaInYears.ts'; +import { NEVER_EXPIRE_DELTA_IN_YEARS } from '@/settings/developers/constants/NeverExpireDeltaInYears'; import { ApiFieldItem } from '@/settings/developers/types/api-key/ApiFieldItem'; import { ApiKey } from '@/settings/developers/types/api-key/ApiKey'; import { beautifyDateDiff } from '~/utils/date-utils'; diff --git a/packages/twenty-front/src/pages/auth/ChooseYourPlan.tsx b/packages/twenty-front/src/pages/auth/ChooseYourPlan.tsx index 6f12824d5..9736eabb6 100644 --- a/packages/twenty-front/src/pages/auth/ChooseYourPlan.tsx +++ b/packages/twenty-front/src/pages/auth/ChooseYourPlan.tsx @@ -7,10 +7,10 @@ import { SubTitle } from '@/auth/components/SubTitle.tsx'; import { Title } from '@/auth/components/Title.tsx'; import { SubscriptionBenefit } from '@/billing/components/SubscriptionBenefit.tsx'; import { SubscriptionCard } from '@/billing/components/SubscriptionCard.tsx'; -import { billingState } from '@/client-config/states/billingState.ts'; -import { AppPath } from '@/types/AppPath.ts'; +import { billingState } from '@/client-config/states/billingState'; +import { AppPath } from '@/types/AppPath'; import { Loader } from '@/ui/feedback/loader/components/Loader.tsx'; -import { useSnackBar } from '@/ui/feedback/snack-bar-manager/hooks/useSnackBar.ts'; +import { useSnackBar } from '@/ui/feedback/snack-bar-manager/hooks/useSnackBar'; import { MainButton } from '@/ui/input/button/components/MainButton.tsx'; import { CardPicker } from '@/ui/input/components/CardPicker.tsx'; import { diff --git a/packages/twenty-front/src/pages/auth/PasswordReset.tsx b/packages/twenty-front/src/pages/auth/PasswordReset.tsx index 579537d62..9de60cc46 100644 --- a/packages/twenty-front/src/pages/auth/PasswordReset.tsx +++ b/packages/twenty-front/src/pages/auth/PasswordReset.tsx @@ -13,7 +13,7 @@ import { Logo } from '@/auth/components/Logo'; import { Title } from '@/auth/components/Title'; import { useAuth } from '@/auth/hooks/useAuth'; import { useIsLogged } from '@/auth/hooks/useIsLogged'; -import { useNavigateAfterSignInUp } from '@/auth/sign-in-up/hooks/useNavigateAfterSignInUp.ts'; +import { useNavigateAfterSignInUp } from '@/auth/sign-in-up/hooks/useNavigateAfterSignInUp'; import { PASSWORD_REGEX } from '@/auth/utils/passwordRegex'; import { AppPath } from '@/types/AppPath'; import { useSnackBar } from '@/ui/feedback/snack-bar-manager/hooks/useSnackBar'; diff --git a/packages/twenty-front/src/pages/auth/PaymentSuccess.tsx b/packages/twenty-front/src/pages/auth/PaymentSuccess.tsx index 4ceda8b8d..200a589b5 100644 --- a/packages/twenty-front/src/pages/auth/PaymentSuccess.tsx +++ b/packages/twenty-front/src/pages/auth/PaymentSuccess.tsx @@ -6,9 +6,9 @@ import { IconCheck } from 'twenty-ui'; import { SubTitle } from '@/auth/components/SubTitle.tsx'; import { Title } from '@/auth/components/Title.tsx'; -import { AppPath } from '@/types/AppPath.ts'; +import { AppPath } from '@/types/AppPath'; import { MainButton } from '@/ui/input/button/components/MainButton.tsx'; -import { RGBA } from '@/ui/theme/constants/Rgba.ts'; +import { RGBA } from '@/ui/theme/constants/Rgba'; import { AnimatedEaseIn } from '@/ui/utilities/animation/components/AnimatedEaseIn.tsx'; const StyledCheckContainer = styled.div` diff --git a/packages/twenty-front/src/pages/settings/SettingsBilling.tsx b/packages/twenty-front/src/pages/settings/SettingsBilling.tsx index 7227da990..7ab7ba755 100644 --- a/packages/twenty-front/src/pages/settings/SettingsBilling.tsx +++ b/packages/twenty-front/src/pages/settings/SettingsBilling.tsx @@ -9,13 +9,13 @@ import { IconCurrencyDollar, } from 'twenty-ui'; -import { useOnboardingStatus } from '@/auth/hooks/useOnboardingStatus.ts'; -import { currentWorkspaceState } from '@/auth/states/currentWorkspaceState.ts'; -import { OnboardingStatus } from '@/auth/utils/getOnboardingStatus.ts'; +import { useOnboardingStatus } from '@/auth/hooks/useOnboardingStatus'; +import { currentWorkspaceState } from '@/auth/states/currentWorkspaceState'; +import { OnboardingStatus } from '@/auth/utils/getOnboardingStatus'; import { SettingsBillingCoverImage } from '@/billing/components/SettingsBillingCoverImage'; import { SettingsPageContainer } from '@/settings/components/SettingsPageContainer'; import { SupportChat } from '@/support/components/SupportChat'; -import { AppPath } from '@/types/AppPath.ts'; +import { AppPath } from '@/types/AppPath'; import { Info } from '@/ui/display/info/components/Info'; import { H1Title } from '@/ui/display/typography/components/H1Title'; import { H2Title } from '@/ui/display/typography/components/H2Title'; diff --git a/packages/twenty-front/src/pages/settings/data-model/SettingsObjectNewField/SettingsObjectNewFieldStep2.tsx b/packages/twenty-front/src/pages/settings/data-model/SettingsObjectNewField/SettingsObjectNewFieldStep2.tsx index c921eba88..89c07742b 100644 --- a/packages/twenty-front/src/pages/settings/data-model/SettingsObjectNewField/SettingsObjectNewFieldStep2.tsx +++ b/packages/twenty-front/src/pages/settings/data-model/SettingsObjectNewField/SettingsObjectNewFieldStep2.tsx @@ -28,7 +28,7 @@ import { Section } from '@/ui/layout/section/components/Section'; import { Breadcrumb } from '@/ui/navigation/bread-crumb/components/Breadcrumb'; import { View } from '@/views/types/View'; import { ViewType } from '@/views/types/ViewType'; -import { useIsFeatureEnabled } from '@/workspace/hooks/useIsFeatureEnabled.ts'; +import { useIsFeatureEnabled } from '@/workspace/hooks/useIsFeatureEnabled'; import { FieldMetadataType } from '~/generated-metadata/graphql'; import { isUndefinedOrNull } from '~/utils/isUndefinedOrNull'; diff --git a/packages/twenty-front/src/utils/array/__tests__/generateILikeFiltersForCompositeFields.test.ts b/packages/twenty-front/src/utils/array/__tests__/generateILikeFiltersForCompositeFields.test.ts new file mode 100644 index 000000000..d4b37f60d --- /dev/null +++ b/packages/twenty-front/src/utils/array/__tests__/generateILikeFiltersForCompositeFields.test.ts @@ -0,0 +1,64 @@ +import { generateILikeFiltersForCompositeFields } from '~/utils/array/generateILikeFiltersForCompositeFields'; + +describe('generateILikeFiltersForCompositeFields', () => { + it('should format composite filters for simple filter string', () => { + expect( + generateILikeFiltersForCompositeFields('john', 'baseField', [ + 'subField1', + 'subField2', + ]), + ).toEqual([ + { + baseField: { + subField1: { + ilike: '%john%', + }, + }, + }, + { + baseField: { + subField2: { + ilike: '%john%', + }, + }, + }, + ]); + }); + it('should format composite filters for complex filter string', () => { + expect( + generateILikeFiltersForCompositeFields('john doe', 'name', [ + 'firstName', + 'lastName', + ]), + ).toEqual([ + { + name: { + firstName: { + ilike: '%john%', + }, + }, + }, + { + name: { + lastName: { + ilike: '%john%', + }, + }, + }, + { + name: { + firstName: { + ilike: '%doe%', + }, + }, + }, + { + name: { + lastName: { + ilike: '%doe%', + }, + }, + }, + ]); + }); +}); diff --git a/packages/twenty-front/src/utils/array/generateILikeFiltersForCompositeFields.ts b/packages/twenty-front/src/utils/array/generateILikeFiltersForCompositeFields.ts new file mode 100644 index 000000000..176931e16 --- /dev/null +++ b/packages/twenty-front/src/utils/array/generateILikeFiltersForCompositeFields.ts @@ -0,0 +1,24 @@ +import { ObjectRecordQueryFilter } from '@/object-record/record-filter/types/ObjectRecordQueryFilter'; + +export const generateILikeFiltersForCompositeFields = ( + filterString: string, + baseFieldName: string, + subFields: string[], +) => { + return filterString + .split(' ') + .reduce((previousValue: ObjectRecordQueryFilter[], currentValue) => { + return [ + ...previousValue, + ...subFields.map((subField) => { + return { + [baseFieldName]: { + [subField]: { + ilike: `%${currentValue}%`, + }, + }, + }; + }), + ]; + }, []); +};