Morph-front-display-table (#13979)
## Add Morph Relation Field Display Support for Tables (one to many & many to one) **Features:** - Display morph relation fields (one-to-many, many-to-one) in table cells - Multi-field record retrieval for improved performance - Enhanced table cell rendering with morph relation support **Components Added:** - `MorphRelationManyToOneFieldDisplay` - Shows many-to-one morph relations - `MorphRelationOneToManyFieldDisplay` - Shows one-to-many morph relations TODO : handle notes and tasks case if we choose these kind of objects as targets/source for a morph relation --------- Co-authored-by: Charles Bochet <charles@twenty.com>
This commit is contained in:
+92
-5
@@ -1,5 +1,4 @@
|
||||
import { mapObjectMetadataToGraphQLQuery } from '@/object-metadata/utils/mapObjectMetadataToGraphQLQuery';
|
||||
import { isUndefined } from '@sniptt/guards';
|
||||
import { FieldMetadataType, RelationType } from '~/generated-metadata/graphql';
|
||||
|
||||
import { type ObjectMetadataItem } from '@/object-metadata/types/ObjectMetadataItem';
|
||||
@@ -7,7 +6,11 @@ import { getObjectPermissionsForObject } from '@/object-metadata/utils/getObject
|
||||
import { type RecordGqlFields } from '@/object-record/graphql/types/RecordGqlFields';
|
||||
import { isNonCompositeField } from '@/object-record/object-filter-dropdown/utils/isNonCompositeField';
|
||||
import { type ObjectPermissions } from 'twenty-shared/types';
|
||||
import { isDefined } from 'twenty-shared/utils';
|
||||
import {
|
||||
computeMorphRelationFieldJoinColumnName,
|
||||
computeMorphRelationFieldName,
|
||||
isDefined,
|
||||
} from 'twenty-shared/utils';
|
||||
import { type FieldMetadataItem } from '../types/FieldMetadataItem';
|
||||
|
||||
type MapFieldMetadataToGraphQLQueryArgs = {
|
||||
@@ -15,7 +18,7 @@ type MapFieldMetadataToGraphQLQueryArgs = {
|
||||
gqlField: string;
|
||||
fieldMetadata: Pick<
|
||||
FieldMetadataItem,
|
||||
'name' | 'type' | 'relation' | 'settings'
|
||||
'name' | 'type' | 'relation' | 'morphRelations' | 'settings'
|
||||
>;
|
||||
relationRecordGqlFields?: RecordGqlFields;
|
||||
computeReferences?: boolean;
|
||||
@@ -41,6 +44,90 @@ export const mapFieldMetadataToGraphQLQuery = ({
|
||||
return gqlField;
|
||||
}
|
||||
|
||||
if (
|
||||
fieldType === FieldMetadataType.MORPH_RELATION &&
|
||||
(fieldMetadata.settings?.relationType === RelationType.ONE_TO_MANY ||
|
||||
fieldMetadata.settings?.relationType === RelationType.MANY_TO_ONE)
|
||||
) {
|
||||
let gqlMorphField = '';
|
||||
for (const morphRelation of fieldMetadata.morphRelations ?? []) {
|
||||
const relationFieldName = computeMorphRelationFieldName({
|
||||
fieldName: fieldMetadata.name,
|
||||
relationDirection: fieldMetadata.settings?.relationType,
|
||||
nameSingular: morphRelation.targetObjectMetadata.nameSingular,
|
||||
namePlural: morphRelation.targetObjectMetadata.namePlural,
|
||||
});
|
||||
const relationMetadataItem = objectMetadataItems.find(
|
||||
(objectMetadataItem) =>
|
||||
objectMetadataItem.id === morphRelation.targetObjectMetadata.id,
|
||||
);
|
||||
|
||||
if (!isDefined(relationMetadataItem)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
if (
|
||||
isDefined(objectPermissionsByObjectMetadataId) &&
|
||||
isDefined(relationMetadataItem.id)
|
||||
) {
|
||||
if (!isDefined(morphRelation.targetObjectMetadata.id)) {
|
||||
throw new Error(
|
||||
`Target object metadata id not found with field metadata ${fieldMetadata.name}`,
|
||||
);
|
||||
}
|
||||
|
||||
const objectPermission = getObjectPermissionsForObject(
|
||||
objectPermissionsByObjectMetadataId,
|
||||
morphRelation.targetObjectMetadata.id,
|
||||
);
|
||||
|
||||
if (!objectPermission.canReadObjectRecords) {
|
||||
continue;
|
||||
}
|
||||
}
|
||||
|
||||
if (fieldMetadata.settings?.relationType === RelationType.ONE_TO_MANY) {
|
||||
gqlMorphField += `${relationFieldName}
|
||||
{
|
||||
edges {
|
||||
node ${mapObjectMetadataToGraphQLQuery({
|
||||
objectMetadataItems,
|
||||
objectMetadataItem: relationMetadataItem,
|
||||
recordGqlFields: relationRecordGqlFields,
|
||||
computeReferences,
|
||||
isRootLevel: false,
|
||||
objectPermissionsByObjectMetadataId,
|
||||
})}
|
||||
}
|
||||
}`;
|
||||
}
|
||||
|
||||
if (fieldMetadata.settings?.relationType === RelationType.MANY_TO_ONE) {
|
||||
const joinColumnName = computeMorphRelationFieldJoinColumnName({
|
||||
name: fieldMetadata.name,
|
||||
targetObjectMetadataNameSingular:
|
||||
morphRelation.targetObjectMetadata.nameSingular,
|
||||
});
|
||||
if (gqlField === joinColumnName) {
|
||||
gqlMorphField += `${gqlField}
|
||||
`;
|
||||
continue;
|
||||
}
|
||||
|
||||
gqlMorphField += `${relationFieldName}
|
||||
${mapObjectMetadataToGraphQLQuery({
|
||||
objectMetadataItems,
|
||||
objectMetadataItem: relationMetadataItem,
|
||||
recordGqlFields: relationRecordGqlFields,
|
||||
computeReferences,
|
||||
isRootLevel: false,
|
||||
objectPermissionsByObjectMetadataId,
|
||||
})}`;
|
||||
}
|
||||
}
|
||||
return `${gqlMorphField}`;
|
||||
}
|
||||
|
||||
if (
|
||||
fieldType === FieldMetadataType.RELATION &&
|
||||
fieldMetadata.relation?.type === RelationType.MANY_TO_ONE
|
||||
@@ -51,7 +138,7 @@ export const mapFieldMetadataToGraphQLQuery = ({
|
||||
fieldMetadata.relation?.targetObjectMetadata.id,
|
||||
);
|
||||
|
||||
if (isUndefined(relationMetadataItem)) {
|
||||
if (!isDefined(relationMetadataItem)) {
|
||||
return '';
|
||||
}
|
||||
|
||||
@@ -100,7 +187,7 @@ ${mapObjectMetadataToGraphQLQuery({
|
||||
fieldMetadata.relation?.targetObjectMetadata.id,
|
||||
);
|
||||
|
||||
if (isUndefined(relationMetadataItem)) {
|
||||
if (!isDefined(relationMetadataItem)) {
|
||||
return '';
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user