Enable deletion of relation fields (#5338)

In this PR
1. Enable deletion of relation fields in the product and via the api
(migration part was missing in the api)
3. Change wording, only use "deactivate" and "delete" everywhere (and
not a mix of the two + "disable", "erase")
This commit is contained in:
Marie
2024-05-13 17:43:51 +02:00
committed by GitHub
parent 0018ec78b0
commit b9154f315e
30 changed files with 519 additions and 117 deletions

View File

@ -2,10 +2,12 @@ import { Field, ObjectType, registerEnumType } from '@nestjs/graphql';
import { IsEnum, IsNotEmpty } from 'class-validator';
import { Relation } from 'typeorm';
import { IDField } from '@ptc-org/nestjs-query-graphql';
import { FieldMetadataDTO } from 'src/engine/metadata-modules/field-metadata/dtos/field-metadata.dto';
import { ObjectMetadataDTO } from 'src/engine/metadata-modules/object-metadata/dtos/object-metadata.dto';
import { RelationMetadataType } from 'src/engine/metadata-modules/relation-metadata/relation-metadata.entity';
import { UUIDScalarType } from 'src/engine/api/graphql/workspace-schema-builder/graphql-types/scalars';
export enum RelationDefinitionType {
ONE_TO_ONE = RelationMetadataType.ONE_TO_ONE,
@ -21,6 +23,10 @@ registerEnumType(RelationDefinitionType, {
@ObjectType('RelationDefinition')
export class RelationDefinitionDTO {
@IsNotEmpty()
@IDField(() => UUIDScalarType)
relationId: string;
@IsNotEmpty()
@Field(() => ObjectMetadataDTO)
sourceObjectMetadata: Relation<ObjectMetadataDTO>;

View File

@ -529,6 +529,7 @@ export class FieldMetadataService extends TypeOrmQueryService<FieldMetadataEntit
: RelationDefinitionType.ONE_TO_MANY;
return {
relationId: relationMetadata.id,
sourceObjectMetadata: relationMetadata.fromObjectMetadata,
sourceFieldMetadata: relationMetadata.fromFieldMetadata,
targetObjectMetadata: relationMetadata.toObjectMetadata,
@ -542,6 +543,7 @@ export class FieldMetadataService extends TypeOrmQueryService<FieldMetadataEntit
: RelationDefinitionType.MANY_TO_ONE;
return {
relationId: relationMetadata.id,
sourceObjectMetadata: relationMetadata.toObjectMetadata,
sourceFieldMetadata: relationMetadata.toFieldMetadata,
targetObjectMetadata: relationMetadata.fromObjectMetadata,

View File

@ -13,6 +13,7 @@ import { WorkspaceMigrationModule } from 'src/engine/metadata-modules/workspace-
import { WorkspaceMigrationRunnerModule } from 'src/engine/workspace-manager/workspace-migration-runner/workspace-migration-runner.module';
import { WorkspaceCacheVersionModule } from 'src/engine/metadata-modules/workspace-cache-version/workspace-cache-version.module';
import { RelationMetadataResolver } from 'src/engine/metadata-modules/relation-metadata/relation-metadata.resolver';
import { FieldMetadataEntity } from 'src/engine/metadata-modules/field-metadata/field-metadata.entity';
import { RelationMetadataService } from './relation-metadata.service';
import { RelationMetadataEntity } from './relation-metadata.entity';
@ -25,7 +26,7 @@ import { RelationMetadataDTO } from './dtos/relation-metadata.dto';
NestjsQueryGraphQLModule.forFeature({
imports: [
NestjsQueryTypeOrmModule.forFeature(
[RelationMetadataEntity],
[RelationMetadataEntity, FieldMetadataEntity],
'metadata',
),
ObjectMetadataModule,

View File

@ -16,9 +16,13 @@ import { FieldMetadataService } from 'src/engine/metadata-modules/field-metadata
import { CreateRelationInput } from 'src/engine/metadata-modules/relation-metadata/dtos/create-relation.input';
import { WorkspaceMigrationRunnerService } from 'src/engine/workspace-manager/workspace-migration-runner/workspace-migration-runner.service';
import { WorkspaceMigrationService } from 'src/engine/metadata-modules/workspace-migration/workspace-migration.service';
import { FieldMetadataType } from 'src/engine/metadata-modules/field-metadata/field-metadata.entity';
import {
FieldMetadataEntity,
FieldMetadataType,
} from 'src/engine/metadata-modules/field-metadata/field-metadata.entity';
import {
WorkspaceMigrationColumnActionType,
WorkspaceMigrationColumnDrop,
WorkspaceMigrationTableActionType,
} from 'src/engine/metadata-modules/workspace-migration/workspace-migration.entity';
import { ObjectMetadataEntity } from 'src/engine/metadata-modules/object-metadata/object-metadata.entity';
@ -39,6 +43,8 @@ export class RelationMetadataService extends TypeOrmQueryService<RelationMetadat
constructor(
@InjectRepository(RelationMetadataEntity, 'metadata')
private readonly relationMetadataRepository: Repository<RelationMetadataEntity>,
@InjectRepository(FieldMetadataEntity, 'metadata')
private readonly fieldMetadataRepository: Repository<FieldMetadataEntity>,
private readonly objectMetadataService: ObjectMetadataService,
private readonly fieldMetadataService: FieldMetadataService,
private readonly workspaceMigrationService: WorkspaceMigrationService,
@ -242,7 +248,7 @@ export class RelationMetadataService extends TypeOrmQueryService<RelationMetadat
label: relationMetadataInput[`${relationDirection}Label`],
description: relationMetadataInput[`${relationDirection}Description`],
icon: relationMetadataInput[`${relationDirection}Icon`],
isCustom: true,
isCustom,
isActive: true,
isNullable: true,
type: FieldMetadataType.RELATION,
@ -320,13 +326,36 @@ export class RelationMetadataService extends TypeOrmQueryService<RelationMetadat
// TODO: This logic is duplicated with the BeforeDeleteOneRelation hook
const relationMetadata = await this.relationMetadataRepository.findOne({
where: { id },
relations: ['fromFieldMetadata', 'toFieldMetadata'],
relations: [
'fromFieldMetadata',
'toFieldMetadata',
'fromObjectMetadata',
'toObjectMetadata',
],
});
if (!relationMetadata) {
throw new NotFoundException('Relation does not exist');
}
const foreignKeyFieldMetadataName = `${camelCase(
relationMetadata.toFieldMetadata.name,
)}Id`;
const foreignKeyFieldMetadata = await this.fieldMetadataRepository.findOne({
where: {
name: foreignKeyFieldMetadataName,
objectMetadataId: relationMetadata.toObjectMetadataId,
workspaceId: relationMetadata.workspaceId,
},
});
if (!foreignKeyFieldMetadata) {
throw new NotFoundException(
`Foreign key fieldMetadata not found (${foreignKeyFieldMetadataName}) for relation ${relationMetadata.id}`,
);
}
await super.deleteOne(id);
// TODO: Move to a cdc scheduler
@ -335,10 +364,26 @@ export class RelationMetadataService extends TypeOrmQueryService<RelationMetadat
in: [
relationMetadata.fromFieldMetadataId,
relationMetadata.toFieldMetadataId,
foreignKeyFieldMetadata.id,
],
},
});
const columnName = `${camelCase(relationMetadata.toFieldMetadata.name)}Id`;
const objectTargetTable = computeObjectTargetTable(
relationMetadata.toObjectMetadata,
);
await this.deleteRelationWorkspaceCustomMigration(
relationMetadata,
objectTargetTable,
columnName,
);
await this.workspaceMigrationRunnerService.executeMigrationFromPendingMigrations(
relationMetadata.workspaceId,
);
await this.workspaceCacheVersionService.incrementVersion(workspaceId);
// TODO: Return id for delete endpoints
@ -383,4 +428,30 @@ export class RelationMetadataService extends TypeOrmQueryService<RelationMetadat
return mappedResult;
}
private async deleteRelationWorkspaceCustomMigration(
relationMetadata: RelationMetadataEntity,
objectTargetTable: string,
columnName: string,
) {
await this.workspaceMigrationService.createCustomMigration(
generateMigrationName(
`delete-relation-from-${relationMetadata.fromObjectMetadata.nameSingular}-to-${relationMetadata.toObjectMetadata.nameSingular}`,
),
relationMetadata.workspaceId,
[
// Delete the column
{
name: objectTargetTable,
action: WorkspaceMigrationTableActionType.ALTER,
columns: [
{
action: WorkspaceMigrationColumnActionType.DROP,
columnName,
} satisfies WorkspaceMigrationColumnDrop,
],
},
],
);
}
}