Use search in multi object pickers (#7909)
Fixes https://github.com/twentyhq/twenty/issues/3298. We still have some existing glitches in the picker yet to fix. --------- Co-authored-by: Weiko <corentin@twenty.com>
This commit is contained in:
@ -0,0 +1,96 @@
|
|||||||
|
import { gql } from '@apollo/client';
|
||||||
|
import { isUndefined } from '@sniptt/guards';
|
||||||
|
import { useRecoilValue } from 'recoil';
|
||||||
|
|
||||||
|
import { objectMetadataItemsState } from '@/object-metadata/states/objectMetadataItemsState';
|
||||||
|
import { mapObjectMetadataToGraphQLQuery } from '@/object-metadata/utils/mapObjectMetadataToGraphQLQuery';
|
||||||
|
import { RecordGqlOperationSignature } from '@/object-record/graphql/types/RecordGqlOperationSignature';
|
||||||
|
import { generateDepthOneRecordGqlFields } from '@/object-record/graphql/utils/generateDepthOneRecordGqlFields';
|
||||||
|
import { getSearchRecordsQueryResponseField } from '@/object-record/utils/getSearchRecordsQueryResponseField';
|
||||||
|
import { isObjectMetadataItemSearchable } from '@/object-record/utils/isObjectMetadataItemSearchable';
|
||||||
|
import { isNonEmptyArray } from '~/utils/isNonEmptyArray';
|
||||||
|
import { capitalize } from '~/utils/string/capitalize';
|
||||||
|
|
||||||
|
export const useGenerateCombinedSearchRecordsQuery = ({
|
||||||
|
operationSignatures,
|
||||||
|
}: {
|
||||||
|
operationSignatures: RecordGqlOperationSignature[];
|
||||||
|
}) => {
|
||||||
|
const objectMetadataItems = useRecoilValue(objectMetadataItemsState);
|
||||||
|
|
||||||
|
if (!isNonEmptyArray(operationSignatures)) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
const filterPerMetadataItemArray = operationSignatures
|
||||||
|
.map(
|
||||||
|
({ objectNameSingular }) =>
|
||||||
|
`$filter${capitalize(objectNameSingular)}: ${capitalize(
|
||||||
|
objectNameSingular,
|
||||||
|
)}FilterInput`,
|
||||||
|
)
|
||||||
|
.join(', ');
|
||||||
|
|
||||||
|
const limitPerMetadataItemArray = operationSignatures
|
||||||
|
.map(
|
||||||
|
({ objectNameSingular }) =>
|
||||||
|
`$limit${capitalize(objectNameSingular)}: Int`,
|
||||||
|
)
|
||||||
|
.join(', ');
|
||||||
|
|
||||||
|
const queryKeyWithObjectMetadataItemArray = operationSignatures.map(
|
||||||
|
(queryKey) => {
|
||||||
|
const objectMetadataItem = objectMetadataItems.find(
|
||||||
|
(objectMetadataItem) =>
|
||||||
|
objectMetadataItem.nameSingular === queryKey.objectNameSingular,
|
||||||
|
);
|
||||||
|
|
||||||
|
if (isUndefined(objectMetadataItem)) {
|
||||||
|
throw new Error(
|
||||||
|
`Object metadata item not found for object name singular: ${queryKey.objectNameSingular}`,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
return { ...queryKey, objectMetadataItem };
|
||||||
|
},
|
||||||
|
);
|
||||||
|
|
||||||
|
const filteredQueryKeyWithObjectMetadataItemArray =
|
||||||
|
queryKeyWithObjectMetadataItemArray.filter(({ objectMetadataItem }) =>
|
||||||
|
isObjectMetadataItemSearchable(objectMetadataItem),
|
||||||
|
);
|
||||||
|
|
||||||
|
return gql`
|
||||||
|
query CombinedSearchRecords(
|
||||||
|
${filterPerMetadataItemArray},
|
||||||
|
${limitPerMetadataItemArray},
|
||||||
|
$search: String,
|
||||||
|
) {
|
||||||
|
${filteredQueryKeyWithObjectMetadataItemArray
|
||||||
|
.map(
|
||||||
|
({ objectMetadataItem, fields }) =>
|
||||||
|
`${getSearchRecordsQueryResponseField(objectMetadataItem.namePlural)}(filter: $filter${capitalize(
|
||||||
|
objectMetadataItem.nameSingular,
|
||||||
|
)},
|
||||||
|
limit: $limit${capitalize(objectMetadataItem.nameSingular)},
|
||||||
|
searchInput: $search
|
||||||
|
){
|
||||||
|
edges {
|
||||||
|
node ${mapObjectMetadataToGraphQLQuery({
|
||||||
|
objectMetadataItems: objectMetadataItems,
|
||||||
|
objectMetadataItem,
|
||||||
|
recordGqlFields:
|
||||||
|
fields ??
|
||||||
|
generateDepthOneRecordGqlFields({
|
||||||
|
objectMetadataItem,
|
||||||
|
}),
|
||||||
|
})}
|
||||||
|
cursor
|
||||||
|
}
|
||||||
|
totalCount
|
||||||
|
}`,
|
||||||
|
)
|
||||||
|
.join('\n')}
|
||||||
|
}
|
||||||
|
`;
|
||||||
|
};
|
||||||
@ -4,18 +4,32 @@ import { useRecoilValue } from 'recoil';
|
|||||||
|
|
||||||
import { objectMetadataItemsState } from '@/object-metadata/states/objectMetadataItemsState';
|
import { objectMetadataItemsState } from '@/object-metadata/states/objectMetadataItemsState';
|
||||||
import { EMPTY_QUERY } from '@/object-record/constants/EmptyQuery';
|
import { EMPTY_QUERY } from '@/object-record/constants/EmptyQuery';
|
||||||
import { useGenerateCombinedFindManyRecordsQuery } from '@/object-record/multiple-objects/hooks/useGenerateCombinedFindManyRecordsQuery';
|
import { useGenerateCombinedSearchRecordsQuery } from '@/object-record/multiple-objects/hooks/useGenerateCombinedSearchRecordsQuery';
|
||||||
import { useLimitPerMetadataItem } from '@/object-record/relation-picker/hooks/useLimitPerMetadataItem';
|
import { useLimitPerMetadataItem } from '@/object-record/relation-picker/hooks/useLimitPerMetadataItem';
|
||||||
import {
|
import {
|
||||||
MultiObjectRecordQueryResult,
|
MultiObjectRecordQueryResult,
|
||||||
useMultiObjectRecordsQueryResultFormattedAsObjectRecordForSelectArray,
|
useMultiObjectRecordsQueryResultFormattedAsObjectRecordForSelectArray,
|
||||||
} from '@/object-record/relation-picker/hooks/useMultiObjectRecordsQueryResultFormattedAsObjectRecordForSelectArray';
|
} from '@/object-record/relation-picker/hooks/useMultiObjectRecordsQueryResultFormattedAsObjectRecordForSelectArray';
|
||||||
import { SelectedObjectRecordId } from '@/object-record/relation-picker/hooks/useMultiObjectSearch';
|
import { SelectedObjectRecordId } from '@/object-record/relation-picker/hooks/useMultiObjectSearch';
|
||||||
import { useOrderByFieldPerMetadataItem } from '@/object-record/relation-picker/hooks/useOrderByFieldPerMetadataItem';
|
import { useMemo } from 'react';
|
||||||
import { useSearchFilterPerMetadataItem } from '@/object-record/relation-picker/hooks/useSearchFilterPerMetadataItem';
|
|
||||||
import { isDefined } from '~/utils/isDefined';
|
import { isDefined } from '~/utils/isDefined';
|
||||||
import { capitalize } from '~/utils/string/capitalize';
|
import { capitalize } from '~/utils/string/capitalize';
|
||||||
|
|
||||||
|
export const formatSearchResults = (
|
||||||
|
searchResults: MultiObjectRecordQueryResult | undefined,
|
||||||
|
): MultiObjectRecordQueryResult => {
|
||||||
|
if (!searchResults) {
|
||||||
|
return {};
|
||||||
|
}
|
||||||
|
|
||||||
|
return Object.entries(searchResults).reduce((acc, [key, value]) => {
|
||||||
|
let newKey = key.replace(/^search/, '');
|
||||||
|
newKey = newKey.charAt(0).toLowerCase() + newKey.slice(1);
|
||||||
|
acc[newKey] = value;
|
||||||
|
return acc;
|
||||||
|
}, {} as MultiObjectRecordQueryResult);
|
||||||
|
};
|
||||||
|
|
||||||
export const useMultiObjectSearchMatchesSearchFilterAndSelectedItemsQuery = ({
|
export const useMultiObjectSearchMatchesSearchFilterAndSelectedItemsQuery = ({
|
||||||
selectedObjectRecordIds,
|
selectedObjectRecordIds,
|
||||||
searchFilterValue,
|
searchFilterValue,
|
||||||
@ -27,18 +41,14 @@ export const useMultiObjectSearchMatchesSearchFilterAndSelectedItemsQuery = ({
|
|||||||
}) => {
|
}) => {
|
||||||
const objectMetadataItems = useRecoilValue(objectMetadataItemsState);
|
const objectMetadataItems = useRecoilValue(objectMetadataItemsState);
|
||||||
|
|
||||||
const { searchFilterPerMetadataItemNameSingular } =
|
const objectMetadataItemsUsedInSelectedIdsQuery = useMemo(
|
||||||
useSearchFilterPerMetadataItem({
|
() =>
|
||||||
objectMetadataItems,
|
objectMetadataItems.filter(({ nameSingular }) => {
|
||||||
searchFilterValue,
|
return selectedObjectRecordIds.some(({ objectNameSingular }) => {
|
||||||
});
|
return objectNameSingular === nameSingular;
|
||||||
|
});
|
||||||
const objectMetadataItemsUsedInSelectedIdsQuery = objectMetadataItems.filter(
|
}),
|
||||||
({ nameSingular }) => {
|
[objectMetadataItems, selectedObjectRecordIds],
|
||||||
return selectedObjectRecordIds.some(({ objectNameSingular }) => {
|
|
||||||
return objectNameSingular === nameSingular;
|
|
||||||
});
|
|
||||||
},
|
|
||||||
);
|
);
|
||||||
|
|
||||||
const selectedAndMatchesSearchFilterTextFilterPerMetadataItem =
|
const selectedAndMatchesSearchFilterTextFilterPerMetadataItem =
|
||||||
@ -53,38 +63,25 @@ export const useMultiObjectSearchMatchesSearchFilterAndSelectedItemsQuery = ({
|
|||||||
|
|
||||||
if (!isNonEmptyArray(selectedIds)) return null;
|
if (!isNonEmptyArray(selectedIds)) return null;
|
||||||
|
|
||||||
const searchFilter =
|
|
||||||
searchFilterPerMetadataItemNameSingular[nameSingular] ?? {};
|
|
||||||
return [
|
return [
|
||||||
`filter${capitalize(nameSingular)}`,
|
`filter${capitalize(nameSingular)}`,
|
||||||
{
|
{
|
||||||
and: [
|
id: {
|
||||||
{
|
in: selectedIds,
|
||||||
...searchFilter,
|
},
|
||||||
},
|
|
||||||
{
|
|
||||||
id: {
|
|
||||||
in: selectedIds,
|
|
||||||
},
|
|
||||||
},
|
|
||||||
],
|
|
||||||
},
|
},
|
||||||
];
|
];
|
||||||
})
|
})
|
||||||
.filter(isDefined),
|
.filter(isDefined),
|
||||||
);
|
);
|
||||||
|
|
||||||
const { orderByFieldPerMetadataItem } = useOrderByFieldPerMetadataItem({
|
|
||||||
objectMetadataItems: objectMetadataItemsUsedInSelectedIdsQuery,
|
|
||||||
});
|
|
||||||
|
|
||||||
const { limitPerMetadataItem } = useLimitPerMetadataItem({
|
const { limitPerMetadataItem } = useLimitPerMetadataItem({
|
||||||
objectMetadataItems: objectMetadataItemsUsedInSelectedIdsQuery,
|
objectMetadataItems: objectMetadataItemsUsedInSelectedIdsQuery,
|
||||||
limit,
|
limit,
|
||||||
});
|
});
|
||||||
|
|
||||||
const multiSelectQueryForSelectedIds =
|
const multiSelectSearchQueryForSelectedIds =
|
||||||
useGenerateCombinedFindManyRecordsQuery({
|
useGenerateCombinedSearchRecordsQuery({
|
||||||
operationSignatures: objectMetadataItemsUsedInSelectedIdsQuery.map(
|
operationSignatures: objectMetadataItemsUsedInSelectedIdsQuery.map(
|
||||||
(objectMetadataItem) => ({
|
(objectMetadataItem) => ({
|
||||||
objectNameSingular: objectMetadataItem.nameSingular,
|
objectNameSingular: objectMetadataItem.nameSingular,
|
||||||
@ -97,22 +94,23 @@ export const useMultiObjectSearchMatchesSearchFilterAndSelectedItemsQuery = ({
|
|||||||
loading: selectedAndMatchesSearchFilterObjectRecordsLoading,
|
loading: selectedAndMatchesSearchFilterObjectRecordsLoading,
|
||||||
data: selectedAndMatchesSearchFilterObjectRecordsQueryResult,
|
data: selectedAndMatchesSearchFilterObjectRecordsQueryResult,
|
||||||
} = useQuery<MultiObjectRecordQueryResult>(
|
} = useQuery<MultiObjectRecordQueryResult>(
|
||||||
multiSelectQueryForSelectedIds ?? EMPTY_QUERY,
|
multiSelectSearchQueryForSelectedIds ?? EMPTY_QUERY,
|
||||||
{
|
{
|
||||||
variables: {
|
variables: {
|
||||||
|
search: searchFilterValue,
|
||||||
...selectedAndMatchesSearchFilterTextFilterPerMetadataItem,
|
...selectedAndMatchesSearchFilterTextFilterPerMetadataItem,
|
||||||
...orderByFieldPerMetadataItem,
|
|
||||||
...limitPerMetadataItem,
|
...limitPerMetadataItem,
|
||||||
},
|
},
|
||||||
skip: !isDefined(multiSelectQueryForSelectedIds),
|
skip: !isDefined(multiSelectSearchQueryForSelectedIds),
|
||||||
},
|
},
|
||||||
);
|
);
|
||||||
|
|
||||||
const {
|
const {
|
||||||
objectRecordForSelectArray: selectedAndMatchesSearchFilterObjectRecords,
|
objectRecordForSelectArray: selectedAndMatchesSearchFilterObjectRecords,
|
||||||
} = useMultiObjectRecordsQueryResultFormattedAsObjectRecordForSelectArray({
|
} = useMultiObjectRecordsQueryResultFormattedAsObjectRecordForSelectArray({
|
||||||
multiObjectRecordsQueryResult:
|
multiObjectRecordsQueryResult: formatSearchResults(
|
||||||
selectedAndMatchesSearchFilterObjectRecordsQueryResult,
|
selectedAndMatchesSearchFilterObjectRecordsQueryResult,
|
||||||
|
),
|
||||||
});
|
});
|
||||||
|
|
||||||
return {
|
return {
|
||||||
|
|||||||
@ -4,15 +4,15 @@ import { useRecoilValue } from 'recoil';
|
|||||||
import { objectMetadataItemsState } from '@/object-metadata/states/objectMetadataItemsState';
|
import { objectMetadataItemsState } from '@/object-metadata/states/objectMetadataItemsState';
|
||||||
import { CoreObjectNameSingular } from '@/object-metadata/types/CoreObjectNameSingular';
|
import { CoreObjectNameSingular } from '@/object-metadata/types/CoreObjectNameSingular';
|
||||||
import { EMPTY_QUERY } from '@/object-record/constants/EmptyQuery';
|
import { EMPTY_QUERY } from '@/object-record/constants/EmptyQuery';
|
||||||
import { useGenerateCombinedFindManyRecordsQuery } from '@/object-record/multiple-objects/hooks/useGenerateCombinedFindManyRecordsQuery';
|
import { useGenerateCombinedSearchRecordsQuery } from '@/object-record/multiple-objects/hooks/useGenerateCombinedSearchRecordsQuery';
|
||||||
import { useLimitPerMetadataItem } from '@/object-record/relation-picker/hooks/useLimitPerMetadataItem';
|
import { useLimitPerMetadataItem } from '@/object-record/relation-picker/hooks/useLimitPerMetadataItem';
|
||||||
import {
|
import {
|
||||||
MultiObjectRecordQueryResult,
|
MultiObjectRecordQueryResult,
|
||||||
useMultiObjectRecordsQueryResultFormattedAsObjectRecordForSelectArray,
|
useMultiObjectRecordsQueryResultFormattedAsObjectRecordForSelectArray,
|
||||||
} from '@/object-record/relation-picker/hooks/useMultiObjectRecordsQueryResultFormattedAsObjectRecordForSelectArray';
|
} from '@/object-record/relation-picker/hooks/useMultiObjectRecordsQueryResultFormattedAsObjectRecordForSelectArray';
|
||||||
import { SelectedObjectRecordId } from '@/object-record/relation-picker/hooks/useMultiObjectSearch';
|
import { SelectedObjectRecordId } from '@/object-record/relation-picker/hooks/useMultiObjectSearch';
|
||||||
import { useOrderByFieldPerMetadataItem } from '@/object-record/relation-picker/hooks/useOrderByFieldPerMetadataItem';
|
import { formatSearchResults } from '@/object-record/relation-picker/hooks/useMultiObjectSearchMatchesSearchFilterAndSelectedItemsQuery';
|
||||||
import { useSearchFilterPerMetadataItem } from '@/object-record/relation-picker/hooks/useSearchFilterPerMetadataItem';
|
import { isObjectMetadataItemSearchableInCombinedRequest } from '@/object-record/utils/isObjectMetadataItemSearchableInCombinedRequest';
|
||||||
import { makeAndFilterVariables } from '@/object-record/utils/makeAndFilterVariables';
|
import { makeAndFilterVariables } from '@/object-record/utils/makeAndFilterVariables';
|
||||||
import { isDefined } from '~/utils/isDefined';
|
import { isDefined } from '~/utils/isDefined';
|
||||||
import { capitalize } from '~/utils/string/capitalize';
|
import { capitalize } from '~/utils/string/capitalize';
|
||||||
@ -36,13 +36,10 @@ export const useMultiObjectSearchMatchesSearchFilterAndToSelectQuery = ({
|
|||||||
.filter(({ isSystem, isRemote }) => !isSystem && !isRemote)
|
.filter(({ isSystem, isRemote }) => !isSystem && !isRemote)
|
||||||
.filter(({ nameSingular }) => {
|
.filter(({ nameSingular }) => {
|
||||||
return !excludedObjects?.includes(nameSingular as CoreObjectNameSingular);
|
return !excludedObjects?.includes(nameSingular as CoreObjectNameSingular);
|
||||||
});
|
})
|
||||||
|
.filter((object) =>
|
||||||
const { searchFilterPerMetadataItemNameSingular } =
|
isObjectMetadataItemSearchableInCombinedRequest(object),
|
||||||
useSearchFilterPerMetadataItem({
|
);
|
||||||
objectMetadataItems: selectableObjectMetadataItems,
|
|
||||||
searchFilterValue,
|
|
||||||
});
|
|
||||||
|
|
||||||
const objectRecordsToSelectAndMatchesSearchFilterTextFilterPerMetadataItem =
|
const objectRecordsToSelectAndMatchesSearchFilterTextFilterPerMetadataItem =
|
||||||
Object.fromEntries(
|
Object.fromEntries(
|
||||||
@ -65,29 +62,19 @@ export const useMultiObjectSearchMatchesSearchFilterAndToSelectQuery = ({
|
|||||||
? { not: { id: { in: excludedIdsUnion } } }
|
? { not: { id: { in: excludedIdsUnion } } }
|
||||||
: undefined;
|
: undefined;
|
||||||
|
|
||||||
const searchFilters = [
|
|
||||||
searchFilterPerMetadataItemNameSingular[nameSingular],
|
|
||||||
excludedIdsFilter,
|
|
||||||
];
|
|
||||||
|
|
||||||
return [
|
return [
|
||||||
`filter${capitalize(nameSingular)}`,
|
`filter${capitalize(nameSingular)}`,
|
||||||
makeAndFilterVariables(searchFilters),
|
makeAndFilterVariables([excludedIdsFilter]),
|
||||||
];
|
];
|
||||||
})
|
})
|
||||||
.filter(isDefined),
|
.filter(isDefined),
|
||||||
);
|
);
|
||||||
|
|
||||||
const { orderByFieldPerMetadataItem } = useOrderByFieldPerMetadataItem({
|
|
||||||
objectMetadataItems: selectableObjectMetadataItems,
|
|
||||||
});
|
|
||||||
|
|
||||||
const { limitPerMetadataItem } = useLimitPerMetadataItem({
|
const { limitPerMetadataItem } = useLimitPerMetadataItem({
|
||||||
objectMetadataItems: selectableObjectMetadataItems,
|
objectMetadataItems: selectableObjectMetadataItems,
|
||||||
limit,
|
limit,
|
||||||
});
|
});
|
||||||
|
|
||||||
const multiSelectQuery = useGenerateCombinedFindManyRecordsQuery({
|
const multiSelectQuery = useGenerateCombinedSearchRecordsQuery({
|
||||||
operationSignatures: selectableObjectMetadataItems.map(
|
operationSignatures: selectableObjectMetadataItems.map(
|
||||||
(objectMetadataItem) => ({
|
(objectMetadataItem) => ({
|
||||||
objectNameSingular: objectMetadataItem.nameSingular,
|
objectNameSingular: objectMetadataItem.nameSingular,
|
||||||
@ -101,8 +88,8 @@ export const useMultiObjectSearchMatchesSearchFilterAndToSelectQuery = ({
|
|||||||
data: toSelectAndMatchesSearchFilterObjectRecordsQueryResult,
|
data: toSelectAndMatchesSearchFilterObjectRecordsQueryResult,
|
||||||
} = useQuery<MultiObjectRecordQueryResult>(multiSelectQuery ?? EMPTY_QUERY, {
|
} = useQuery<MultiObjectRecordQueryResult>(multiSelectQuery ?? EMPTY_QUERY, {
|
||||||
variables: {
|
variables: {
|
||||||
|
search: searchFilterValue,
|
||||||
...objectRecordsToSelectAndMatchesSearchFilterTextFilterPerMetadataItem,
|
...objectRecordsToSelectAndMatchesSearchFilterTextFilterPerMetadataItem,
|
||||||
...orderByFieldPerMetadataItem,
|
|
||||||
...limitPerMetadataItem,
|
...limitPerMetadataItem,
|
||||||
},
|
},
|
||||||
skip: !isDefined(multiSelectQuery),
|
skip: !isDefined(multiSelectQuery),
|
||||||
@ -111,8 +98,9 @@ export const useMultiObjectSearchMatchesSearchFilterAndToSelectQuery = ({
|
|||||||
const {
|
const {
|
||||||
objectRecordForSelectArray: toSelectAndMatchesSearchFilterObjectRecords,
|
objectRecordForSelectArray: toSelectAndMatchesSearchFilterObjectRecords,
|
||||||
} = useMultiObjectRecordsQueryResultFormattedAsObjectRecordForSelectArray({
|
} = useMultiObjectRecordsQueryResultFormattedAsObjectRecordForSelectArray({
|
||||||
multiObjectRecordsQueryResult:
|
multiObjectRecordsQueryResult: formatSearchResults(
|
||||||
toSelectAndMatchesSearchFilterObjectRecordsQueryResult,
|
toSelectAndMatchesSearchFilterObjectRecordsQueryResult,
|
||||||
|
),
|
||||||
});
|
});
|
||||||
|
|
||||||
return {
|
return {
|
||||||
|
|||||||
@ -1,67 +0,0 @@
|
|||||||
import { isNonEmptyString } from '@sniptt/guards';
|
|
||||||
|
|
||||||
import { ObjectMetadataItem } from '@/object-metadata/types/ObjectMetadataItem';
|
|
||||||
import { getLabelIdentifierFieldMetadataItem } from '@/object-metadata/utils/getLabelIdentifierFieldMetadataItem';
|
|
||||||
import { RecordGqlOperationFilter } from '@/object-record/graphql/types/RecordGqlOperationFilter';
|
|
||||||
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 = ({
|
|
||||||
objectMetadataItems,
|
|
||||||
searchFilterValue,
|
|
||||||
}: {
|
|
||||||
objectMetadataItems: ObjectMetadataItem[];
|
|
||||||
searchFilterValue: string;
|
|
||||||
}) => {
|
|
||||||
const searchFilterPerMetadataItemNameSingular =
|
|
||||||
Object.fromEntries<RecordGqlOperationFilter>(
|
|
||||||
objectMetadataItems
|
|
||||||
.map((objectMetadataItem) => {
|
|
||||||
if (searchFilterValue === '') return null;
|
|
||||||
|
|
||||||
const labelIdentifierFieldMetadataItem =
|
|
||||||
getLabelIdentifierFieldMetadataItem(objectMetadataItem);
|
|
||||||
|
|
||||||
let searchFilter: RecordGqlOperationFilter = {};
|
|
||||||
|
|
||||||
if (isDefined(labelIdentifierFieldMetadataItem)) {
|
|
||||||
switch (labelIdentifierFieldMetadataItem.type) {
|
|
||||||
case FieldMetadataType.FullName: {
|
|
||||||
if (isNonEmptyString(searchFilterValue)) {
|
|
||||||
const compositeFilter = makeOrFilterVariables(
|
|
||||||
generateILikeFiltersForCompositeFields(
|
|
||||||
searchFilterValue,
|
|
||||||
labelIdentifierFieldMetadataItem.name,
|
|
||||||
['firstName', 'lastName'],
|
|
||||||
),
|
|
||||||
);
|
|
||||||
|
|
||||||
if (isDefined(compositeFilter)) {
|
|
||||||
searchFilter = compositeFilter;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
default: {
|
|
||||||
if (isNonEmptyString(searchFilterValue)) {
|
|
||||||
searchFilter = {
|
|
||||||
[labelIdentifierFieldMetadataItem.name]: {
|
|
||||||
ilike: `%${searchFilterValue}%`,
|
|
||||||
},
|
|
||||||
};
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return [objectMetadataItem.nameSingular, searchFilter] as const;
|
|
||||||
})
|
|
||||||
.filter(isDefined),
|
|
||||||
);
|
|
||||||
|
|
||||||
return {
|
|
||||||
searchFilterPerMetadataItemNameSingular,
|
|
||||||
};
|
|
||||||
};
|
|
||||||
@ -0,0 +1,17 @@
|
|||||||
|
import { ObjectMetadataItem } from '@/object-metadata/types/ObjectMetadataItem';
|
||||||
|
|
||||||
|
const SEARCHABLE_STANDARD_OBJECTS_NAMES_PLURAL = [
|
||||||
|
'companies',
|
||||||
|
'people',
|
||||||
|
'opportunities',
|
||||||
|
];
|
||||||
|
export const isObjectMetadataItemSearchable = (
|
||||||
|
objectMetadataItem: ObjectMetadataItem,
|
||||||
|
) => {
|
||||||
|
return (
|
||||||
|
objectMetadataItem.isCustom ||
|
||||||
|
SEARCHABLE_STANDARD_OBJECTS_NAMES_PLURAL.includes(
|
||||||
|
objectMetadataItem.namePlural,
|
||||||
|
)
|
||||||
|
);
|
||||||
|
};
|
||||||
@ -0,0 +1,17 @@
|
|||||||
|
import { ObjectMetadataItem } from '@/object-metadata/types/ObjectMetadataItem';
|
||||||
|
|
||||||
|
const SEARCHABLE_STANDARD_OBJECTS_IN_COMBINED_REQUEST_NAMES_PLURAL = [
|
||||||
|
'companies',
|
||||||
|
'people',
|
||||||
|
'opportunities',
|
||||||
|
];
|
||||||
|
export const isObjectMetadataItemSearchableInCombinedRequest = (
|
||||||
|
objectMetadataItem: ObjectMetadataItem,
|
||||||
|
) => {
|
||||||
|
return (
|
||||||
|
objectMetadataItem.isCustom ||
|
||||||
|
SEARCHABLE_STANDARD_OBJECTS_IN_COMBINED_REQUEST_NAMES_PLURAL.includes(
|
||||||
|
objectMetadataItem.namePlural,
|
||||||
|
)
|
||||||
|
);
|
||||||
|
};
|
||||||
Reference in New Issue
Block a user