add WorkspaceDuplicateCriteria decorator + update duplicate resolver logic (#10128)
## Context All objects have '...duplicates' resolver but only companies and people have duplicate criteria (hard coded constant). Gql schema and resolver should be created only if duplicate criteria exist. ## Solution - Add a new @WorkspaceDuplicateCriteria decorator at object level, defining duplicate criteria for given object. - Add a new duplicate criteria field in ObjectMetadata table - Update schema and resolver building logic - Update front requests for duplicate check (only for object with criteria defined) closes https://github.com/twentyhq/twenty/issues/9828
This commit is contained in:
@ -0,0 +1,14 @@
|
||||
import { WorkspaceEntityDuplicateCriteria } from 'src/engine/api/graphql/workspace-query-builder/types/workspace-entity-duplicate-criteria.type';
|
||||
import { TypedReflect } from 'src/utils/typed-reflect';
|
||||
|
||||
export function WorkspaceDuplicateCriteria(
|
||||
duplicateCriteria: WorkspaceEntityDuplicateCriteria[],
|
||||
): ClassDecorator {
|
||||
return (target) => {
|
||||
TypedReflect.defineMetadata(
|
||||
'workspace:duplicate-criteria-metadata-args',
|
||||
duplicateCriteria,
|
||||
target,
|
||||
);
|
||||
};
|
||||
}
|
||||
@ -33,6 +33,11 @@ export function WorkspaceEntity(
|
||||
'workspace:gate-metadata-args',
|
||||
target,
|
||||
);
|
||||
const duplicateCriteria = TypedReflect.getMetadata(
|
||||
'workspace:duplicate-criteria-metadata-args',
|
||||
target,
|
||||
);
|
||||
|
||||
const objectName = convertClassNameToObjectMetadataName(target.name);
|
||||
|
||||
metadataArgsStorage.addEntities({
|
||||
@ -51,6 +56,7 @@ export function WorkspaceEntity(
|
||||
isAuditLogged,
|
||||
isSystem,
|
||||
gate,
|
||||
duplicateCriteria,
|
||||
});
|
||||
};
|
||||
}
|
||||
|
||||
@ -1,5 +1,7 @@
|
||||
import { Gate } from 'src/engine/twenty-orm/interfaces/gate.interface';
|
||||
|
||||
import { WorkspaceEntityDuplicateCriteria } from 'src/engine/api/graphql/workspace-query-builder/types/workspace-entity-duplicate-criteria.type';
|
||||
|
||||
export interface WorkspaceEntityMetadataArgs {
|
||||
/**
|
||||
* Standard id.
|
||||
@ -65,4 +67,9 @@ export interface WorkspaceEntityMetadataArgs {
|
||||
* Image identifier.
|
||||
*/
|
||||
readonly imageIdentifierStandardId: string | null;
|
||||
|
||||
/**
|
||||
* Duplicate criteria.
|
||||
*/
|
||||
readonly duplicateCriteria?: WorkspaceEntityDuplicateCriteria[];
|
||||
}
|
||||
|
||||
@ -40,27 +40,10 @@ export function formatResult<T>(
|
||||
throw new Error('Object metadata is missing');
|
||||
}
|
||||
|
||||
const compositeFieldMetadataCollection = getCompositeFieldMetadataCollection(
|
||||
const compositeFieldMetadataMap = getCompositeFieldMetadataMap(
|
||||
objectMetadataItemWithFieldMaps,
|
||||
);
|
||||
|
||||
const compositeFieldMetadataMap = new Map(
|
||||
compositeFieldMetadataCollection.flatMap((fieldMetadata) => {
|
||||
const compositeType = compositeTypeDefinitions.get(fieldMetadata.type);
|
||||
|
||||
if (!compositeType) return [];
|
||||
|
||||
// Map each composite property to a [key, value] pair
|
||||
return compositeType.properties.map((compositeProperty) => [
|
||||
computeCompositeColumnName(fieldMetadata.name, compositeProperty),
|
||||
{
|
||||
parentField: fieldMetadata.name,
|
||||
...compositeProperty,
|
||||
},
|
||||
]);
|
||||
}),
|
||||
);
|
||||
|
||||
const relationMetadataMap = new Map(
|
||||
Object.values(objectMetadataItemWithFieldMaps.fieldsById)
|
||||
.filter(({ type }) => isRelationFieldMetadataType(type))
|
||||
@ -199,6 +182,31 @@ export function formatResult<T>(
|
||||
return newData as T;
|
||||
}
|
||||
|
||||
export function getCompositeFieldMetadataMap(
|
||||
objectMetadataItemWithFieldMaps: ObjectMetadataItemWithFieldMaps,
|
||||
) {
|
||||
const compositeFieldMetadataCollection = getCompositeFieldMetadataCollection(
|
||||
objectMetadataItemWithFieldMaps,
|
||||
);
|
||||
|
||||
return new Map(
|
||||
compositeFieldMetadataCollection.flatMap((fieldMetadata) => {
|
||||
const compositeType = compositeTypeDefinitions.get(fieldMetadata.type);
|
||||
|
||||
if (!compositeType) return [];
|
||||
|
||||
// Map each composite property to a [key, value] pair
|
||||
return compositeType.properties.map((compositeProperty) => [
|
||||
computeCompositeColumnName(fieldMetadata.name, compositeProperty),
|
||||
{
|
||||
parentField: fieldMetadata.name,
|
||||
...compositeProperty,
|
||||
},
|
||||
]);
|
||||
}),
|
||||
);
|
||||
}
|
||||
|
||||
function formatFieldMetadataValue(
|
||||
value: any,
|
||||
fieldMetadata: FieldMetadataInterface,
|
||||
|
||||
Reference in New Issue
Block a user