From 76e8bf33ac05d0e4bee1e9a8e05a20da804202ed Mon Sep 17 00:00:00 2001 From: Marie <51697796+ijreilly@users.noreply.github.com> Date: Mon, 4 Nov 2024 14:39:48 +0100 Subject: [PATCH] Fix relation picker for activity target (#8303) [This PR](https://github.com/twentyhq/twenty/pull/8210) introduced a regression, causing noteId or taskId (respectively for noteTarget or taskTarget creation) to be overwritten with an undefined value in the input for noteTarget or taskTarget creation. This is because in ActivityTargetInlineCellEditMode, in addition to the noteId and taskId we are declaring, we are looking into the object (noteTarget or taskTarget)'s fields and prefilling the record-to-create with a value, potentially undefined, for all of the object fields. So when looping over noteTarget's fields, we would find the `note` relation field, and eventually add `note: undefined` to the record-to-create input, in addition to the non-empty and valid existing `noteId`. Then in sanitizeRecordInput, from the note added right above, we add an empty noteId to the input from node, overwriting the "good" noteId. There are several ways to fix this, I chose to update prefillRecord not to add an empty "note" object that makes no sense in addition to the "noteId" we already have at this stage. It is also possible to update `sanitizeRecordInput` not to overwrite a value from a relation (noteId from note relation) if there is already a value in the input. --- .../ActivityTargetInlineCellEditMode.tsx | 8 +++++++ .../modules/favorites/hooks/useFavorites.ts | 1 + .../object-record/utils/prefillRecord.ts | 22 +++++++++++++++++++ 3 files changed, 31 insertions(+) diff --git a/packages/twenty-front/src/modules/activities/inline-cell/components/ActivityTargetInlineCellEditMode.tsx b/packages/twenty-front/src/modules/activities/inline-cell/components/ActivityTargetInlineCellEditMode.tsx index 4ed47174a..5b9d62b6c 100644 --- a/packages/twenty-front/src/modules/activities/inline-cell/components/ActivityTargetInlineCellEditMode.tsx +++ b/packages/twenty-front/src/modules/activities/inline-cell/components/ActivityTargetInlineCellEditMode.tsx @@ -185,10 +185,18 @@ export const ActivityTargetInlineCellEditMode = ({ activityObjectNameSingular === CoreObjectNameSingular.Task ? activity.id : null, + task: + activityObjectNameSingular === CoreObjectNameSingular.Task + ? activity + : null, noteId: activityObjectNameSingular === CoreObjectNameSingular.Note ? activity.id : null, + note: + activityObjectNameSingular === CoreObjectNameSingular.Note + ? activity + : null, createdAt: new Date().toISOString(), updatedAt: new Date().toISOString(), [fieldName]: record.record, diff --git a/packages/twenty-front/src/modules/favorites/hooks/useFavorites.ts b/packages/twenty-front/src/modules/favorites/hooks/useFavorites.ts index cd665de32..d2beb115d 100644 --- a/packages/twenty-front/src/modules/favorites/hooks/useFavorites.ts +++ b/packages/twenty-front/src/modules/favorites/hooks/useFavorites.ts @@ -98,6 +98,7 @@ export const useFavorites = () => { ) => { createOneFavorite({ [targetObjectNameSingular]: targetRecord, + [`${targetObjectNameSingular}Id`]: targetRecord.id, position: favorites.length + 1, workspaceMemberId: currentWorkspaceMember?.id, }); diff --git a/packages/twenty-front/src/modules/object-record/utils/prefillRecord.ts b/packages/twenty-front/src/modules/object-record/utils/prefillRecord.ts index 2ec83214d..e3128edcf 100644 --- a/packages/twenty-front/src/modules/object-record/utils/prefillRecord.ts +++ b/packages/twenty-front/src/modules/object-record/utils/prefillRecord.ts @@ -1,8 +1,10 @@ import { isUndefined } from '@sniptt/guards'; +import { FieldMetadataItem } from '@/object-metadata/types/FieldMetadataItem'; import { ObjectMetadataItem } from '@/object-metadata/types/ObjectMetadataItem'; import { ObjectRecord } from '@/object-record/types/ObjectRecord'; import { generateDefaultFieldValue } from '@/object-record/utils/generateDefaultFieldValue'; +import { FieldMetadataType, RelationDefinitionType } from '~/generated/graphql'; import { isDefined } from '~/utils/isDefined'; export const prefillRecord = ({ @@ -16,6 +18,13 @@ export const prefillRecord = ({ objectMetadataItem.fields .map((fieldMetadataItem) => { const inputValue = input[fieldMetadataItem.name]; + if ( + fieldMetadataItem.type === FieldMetadataType.Relation && + fieldMetadataItem.relationDefinition?.direction === + RelationDefinitionType.ManyToOne + ) { + throwIfInputRelationDataIsInconsistent(input, fieldMetadataItem); + } return [ fieldMetadataItem.name, @@ -27,3 +36,16 @@ export const prefillRecord = ({ .filter(isDefined), ) as T; }; + +const throwIfInputRelationDataIsInconsistent = ( + input: Record, + fieldMetadataItem: FieldMetadataItem, +) => { + const inputValue = input[fieldMetadataItem.name]; + const relationIdFieldName = `${fieldMetadataItem.name}Id`; + if (isDefined(inputValue) && !isDefined(input[relationIdFieldName])) { + throw new Error( + `Inconsistent input: ${fieldMetadataItem.name} is specified but ${relationIdFieldName} is missing`, + ); + } +};