clean searchResolvers in server (#11114)

Introduces break in change

- remove search... resolvers
- rename globalSearch to search
- rename searchRecord.objectSingularName > objectNameSingular
closes https://github.com/twentyhq/core-team-issues/issues/643
This commit is contained in:
Etienne
2025-03-24 13:42:51 +01:00
committed by GitHub
parent 6e7d2db58f
commit 1c5f3ef5fa
52 changed files with 236 additions and 529 deletions

View File

@ -164,10 +164,10 @@ export const NoResultsSearchFallback: Story = {
parameters: {
msw: {
handlers: [
graphql.query('GlobalSearch', () => {
graphql.query('Search', () => {
return HttpResponse.json({
data: {
globalSearch: [],
search: [],
},
});
}),

View File

@ -1,14 +1,14 @@
import gql from 'graphql-tag';
export const globalSearch = gql`
query GlobalSearch(
export const search = gql`
query Search(
$searchInput: String!
$limit: Int!
$excludedObjectNameSingulars: [String!]
$includedObjectNameSingulars: [String!]
$filter: ObjectRecordFilterInput
) {
globalSearch(
search(
searchInput: $searchInput
limit: $limit
excludedObjectNameSingulars: $excludedObjectNameSingulars
@ -16,7 +16,7 @@ export const globalSearch = gql`
filter: $filter
) {
recordId
objectSingularName
objectNameSingular
label
imageUrl
tsRankCD

View File

@ -5,17 +5,17 @@ import { CoreObjectNameSingular } from '@/object-metadata/types/CoreObjectNameSi
import { t } from '@lingui/core/macro';
import { useMemo } from 'react';
import { useRecoilValue } from 'recoil';
import { capitalize } from 'twenty-shared/utils';
import { Avatar } from 'twenty-ui';
import { useDebounce } from 'use-debounce';
import { useGlobalSearchQuery } from '~/generated/graphql';
import { capitalize } from 'twenty-shared/utils';
import { useSearchQuery } from '~/generated/graphql';
export const useCommandMenuSearchRecords = () => {
const commandMenuSearch = useRecoilValue(commandMenuSearchState);
const [deferredCommandMenuSearch] = useDebounce(commandMenuSearch, 300);
const { data: globalSearchData, loading } = useGlobalSearchQuery({
const { data: searchData, loading } = useSearchQuery({
variables: {
searchInput: deferredCommandMenuSearch ?? '',
limit: MAX_SEARCH_RESULTS,
@ -26,17 +26,17 @@ export const useCommandMenuSearchRecords = () => {
const { openRecordInCommandMenu } = useOpenRecordInCommandMenu();
const commands = useMemo(() => {
return (globalSearchData?.globalSearch ?? []).map((searchRecord) => {
return (searchData?.search ?? []).map((searchRecord) => {
const command = {
id: searchRecord.recordId,
label: searchRecord.label,
description: capitalize(searchRecord.objectSingularName),
to: `object/${searchRecord.objectSingularName}/${searchRecord.recordId}`,
description: capitalize(searchRecord.objectNameSingular),
to: `object/${searchRecord.objectNameSingular}/${searchRecord.recordId}`,
shouldCloseCommandMenuOnClick: true,
Icon: () => (
<Avatar
type={
searchRecord.objectSingularName === 'company'
searchRecord.objectNameSingular === 'company'
? 'squared'
: 'rounded'
}
@ -48,14 +48,14 @@ export const useCommandMenuSearchRecords = () => {
};
if (
[CoreObjectNameSingular.Task, CoreObjectNameSingular.Note].includes(
searchRecord.objectSingularName as CoreObjectNameSingular,
searchRecord.objectNameSingular as CoreObjectNameSingular,
)
) {
return {
...command,
to: '',
onCommandClick: () => {
searchRecord.objectSingularName === 'task'
searchRecord.objectNameSingular === 'task'
? openRecordInCommandMenu({
recordId: searchRecord.recordId,
objectNameSingular: CoreObjectNameSingular.Task,
@ -69,7 +69,7 @@ export const useCommandMenuSearchRecords = () => {
}
return command;
});
}, [globalSearchData, openRecordInCommandMenu]);
}, [searchData, openRecordInCommandMenu]);
return {
loading,

View File

@ -1,23 +1,23 @@
import { getAvatarType } from '@/object-metadata/utils/getAvatarType';
import { getBasePathToShowPage } from '@/object-metadata/utils/getBasePathToShowPage';
import { SingleRecordPickerRecord } from '@/object-record/record-picker/single-record-picker/types/SingleRecordPickerRecord';
import { GlobalSearchRecord } from '~/generated/graphql';
import { SearchRecord } from '~/generated/graphql';
export const formatGlobalSearchRecordAsSingleRecordPickerRecord = (
searchRecord: GlobalSearchRecord,
export const formatSearchRecordAsSingleRecordPickerRecord = (
searchRecord: SearchRecord,
): SingleRecordPickerRecord => {
return {
id: searchRecord.recordId,
name: searchRecord.label,
avatarUrl: searchRecord.imageUrl ?? undefined,
avatarType: getAvatarType(searchRecord.objectSingularName),
avatarType: getAvatarType(searchRecord.objectNameSingular),
linkToShowPage:
getBasePathToShowPage({
objectNameSingular: searchRecord.objectSingularName,
objectNameSingular: searchRecord.objectNameSingular,
}) + searchRecord.recordId,
record: {
id: searchRecord.recordId,
__typename: searchRecord.objectSingularName,
__typename: searchRecord.objectNameSingular,
},
};
};

View File

@ -7,12 +7,9 @@ import { useSnackBar } from '@/ui/feedback/snack-bar-manager/hooks/useSnackBar';
import { WatchQueryFetchPolicy } from '@apollo/client';
import { useMemo } from 'react';
import { useRecoilValue } from 'recoil';
import {
ObjectRecordFilterInput,
useGlobalSearchQuery,
} from '~/generated/graphql';
import { logError } from '~/utils/logError';
import { isDefined } from 'twenty-shared/utils';
import { ObjectRecordFilterInput, useSearchQuery } from '~/generated/graphql';
import { logError } from '~/utils/logError';
export type UseSearchRecordsParams = ObjectMetadataItemIdentifier & {
limit?: number;
@ -38,7 +35,7 @@ export const useObjectRecordSearchRecords = ({
const { enqueueSnackBar } = useSnackBar();
const { data, loading, error, previousData } = useGlobalSearchQuery({
const { data, loading, error, previousData } = useSearchQuery({
skip:
skip ||
!objectMetadataItem ||
@ -53,11 +50,11 @@ export const useObjectRecordSearchRecords = ({
fetchPolicy: fetchPolicy,
onError: (error) => {
logError(
`useGlobalSearchRecords for "${objectMetadataItem.namePlural}" error : ` +
`useSearchRecords for "${objectMetadataItem.namePlural}" error : ` +
error,
);
enqueueSnackBar(
`Error during useGlobalSearchRecords for "${objectMetadataItem.namePlural}", ${error.message}`,
`Error during useSearchRecords for "${objectMetadataItem.namePlural}", ${error.message}`,
{
variant: SnackBarVariant.Error,
},
@ -68,7 +65,7 @@ export const useObjectRecordSearchRecords = ({
const effectiveData = loading ? previousData : data;
const searchRecords = useMemo(
() => effectiveData?.globalSearch || [],
() => effectiveData?.search || [],
[effectiveData],
);

View File

@ -12,7 +12,7 @@ import { SelectableItem } from '@/ui/layout/selectable-list/components/Selectabl
import { useSelectableList } from '@/ui/layout/selectable-list/hooks/useSelectableList';
import { useAvailableComponentInstanceIdOrThrow } from '@/ui/utilities/state/component-state/hooks/useAvailableComponentInstanceIdOrThrow';
import { useRecoilComponentFamilyValueV2 } from '@/ui/utilities/state/component-state/hooks/useRecoilComponentFamilyValueV2';
import { GlobalSearchRecord } from '~/generated-metadata/graphql';
import { SearchRecord } from '~/generated-metadata/graphql';
export const StyledSelectableItem = styled(SelectableItem)`
height: 100%;
@ -20,7 +20,7 @@ export const StyledSelectableItem = styled(SelectableItem)`
`;
type MultipleRecordPickerMenuItemContentProps = {
searchRecord: GlobalSearchRecord;
searchRecord: SearchRecord;
objectMetadataItem: ObjectMetadataItem;
onChange: (morphItem: RecordPickerPickableMorphItem) => void;
};

View File

@ -1,5 +1,5 @@
import { MAX_SEARCH_RESULTS } from '@/command-menu/constants/MaxSearchResults';
import { globalSearch } from '@/command-menu/graphql/queries/globalSearch';
import { search } from '@/command-menu/graphql/queries/search';
import { ObjectMetadataItem } from '@/object-metadata/types/ObjectMetadataItem';
import { usePerformCombinedFindManyRecords } from '@/object-record/multiple-objects/hooks/usePerformCombinedFindManyRecords';
import { multipleRecordPickerPickableMorphItemsComponentState } from '@/object-record/record-picker/multiple-record-picker/states/multipleRecordPickerPickableMorphItemsComponentState';
@ -10,8 +10,8 @@ import { RecordPickerPickableMorphItem } from '@/object-record/record-picker/typ
import { ApolloClient, useApolloClient } from '@apollo/client';
import { isNonEmptyArray } from '@sniptt/guards';
import { useRecoilCallback } from 'recoil';
import { GlobalSearchRecord } from '~/generated-metadata/graphql';
import { capitalize, isDefined } from 'twenty-shared/utils';
import { SearchRecord } from '~/generated-metadata/graphql';
export const useMultipleRecordPickerPerformSearch = () => {
const client = useApolloClient();
@ -117,23 +117,23 @@ export const useMultipleRecordPickerPerformSearch = () => {
const morphItems = [
...updatedPickedMorphItems,
...searchRecordsFilteredOnPickedRecordsWithoutDuplicates.map(
({ recordId, objectSingularName }) => ({
({ recordId, objectNameSingular }) => ({
isMatchingSearchFilter: true,
isSelected: true,
objectMetadataId: searchableObjectMetadataItems.find(
(objectMetadata) =>
objectMetadata.nameSingular === objectSingularName,
objectMetadata.nameSingular === objectNameSingular,
)?.id,
recordId,
}),
),
...searchRecordsExcludingPickedRecordsWithoutDuplicates.map(
({ recordId, objectSingularName }) => ({
({ recordId, objectNameSingular }) => ({
isMatchingSearchFilter: true,
isSelected: false,
objectMetadataId: searchableObjectMetadataItems.find(
(objectMetadata) =>
objectMetadata.nameSingular === objectSingularName,
objectMetadata.nameSingular === objectNameSingular,
)?.id,
recordId,
}),
@ -168,8 +168,8 @@ export const useMultipleRecordPickerPerformSearch = () => {
.map(({ nameSingular }) => {
const recordIdsForMetadataItem = searchRecords
.filter(
({ objectSingularName }) =>
objectSingularName === nameSingular,
({ objectNameSingular }) =>
objectNameSingular === nameSingular,
)
.map(({ recordId }) => recordId);
@ -251,14 +251,14 @@ const performSearchQueries = async ({
searchFilter: string;
searchableObjectMetadataItems: ObjectMetadataItem[];
pickedRecordIds: string[];
}): Promise<[GlobalSearchRecord[], GlobalSearchRecord[]]> => {
}): Promise<[SearchRecord[], SearchRecord[]]> => {
if (searchableObjectMetadataItems.length === 0) {
return [[], []];
}
const searchRecords = async (filter: any) => {
const { data } = await client.query({
query: globalSearch,
query: search,
variables: {
searchInput: searchFilter,
includedObjectNameSingulars: searchableObjectMetadataItems.map(
@ -268,7 +268,7 @@ const performSearchQueries = async ({
limit: MAX_SEARCH_RESULTS,
},
});
return data.globalSearch;
return data.search;
};
const searchRecordsExcludingPickedRecords = await searchRecords(

View File

@ -1,11 +1,11 @@
import { MultipleRecordPickerComponentInstanceContext } from '@/object-record/record-picker/multiple-record-picker/states/contexts/MultipleRecordPickerComponentInstanceContext';
import { ObjectRecord } from '@/object-record/types/ObjectRecord';
import { createComponentFamilyStateV2 } from '@/ui/utilities/state/component-state/utils/createComponentFamilyStateV2';
import { GlobalSearchRecord } from '~/generated-metadata/graphql';
import { SearchRecord } from '~/generated-metadata/graphql';
export const searchRecordStoreComponentFamilyState =
createComponentFamilyStateV2<
(GlobalSearchRecord & { record?: ObjectRecord }) | undefined,
(SearchRecord & { record?: ObjectRecord }) | undefined,
string
>({
key: 'searchRecordStoreComponentFamilyState',

View File

@ -1,4 +1,4 @@
import { formatGlobalSearchRecordAsSingleRecordPickerRecord } from '@/object-metadata/utils/formatGlobalSearchRecordAsSingleRecordPickerRecord';
import { formatSearchRecordAsSingleRecordPickerRecord } from '@/object-metadata/utils/formatSearchRecordAsSingleRecordPickerRecord';
import { DEFAULT_SEARCH_REQUEST_LIMIT } from '@/object-record/constants/DefaultSearchRequestLimit';
import { useObjectRecordSearchRecords } from '@/object-record/hooks/useObjectRecordSearchRecords';
import { SingleRecordPickerRecord } from '@/object-record/record-picker/single-record-picker/types/SingleRecordPickerRecord';
@ -57,13 +57,13 @@ export const useFilteredSearchRecordQuery = ({
return {
selectedRecords: selectedRecords
.map(formatGlobalSearchRecordAsSingleRecordPickerRecord)
.map(formatSearchRecordAsSingleRecordPickerRecord)
.filter(isDefined),
filteredSelectedRecords: filteredSelectedRecords
.map(formatGlobalSearchRecordAsSingleRecordPickerRecord)
.map(formatSearchRecordAsSingleRecordPickerRecord)
.filter(isDefined),
recordsToSelect: recordsToSelect
.map(formatGlobalSearchRecordAsSingleRecordPickerRecord)
.map(formatSearchRecordAsSingleRecordPickerRecord)
.filter(isDefined),
loading:
recordsToSelectLoading ||

View File

@ -22,8 +22,8 @@ import {
TooltipDelay,
} from 'twenty-ui';
import {
GlobalSearchRecord,
Role,
SearchRecord,
WorkspaceMember,
} from '~/generated-metadata/graphql';
import {
@ -134,7 +134,7 @@ export const RoleAssignment = ({ role }: RoleAssignmentProps) => {
};
const handleSelectWorkspaceMember = (
workspaceMemberSearchRecord: GlobalSearchRecord,
workspaceMemberSearchRecord: SearchRecord,
) => {
const existingRole = workspaceMemberRoleMap.get(
workspaceMemberSearchRecord.recordId,

View File

@ -6,11 +6,11 @@ import { DropdownMenuItemsContainer } from '@/ui/layout/dropdown/components/Drop
import { DropdownMenuSearchInput } from '@/ui/layout/dropdown/components/DropdownMenuSearchInput';
import { DropdownMenuSeparator } from '@/ui/layout/dropdown/components/DropdownMenuSeparator';
import { ChangeEvent, useState } from 'react';
import { GlobalSearchRecord } from '~/generated-metadata/graphql';
import { SearchRecord } from '~/generated-metadata/graphql';
type RoleAssignmentWorkspaceMemberPickerDropdownProps = {
excludedWorkspaceMemberIds: string[];
onSelect: (workspaceMemberSearchRecord: GlobalSearchRecord) => void;
onSelect: (workspaceMemberSearchRecord: SearchRecord) => void;
};
export const RoleAssignmentWorkspaceMemberPickerDropdown = ({

View File

@ -1,12 +1,12 @@
import { t } from '@lingui/core/macro';
import { MenuItem, MenuItemAvatar } from 'twenty-ui';
import { GlobalSearchRecord } from '~/generated-metadata/graphql';
import { SearchRecord } from '~/generated-metadata/graphql';
type RoleAssignmentWorkspaceMemberPickerDropdownContentProps = {
loading: boolean;
searchFilter: string;
filteredWorkspaceMembers: GlobalSearchRecord[];
onSelect: (workspaceMemberSearchRecord: GlobalSearchRecord) => void;
filteredWorkspaceMembers: SearchRecord[];
onSelect: (workspaceMemberSearchRecord: SearchRecord) => void;
};
export const RoleAssignmentWorkspaceMemberPickerDropdownContent = ({