diff --git a/front/src/modules/object-metadata/components/ObjectMetadataItemsProvider.tsx b/front/src/modules/object-metadata/components/ObjectMetadataItemsProvider.tsx
index b4d55bcb5..749a5dfd6 100644
--- a/front/src/modules/object-metadata/components/ObjectMetadataItemsProvider.tsx
+++ b/front/src/modules/object-metadata/components/ObjectMetadataItemsProvider.tsx
@@ -1,9 +1,18 @@
+import { ObjectMetadataItemsRelationPickerEffect } from '@/object-metadata/components/ObjectMetadataItemsRelationPickerEffect';
import { useFindManyObjectMetadataItems } from '@/object-metadata/hooks/useFindManyObjectMetadataItems';
+import { RelationPickerScope } from '@/ui/input/components/internal/relation-picker/scopes/RelationPickerScope';
export const ObjectMetadataItemsProvider = ({
children,
}: React.PropsWithChildren) => {
const { loading } = useFindManyObjectMetadataItems();
- return loading ? <>> : <>{children}>;
+ return loading ? (
+ <>>
+ ) : (
+
+
+ {children}
+
+ );
};
diff --git a/front/src/modules/object-metadata/components/ObjectMetadataItemsRelationPickerEffect.tsx b/front/src/modules/object-metadata/components/ObjectMetadataItemsRelationPickerEffect.tsx
new file mode 100644
index 000000000..ee7ff6ebd
--- /dev/null
+++ b/front/src/modules/object-metadata/components/ObjectMetadataItemsRelationPickerEffect.tsx
@@ -0,0 +1,51 @@
+import { useEffect } from 'react';
+
+import { useRelationPicker } from '@/ui/input/components/internal/relation-picker/hooks/useRelationPicker';
+import { IdentifiersMapper } from '@/ui/input/components/internal/relation-picker/types/IdentifiersMapper';
+
+export const ObjectMetadataItemsRelationPickerEffect = () => {
+ const { setIdentifiersMapper } = useRelationPicker();
+
+ const identifierMapper: IdentifiersMapper = (
+ record: any,
+ objectMetadataItemSingularName: string,
+ ) => {
+ if (!record) {
+ return;
+ }
+
+ if (objectMetadataItemSingularName === 'company') {
+ return {
+ id: record.id,
+ name: record.name,
+ avatarUrl: record.avatarUrl,
+ avatarType: 'squared',
+ record: record,
+ };
+ }
+
+ if (objectMetadataItemSingularName === 'workspaceMember') {
+ return {
+ id: record.id,
+ name: record.name.firstName + ' ' + record.name.lastName,
+ avatarUrl: record.avatarUrl,
+ avatarType: 'rounded',
+ record: record,
+ };
+ }
+
+ return {
+ id: record.id,
+ name: record.name,
+ avatarUrl: record.avatarUrl,
+ avatarType: 'rounded',
+ record,
+ };
+ };
+
+ useEffect(() => {
+ setIdentifiersMapper(() => identifierMapper);
+ }, [setIdentifiersMapper]);
+
+ return <>>;
+};
diff --git a/front/src/modules/object-metadata/hooks/useObjectMainIdentifier.ts b/front/src/modules/object-metadata/hooks/useObjectMainIdentifier.ts
index dd4121f51..d30f477cc 100644
--- a/front/src/modules/object-metadata/hooks/useObjectMainIdentifier.ts
+++ b/front/src/modules/object-metadata/hooks/useObjectMainIdentifier.ts
@@ -1,5 +1,4 @@
import { ObjectMetadataItem } from '@/object-metadata/types/ObjectMetadataItem';
-import { AvatarType } from '@/users/components/Avatar';
import { Nullable } from '~/types/Nullable';
export const useObjectMainIdentifier = (
@@ -9,39 +8,14 @@ export const useObjectMainIdentifier = (
return {};
}
- const labelIdentifierFieldPaths = ['person', 'workspaceMember'].includes(
- objectMetadataItem.nameSingular,
- )
- ? ['name.firstName', 'name.lastName']
- : ['name'];
- const imageIdentifierFormat: AvatarType = ['company'].includes(
- objectMetadataItem.nameSingular,
- )
- ? 'squared'
- : 'rounded';
- const imageIdentifierUrlPrefix = ['company'].includes(
- objectMetadataItem.nameSingular,
- )
- ? 'https://favicon.twenty.com/'
- : '';
- const imageIdentifierUrlField = ['company'].includes(
- objectMetadataItem.nameSingular,
- )
- ? 'domainName'
- : 'avatarUrl';
-
- const mainIdentifierFieldMetadataId = objectMetadataItem.fields.find(
+ const labelIdentifierFieldMetadataId = objectMetadataItem.fields.find(
({ name }) => name === 'name',
)?.id;
const basePathToShowPage = `/object/${objectMetadataItem.nameSingular}/`;
return {
- labelIdentifierFieldPaths,
- imageIdentifierUrlField,
- imageIdentifierUrlPrefix,
- imageIdentifierFormat,
- mainIdentifierFieldMetadataId,
+ labelIdentifierFieldMetadataId,
basePathToShowPage,
};
};
diff --git a/front/src/modules/object-metadata/utils/formatFieldMetadataItemAsColumnDefinition.ts b/front/src/modules/object-metadata/utils/formatFieldMetadataItemAsColumnDefinition.ts
index d5ee3859b..5e5ceabe8 100644
--- a/front/src/modules/object-metadata/utils/formatFieldMetadataItemAsColumnDefinition.ts
+++ b/front/src/modules/object-metadata/utils/formatFieldMetadataItemAsColumnDefinition.ts
@@ -1,7 +1,6 @@
import { parseFieldRelationType } from '@/object-metadata/utils/parseFieldRelationType';
import { FieldMetadata } from '@/ui/object/field/types/FieldMetadata';
import { ColumnDefinition } from '@/ui/object/record-table/types/ColumnDefinition';
-import { AvatarType } from '@/users/components/Avatar';
import { FieldMetadataItem } from '../types/FieldMetadataItem';
@@ -17,27 +16,6 @@ export const formatFieldMetadataItemAsColumnDefinition = ({
const relationObjectMetadataItem =
field.toRelationMetadata?.fromObjectMetadata;
- const labelIdentifierFieldPaths = ['person', 'workspaceMember'].includes(
- relationObjectMetadataItem?.nameSingular ?? '',
- )
- ? ['name.firstName', 'name.lastName']
- : ['name'];
- const imageIdentifierFormat: AvatarType = ['company'].includes(
- relationObjectMetadataItem?.nameSingular ?? '',
- )
- ? 'squared'
- : 'rounded';
- const imageIdentifierUrlPrefix = ['company'].includes(
- relationObjectMetadataItem?.nameSingular ?? '',
- )
- ? 'https://favicon.twenty.com/'
- : '';
- const imageIdentifierUrlField = ['company'].includes(
- relationObjectMetadataItem?.nameSingular ?? '',
- )
- ? 'domainName'
- : 'avatarUrl';
-
return {
position,
fieldMetadataId: field.id,
@@ -47,15 +25,10 @@ export const formatFieldMetadataItemAsColumnDefinition = ({
metadata: {
fieldName: field.name,
placeHolder: field.label,
- labelIdentifierFieldPaths,
- imageIdentifierUrlField,
- imageIdentifierUrlPrefix,
- imageIdentifierFormat,
relationType: parseFieldRelationType(field),
- searchFields: ['name'],
- objectMetadataNamePlural: relationObjectMetadataItem?.namePlural ?? '',
objectMetadataNameSingular:
relationObjectMetadataItem?.nameSingular ?? '',
+ objectMetadataNamePlural: relationObjectMetadataItem?.namePlural ?? '',
},
iconName: field.icon ?? 'Icon123',
isVisible: true,
diff --git a/front/src/modules/object-record/components/RecordTableEffect.tsx b/front/src/modules/object-record/components/RecordTableEffect.tsx
index da3f7db08..aec52c93a 100644
--- a/front/src/modules/object-record/components/RecordTableEffect.tsx
+++ b/front/src/modules/object-record/components/RecordTableEffect.tsx
@@ -21,14 +21,8 @@ export const RecordTableEffect = () => {
objectNamePlural,
});
- const {
- basePathToShowPage,
- mainIdentifierFieldMetadataId,
- labelIdentifierFieldPaths,
- imageIdentifierUrlField,
- imageIdentifierUrlPrefix,
- imageIdentifierFormat,
- } = useObjectMainIdentifier(objectMetadataItem);
+ const { basePathToShowPage, labelIdentifierFieldMetadataId } =
+ useObjectMainIdentifier(objectMetadataItem);
const { columnDefinitions, filterDefinitions, sortDefinitions } =
useComputeDefinitionsFromFieldMetadata(objectMetadataItem);
@@ -43,25 +37,17 @@ export const RecordTableEffect = () => {
} = useView();
useEffect(() => {
- if (basePathToShowPage && mainIdentifierFieldMetadataId) {
+ if (basePathToShowPage && labelIdentifierFieldMetadataId) {
setObjectMetadataConfig?.({
- labelIdentifierFieldPaths,
- imageIdentifierUrlField,
- imageIdentifierUrlPrefix,
- imageIdentifierFormat,
basePathToShowPage,
- mainIdentifierFieldMetadataId,
+ labelIdentifierFieldMetadataId,
});
}
}, [
basePathToShowPage,
objectMetadataItem,
- mainIdentifierFieldMetadataId,
+ labelIdentifierFieldMetadataId,
setObjectMetadataConfig,
- labelIdentifierFieldPaths,
- imageIdentifierUrlField,
- imageIdentifierUrlPrefix,
- imageIdentifierFormat,
]);
useEffect(() => {
diff --git a/front/src/modules/search/hooks/useFilteredSearchEntityQuery.ts b/front/src/modules/search/hooks/useFilteredSearchEntityQuery.ts
index e01ea17f4..3344cd8f2 100644
--- a/front/src/modules/search/hooks/useFilteredSearchEntityQuery.ts
+++ b/front/src/modules/search/hooks/useFilteredSearchEntityQuery.ts
@@ -4,6 +4,7 @@ import { isNonEmptyString } from '@sniptt/guards';
import { mapPaginatedObjectsToObjects } from '@/object-record/utils/mapPaginatedObjectsToObjects';
import { EntitiesForMultipleEntitySelect } from '@/ui/input/relation-picker/components/MultipleEntitySelect';
import { EntityForSelect } from '@/ui/input/relation-picker/types/EntityForSelect';
+import { assertNotNull } from '~/utils/assert';
import { isDefined } from '~/utils/isDefined';
type SearchFilter = { fieldNames: string[]; filter: string | number };
@@ -36,7 +37,7 @@ export const useFilteredSearchEntityQuery = ({
filters: SearchFilter[];
sortOrder?: OrderBy;
selectedIds: string[];
- mappingFunction: (entity: any) => EntityForSelect;
+ mappingFunction: (entity: any) => EntityForSelect | undefined;
limit?: number;
excludeEntityIds?: string[];
objectNamePlural: string;
@@ -139,15 +140,21 @@ export const useFilteredSearchEntityQuery = ({
selectedEntities: mapPaginatedObjectsToObjects({
objectNamePlural: objectNamePlural,
pagedObjects: selectedEntitiesData,
- }).map(mappingFunction),
+ })
+ .map(mappingFunction)
+ .filter(assertNotNull),
filteredSelectedEntities: mapPaginatedObjectsToObjects({
objectNamePlural: objectNamePlural,
pagedObjects: filteredSelectedEntitiesData,
- }).map(mappingFunction),
+ })
+ .map(mappingFunction)
+ .filter(assertNotNull),
entitiesToSelect: mapPaginatedObjectsToObjects({
objectNamePlural: objectNamePlural,
pagedObjects: entitiesToSelectData,
- }).map(mappingFunction),
+ })
+ .map(mappingFunction)
+ .filter(assertNotNull),
loading:
entitiesToSelectLoading ||
filteredSelectedEntitiesLoading ||
diff --git a/front/src/modules/settings/data-model/components/SettingsObjectFieldPreview.tsx b/front/src/modules/settings/data-model/components/SettingsObjectFieldPreview.tsx
index bd71de588..f542751b3 100644
--- a/front/src/modules/settings/data-model/components/SettingsObjectFieldPreview.tsx
+++ b/front/src/modules/settings/data-model/components/SettingsObjectFieldPreview.tsx
@@ -90,13 +90,7 @@ export const SettingsObjectFieldPreview = ({
objectMetadataId,
});
- const {
- defaultValue: relationDefaultValue,
- labelIdentifierFieldPaths,
- imageIdentifierUrlField,
- imageIdentifierUrlPrefix,
- imageIdentifierFormat,
- } = useRelationFieldPreview({
+ const { defaultValue: relationDefaultValue } = useRelationFieldPreview({
relationObjectMetadataId,
skipDefaultValue:
fieldMetadata.type !== FieldMetadataType.Relation || hasValue,
@@ -107,15 +101,6 @@ export const SettingsObjectFieldPreview = ({
? relationDefaultValue
: dataTypes[fieldMetadata.type].defaultValue;
- if (
- !labelIdentifierFieldPaths ||
- !imageIdentifierUrlField ||
- !imageIdentifierUrlPrefix ||
- !imageIdentifierFormat
- ) {
- return <>>;
- }
-
return (
@@ -160,10 +145,6 @@ export const SettingsObjectFieldPreview = ({
label: fieldMetadata.label,
metadata: {
fieldName,
- labelIdentifierFieldPaths,
- imageIdentifierUrlField,
- imageIdentifierUrlPrefix,
- imageIdentifierFormat,
},
},
hotkeyScope: 'field-preview',
diff --git a/front/src/modules/settings/data-model/hooks/useRelationFieldPreview.ts b/front/src/modules/settings/data-model/hooks/useRelationFieldPreview.ts
index f0300587d..9b297c3cb 100644
--- a/front/src/modules/settings/data-model/hooks/useRelationFieldPreview.ts
+++ b/front/src/modules/settings/data-model/hooks/useRelationFieldPreview.ts
@@ -1,4 +1,3 @@
-import { useObjectMainIdentifier } from '@/object-metadata/hooks/useObjectMainIdentifier';
import { useObjectMetadataItemForSettings } from '@/object-metadata/hooks/useObjectMetadataItemForSettings';
import { useFindManyObjectRecords } from '@/object-record/hooks/useFindManyObjectRecords';
@@ -20,18 +19,7 @@ export const useRelationFieldPreview = ({
skip: skipDefaultValue || !relationObjectMetadataItem,
});
- const {
- labelIdentifierFieldPaths,
- imageIdentifierUrlField,
- imageIdentifierUrlPrefix,
- imageIdentifierFormat,
- } = useObjectMainIdentifier(relationObjectMetadataItem);
-
return {
defaultValue: relationObjects?.[0],
- labelIdentifierFieldPaths,
- imageIdentifierUrlField,
- imageIdentifierUrlPrefix,
- imageIdentifierFormat,
};
};
diff --git a/front/src/modules/ui/object/field/meta-types/input/components/internal/RelationPicker.tsx b/front/src/modules/ui/input/components/internal/relation-picker/RelationPicker.tsx
similarity index 88%
rename from front/src/modules/ui/object/field/meta-types/input/components/internal/RelationPicker.tsx
rename to front/src/modules/ui/input/components/internal/relation-picker/RelationPicker.tsx
index 716731d1d..ce0d76798 100644
--- a/front/src/modules/ui/object/field/meta-types/input/components/internal/RelationPicker.tsx
+++ b/front/src/modules/ui/input/components/internal/relation-picker/RelationPicker.tsx
@@ -42,18 +42,25 @@ export const RelationPicker = ({
const useFindManyQuery = (options: any) => useQuery(findManyQuery, options);
- const { mapToObjectIdentifiers } = useRelationField();
+ const { identifiersMapper, searchQuery } = useRelationField();
const workspaceMembers = useFilteredSearchEntityQuery({
queryHook: useFindManyQuery,
filters: [
{
- fieldNames: fieldDefinition.metadata.searchFields,
+ fieldNames:
+ searchQuery?.filterFields?.(
+ fieldDefinition.metadata.objectMetadataNameSingular,
+ ) ?? [],
filter: relationPickerSearchFilter,
},
],
orderByField: 'createdAt',
- mappingFunction: mapToObjectIdentifiers,
+ mappingFunction: (record: any) =>
+ identifiersMapper?.(
+ record,
+ fieldDefinition.metadata.objectMetadataNameSingular,
+ ),
selectedIds: recordId ? [recordId] : [],
objectNamePlural: fieldDefinition.metadata.objectMetadataNamePlural,
});
diff --git a/front/src/modules/ui/input/components/internal/relation-picker/hooks/internal/useRelationPickerScopedStates.ts b/front/src/modules/ui/input/components/internal/relation-picker/hooks/internal/useRelationPickerScopedStates.ts
new file mode 100644
index 000000000..ba3212444
--- /dev/null
+++ b/front/src/modules/ui/input/components/internal/relation-picker/hooks/internal/useRelationPickerScopedStates.ts
@@ -0,0 +1,28 @@
+import { getRelationPickerScopedStates } from '@/ui/input/components/internal/relation-picker/utils/getRelationPickerScopedStates';
+import { RecordTableScopeInternalContext } from '@/ui/object/record-table/scopes/scope-internal-context/RecordTableScopeInternalContext';
+import { useAvailableScopeIdOrThrow } from '@/ui/utilities/recoil-scope/scopes-internal/hooks/useAvailableScopeId';
+
+export const useRelationPickerScopedStates = (args?: {
+ relationPickerScopedId?: string;
+}) => {
+ const { relationPickerScopedId } = args ?? {};
+
+ const scopeId = useAvailableScopeIdOrThrow(
+ RecordTableScopeInternalContext,
+ relationPickerScopedId,
+ );
+
+ const { identifiersMapperState } = getRelationPickerScopedStates({
+ relationPickerScopeId: scopeId,
+ });
+
+ const { searchQueryState } = getRelationPickerScopedStates({
+ relationPickerScopeId: scopeId,
+ });
+
+ return {
+ scopeId,
+ identifiersMapperState,
+ searchQueryState,
+ };
+};
diff --git a/front/src/modules/ui/input/components/internal/relation-picker/hooks/useRelationPicker.ts b/front/src/modules/ui/input/components/internal/relation-picker/hooks/useRelationPicker.ts
new file mode 100644
index 000000000..6308f61f4
--- /dev/null
+++ b/front/src/modules/ui/input/components/internal/relation-picker/hooks/useRelationPicker.ts
@@ -0,0 +1,35 @@
+import { useRecoilState } from 'recoil';
+
+import { useRelationPickerScopedStates } from '@/ui/input/components/internal/relation-picker/hooks/internal/useRelationPickerScopedStates';
+import { RelationPickerScopeInternalContext } from '@/ui/input/components/internal/relation-picker/scopes/scope-internal-context/RelationPickerScopeInternalContext';
+import { useAvailableScopeIdOrThrow } from '@/ui/utilities/recoil-scope/scopes-internal/hooks/useAvailableScopeId';
+
+type useRelationPickeProps = {
+ relationPickerScopeId?: string;
+};
+
+export const useRelationPicker = (props?: useRelationPickeProps) => {
+ const scopeId = useAvailableScopeIdOrThrow(
+ RelationPickerScopeInternalContext,
+ props?.relationPickerScopeId,
+ );
+
+ const { identifiersMapperState, searchQueryState } =
+ useRelationPickerScopedStates({
+ relationPickerScopedId: scopeId,
+ });
+
+ const [identifiersMapper, setIdentifiersMapper] = useRecoilState(
+ identifiersMapperState,
+ );
+
+ const [searchQuery, setSearchQuery] = useRecoilState(searchQueryState);
+
+ return {
+ scopeId,
+ identifiersMapper,
+ setIdentifiersMapper,
+ searchQuery,
+ setSearchQuery,
+ };
+};
diff --git a/front/src/modules/ui/input/components/internal/relation-picker/scopes/RelationPickerScope.tsx b/front/src/modules/ui/input/components/internal/relation-picker/scopes/RelationPickerScope.tsx
new file mode 100644
index 000000000..6a3e4b7ca
--- /dev/null
+++ b/front/src/modules/ui/input/components/internal/relation-picker/scopes/RelationPickerScope.tsx
@@ -0,0 +1,21 @@
+import { ReactNode } from 'react';
+
+import { RelationPickerScopeInternalContext } from '@/ui/input/components/internal/relation-picker/scopes/scope-internal-context/RelationPickerScopeInternalContext';
+
+type RelationPickerScopeProps = {
+ children: ReactNode;
+ relationPickerScopeId: string;
+};
+
+export const RelationPickerScope = ({
+ children,
+ relationPickerScopeId,
+}: RelationPickerScopeProps) => {
+ return (
+
+ {children}
+
+ );
+};
diff --git a/front/src/modules/ui/input/components/internal/relation-picker/scopes/scope-internal-context/RelationPickerScopeInternalContext.ts b/front/src/modules/ui/input/components/internal/relation-picker/scopes/scope-internal-context/RelationPickerScopeInternalContext.ts
new file mode 100644
index 000000000..6458f6065
--- /dev/null
+++ b/front/src/modules/ui/input/components/internal/relation-picker/scopes/scope-internal-context/RelationPickerScopeInternalContext.ts
@@ -0,0 +1,7 @@
+import { ScopedStateKey } from '@/ui/utilities/recoil-scope/scopes-internal/types/ScopedStateKey';
+import { createScopeInternalContext } from '@/ui/utilities/recoil-scope/scopes-internal/utils/createScopeInternalContext';
+
+type RelationPickerScopeInternalContextProps = ScopedStateKey;
+
+export const RelationPickerScopeInternalContext =
+ createScopeInternalContext();
diff --git a/front/src/modules/ui/input/components/internal/relation-picker/states/identifiersMapperScopedState.ts b/front/src/modules/ui/input/components/internal/relation-picker/states/identifiersMapperScopedState.ts
new file mode 100644
index 000000000..c01353ff7
--- /dev/null
+++ b/front/src/modules/ui/input/components/internal/relation-picker/states/identifiersMapperScopedState.ts
@@ -0,0 +1,8 @@
+import { IdentifiersMapper } from '@/ui/input/components/internal/relation-picker/types/IdentifiersMapper';
+import { createScopedState } from '@/ui/utilities/recoil-scope/utils/createScopedState';
+
+export const identifiersMapperScopedState =
+ createScopedState({
+ key: 'identifiersMapperScopedState',
+ defaultValue: null,
+ });
diff --git a/front/src/modules/ui/input/components/internal/relation-picker/states/searchQueryScopedState.ts b/front/src/modules/ui/input/components/internal/relation-picker/states/searchQueryScopedState.ts
new file mode 100644
index 000000000..54982f92d
--- /dev/null
+++ b/front/src/modules/ui/input/components/internal/relation-picker/states/searchQueryScopedState.ts
@@ -0,0 +1,7 @@
+import { SearchQuery } from '@/ui/input/components/internal/relation-picker/types/SearchQuery';
+import { createScopedState } from '@/ui/utilities/recoil-scope/utils/createScopedState';
+
+export const searchQueryScopedState = createScopedState({
+ key: 'searchQueryScopedState',
+ defaultValue: null,
+});
diff --git a/front/src/modules/ui/input/components/internal/relation-picker/types/IdentifiersMapper.tsx b/front/src/modules/ui/input/components/internal/relation-picker/types/IdentifiersMapper.tsx
new file mode 100644
index 000000000..3a477df0e
--- /dev/null
+++ b/front/src/modules/ui/input/components/internal/relation-picker/types/IdentifiersMapper.tsx
@@ -0,0 +1,14 @@
+import { AvatarType } from '@/users/components/Avatar';
+
+type RecordMappedToIdentifiers = {
+ id: string;
+ name: string;
+ avatarUrl?: string;
+ avatarType: AvatarType;
+ record: any;
+};
+
+export type IdentifiersMapper = (
+ record: any,
+ relationPickerType: string,
+) => RecordMappedToIdentifiers | undefined;
diff --git a/front/src/modules/ui/input/components/internal/relation-picker/types/SearchQuery.tsx b/front/src/modules/ui/input/components/internal/relation-picker/types/SearchQuery.tsx
new file mode 100644
index 000000000..e34cb9f56
--- /dev/null
+++ b/front/src/modules/ui/input/components/internal/relation-picker/types/SearchQuery.tsx
@@ -0,0 +1,3 @@
+export type SearchQuery = {
+ filterFields: (relationPickerType: string) => string[];
+};
diff --git a/front/src/modules/ui/input/components/internal/relation-picker/utils/getRelationPickerScopedStates.ts b/front/src/modules/ui/input/components/internal/relation-picker/utils/getRelationPickerScopedStates.ts
new file mode 100644
index 000000000..228f4c2a6
--- /dev/null
+++ b/front/src/modules/ui/input/components/internal/relation-picker/utils/getRelationPickerScopedStates.ts
@@ -0,0 +1,24 @@
+import { identifiersMapperScopedState } from '@/ui/input/components/internal/relation-picker/states/identifiersMapperScopedState';
+import { searchQueryScopedState } from '@/ui/input/components/internal/relation-picker/states/searchQueryScopedState';
+import { getScopedState } from '@/ui/utilities/recoil-scope/utils/getScopedState';
+
+export const getRelationPickerScopedStates = ({
+ relationPickerScopeId,
+}: {
+ relationPickerScopeId: string;
+}) => {
+ const identifiersMapperState = getScopedState(
+ identifiersMapperScopedState,
+ relationPickerScopeId,
+ );
+
+ const searchQueryState = getScopedState(
+ searchQueryScopedState,
+ relationPickerScopeId,
+ );
+
+ return {
+ identifiersMapperState,
+ searchQueryState,
+ };
+};
diff --git a/front/src/modules/ui/layout/dropdown/scopes/scope-internal-context/DropdownScopeInternalContext.ts b/front/src/modules/ui/layout/dropdown/scopes/scope-internal-context/DropdownScopeInternalContext.ts
index 7dbd1ce36..de5e7d3f1 100644
--- a/front/src/modules/ui/layout/dropdown/scopes/scope-internal-context/DropdownScopeInternalContext.ts
+++ b/front/src/modules/ui/layout/dropdown/scopes/scope-internal-context/DropdownScopeInternalContext.ts
@@ -1,9 +1,7 @@
import { ScopedStateKey } from '@/ui/utilities/recoil-scope/scopes-internal/types/ScopedStateKey';
import { createScopeInternalContext } from '@/ui/utilities/recoil-scope/scopes-internal/utils/createScopeInternalContext';
-type DropdownScopeInternalContextProps = ScopedStateKey & {
- test?: string;
-};
+type DropdownScopeInternalContextProps = ScopedStateKey;
export const DropdownScopeInternalContext =
createScopeInternalContext();
diff --git a/front/src/modules/ui/object/field/meta-types/display/components/RelationFieldDisplay.tsx b/front/src/modules/ui/object/field/meta-types/display/components/RelationFieldDisplay.tsx
index 414f52e10..5d52a0a28 100644
--- a/front/src/modules/ui/object/field/meta-types/display/components/RelationFieldDisplay.tsx
+++ b/front/src/modules/ui/object/field/meta-types/display/components/RelationFieldDisplay.tsx
@@ -5,20 +5,23 @@ import { useRelationField } from '../../hooks/useRelationField';
export const RelationFieldDisplay = () => {
const { fieldValue, fieldDefinition } = useRelationField();
- const { mapToObjectIdentifiers } = useRelationField();
+ const { identifiersMapper } = useRelationField();
- if (!fieldValue || !fieldDefinition) {
+ if (!fieldValue || !fieldDefinition || !identifiersMapper) {
return <>>;
}
- const objectIdentifiers = mapToObjectIdentifiers(fieldValue);
+ const objectIdentifiers = identifiersMapper(
+ fieldValue,
+ fieldDefinition.metadata.objectMetadataNameSingular,
+ );
return (
);
};
diff --git a/front/src/modules/ui/object/field/meta-types/hooks/useRelationField.ts b/front/src/modules/ui/object/field/meta-types/hooks/useRelationField.ts
index 6eeaef7b4..47541b1b4 100644
--- a/front/src/modules/ui/object/field/meta-types/hooks/useRelationField.ts
+++ b/front/src/modules/ui/object/field/meta-types/hooks/useRelationField.ts
@@ -1,6 +1,8 @@
import { useContext } from 'react';
import { useRecoilState } from 'recoil';
+import { useRelationPicker } from '@/ui/input/components/internal/relation-picker/hooks/useRelationPicker';
+
import { FieldContext } from '../../contexts/FieldContext';
import { useFieldInitialValue } from '../../hooks/useFieldInitialValue';
import { entityFieldsFamilySelector } from '../../states/selectors/entityFieldsFamilySelector';
@@ -30,35 +32,7 @@ export const useRelationField = () => {
const initialValue = fieldInitialValue?.isEmpty ? null : fieldValue;
- const mapToObjectIdentifiers = (record: any) => {
- let name = '';
- for (const fieldPath of fieldDefinition.metadata
- .labelIdentifierFieldPaths) {
- const fieldPathParts = fieldPath.split('.');
-
- if (fieldPathParts.length === 1) {
- name += record[fieldPathParts[0]];
- } else if (fieldPathParts.length === 2) {
- name += record[fieldPathParts[0]][fieldPathParts[1]] + ' ';
- } else {
- throw new Error(
- `Invalid field path ${fieldPath}. Relation picker only supports field paths with 1 or 2 parts.`,
- );
- }
- }
-
- const avatarUrl = record[fieldDefinition.metadata.imageIdentifierUrlField];
- return {
- id: record.id,
- name: name.trimEnd(),
- avatarUrl: avatarUrl
- ? fieldDefinition.metadata.imageIdentifierUrlPrefix +
- record[fieldDefinition.metadata.imageIdentifierUrlField]
- : '',
- avatarType: fieldDefinition.metadata.imageIdentifierFormat,
- record: record,
- };
- };
+ const { identifiersMapper, searchQuery } = useRelationPicker();
return {
fieldDefinition,
@@ -66,6 +40,7 @@ export const useRelationField = () => {
initialValue,
initialSearchValue,
setFieldValue,
- mapToObjectIdentifiers,
+ searchQuery,
+ identifiersMapper,
};
};
diff --git a/front/src/modules/ui/object/field/meta-types/input/components/RelationFieldInput.tsx b/front/src/modules/ui/object/field/meta-types/input/components/RelationFieldInput.tsx
index afca7f2c3..76f43c537 100644
--- a/front/src/modules/ui/object/field/meta-types/input/components/RelationFieldInput.tsx
+++ b/front/src/modules/ui/object/field/meta-types/input/components/RelationFieldInput.tsx
@@ -1,8 +1,8 @@
import { useEffect } from 'react';
import styled from '@emotion/styled';
+import { RelationPicker } from '@/ui/input/components/internal/relation-picker/RelationPicker';
import { EntityForSelect } from '@/ui/input/relation-picker/types/EntityForSelect';
-import { RelationPicker } from '@/ui/object/field/meta-types/input/components/internal/RelationPicker';
import { usePersistField } from '../../../hooks/usePersistField';
import { useRelationField } from '../../hooks/useRelationField';
diff --git a/front/src/modules/ui/object/field/types/FieldMetadata.ts b/front/src/modules/ui/object/field/types/FieldMetadata.ts
index 24559560c..fef641964 100644
--- a/front/src/modules/ui/object/field/types/FieldMetadata.ts
+++ b/front/src/modules/ui/object/field/types/FieldMetadata.ts
@@ -64,11 +64,6 @@ export type FieldRelationMetadata = {
fieldName: string;
useEditButton?: boolean;
relationType?: FieldDefinitionRelationType;
- labelIdentifierFieldPaths: string[];
- imageIdentifierUrlField: string;
- imageIdentifierUrlPrefix: string;
- imageIdentifierFormat: 'squared' | 'rounded';
- searchFields: string[];
objectMetadataNameSingular: string;
objectMetadataNamePlural: string;
};
diff --git a/front/src/modules/ui/object/record-table/components/RecordTableCell.tsx b/front/src/modules/ui/object/record-table/components/RecordTableCell.tsx
index 1181f2870..87ae6aff3 100644
--- a/front/src/modules/ui/object/record-table/components/RecordTableCell.tsx
+++ b/front/src/modules/ui/object/record-table/components/RecordTableCell.tsx
@@ -62,7 +62,7 @@ export const RecordTableCell = ({ cellIndex }: { cellIndex: number }) => {
hotkeyScope: customHotkeyScope,
isMainIdentifier:
columnDefinition.fieldMetadataId ===
- objectMetadataConfig?.mainIdentifierFieldMetadataId,
+ objectMetadataConfig?.labelIdentifierFieldMetadataId,
}}
>
diff --git a/front/src/modules/ui/object/record-table/types/ObjectMetadataConfig.ts b/front/src/modules/ui/object/record-table/types/ObjectMetadataConfig.ts
index d12811ae7..97efb00b5 100644
--- a/front/src/modules/ui/object/record-table/types/ObjectMetadataConfig.ts
+++ b/front/src/modules/ui/object/record-table/types/ObjectMetadataConfig.ts
@@ -1,10 +1,4 @@
-import { AvatarType } from '@/users/components/Avatar';
-
export type ObjectMetadataConfig = {
- mainIdentifierFieldMetadataId: string;
- labelIdentifierFieldPaths: string[];
- imageIdentifierUrlField: string;
- imageIdentifierUrlPrefix: string;
- imageIdentifierFormat: AvatarType;
+ labelIdentifierFieldMetadataId: string;
basePathToShowPage: string;
};