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:
@ -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>;
|
||||
|
||||
@ -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,
|
||||
|
||||
@ -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,
|
||||
|
||||
@ -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,
|
||||
],
|
||||
},
|
||||
],
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user