diff --git a/packages/twenty-front/src/modules/activities/utils/__tests__/flatMapAndSortEntityForSelectArrayOfArrayByName.test.ts b/packages/twenty-front/src/modules/activities/utils/__tests__/flatMapAndSortEntityForSelectArrayOfArrayByName.test.ts deleted file mode 100644 index 190601334..000000000 --- a/packages/twenty-front/src/modules/activities/utils/__tests__/flatMapAndSortEntityForSelectArrayOfArrayByName.test.ts +++ /dev/null @@ -1,27 +0,0 @@ -import { EntityForSelect } from '@/object-record/relation-picker/types/EntityForSelect'; - -import { flatMapAndSortEntityForSelectArrayOfArrayByName } from '../flatMapAndSortEntityForSelectArrayByName'; - -describe('flatMapAndSortEntityForSelectArrayOfArrayByName', () => { - it('should return the correct value', () => { - const entityForSelectArray = [ - [ - { id: 1, name: 'xRya' }, - { id: 2, name: 'BrcA' }, - ], - [ - { id: 3, name: 'aCxd' }, - { id: 4, name: 'kp7u' }, - ], - ] as unknown as EntityForSelect[][]; - - const res = - flatMapAndSortEntityForSelectArrayOfArrayByName(entityForSelectArray); - - expect(res).toHaveLength(4); - expect(res[0].id).toBe(3); - expect(res[1].id).toBe(2); - expect(res[2].id).toBe(4); - expect(res[3].id).toBe(1); - }); -}); diff --git a/packages/twenty-front/src/modules/activities/utils/flatMapAndSortEntityForSelectArrayByName.ts b/packages/twenty-front/src/modules/activities/utils/flatMapAndSortEntityForSelectArrayByName.ts deleted file mode 100644 index bd6f5c48a..000000000 --- a/packages/twenty-front/src/modules/activities/utils/flatMapAndSortEntityForSelectArrayByName.ts +++ /dev/null @@ -1,11 +0,0 @@ -import { EntityForSelect } from '@/object-record/relation-picker/types/EntityForSelect'; - -export const flatMapAndSortEntityForSelectArrayOfArrayByName = < - T extends EntityForSelect, ->( - entityForSelectArray: T[][], -) => { - const sortByName = (a: T, b: T) => a.name.localeCompare(b.name); - - return entityForSelectArray.flatMap((entity) => entity).sort(sortByName); -}; diff --git a/packages/twenty-front/src/modules/companies/components/AddPersonToCompany.tsx b/packages/twenty-front/src/modules/companies/components/AddPersonToCompany.tsx deleted file mode 100644 index 2a7adb4f4..000000000 --- a/packages/twenty-front/src/modules/companies/components/AddPersonToCompany.tsx +++ /dev/null @@ -1,99 +0,0 @@ -import styled from '@emotion/styled'; -import { v4 } from 'uuid'; - -import { FieldDoubleText } from '@/object-record/field/types/FieldDoubleText'; -import { useCreateOneRecord } from '@/object-record/hooks/useCreateOneRecord'; -import { EntityForSelect } from '@/object-record/relation-picker/types/EntityForSelect'; -import { RelationPickerHotkeyScope } from '@/object-record/relation-picker/types/RelationPickerHotkeyScope'; -import { Person } from '@/people/types/Person'; -import { DoubleTextInput } from '@/ui/field/input/components/DoubleTextInput'; -import { usePreviousHotkeyScope } from '@/ui/utilities/hotkey/hooks/usePreviousHotkeyScope'; - -export const StyledInputContainer = styled.div` - background-color: transparent; - box-shadow: ${({ theme }) => theme.boxShadow.strong}; - display: flex; - gap: ${({ theme }) => theme.spacing(0.5)}; - width: ${({ theme }) => theme.spacing(62.5)}; - & input, - div { - background-color: ${({ theme }) => theme.background.primary}; - width: 100%; - } - div { - border-radius: ${({ theme }) => theme.spacing(1)}; - overflow: hidden; - } - input { - display: flex; - flex-grow: 1; - padding: ${({ theme }) => theme.spacing(2)}; - } -`; - -type AddPersonToCompanyProps = { - companyId: string; - onEntitySelected: (entity?: EntityForSelect | undefined) => void; - closeDropdown?: () => void; -}; - -export const AddPersonToCompany = ({ - companyId, - onEntitySelected, - closeDropdown, -}: AddPersonToCompanyProps) => { - const { goBackToPreviousHotkeyScope } = usePreviousHotkeyScope(); - - const handleEscape = () => { - goBackToPreviousHotkeyScope(); - closeDropdown?.(); - }; - - const { createOneRecord: createPerson } = useCreateOneRecord({ - objectNameSingular: 'person', - }); - - const handleCreatePerson = async ({ - firstValue, - secondValue, - }: FieldDoubleText) => { - if (!firstValue && !secondValue) return; - - const person = await createPerson({ - companyId, - id: v4(), - name: { - firstName: firstValue, - lastName: secondValue, - }, - }); - - if (person) { - const entityForSelect: EntityForSelect = { - id: person.id, - name: person.name?.firstName ?? '', - avatarUrl: person.avatarUrl ?? '', - avatarType: 'rounded', - record: person, - }; - onEntitySelected(entityForSelect); - } - goBackToPreviousHotkeyScope(); - closeDropdown?.(); - }; - - return ( - - - - ); -}; diff --git a/packages/twenty-front/src/modules/companies/components/NewOpportunityButton.tsx b/packages/twenty-front/src/modules/companies/components/NewOpportunityButton.tsx index 8a9596e91..184bd95ba 100644 --- a/packages/twenty-front/src/modules/companies/components/NewOpportunityButton.tsx +++ b/packages/twenty-front/src/modules/companies/components/NewOpportunityButton.tsx @@ -52,8 +52,7 @@ export const NewOpportunityButton = () => { setIsCreatingCard(false); }; - const { relationPickerSearchFilter, identifiersMapper, searchQuery } = - useRelationPicker(); + const { relationPickerSearchFilter, searchQuery } = useRelationPicker(); const filteredSearchEntityResults = useFilteredSearchEntityQuery({ filters: [ @@ -64,7 +63,6 @@ export const NewOpportunityButton = () => { ], orderByField: 'createdAt', selectedIds: [], - mappingFunction: (record: any) => identifiersMapper?.(record, 'company'), objectNameSingular: CoreObjectNameSingular.Company, }); diff --git a/packages/twenty-front/src/modules/companies/components/OpportunityPicker.tsx b/packages/twenty-front/src/modules/companies/components/OpportunityPicker.tsx index 2d121f643..986ce9d1e 100644 --- a/packages/twenty-front/src/modules/companies/components/OpportunityPicker.tsx +++ b/packages/twenty-front/src/modules/companies/components/OpportunityPicker.tsx @@ -20,7 +20,7 @@ import { RecoilScope } from '@/ui/utilities/recoil-scope/components/RecoilScope' export type OpportunityPickerProps = { companyId: string | null; onSubmit: ( - newCompanyId: EntityForSelect | null, + newCompany: EntityForSelect | null, newPipelineStepId: string | null, ) => void; onCancel?: () => void; @@ -34,7 +34,7 @@ export const OpportunityPicker = ({ const { searchFilter, handleSearchFilterChange } = useEntitySelectSearch(); - const { identifiersMapper, searchQuery } = useRelationPicker(); + const { searchQuery } = useRelationPicker(); const filteredSearchEntityResults = useFilteredSearchEntityQuery({ filters: [ @@ -45,7 +45,6 @@ export const OpportunityPicker = ({ ], orderByField: 'createdAt', selectedIds: [], - mappingFunction: (record: any) => identifiersMapper?.(record, 'company'), objectNameSingular: CoreObjectNameSingular.Company, }); diff --git a/packages/twenty-front/src/modules/object-metadata/components/ObjectMetadataItemsRelationPickerEffect.tsx b/packages/twenty-front/src/modules/object-metadata/components/ObjectMetadataItemsRelationPickerEffect.tsx index ba6b68dfe..eda6ca89d 100644 --- a/packages/twenty-front/src/modules/object-metadata/components/ObjectMetadataItemsRelationPickerEffect.tsx +++ b/packages/twenty-front/src/modules/object-metadata/components/ObjectMetadataItemsRelationPickerEffect.tsx @@ -1,11 +1,9 @@ import { useEffect } from 'react'; import { useRelationPicker } from '@/object-record/relation-picker/hooks/useRelationPicker'; -import { IdentifiersMapper } from '@/object-record/relation-picker/types/IdentifiersMapper'; -import { getLogoUrlFromDomainName } from '~/utils'; export const ObjectMetadataItemsRelationPickerEffect = () => { - const { setIdentifiersMapper, setSearchQuery } = useRelationPicker({ + const { setSearchQuery } = useRelationPicker({ relationPickerScopeId: 'relation-picker', }); @@ -21,62 +19,9 @@ export const ObjectMetadataItemsRelationPickerEffect = () => { return ['name']; }; - const identifierMapper: IdentifiersMapper = ( - record: any, - objectMetadataItemSingularName: string, - ) => { - if (!record) { - return; - } - - if (objectMetadataItemSingularName === 'company') { - return { - id: record.id, - name: record.name, - avatarUrl: getLogoUrlFromDomainName(record.domainName ?? ''), - avatarType: 'squared', - record: record, - }; - } - - if ( - ['workspaceMember', 'person'].includes(objectMetadataItemSingularName) - ) { - return { - id: record.id, - name: - (record.name?.firstName ?? '') + ' ' + (record.name?.lastName ?? ''), - avatarUrl: record.avatarUrl, - avatarType: 'rounded', - record: record, - }; - } - - if (['opportunity'].includes(objectMetadataItemSingularName)) { - return { - id: record.id, - name: record?.company?.name ?? record.name, - avatarUrl: record.avatarUrl, - avatarType: 'rounded', - record: record, - }; - } - - return { - id: record.id, - name: record.name, - avatarUrl: record.avatarUrl, - avatarType: 'rounded', - record, - }; - }; - useEffect(() => { - setIdentifiersMapper(() => identifierMapper); - setSearchQuery({ - computeFilterFields, - }); - }, [setIdentifiersMapper, setSearchQuery]); + setSearchQuery({ computeFilterFields }); + }, [setSearchQuery]); return <>; }; diff --git a/packages/twenty-front/src/modules/object-metadata/hooks/useMapToObjectRecordIdentifier.ts b/packages/twenty-front/src/modules/object-metadata/hooks/useMapToObjectRecordIdentifier.ts index 53fcaec74..f25b74293 100644 --- a/packages/twenty-front/src/modules/object-metadata/hooks/useMapToObjectRecordIdentifier.ts +++ b/packages/twenty-front/src/modules/object-metadata/hooks/useMapToObjectRecordIdentifier.ts @@ -1,16 +1,8 @@ import { ObjectMetadataItem } from '@/object-metadata/types/ObjectMetadataItem'; import { getObjectRecordIdentifier } from '@/object-metadata/utils/getObjectRecordIdentifier'; import { ObjectRecord } from '@/object-record/types/ObjectRecord'; -import { ObjectRecordIdentifier } from '@/object-record/types/ObjectRecordIdentifier'; -export const useMapToObjectRecordIdentifier = ({ - objectMetadataItem, -}: { - objectMetadataItem: ObjectMetadataItem; -}): ((record: ObjectRecord) => ObjectRecordIdentifier) => { - return (record: ObjectRecord) => - getObjectRecordIdentifier({ - objectMetadataItem, - record, - }); -}; +export const useMapToObjectRecordIdentifier = + ({ objectMetadataItem }: { objectMetadataItem: ObjectMetadataItem }) => + (record: ObjectRecord) => + getObjectRecordIdentifier({ objectMetadataItem, record }); diff --git a/packages/twenty-front/src/modules/object-metadata/utils/getObjectRecordIdentifier.ts b/packages/twenty-front/src/modules/object-metadata/utils/getObjectRecordIdentifier.ts index 4d2fabc15..aed686c6e 100644 --- a/packages/twenty-front/src/modules/object-metadata/utils/getObjectRecordIdentifier.ts +++ b/packages/twenty-front/src/modules/object-metadata/utils/getObjectRecordIdentifier.ts @@ -14,34 +14,25 @@ export const getObjectRecordIdentifier = ({ objectMetadataItem: ObjectMetadataItem; record: ObjectRecord; }): ObjectRecordIdentifier => { - switch (objectMetadataItem.nameSingular) { - case CoreObjectNameSingular.Opportunity: - return { - id: record.id, - name: record?.company?.name ?? record.name, - avatarUrl: record.avatarUrl, - avatarType: 'rounded', - linkToShowPage: `/opportunities/${record.id}`, - }; + if (objectMetadataItem.nameSingular === CoreObjectNameSingular.Opportunity) { + return { + id: record.id, + name: record?.company?.name ?? record.name, + avatarUrl: record.avatarUrl, + avatarType: 'rounded', + linkToShowPage: `/opportunities/${record.id}`, + }; } const labelIdentifierFieldMetadataItem = getLabelIdentifierFieldMetadataItem(objectMetadataItem); - let labelIdentifierFieldValue = ''; - - switch (labelIdentifierFieldMetadataItem?.type) { - case FieldMetadataType.FullName: { - labelIdentifierFieldValue = `${record.name?.firstName ?? ''} ${ - record.name?.lastName ?? '' - }`; - break; - } - default: - labelIdentifierFieldValue = labelIdentifierFieldMetadataItem - ? record[labelIdentifierFieldMetadataItem.name] + const labelIdentifierFieldValue = + labelIdentifierFieldMetadataItem?.type === FieldMetadataType.FullName + ? `${record.name?.firstName ?? ''} ${record.name?.lastName ?? ''}` + : labelIdentifierFieldMetadataItem?.name + ? (record[labelIdentifierFieldMetadataItem.name] as string | number) : ''; - } const imageIdentifierFieldMetadata = objectMetadataItem.fields.find( (field) => field.id === objectMetadataItem.imageIdentifierFieldMetadataId, @@ -57,9 +48,9 @@ export const getObjectRecordIdentifier = ({ : 'rounded'; const avatarUrl = - objectMetadataItem.nameSingular === CoreObjectNameSingular.Company + (objectMetadataItem.nameSingular === CoreObjectNameSingular.Company ? getLogoUrlFromDomainName(record['domainName'] ?? '') - : imageIdentifierFieldValue ?? null; + : imageIdentifierFieldValue) ?? ''; const basePathToShowPage = getBasePathToShowPage({ objectMetadataItem, @@ -69,7 +60,7 @@ export const getObjectRecordIdentifier = ({ return { id: record.id, - name: labelIdentifierFieldValue, + name: `${labelIdentifierFieldValue}`, avatarUrl, avatarType, linkToShowPage, diff --git a/packages/twenty-front/src/modules/object-record/components/RecordChip.tsx b/packages/twenty-front/src/modules/object-record/components/RecordChip.tsx index aaad350f7..a03f1feee 100644 --- a/packages/twenty-front/src/modules/object-record/components/RecordChip.tsx +++ b/packages/twenty-front/src/modules/object-record/components/RecordChip.tsx @@ -21,7 +21,7 @@ export const RecordChip = ({ objectNameSingular, record }: RecordChipProps) => { entityId={record.id} name={objectRecordIdentifier.name} avatarType={objectRecordIdentifier.avatarType} - avatarUrl={objectRecordIdentifier.avatarUrl ?? undefined} + avatarUrl={objectRecordIdentifier.avatarUrl} linkToEntity={objectRecordIdentifier.linkToShowPage} /> ); diff --git a/packages/twenty-front/src/modules/object-record/field/components/FieldDisplay.tsx b/packages/twenty-front/src/modules/object-record/field/components/FieldDisplay.tsx index 96461bb95..93efc4001 100644 --- a/packages/twenty-front/src/modules/object-record/field/components/FieldDisplay.tsx +++ b/packages/twenty-front/src/modules/object-record/field/components/FieldDisplay.tsx @@ -27,39 +27,33 @@ import { isFieldUuid } from '../types/guards/isFieldUuid'; export const FieldDisplay = () => { const { fieldDefinition, isLabelIdentifier } = useContext(FieldContext); - if ( - isLabelIdentifier && - (isFieldText(fieldDefinition) || isFieldFullName(fieldDefinition)) - ) { - return ; - } - return ( - <> - {isFieldRelation(fieldDefinition) ? ( - - ) : isFieldText(fieldDefinition) ? ( - - ) : isFieldUuid(fieldDefinition) ? ( - - ) : isFieldEmail(fieldDefinition) ? ( - - ) : isFieldDateTime(fieldDefinition) ? ( - - ) : isFieldNumber(fieldDefinition) ? ( - - ) : isFieldLink(fieldDefinition) ? ( - - ) : isFieldCurrency(fieldDefinition) ? ( - - ) : isFieldFullName(fieldDefinition) ? ( - - ) : isFieldPhone(fieldDefinition) ? ( - - ) : isFieldSelect(fieldDefinition) ? ( - - ) : ( - <> - )} - - ); + + return isLabelIdentifier && + (isFieldText(fieldDefinition) || + isFieldFullName(fieldDefinition) || + isFieldNumber(fieldDefinition)) ? ( + + ) : isFieldRelation(fieldDefinition) ? ( + + ) : isFieldText(fieldDefinition) ? ( + + ) : isFieldUuid(fieldDefinition) ? ( + + ) : isFieldEmail(fieldDefinition) ? ( + + ) : isFieldDateTime(fieldDefinition) ? ( + + ) : isFieldNumber(fieldDefinition) ? ( + + ) : isFieldLink(fieldDefinition) ? ( + + ) : isFieldCurrency(fieldDefinition) ? ( + + ) : isFieldFullName(fieldDefinition) ? ( + + ) : isFieldPhone(fieldDefinition) ? ( + + ) : isFieldSelect(fieldDefinition) ? ( + + ) : null; }; diff --git a/packages/twenty-front/src/modules/object-record/field/meta-types/display/components/ChipFieldDisplay.tsx b/packages/twenty-front/src/modules/object-record/field/meta-types/display/components/ChipFieldDisplay.tsx index 8e89cff5b..1fbc34038 100644 --- a/packages/twenty-front/src/modules/object-record/field/meta-types/display/components/ChipFieldDisplay.tsx +++ b/packages/twenty-front/src/modules/object-record/field/meta-types/display/components/ChipFieldDisplay.tsx @@ -1,25 +1,12 @@ +import { RecordChip } from '@/object-record/components/RecordChip'; import { useChipField } from '@/object-record/field/meta-types/hooks/useChipField'; -import { EntityChip } from '@/ui/display/chip/components/EntityChip'; export const ChipFieldDisplay = () => { - const { - record, - entityId, - identifiersMapper, - objectNameSingular, - basePathToShowPage, - } = useChipField(); + const { objectNameSingular, record } = useChipField(); - // TODO: remove this and use ObjectRecordChip instead - const identifiers = identifiersMapper?.(record, objectNameSingular ?? ''); + if (!record) return null; return ( - + ); }; diff --git a/packages/twenty-front/src/modules/object-record/field/meta-types/display/components/RelationFieldDisplay.tsx b/packages/twenty-front/src/modules/object-record/field/meta-types/display/components/RelationFieldDisplay.tsx index 3db283f15..80c000d12 100644 --- a/packages/twenty-front/src/modules/object-record/field/meta-types/display/components/RelationFieldDisplay.tsx +++ b/packages/twenty-front/src/modules/object-record/field/meta-types/display/components/RelationFieldDisplay.tsx @@ -1,30 +1,18 @@ -import { useRelationPicker } from '@/object-record/relation-picker/hooks/useRelationPicker'; -import { EntityChip } from '@/ui/display/chip/components/EntityChip'; +import { RecordChip } from '@/object-record/components/RecordChip'; import { useRelationField } from '../../hooks/useRelationField'; export const RelationFieldDisplay = () => { const { fieldValue, fieldDefinition } = useRelationField(); - const { identifiersMapper } = useRelationPicker({ - relationPickerScopeId: 'relation-picker', - }); - - if (!fieldValue || !fieldDefinition || !identifiersMapper) { - return <>; - } - - const objectIdentifiers = identifiersMapper( - fieldValue, - fieldDefinition.metadata.relationObjectMetadataNameSingular, - ); + if (!fieldValue || !fieldDefinition) return null; return ( - ); }; diff --git a/packages/twenty-front/src/modules/object-record/field/meta-types/hooks/useChipField.ts b/packages/twenty-front/src/modules/object-record/field/meta-types/hooks/useChipField.ts index f5da173ee..3a9ecc402 100644 --- a/packages/twenty-front/src/modules/object-record/field/meta-types/hooks/useChipField.ts +++ b/packages/twenty-front/src/modules/object-record/field/meta-types/hooks/useChipField.ts @@ -3,31 +3,25 @@ import { useRecoilValue } from 'recoil'; import { entityFieldsFamilyState } from '@/object-record/field/states/entityFieldsFamilyState'; import { isFieldFullName } from '@/object-record/field/types/guards/isFieldFullName'; +import { isFieldNumber } from '@/object-record/field/types/guards/isFieldNumber'; import { isFieldText } from '@/object-record/field/types/guards/isFieldText'; -import { useRelationPicker } from '@/object-record/relation-picker/hooks/useRelationPicker'; import { FieldContext } from '../../contexts/FieldContext'; export const useChipField = () => { - const { entityId, fieldDefinition, basePathToShowPage } = - useContext(FieldContext); + const { entityId, fieldDefinition } = useContext(FieldContext); const objectNameSingular = - isFieldText(fieldDefinition) || isFieldFullName(fieldDefinition) + isFieldText(fieldDefinition) || + isFieldFullName(fieldDefinition) || + isFieldNumber(fieldDefinition) ? fieldDefinition.metadata.objectMetadataNameSingular : undefined; - const record = useRecoilValue(entityFieldsFamilyState(entityId)); - - const { identifiersMapper } = useRelationPicker({ - relationPickerScopeId: 'relation-picker', - }); + const record = useRecoilValue(entityFieldsFamilyState(entityId)); return { - basePathToShowPage, - entityId, objectNameSingular, record, - identifiersMapper, }; }; diff --git a/packages/twenty-front/src/modules/object-record/field/meta-types/input/components/__stories__/BooleanFieldInput.stories.tsx b/packages/twenty-front/src/modules/object-record/field/meta-types/input/components/__stories__/BooleanFieldInput.stories.tsx index 55aea0168..18120f187 100644 --- a/packages/twenty-front/src/modules/object-record/field/meta-types/input/components/__stories__/BooleanFieldInput.stories.tsx +++ b/packages/twenty-front/src/modules/object-record/field/meta-types/input/components/__stories__/BooleanFieldInput.stories.tsx @@ -1,20 +1,28 @@ import { useEffect } from 'react'; import { Meta, StoryObj } from '@storybook/react'; import { expect, fn, userEvent, within } from '@storybook/test'; +import { useSetRecoilState } from 'recoil'; + +import { entityFieldsFamilyState } from '@/object-record/field/states/entityFieldsFamilyState'; import { FieldContextProvider } from '../../../__stories__/FieldContextProvider'; -import { useBooleanField } from '../../../hooks/useBooleanField'; import { BooleanFieldInput, BooleanFieldInputProps, } from '../BooleanFieldInput'; -const BooleanFieldValueSetterEffect = ({ value }: { value: boolean }) => { - const { setFieldValue } = useBooleanField(); +const BooleanFieldValueSetterEffect = ({ + value, + entityId, +}: { + value: boolean; + entityId: string; +}) => { + const setField = useSetRecoilState(entityFieldsFamilyState(entityId)); useEffect(() => { - setFieldValue(value); - }, [setFieldValue, value]); + setField({ id: entityId, Boolean: value }); + }, [entityId, setField, value]); return <>; }; @@ -42,7 +50,7 @@ const BooleanFieldInputWithContext = ({ }} entityId={entityId} > - + ); @@ -53,6 +61,7 @@ const meta: Meta = { component: BooleanFieldInputWithContext, args: { value: true, + entityId: 'id-1', }, }; diff --git a/packages/twenty-front/src/modules/object-record/field/states/entityFieldsFamilyState.ts b/packages/twenty-front/src/modules/object-record/field/states/entityFieldsFamilyState.ts index 6ddec3775..c4dc4a6b8 100644 --- a/packages/twenty-front/src/modules/object-record/field/states/entityFieldsFamilyState.ts +++ b/packages/twenty-front/src/modules/object-record/field/states/entityFieldsFamilyState.ts @@ -1,9 +1,8 @@ import { atomFamily } from 'recoil'; -export const entityFieldsFamilyState = atomFamily< - Record | null, - string ->({ +import { ObjectRecord } from '@/object-record/types/ObjectRecord'; + +export const entityFieldsFamilyState = atomFamily({ key: 'entityFieldsFamilyState', default: null, }); diff --git a/packages/twenty-front/src/modules/object-record/field/states/selectors/entityFieldsFamilySelector.ts b/packages/twenty-front/src/modules/object-record/field/states/selectors/entityFieldsFamilySelector.ts index 89d29ea5c..03b2c3e8c 100644 --- a/packages/twenty-front/src/modules/object-record/field/states/selectors/entityFieldsFamilySelector.ts +++ b/packages/twenty-front/src/modules/object-record/field/states/selectors/entityFieldsFamilySelector.ts @@ -11,8 +11,7 @@ export const entityFieldsFamilySelector = selectorFamily({ set: ({ fieldName, entityId }: { fieldName: string; entityId: string }) => ({ set }, newValue: T) => - set(entityFieldsFamilyState(entityId), (prevState) => ({ - ...prevState, - [fieldName]: newValue, - })), + set(entityFieldsFamilyState(entityId), (prevState) => + prevState ? { ...prevState, [fieldName]: newValue } : null, + ), }); diff --git a/packages/twenty-front/src/modules/object-record/record-relation-card/components/RecordRelationFieldCardSection.tsx b/packages/twenty-front/src/modules/object-record/record-relation-card/components/RecordRelationFieldCardSection.tsx index 1c744da47..54633ecc4 100644 --- a/packages/twenty-front/src/modules/object-record/record-relation-card/components/RecordRelationFieldCardSection.tsx +++ b/packages/twenty-front/src/modules/object-record/record-relation-card/components/RecordRelationFieldCardSection.tsx @@ -125,7 +125,7 @@ export const RecordRelationFieldCardSection = () => { const { relationPickerSearchFilter, setRelationPickerSearchFilter } = useRelationPicker({ relationPickerScopeId: dropdownId }); - const { identifiersMapper, searchQuery } = useRelationPicker(); + const { searchQuery } = useRelationPicker(); const entities = useFilteredSearchEntityQuery({ filters: [ @@ -138,8 +138,6 @@ export const RecordRelationFieldCardSection = () => { }, ], orderByField: 'createdAt', - mappingFunction: (recordToMap) => - identifiersMapper?.(recordToMap, relationObjectMetadataNameSingular), selectedIds: relationRecordIds, excludeEntityIds: relationRecordIds, objectNameSingular: relationObjectMetadataNameSingular, diff --git a/packages/twenty-front/src/modules/object-record/record-table/components/RecordTable.tsx b/packages/twenty-front/src/modules/object-record/record-table/components/RecordTable.tsx index 6a8a3e53e..0ef044ed5 100644 --- a/packages/twenty-front/src/modules/object-record/record-table/components/RecordTable.tsx +++ b/packages/twenty-front/src/modules/object-record/record-table/components/RecordTable.tsx @@ -117,17 +117,13 @@ export const RecordTable = ({ recordTableScopeId={scopeId} onColumnsChange={onColumnsChange} > - <> - {objectNamePlural ? ( - - - - - - ) : ( - <> - )} - + {!!objectNamePlural && ( + + + + + + )} ); }; diff --git a/packages/twenty-front/src/modules/object-record/record-table/components/RecordTableCellContainer.tsx b/packages/twenty-front/src/modules/object-record/record-table/components/RecordTableCellContainer.tsx index 132a2c9ff..26d2a52e4 100644 --- a/packages/twenty-front/src/modules/object-record/record-table/components/RecordTableCellContainer.tsx +++ b/packages/twenty-front/src/modules/object-record/record-table/components/RecordTableCellContainer.tsx @@ -1,8 +1,8 @@ import { useContext } from 'react'; -import { useRecoilValue, useSetRecoilState } from 'recoil'; +import { useSetRecoilState } from 'recoil'; +import { useObjectMetadataItem } from '@/object-metadata/hooks/useObjectMetadataItem'; import { isLabelIdentifierField } from '@/object-metadata/utils/isLabelIdentifierField'; -import { useRecordTableStates } from '@/object-record/record-table/hooks/internal/useRecordTableStates'; import { RelationPickerHotkeyScope } from '@/object-record/relation-picker/types/RelationPickerHotkeyScope'; import { contextMenuIsOpenState } from '@/ui/navigation/context-menu/states/contextMenuIsOpenState'; import { contextMenuPositionState } from '@/ui/navigation/context-menu/states/contextMenuPositionState'; @@ -26,9 +26,6 @@ export const RecordTableCellContainer = ({ const setContextMenuPosition = useSetRecoilState(contextMenuPositionState); const setContextMenuOpenState = useSetRecoilState(contextMenuIsOpenState); const currentRowId = useContext(RowIdContext); - const { getObjectMetadataConfigState } = useRecordTableStates(); - - const objectMetadataConfig = useRecoilValue(getObjectMetadataConfigState()); const { setCurrentRowSelected } = useCurrentRowSelected(); @@ -44,6 +41,11 @@ export const RecordTableCellContainer = ({ const columnDefinition = useContext(ColumnContext); + const { basePathToShowPage, objectMetadataItem } = useObjectMetadataItem({ + objectNameSingular: + columnDefinition?.metadata.objectMetadataNameSingular || '', + }); + const updateRecord = useContext(RecordUpdateContext); if (!columnDefinition || !currentRowId) { @@ -65,16 +67,13 @@ export const RecordTableCellContainer = ({ fieldDefinition: columnDefinition, useUpdateRecord: () => [updateRecord, {}], hotkeyScope: customHotkeyScope, - basePathToShowPage: objectMetadataConfig?.basePathToShowPage, + basePathToShowPage, isLabelIdentifier: isLabelIdentifierField({ fieldMetadataItem: { id: columnDefinition.fieldMetadataId, name: columnDefinition.metadata.fieldName, }, - objectMetadataItem: { - labelIdentifierFieldMetadataId: - objectMetadataConfig?.labelIdentifierFieldMetadataId, - }, + objectMetadataItem, }), }} > diff --git a/packages/twenty-front/src/modules/object-record/record-table/record-table-cell/components/RecordTableCell.tsx b/packages/twenty-front/src/modules/object-record/record-table/record-table-cell/components/RecordTableCell.tsx index 3ae492cc4..635f565f9 100644 --- a/packages/twenty-front/src/modules/object-record/record-table/record-table-cell/components/RecordTableCell.tsx +++ b/packages/twenty-front/src/modules/object-record/record-table/record-table-cell/components/RecordTableCell.tsx @@ -96,6 +96,6 @@ export const RecordTableCell = ({ /> } nonEditModeContent={} - > + /> ); }; diff --git a/packages/twenty-front/src/modules/object-record/relation-picker/components/RelationPicker.tsx b/packages/twenty-front/src/modules/object-record/relation-picker/components/RelationPicker.tsx index 38ebc53a7..552f9e4d0 100644 --- a/packages/twenty-front/src/modules/object-record/relation-picker/components/RelationPicker.tsx +++ b/packages/twenty-front/src/modules/object-record/relation-picker/components/RelationPicker.tsx @@ -1,6 +1,5 @@ import { useEffect } from 'react'; -import { useObjectNameSingularFromPlural } from '@/object-metadata/hooks/useObjectNameSingularFromPlural'; import { FieldDefinition } from '@/object-record/field/types/FieldDefinition'; import { FieldRelationMetadata } from '@/object-record/field/types/FieldMetadata'; import { SingleEntitySelect } from '@/object-record/relation-picker/components/SingleEntitySelect'; @@ -31,7 +30,6 @@ export const RelationPicker = ({ const { relationPickerSearchFilter, setRelationPickerSearchFilter, - identifiersMapper, searchQuery, } = useRelationPicker({ relationPickerScopeId: 'relation-picker' }); @@ -39,12 +37,6 @@ export const RelationPicker = ({ setRelationPickerSearchFilter(initialSearchFilter ?? ''); }, [initialSearchFilter, setRelationPickerSearchFilter]); - const { objectNameSingular: relationObjectNameSingular } = - useObjectNameSingularFromPlural({ - objectNamePlural: - fieldDefinition.metadata.relationObjectMetadataNamePlural, - }); - const entities = useFilteredSearchEntityQuery({ filters: [ { @@ -56,18 +48,15 @@ export const RelationPicker = ({ }, ], orderByField: 'createdAt', - mappingFunction: (record: any) => - identifiersMapper?.( - record, - fieldDefinition.metadata.relationObjectMetadataNameSingular, - ), selectedIds: recordId ? [recordId] : [], excludeEntityIds: excludeRecordIds, - objectNameSingular: relationObjectNameSingular, + objectNameSingular: + fieldDefinition.metadata.relationObjectMetadataNameSingular, }); - const handleEntitySelected = (selectedEntity: any | null | undefined) => - onSubmit(selectedEntity ?? null); + const handleEntitySelected = ( + selectedEntity: EntityForSelect | null | undefined, + ) => onSubmit(selectedEntity ?? null); return ( ((person) => ({ id: person.id, name: person.name.firstName + ' ' + person.name.lastName, + avatarUrl: person.avatarUrl, + avatarType: 'rounded', record: person, })); diff --git a/packages/twenty-front/src/modules/object-record/relation-picker/hooks/internal/useRelationPickerScopedStates.ts b/packages/twenty-front/src/modules/object-record/relation-picker/hooks/internal/useRelationPickerScopedStates.ts index bde51d628..34bc3f77a 100644 --- a/packages/twenty-front/src/modules/object-record/relation-picker/hooks/internal/useRelationPickerScopedStates.ts +++ b/packages/twenty-front/src/modules/object-record/relation-picker/hooks/internal/useRelationPickerScopedStates.ts @@ -13,7 +13,6 @@ export const useRelationPickerScopedStates = (args?: { ); const { - identifiersMapperState, relationPickerSearchFilterState, relationPickerPreselectedIdState, searchQueryState, @@ -23,7 +22,6 @@ export const useRelationPickerScopedStates = (args?: { return { scopeId, - identifiersMapperState, relationPickerSearchFilterState, relationPickerPreselectedIdState, searchQueryState, diff --git a/packages/twenty-front/src/modules/object-record/relation-picker/hooks/useRelationPicker.ts b/packages/twenty-front/src/modules/object-record/relation-picker/hooks/useRelationPicker.ts index b71671b2e..b0bd18ebe 100644 --- a/packages/twenty-front/src/modules/object-record/relation-picker/hooks/useRelationPicker.ts +++ b/packages/twenty-front/src/modules/object-record/relation-picker/hooks/useRelationPicker.ts @@ -15,7 +15,6 @@ export const useRelationPicker = (props?: useRelationPickeProps) => { ); const { - identifiersMapperState, searchQueryState, relationPickerSearchFilterState, relationPickerPreselectedIdState, @@ -23,10 +22,6 @@ export const useRelationPicker = (props?: useRelationPickeProps) => { relationPickerScopedId: scopeId, }); - const [identifiersMapper, setIdentifiersMapper] = useRecoilState( - identifiersMapperState, - ); - const [searchQuery, setSearchQuery] = useRecoilState(searchQueryState); const [relationPickerSearchFilter, setRelationPickerSearchFilter] = @@ -37,8 +32,6 @@ export const useRelationPicker = (props?: useRelationPickeProps) => { return { scopeId, - identifiersMapper, - setIdentifiersMapper, searchQuery, setSearchQuery, relationPickerSearchFilter, diff --git a/packages/twenty-front/src/modules/object-record/relation-picker/states/identifiersMapperScopedState.ts b/packages/twenty-front/src/modules/object-record/relation-picker/states/identifiersMapperScopedState.ts deleted file mode 100644 index 7b2683e25..000000000 --- a/packages/twenty-front/src/modules/object-record/relation-picker/states/identifiersMapperScopedState.ts +++ /dev/null @@ -1,8 +0,0 @@ -import { IdentifiersMapper } from '@/object-record/relation-picker/types/IdentifiersMapper'; -import { createStateScopeMap } from '@/ui/utilities/recoil-scope/utils/createStateScopeMap'; - -export const identifiersMapperScopedState = - createStateScopeMap({ - key: 'identifiersMapperScopedState', - defaultValue: null, - }); diff --git a/packages/twenty-front/src/modules/object-record/relation-picker/types/EntityForSelect.ts b/packages/twenty-front/src/modules/object-record/relation-picker/types/EntityForSelect.ts index 4737e6b8c..7ac1147b9 100644 --- a/packages/twenty-front/src/modules/object-record/relation-picker/types/EntityForSelect.ts +++ b/packages/twenty-front/src/modules/object-record/relation-picker/types/EntityForSelect.ts @@ -1,9 +1,4 @@ -import { AvatarType } from '@/users/components/Avatar'; +import { ObjectRecord } from '@/object-record/types/ObjectRecord'; +import { ObjectRecordIdentifier } from '@/object-record/types/ObjectRecordIdentifier'; -export type EntityForSelect = { - id: string; - name: string; - avatarUrl?: string; - avatarType?: AvatarType; - record: any; -}; +export type EntityForSelect = ObjectRecordIdentifier & { record: ObjectRecord }; diff --git a/packages/twenty-front/src/modules/object-record/relation-picker/types/IdentifiersMapper.tsx b/packages/twenty-front/src/modules/object-record/relation-picker/types/IdentifiersMapper.tsx deleted file mode 100644 index 3a477df0e..000000000 --- a/packages/twenty-front/src/modules/object-record/relation-picker/types/IdentifiersMapper.tsx +++ /dev/null @@ -1,14 +0,0 @@ -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/packages/twenty-front/src/modules/object-record/relation-picker/utils/getRelationPickerScopedStates.ts b/packages/twenty-front/src/modules/object-record/relation-picker/utils/getRelationPickerScopedStates.ts index ef052f37c..52e171ba9 100644 --- a/packages/twenty-front/src/modules/object-record/relation-picker/utils/getRelationPickerScopedStates.ts +++ b/packages/twenty-front/src/modules/object-record/relation-picker/utils/getRelationPickerScopedStates.ts @@ -1,4 +1,3 @@ -import { identifiersMapperScopedState } from '@/object-record/relation-picker/states/identifiersMapperScopedState'; import { relationPickerPreselectedIdScopedState } from '@/object-record/relation-picker/states/relationPickerPreselectedIdScopedState'; import { relationPickerSearchFilterScopedState } from '@/object-record/relation-picker/states/relationPickerSearchFilterScopedState'; import { searchQueryScopedState } from '@/object-record/relation-picker/states/searchQueryScopedState'; @@ -9,11 +8,6 @@ export const getRelationPickerScopedStates = ({ }: { relationPickerScopeId: string; }) => { - const identifiersMapperState = getScopedStateDeprecated( - identifiersMapperScopedState, - relationPickerScopeId, - ); - const searchQueryState = getScopedStateDeprecated( searchQueryScopedState, relationPickerScopeId, @@ -30,7 +24,6 @@ export const getRelationPickerScopedStates = ({ ); return { - identifiersMapperState, relationPickerSearchFilterState, relationPickerPreselectedIdState, searchQueryState, diff --git a/packages/twenty-front/src/modules/object-record/types/ObjectRecordIdentifier.ts b/packages/twenty-front/src/modules/object-record/types/ObjectRecordIdentifier.ts index 50856064c..023bc2b8e 100644 --- a/packages/twenty-front/src/modules/object-record/types/ObjectRecordIdentifier.ts +++ b/packages/twenty-front/src/modules/object-record/types/ObjectRecordIdentifier.ts @@ -3,7 +3,7 @@ import { AvatarType } from '@/users/components/Avatar'; export type ObjectRecordIdentifier = { id: string; name: string; - avatarUrl?: string | null; + avatarUrl: string; avatarType?: AvatarType | null; linkToShowPage?: string; }; diff --git a/packages/twenty-front/src/modules/search/hooks/__tests__/useFilteredSearchEntityQuery.test.tsx b/packages/twenty-front/src/modules/search/hooks/__tests__/useFilteredSearchEntityQuery.test.tsx index 26c8378aa..b562b7468 100644 --- a/packages/twenty-front/src/modules/search/hooks/__tests__/useFilteredSearchEntityQuery.test.tsx +++ b/packages/twenty-front/src/modules/search/hooks/__tests__/useFilteredSearchEntityQuery.test.tsx @@ -85,10 +85,6 @@ describe('useFilteredSearchEntityQuery', () => { filters: [{ fieldNames: ['name'], filter: 'Entity' }], sortOrder: 'AscNullsLast', selectedIds: ['1'], - mappingFunction: (entity): any => ({ - value: entity.id, - label: entity.name, - }), limit: 10, excludeEntityIds: ['2'], objectNameSingular: 'person', diff --git a/packages/twenty-front/src/modules/search/hooks/useFilteredSearchEntityQuery.ts b/packages/twenty-front/src/modules/search/hooks/useFilteredSearchEntityQuery.ts index b27492123..e2f294fa4 100644 --- a/packages/twenty-front/src/modules/search/hooks/useFilteredSearchEntityQuery.ts +++ b/packages/twenty-front/src/modules/search/hooks/useFilteredSearchEntityQuery.ts @@ -1,9 +1,11 @@ import { isNonEmptyString } from '@sniptt/guards'; +import { useObjectMetadataItem } from '@/object-metadata/hooks/useObjectMetadataItem'; import { OrderBy } from '@/object-metadata/types/OrderBy'; import { useFindManyRecords } from '@/object-record/hooks/useFindManyRecords'; 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 { assertNotNull } from '~/utils/assert'; import { isDefined } from '~/utils/isDefined'; @@ -19,7 +21,6 @@ export const useFilteredSearchEntityQuery = ({ filters, sortOrder = 'AscNullsLast', selectedIds, - mappingFunction, limit, excludeEntityIds = [], objectNameSingular, @@ -28,11 +29,18 @@ export const useFilteredSearchEntityQuery = ({ filters: SearchFilter[]; sortOrder?: OrderBy; selectedIds: string[]; - mappingFunction: (entity: any) => EntityForSelect | undefined; limit?: number; excludeEntityIds?: string[]; objectNameSingular: string; }): EntitiesForMultipleEntitySelect => { + const { mapToObjectRecordIdentifier } = useObjectMetadataItem({ + objectNameSingular, + }); + const mappingFunction = (record: ObjectRecord) => ({ + ...mapToObjectRecordIdentifier(record), + record, + }); + const { loading: selectedRecordsLoading, records: selectedRecords } = useFindManyRecords({ objectNameSingular, diff --git a/packages/twenty-front/src/modules/ui/display/chip/components/EntityChip.tsx b/packages/twenty-front/src/modules/ui/display/chip/components/EntityChip.tsx index a32bee0b3..c23951fbf 100644 --- a/packages/twenty-front/src/modules/ui/display/chip/components/EntityChip.tsx +++ b/packages/twenty-front/src/modules/ui/display/chip/components/EntityChip.tsx @@ -47,34 +47,34 @@ export const EntityChip = ({ } }; - return isNonEmptyString(name) ? ( - - ) : ( - - ) - } - clickable={!!linkToEntity} - onClick={handleLinkClick} - className={className} - /> - ) : ( - <> + return ( + isNonEmptyString(name) && ( + + ) : ( + + ) + } + clickable={!!linkToEntity} + onClick={handleLinkClick} + className={className} + /> + ) ); };