Fix issues with one to many activity targets (#15656)

This PR fixes issues with one to many activity target bugs described
here :
https://github.com/twentyhq/twenty/issues/14280#issuecomment-3490170714

It also improves the request that fetches notes and tasks in index
pages, to only fetch the notes and tasks identifier fields, thus
reducing the amount of network load.

Fixes https://github.com/twentyhq/twenty/issues/14280
This commit is contained in:
Lucas Bordeau
2025-11-11 17:19:20 +01:00
committed by GitHub
parent de978960d0
commit 5f3253d5a5
11 changed files with 147 additions and 194 deletions
@@ -0,0 +1,68 @@
import { CoreObjectNameSingular } from '@/object-metadata/types/CoreObjectNameSingular';
import { type ObjectMetadataItem } from '@/object-metadata/types/ObjectMetadataItem';
import { getLabelIdentifierFieldMetadataItem } from '@/object-metadata/utils/getLabelIdentifierFieldMetadataItem';
import { generateDepthRecordGqlFieldsFromFields } from '@/object-record/graphql/record-gql-fields/utils/generateDepthRecordGqlFieldsFromFields';
import { isDefined } from 'twenty-shared/utils';
export type GenerateDepthRecordGqlFields = {
objectMetadataItems: ObjectMetadataItem[];
activityObjectNameSingular:
| CoreObjectNameSingular.Note
| CoreObjectNameSingular.Task;
depth: 0 | 1;
shouldOnlyLoadActivityIdentifiers?: boolean;
};
export const generateActivityTargetGqlFields = ({
objectMetadataItems,
activityObjectNameSingular,
depth,
shouldOnlyLoadActivityIdentifiers = true,
}: GenerateDepthRecordGqlFields) => {
const isNote = activityObjectNameSingular === CoreObjectNameSingular.Note;
const activityTargetNameSingular = isNote
? CoreObjectNameSingular.NoteTarget
: CoreObjectNameSingular.TaskTarget;
const activityTargetObjectMetadataItem = objectMetadataItems.find(
(objectMetadataItem) =>
objectMetadataItem.nameSingular === activityTargetNameSingular,
);
const activityObjectMetadataItem = objectMetadataItems.find(
(objectMetadataItem) =>
objectMetadataItem.nameSingular === activityObjectNameSingular,
);
if (
!isDefined(activityTargetObjectMetadataItem) ||
!isDefined(activityObjectMetadataItem)
) {
return {};
}
if (shouldOnlyLoadActivityIdentifiers) {
const activityLabelIdentifierFieldMetadataItem =
getLabelIdentifierFieldMetadataItem(activityObjectMetadataItem);
return {
id: true,
[activityObjectNameSingular]: {
id: true,
...(isDefined(activityLabelIdentifierFieldMetadataItem)
? { [activityLabelIdentifierFieldMetadataItem.name]: true }
: {}),
},
};
} else {
return {
...generateDepthRecordGqlFieldsFromFields({
depth,
fields: activityTargetObjectMetadataItem.fields,
objectMetadataItems,
shouldOnlyLoadRelationIdentifiers: false,
}),
[activityObjectNameSingular]: true,
};
}
};