fix(server): morph relation fields filtering (#14365)
Tested: object metadata items retrieval and standard overrides Please be sure to cache flush before testing this for the data loader to be hit
This commit is contained in:
@@ -10,12 +10,13 @@ import { type IndexMetadataInterface } from 'src/engine/metadata-modules/index-m
|
||||
import { I18nService } from 'src/engine/core-modules/i18n/i18n.service';
|
||||
import { type IDataloaders } from 'src/engine/dataloaders/dataloader.interface';
|
||||
import { filterMorphRelationDuplicateFields } from 'src/engine/dataloaders/utils/filter-morph-relation-duplicate-fields.util';
|
||||
import { FIELD_METADATA_STANDARD_OVERRIDES_PROPERTIES } from 'src/engine/metadata-modules/field-metadata/constants/field-metadata-standard-overrides-properties.constant';
|
||||
import { type FieldMetadataDTO } from 'src/engine/metadata-modules/field-metadata/dtos/field-metadata.dto';
|
||||
import { RelationDTO } from 'src/engine/metadata-modules/field-metadata/dtos/relation.dto';
|
||||
import { type FieldMetadataEntity } from 'src/engine/metadata-modules/field-metadata/field-metadata.entity';
|
||||
import { fromFieldMetadataEntityToFieldMetadataDto } from 'src/engine/metadata-modules/field-metadata/utils/from-field-metadata-entity-to-field-metadata-dto.util';
|
||||
import { resolveFieldMetadataStandardOverride } from 'src/engine/metadata-modules/field-metadata/utils/resolve-field-metadata-standard-override.util';
|
||||
import { findAllOthersMorphRelationFlatFieldMetadatasOrThrow } from 'src/engine/metadata-modules/flat-field-metadata/utils/find-all-others-morph-relation-flat-field-metadatas-or-throw.util';
|
||||
import { fromFlatFieldMetadataToFieldMetadataDto } from 'src/engine/metadata-modules/flat-field-metadata/utils/from-flat-field-metadata-to-field-metadata-dto.util';
|
||||
import { fromMorphOrRelationFlatFieldMetadataToRelationDto } from 'src/engine/metadata-modules/flat-field-metadata/utils/from-morph-or-relation-flat-field-metadata-to-relation-dto.util';
|
||||
import { isFlatFieldMetadataOfType } from 'src/engine/metadata-modules/flat-field-metadata/utils/is-flat-field-metadata-of-type.util';
|
||||
import { findFlatFieldMetadataInFlatObjectMetadataMapsOrThrow } from 'src/engine/metadata-modules/flat-object-metadata-maps/utils/find-flat-field-metadata-in-flat-object-metadata-maps-or-throw.util';
|
||||
@@ -25,7 +26,6 @@ import { type IndexMetadataDTO } from 'src/engine/metadata-modules/index-metadat
|
||||
import { type ObjectMetadataEntity } from 'src/engine/metadata-modules/object-metadata/object-metadata.entity';
|
||||
import { type ObjectMetadataItemWithFieldMaps } from 'src/engine/metadata-modules/types/object-metadata-item-with-field-maps';
|
||||
import { WorkspaceMetadataCacheService } from 'src/engine/metadata-modules/workspace-metadata-cache/services/workspace-metadata-cache.service';
|
||||
import { transpileToDateIfNot } from 'src/utils/transpile-to-date-if-not.util';
|
||||
|
||||
export type RelationMetadataLoaderPayload = {
|
||||
workspaceId: string;
|
||||
@@ -138,11 +138,7 @@ export class DataloaderService {
|
||||
flatFieldMetadata:
|
||||
sourceFlatFieldMetadata.flatRelationTargetFieldMetadata,
|
||||
flatObjectMetadataMaps: existingFlatObjectMetadataMaps,
|
||||
}).sort(
|
||||
(a, b) =>
|
||||
transpileToDateIfNot(a.createdAt).getTime() -
|
||||
transpileToDateIfNot(b.createdAt).getTime(),
|
||||
);
|
||||
}).sort((a, b) => (a.id > b.id ? 1 : -1));
|
||||
|
||||
relationDtos.push(
|
||||
fromMorphOrRelationFlatFieldMetadataToRelationDto({
|
||||
@@ -283,62 +279,49 @@ export class DataloaderService {
|
||||
(dataLoaderParam) => dataLoaderParam.objectMetadata.id,
|
||||
);
|
||||
|
||||
const { objectMetadataMaps } =
|
||||
await this.workspaceMetadataCacheService.getExistingOrRecomputeMetadataMaps(
|
||||
const { flatObjectMetadataMaps: existingFlatObjectMetadataMaps } =
|
||||
await this.workspaceMetadataCacheService.getExistingOrRecomputeFlatObjectMetadataMaps(
|
||||
{ workspaceId },
|
||||
);
|
||||
|
||||
const fieldMetadataCollection = objectMetadataIds.map((id) => {
|
||||
const objectMetadata = objectMetadataMaps.byId[id];
|
||||
const flatObjectMetadataWithFlatFieldMaps =
|
||||
existingFlatObjectMetadataMaps.byId[id];
|
||||
|
||||
if (!isDefined(objectMetadata)) {
|
||||
if (!isDefined(flatObjectMetadataWithFlatFieldMaps)) {
|
||||
return [];
|
||||
}
|
||||
|
||||
const overriddenFieldMetadataEntities = Object.values(
|
||||
objectMetadata.fieldsById,
|
||||
).map<FieldMetadataEntity>((fieldMetadata) => {
|
||||
const overridesFieldToCompute = [
|
||||
'icon',
|
||||
'label',
|
||||
'description',
|
||||
] as const satisfies (keyof FieldMetadataEntity)[];
|
||||
|
||||
const overrides = overridesFieldToCompute.reduce<
|
||||
Partial<Record<(typeof overridesFieldToCompute)[number], string>>
|
||||
>(
|
||||
(acc, field) => ({
|
||||
...acc,
|
||||
[field]: resolveFieldMetadataStandardOverride(
|
||||
{
|
||||
label: fieldMetadata.label,
|
||||
description: fieldMetadata.description ?? undefined,
|
||||
icon: fieldMetadata.icon ?? undefined,
|
||||
isCustom: fieldMetadata.isCustom,
|
||||
standardOverrides:
|
||||
fieldMetadata.standardOverrides ?? undefined,
|
||||
},
|
||||
field,
|
||||
dataLoaderParams[0].locale,
|
||||
i18nInstance,
|
||||
),
|
||||
}),
|
||||
{},
|
||||
const overriddenFieldMetadataEntities =
|
||||
flatObjectMetadataWithFlatFieldMaps.flatFieldMetadatas.map(
|
||||
(flatFieldMetadata) => {
|
||||
return FIELD_METADATA_STANDARD_OVERRIDES_PROPERTIES.reduce(
|
||||
(acc, property) => ({
|
||||
...acc,
|
||||
[property]: resolveFieldMetadataStandardOverride(
|
||||
{
|
||||
label: flatFieldMetadata.label,
|
||||
description: flatFieldMetadata.description ?? undefined,
|
||||
icon: flatFieldMetadata.icon ?? undefined,
|
||||
isCustom: flatFieldMetadata.isCustom,
|
||||
standardOverrides:
|
||||
flatFieldMetadata.standardOverrides ?? undefined,
|
||||
},
|
||||
property,
|
||||
dataLoaderParams[0].locale,
|
||||
i18nInstance,
|
||||
),
|
||||
}),
|
||||
flatFieldMetadata,
|
||||
);
|
||||
},
|
||||
);
|
||||
|
||||
return {
|
||||
...fieldMetadata,
|
||||
...overrides,
|
||||
};
|
||||
});
|
||||
|
||||
const filteredFieldMetadataEntities =
|
||||
filterMorphRelationDuplicateFields<FieldMetadataEntity>(
|
||||
overriddenFieldMetadataEntities,
|
||||
);
|
||||
filterMorphRelationDuplicateFields(overriddenFieldMetadataEntities);
|
||||
|
||||
return filteredFieldMetadataEntities.map(
|
||||
fromFieldMetadataEntityToFieldMetadataDto,
|
||||
fromFlatFieldMetadataToFieldMetadataDto,
|
||||
);
|
||||
});
|
||||
|
||||
|
||||
+51
-14
@@ -1,16 +1,53 @@
|
||||
import { transpileToDateIfNot } from 'src/utils/transpile-to-date-if-not.util';
|
||||
import { FieldMetadataType } from 'twenty-shared/types';
|
||||
|
||||
export const filterMorphRelationDuplicateFields = <
|
||||
T extends { createdAt: Date; morphId: string | null },
|
||||
>(
|
||||
fields: T[],
|
||||
) => {
|
||||
return fields.filter((currentField) => {
|
||||
return !fields.some(
|
||||
(otherField) =>
|
||||
otherField.morphId === currentField.morphId &&
|
||||
transpileToDateIfNot(otherField.createdAt).getTime() >
|
||||
transpileToDateIfNot(currentField.createdAt).getTime(),
|
||||
);
|
||||
});
|
||||
import { type FlatFieldMetadata } from 'src/engine/metadata-modules/flat-field-metadata/types/flat-field-metadata.type';
|
||||
import { isFlatFieldMetadataOfType } from 'src/engine/metadata-modules/flat-field-metadata/utils/is-flat-field-metadata-of-type.util';
|
||||
|
||||
export const filterMorphRelationDuplicateFields = (
|
||||
flatFieldMetadatas: FlatFieldMetadata[],
|
||||
): FlatFieldMetadata[] => {
|
||||
const initialAccumulator: {
|
||||
morphFlatFieldMetadatas: FlatFieldMetadata<FieldMetadataType.MORPH_RELATION>[];
|
||||
otherFlatFieldMetadatas: FlatFieldMetadata[];
|
||||
} = {
|
||||
morphFlatFieldMetadatas: [],
|
||||
otherFlatFieldMetadatas: [],
|
||||
};
|
||||
const { morphFlatFieldMetadatas, otherFlatFieldMetadatas } =
|
||||
flatFieldMetadatas.reduce((acc, flatFieldMetadata) => {
|
||||
if (
|
||||
isFlatFieldMetadataOfType(
|
||||
flatFieldMetadata,
|
||||
FieldMetadataType.MORPH_RELATION,
|
||||
)
|
||||
) {
|
||||
return {
|
||||
...acc,
|
||||
morphFlatFieldMetadatas: [
|
||||
...acc.morphFlatFieldMetadatas,
|
||||
flatFieldMetadata,
|
||||
],
|
||||
};
|
||||
}
|
||||
|
||||
return {
|
||||
...acc,
|
||||
otherFlatFieldMetadatas: [
|
||||
...acc.otherFlatFieldMetadatas,
|
||||
flatFieldMetadata,
|
||||
],
|
||||
};
|
||||
}, initialAccumulator);
|
||||
|
||||
const filteredMorphFlatFieldMetadatas = morphFlatFieldMetadatas.filter(
|
||||
(currentField) =>
|
||||
!morphFlatFieldMetadatas.some(
|
||||
(otherField) =>
|
||||
currentField.id !== otherField.id &&
|
||||
otherField.morphId === currentField.morphId &&
|
||||
otherField.id < currentField.id,
|
||||
),
|
||||
);
|
||||
|
||||
return [...otherFlatFieldMetadatas, ...filteredMorphFlatFieldMetadatas];
|
||||
};
|
||||
|
||||
@@ -1,3 +0,0 @@
|
||||
// Temporary quick workaround until we eject from nestjs-query that seems to convert date to string and vice-versa
|
||||
export const transpileToDateIfNot = (dateToVerify: string | Date): Date =>
|
||||
dateToVerify instanceof Date ? dateToVerify : new Date(dateToVerify);
|
||||
Reference in New Issue
Block a user