From 4a5ffcc9d27cbc13dd2eeab34fbc3fda85f96d54 Mon Sep 17 00:00:00 2001 From: Arun <184187559+carbonFibreCode@users.noreply.github.com> Date: Mon, 26 Jan 2026 18:57:56 +0530 Subject: [PATCH] [Fix] Bug with one to many update in table #16340 (#17416) fixes #16340 we are updating the cache partially to prevent the flow of the corrupted fields into the cache the fields get corrupted during the mutation process potentially overriding the recoil cache as we are passing the `newRecordCache` directly in `upsertRecordsInStore`, the newRecordCache is thin and hence the recoil wipes out the fields that are undefined or empty we prevent this by extracting the partial data ( only the data which is being updated in the field ) and passing it to `upsertRecordsInStore`, as it only touched the specific fields and updates the data, leaving the other fields untouched. https://github.com/user-attachments/assets/5256bef7-70c3-47b3-b2ce-dd02ee1a2de8 --------- Co-authored-by: Arun kumar Co-authored-by: Lucas Bordeau --- ...epthRecordGqlFieldsFromObject.test.ts.snap | 10 +++++++- .../generateDepthRecordGqlFieldsFromFields.ts | 25 +++++++++++++++++++ .../hooks/__mocks__/personFragments.ts | 10 ++++++++ 3 files changed, 44 insertions(+), 1 deletion(-) diff --git a/packages/twenty-front/src/modules/object-record/graphql/record-gql-fields/utils/__tests__/__snapshots__/generateDepthRecordGqlFieldsFromObject.test.ts.snap b/packages/twenty-front/src/modules/object-record/graphql/record-gql-fields/utils/__tests__/__snapshots__/generateDepthRecordGqlFieldsFromObject.test.ts.snap index 7ca8666fea..38e7e69514 100644 --- a/packages/twenty-front/src/modules/object-record/graphql/record-gql-fields/utils/__tests__/__snapshots__/generateDepthRecordGqlFieldsFromObject.test.ts.snap +++ b/packages/twenty-front/src/modules/object-record/graphql/record-gql-fields/utils/__tests__/__snapshots__/generateDepthRecordGqlFieldsFromObject.test.ts.snap @@ -1,4 +1,4 @@ -// Jest Snapshot v1, https://jestjs.io/docs/snapshot-testing +// Jest Snapshot v1, https://goo.gl/fbAQLP exports[`generateDepthRecordGqlFieldsFromObject should generate depth one record gql fields from object 1`] = ` { @@ -29,6 +29,10 @@ exports[`generateDepthRecordGqlFieldsFromObject should generate depth one record "name": true, "noteTargets": { "id": true, + "note": { + "id": true, + "title": true, + }, }, "opportunities": { "id": true, @@ -44,6 +48,10 @@ exports[`generateDepthRecordGqlFieldsFromObject should generate depth one record "tagline": true, "taskTargets": { "id": true, + "task": { + "id": true, + "title": true, + }, }, "timelineActivities": { "id": true, diff --git a/packages/twenty-front/src/modules/object-record/graphql/record-gql-fields/utils/generateDepthRecordGqlFieldsFromFields.ts b/packages/twenty-front/src/modules/object-record/graphql/record-gql-fields/utils/generateDepthRecordGqlFieldsFromFields.ts index 4b8f5897db..fe6fe3c97d 100644 --- a/packages/twenty-front/src/modules/object-record/graphql/record-gql-fields/utils/generateDepthRecordGqlFieldsFromFields.ts +++ b/packages/twenty-front/src/modules/object-record/graphql/record-gql-fields/utils/generateDepthRecordGqlFieldsFromFields.ts @@ -1,8 +1,11 @@ +import { CoreObjectNamePlural } from '@/object-metadata/types/CoreObjectNamePlural'; +import { CoreObjectNameSingular } from '@/object-metadata/types/CoreObjectNameSingular'; import { type FieldMetadataItem } from '@/object-metadata/types/FieldMetadataItem'; import { type ObjectMetadataItem } from '@/object-metadata/types/ObjectMetadataItem'; import { getImageIdentifierFieldMetadataItem } from '@/object-metadata/utils/getImageIdentifierFieldMetadataItem'; import { getLabelIdentifierFieldMetadataItem } from '@/object-metadata/utils/getLabelIdentifierFieldMetadataItem'; import { type RecordGqlFields } from '@/object-record/graphql/record-gql-fields/types/RecordGqlFields'; +import { generateActivityTargetGqlFields } from '@/object-record/graphql/record-gql-fields/utils/generateActivityTargetGqlFields'; import { generateJunctionRelationGqlFields } from '@/object-record/graphql/record-gql-fields/utils/generateJunctionRelationGqlFields'; import { isJunctionRelationField } from '@/object-record/record-field/ui/utils/junction/isJunctionRelationField'; import { FieldMetadataType, RelationType } from 'twenty-shared/types'; @@ -54,6 +57,28 @@ export const generateDepthRecordGqlFieldsFromFields = ({ ); } + const isActivityTargetField = + fieldMetadata.name === CoreObjectNamePlural.NoteTarget || + fieldMetadata.name === CoreObjectNamePlural.TaskTarget; + + if (isActivityTargetField && depth === 1) { + const activityTargetObjectNameSingular = + fieldMetadata.name === CoreObjectNamePlural.NoteTarget + ? CoreObjectNameSingular.Note + : CoreObjectNameSingular.Task; + + const activityTargetGqlFields = generateActivityTargetGqlFields({ + activityObjectNameSingular: activityTargetObjectNameSingular, + objectMetadataItems, + loadRelations: 'activity', + }); + + return { + ...recordGqlFields, + [fieldMetadata.name]: activityTargetGqlFields, + }; + } + if (isJunctionRelationField(fieldMetadata)) { const junctionGqlFields = generateJunctionRelationGqlFields({ fieldMetadataItem: fieldMetadata, diff --git a/packages/twenty-front/src/modules/object-record/hooks/__mocks__/personFragments.ts b/packages/twenty-front/src/modules/object-record/hooks/__mocks__/personFragments.ts index 875032958f..d0b4b8ccc0 100644 --- a/packages/twenty-front/src/modules/object-record/hooks/__mocks__/personFragments.ts +++ b/packages/twenty-front/src/modules/object-record/hooks/__mocks__/personFragments.ts @@ -129,6 +129,11 @@ export const PERSON_FRAGMENT_WITH_DEPTH_ONE_RELATIONS = ` node { __typename id + note { + __typename + id + title + } } } } @@ -154,6 +159,11 @@ export const PERSON_FRAGMENT_WITH_DEPTH_ONE_RELATIONS = ` node { __typename id + task { + __typename + id + title + } } } }