Page layout tab v2 (#16319)

# Introduction
Migrating `pageLayoutTab` to the v2 engine
- Types and constants
- Builder and validate
- Runner

Introduced a new `StrictSyncableEntity` that enforces that
`universalIdentifier` and `applicationId` are defined
As these entities are brand new we could enforce this rule already
This still requires a migration command to associate the existing
entities to custom workspace application instance and define
universalIdentifier

Handled retro-comp of the migration through a migration as upgrade
command fallback

---------

Co-authored-by: bosiraphael <raphael.bosi@gmail.com>
This commit is contained in:
Paul Rastoin
2025-12-04 17:37:16 +01:00
committed by GitHub
parent 1981cf0ed6
commit b2d785de4b
56 changed files with 1284 additions and 13 deletions
@@ -32,6 +32,7 @@ export const fromWorkspaceMigrationBuilderExceptionToMetadataValidationResponseE
invalidRole: 0,
invalidRoleTarget: 0,
totalErrors: 0,
invalidPageLayoutTab: 0,
},
errors: translatedReport,
};
@@ -15,6 +15,7 @@ import {
} from 'src/engine/workspace-manager/workspace-migration-v2/types/workspace-migration-orchestrator.type';
import { aggregateOrchestratorActionsReport } from 'src/engine/workspace-manager/workspace-migration-v2/utils/aggregate-orchestrator-actions-report.util';
import { WorkspaceMigrationV2AgentActionsBuilderService } from 'src/engine/workspace-manager/workspace-migration-v2/workspace-migration-builder-v2/builders/agent/workspace-migration-v2-agent-actions-builder.service';
import { WorkspaceMigrationV2PageLayoutTabActionsBuilderService } from 'src/engine/workspace-manager/workspace-migration-v2/workspace-migration-builder-v2/builders/page-layout-tab/workspace-migration-v2-page-layout-tab-actions-builder.service';
import { WorkspaceMigrationV2CronTriggerActionsBuilderService } from 'src/engine/workspace-manager/workspace-migration-v2/workspace-migration-builder-v2/builders/cron-trigger/workspace-migration-v2-cron-trigger-action-builder.service';
import { WorkspaceMigrationV2DatabaseEventTriggerActionsBuilderService } from 'src/engine/workspace-manager/workspace-migration-v2/workspace-migration-builder-v2/builders/database-event-trigger/workspace-migration-v2-database-event-trigger-actions-builder.service';
import { WorkspaceMigrationV2FieldActionsBuilderService } from 'src/engine/workspace-manager/workspace-migration-v2/workspace-migration-builder-v2/builders/field/workspace-migration-v2-field-actions-builder.service';
@@ -46,6 +47,7 @@ export class WorkspaceMigrationBuildOrchestratorService {
private readonly workspaceMigrationV2FieldActionsBuilderService: WorkspaceMigrationV2FieldActionsBuilderService,
private readonly workspaceMigrationV2RoleActionsBuilderService: WorkspaceMigrationV2RoleActionsBuilderService,
private readonly workspaceMigrationV2AgentActionsBuilderService: WorkspaceMigrationV2AgentActionsBuilderService,
private readonly workspaceMigrationV2PageLayoutTabActionsBuilderService: WorkspaceMigrationV2PageLayoutTabActionsBuilderService,
) {}
private setupOptimisticCache({
@@ -134,6 +136,7 @@ export class WorkspaceMigrationBuildOrchestratorService {
flatRoleMaps,
flatRoleTargetMaps,
flatAgentMaps,
flatPageLayoutTabMaps,
} = fromToAllFlatEntityMaps;
if (isDefined(flatObjectMetadataMaps)) {
@@ -608,6 +611,38 @@ export class WorkspaceMigrationBuildOrchestratorService {
}
}
if (isDefined(flatPageLayoutTabMaps)) {
const { from: fromFlatPageLayoutTabMaps, to: toFlatPageLayoutTabMaps } =
flatPageLayoutTabMaps;
const pageLayoutTabResult =
this.workspaceMigrationV2PageLayoutTabActionsBuilderService.validateAndBuild(
{
from: fromFlatPageLayoutTabMaps,
to: toFlatPageLayoutTabMaps,
buildOptions,
dependencyOptimisticFlatEntityMaps: undefined,
workspaceId,
},
);
this.mergeFlatEntityMapsAndRelatedFlatEntityMapsInAllFlatEntityMapsThroughMutation(
{
allFlatEntityMaps: optimisticAllFlatEntityMaps,
flatEntityMapsAndRelatedFlatEntityMaps:
pageLayoutTabResult.optimisticFlatEntityMapsAndRelatedFlatEntityMaps,
},
);
if (pageLayoutTabResult.status === 'fail') {
orchestratorFailureReport.pageLayoutTab.push(
...pageLayoutTabResult.errors,
);
} else {
orchestratorActionsReport.pageLayoutTab = pageLayoutTabResult.actions;
}
}
const allErrors = Object.values(orchestratorFailureReport);
if (allErrors.some((report) => report.length > 0)) {
@@ -702,6 +737,12 @@ export class WorkspaceMigrationBuildOrchestratorService {
...aggregatedOrchestratorActionsReport.agent.created,
...aggregatedOrchestratorActionsReport.agent.updated,
///
// Page layout tabs
...aggregatedOrchestratorActionsReport.pageLayoutTab.deleted,
...aggregatedOrchestratorActionsReport.pageLayoutTab.created,
...aggregatedOrchestratorActionsReport.pageLayoutTab.updated,
///
],
workspaceId,
},
@@ -0,0 +1,18 @@
import { type FlatPageLayoutTab } from 'src/engine/metadata-modules/flat-page-layout-tab/types/flat-page-layout-tab.type';
import { type FlatEntityPropertiesUpdates } from 'src/engine/metadata-modules/flat-entity/types/flat-entity-properties-updates.type';
export type UpdatePageLayoutTabAction = {
type: 'update_page_layout_tab';
flatEntityId: string;
flatEntityUpdates: FlatEntityPropertiesUpdates<'pageLayoutTab'>;
};
export type CreatePageLayoutTabAction = {
type: 'create_page_layout_tab';
flatEntity: FlatPageLayoutTab;
};
export type DeletePageLayoutTabAction = {
type: 'delete_page_layout_tab';
flatEntityId: string;
};
@@ -0,0 +1,113 @@
import { Injectable } from '@nestjs/common';
import { ALL_METADATA_NAME } from 'twenty-shared/metadata';
import { UpdatePageLayoutTabAction } from 'src/engine/workspace-manager/workspace-migration-v2/workspace-migration-builder-v2/builders/page-layout-tab/types/workspace-migration-page-layout-tab-action-v2.type';
import { WorkspaceEntityMigrationBuilderV2Service } from 'src/engine/workspace-manager/workspace-migration-v2/workspace-migration-builder-v2/services/workspace-entity-migration-builder-v2.service';
import { FlatEntityUpdateValidationArgs } from 'src/engine/workspace-manager/workspace-migration-v2/workspace-migration-builder-v2/types/flat-entity-update-validation-args.type';
import { FlatEntityValidationArgs } from 'src/engine/workspace-manager/workspace-migration-v2/workspace-migration-builder-v2/types/flat-entity-validation-args.type';
import { FlatEntityValidationReturnType } from 'src/engine/workspace-manager/workspace-migration-v2/workspace-migration-builder-v2/types/flat-entity-validation-result.type';
import { FlatPageLayoutTabValidatorService } from 'src/engine/workspace-manager/workspace-migration-v2/workspace-migration-builder-v2/validators/services/flat-page-layout-tab-validator.service';
@Injectable()
export class WorkspaceMigrationV2PageLayoutTabActionsBuilderService extends WorkspaceEntityMigrationBuilderV2Service<
typeof ALL_METADATA_NAME.pageLayoutTab
> {
constructor(
private readonly flatPageLayoutTabValidatorService: FlatPageLayoutTabValidatorService,
) {
super(ALL_METADATA_NAME.pageLayoutTab);
}
protected validateFlatEntityCreation(
args: FlatEntityValidationArgs<typeof ALL_METADATA_NAME.pageLayoutTab>,
): FlatEntityValidationReturnType<
typeof ALL_METADATA_NAME.pageLayoutTab,
'created'
> {
const validationResult =
this.flatPageLayoutTabValidatorService.validateFlatPageLayoutTabCreation(
args,
);
if (validationResult.errors.length > 0) {
return {
status: 'fail',
...validationResult,
};
}
const { flatEntityToValidate: flatPageLayoutTabToValidate } = args;
return {
status: 'success',
action: {
type: 'create_page_layout_tab',
flatEntity: flatPageLayoutTabToValidate,
},
};
}
protected validateFlatEntityDeletion(
args: FlatEntityValidationArgs<typeof ALL_METADATA_NAME.pageLayoutTab>,
): FlatEntityValidationReturnType<
typeof ALL_METADATA_NAME.pageLayoutTab,
'deleted'
> {
const validationResult =
this.flatPageLayoutTabValidatorService.validateFlatPageLayoutTabDeletion(
args,
);
if (validationResult.errors.length > 0) {
return {
status: 'fail',
...validationResult,
};
}
const { flatEntityToValidate: flatPageLayoutTabToValidate } = args;
return {
status: 'success',
action: {
type: 'delete_page_layout_tab',
flatEntityId: flatPageLayoutTabToValidate.id,
},
};
}
protected validateFlatEntityUpdate(
args: FlatEntityUpdateValidationArgs<
typeof ALL_METADATA_NAME.pageLayoutTab
>,
): FlatEntityValidationReturnType<
typeof ALL_METADATA_NAME.pageLayoutTab,
'updated'
> {
const validationResult =
this.flatPageLayoutTabValidatorService.validateFlatPageLayoutTabUpdate(
args,
);
if (validationResult.errors.length > 0) {
return {
status: 'fail',
...validationResult,
};
}
const { flatEntityId, flatEntityUpdates } = args;
const updatePageLayoutTabAction: UpdatePageLayoutTabAction = {
type: 'update_page_layout_tab',
flatEntityId,
flatEntityUpdates,
};
return {
status: 'success',
action: updatePageLayoutTabAction,
};
}
}
@@ -0,0 +1,104 @@
import { Injectable } from '@nestjs/common';
import { msg, t } from '@lingui/core/macro';
import { type ALL_METADATA_NAME } from 'twenty-shared/metadata';
import { isDefined } from 'twenty-shared/utils';
import { type FlatPageLayoutTab } from 'src/engine/metadata-modules/flat-page-layout-tab/types/flat-page-layout-tab.type';
import { findFlatEntityByIdInFlatEntityMaps } from 'src/engine/metadata-modules/flat-entity/utils/find-flat-entity-by-id-in-flat-entity-maps.util';
import { type FailedFlatEntityValidation } from 'src/engine/workspace-manager/workspace-migration-v2/workspace-migration-builder-v2/builders/types/failed-flat-entity-validation.type';
import { type FlatEntityUpdateValidationArgs } from 'src/engine/workspace-manager/workspace-migration-v2/workspace-migration-builder-v2/types/flat-entity-update-validation-args.type';
import { type FlatEntityValidationArgs } from 'src/engine/workspace-manager/workspace-migration-v2/workspace-migration-builder-v2/types/flat-entity-validation-args.type';
const PAGE_LAYOUT_TAB_EXCEPTION_CODE = {
PAGE_LAYOUT_TAB_NOT_FOUND: 'PAGE_LAYOUT_TAB_NOT_FOUND',
} as const;
@Injectable()
export class FlatPageLayoutTabValidatorService {
public validateFlatPageLayoutTabCreation({
flatEntityToValidate: flatPageLayoutTab,
}: FlatEntityValidationArgs<
typeof ALL_METADATA_NAME.pageLayoutTab
>): FailedFlatEntityValidation<FlatPageLayoutTab> {
const validationResult: FailedFlatEntityValidation<FlatPageLayoutTab> = {
type: 'create_page_layout_tab',
errors: [],
flatEntityMinimalInformation: {
id: flatPageLayoutTab.id,
title: flatPageLayoutTab.title,
},
};
return validationResult;
}
public validateFlatPageLayoutTabDeletion({
flatEntityToValidate,
optimisticFlatEntityMapsAndRelatedFlatEntityMaps: {
flatPageLayoutTabMaps: optimisticFlatPageLayoutTabMaps,
},
}: FlatEntityValidationArgs<
typeof ALL_METADATA_NAME.pageLayoutTab
>): FailedFlatEntityValidation<FlatPageLayoutTab> {
const validationResult: FailedFlatEntityValidation<FlatPageLayoutTab> = {
type: 'delete_page_layout_tab',
errors: [],
flatEntityMinimalInformation: {
id: flatEntityToValidate.id,
title: flatEntityToValidate.title,
},
};
const existingPageLayoutTab = findFlatEntityByIdInFlatEntityMaps({
flatEntityId: flatEntityToValidate.id,
flatEntityMaps: optimisticFlatPageLayoutTabMaps,
});
if (!isDefined(existingPageLayoutTab)) {
validationResult.errors.push({
code: PAGE_LAYOUT_TAB_EXCEPTION_CODE.PAGE_LAYOUT_TAB_NOT_FOUND,
message: t`Page layout tab not found`,
userFriendlyMessage: msg`Page layout tab not found`,
});
return validationResult;
}
return validationResult;
}
public validateFlatPageLayoutTabUpdate({
flatEntityId,
optimisticFlatEntityMapsAndRelatedFlatEntityMaps: {
flatPageLayoutTabMaps: optimisticFlatPageLayoutTabMaps,
},
}: FlatEntityUpdateValidationArgs<
typeof ALL_METADATA_NAME.pageLayoutTab
>): FailedFlatEntityValidation<FlatPageLayoutTab> {
const validationResult: FailedFlatEntityValidation<FlatPageLayoutTab> = {
type: 'update_page_layout_tab',
errors: [],
flatEntityMinimalInformation: {
id: flatEntityId,
},
};
const fromFlatPageLayoutTab = findFlatEntityByIdInFlatEntityMaps({
flatEntityId,
flatEntityMaps: optimisticFlatPageLayoutTabMaps,
});
if (!isDefined(fromFlatPageLayoutTab)) {
validationResult.errors.push({
code: PAGE_LAYOUT_TAB_EXCEPTION_CODE.PAGE_LAYOUT_TAB_NOT_FOUND,
message: t`Page layout tab not found`,
userFriendlyMessage: msg`Page layout tab not found`,
});
return validationResult;
}
return validationResult;
}
}
@@ -3,6 +3,7 @@ import { Module } from '@nestjs/common';
import { FeatureFlagModule } from 'src/engine/core-modules/feature-flag/feature-flag.module';
import { FlatFieldMetadataTypeValidatorService } from 'src/engine/metadata-modules/flat-field-metadata/services/flat-field-metadata-type-validator.service';
import { FlatAgentValidatorService } from 'src/engine/workspace-manager/workspace-migration-v2/workspace-migration-builder-v2/validators/services/flat-agent-validator.service';
import { FlatPageLayoutTabValidatorService } from 'src/engine/workspace-manager/workspace-migration-v2/workspace-migration-builder-v2/validators/services/flat-page-layout-tab-validator.service';
import { FlatCronTriggerValidatorService } from 'src/engine/workspace-manager/workspace-migration-v2/workspace-migration-builder-v2/validators/services/flat-cron-trigger-validator.service';
import { FlatDatabaseEventTriggerValidatorService } from 'src/engine/workspace-manager/workspace-migration-v2/workspace-migration-builder-v2/validators/services/flat-database-event-trigger-validator.service';
import { FlatFieldMetadataValidatorService } from 'src/engine/workspace-manager/workspace-migration-v2/workspace-migration-builder-v2/validators/services/flat-field-metadata-validator.service';
@@ -35,6 +36,7 @@ import { FlatViewValidatorService } from 'src/engine/workspace-manager/workspace
FlatRoleValidatorService,
FlatRoleTargetValidatorService,
FlatAgentValidatorService,
FlatPageLayoutTabValidatorService,
],
exports: [
FlatViewValidatorService,
@@ -52,6 +54,7 @@ import { FlatViewValidatorService } from 'src/engine/workspace-manager/workspace
FlatRoleValidatorService,
FlatRoleTargetValidatorService,
FlatAgentValidatorService,
FlatPageLayoutTabValidatorService,
],
})
export class WorkspaceMigrationBuilderValidatorsModule {}
@@ -3,6 +3,7 @@ import { Module } from '@nestjs/common';
import { FeatureFlagModule } from 'src/engine/core-modules/feature-flag/feature-flag.module';
import { FlatFieldMetadataTypeValidatorService } from 'src/engine/metadata-modules/flat-field-metadata/services/flat-field-metadata-type-validator.service';
import { WorkspaceMigrationV2AgentActionsBuilderService } from 'src/engine/workspace-manager/workspace-migration-v2/workspace-migration-builder-v2/builders/agent/workspace-migration-v2-agent-actions-builder.service';
import { WorkspaceMigrationV2PageLayoutTabActionsBuilderService } from 'src/engine/workspace-manager/workspace-migration-v2/workspace-migration-builder-v2/builders/page-layout-tab/workspace-migration-v2-page-layout-tab-actions-builder.service';
import { WorkspaceMigrationV2CronTriggerActionsBuilderService } from 'src/engine/workspace-manager/workspace-migration-v2/workspace-migration-builder-v2/builders/cron-trigger/workspace-migration-v2-cron-trigger-action-builder.service';
import { WorkspaceMigrationV2DatabaseEventTriggerActionsBuilderService } from 'src/engine/workspace-manager/workspace-migration-v2/workspace-migration-builder-v2/builders/database-event-trigger/workspace-migration-v2-database-event-trigger-actions-builder.service';
import { WorkspaceMigrationV2FieldActionsBuilderService } from 'src/engine/workspace-manager/workspace-migration-v2/workspace-migration-builder-v2/builders/field/workspace-migration-v2-field-actions-builder.service';
@@ -36,6 +37,7 @@ import { WorkspaceMigrationBuilderValidatorsModule } from 'src/engine/workspace-
WorkspaceMigrationV2RoleActionsBuilderService,
WorkspaceMigrationV2RoleTargetActionsBuilderService,
WorkspaceMigrationV2AgentActionsBuilderService,
WorkspaceMigrationV2PageLayoutTabActionsBuilderService,
],
exports: [
WorkspaceMigrationV2ViewActionsBuilderService,
@@ -52,6 +54,7 @@ import { WorkspaceMigrationBuilderValidatorsModule } from 'src/engine/workspace-
WorkspaceMigrationV2RoleActionsBuilderService,
WorkspaceMigrationV2RoleTargetActionsBuilderService,
WorkspaceMigrationV2AgentActionsBuilderService,
WorkspaceMigrationV2PageLayoutTabActionsBuilderService,
FlatFieldMetadataTypeValidatorService,
],
})
@@ -0,0 +1,61 @@
import { Injectable } from '@nestjs/common';
import {
OptimisticallyApplyActionOnAllFlatEntityMapsArgs,
WorkspaceMigrationRunnerActionHandler,
} from 'src/engine/workspace-manager/workspace-migration-v2/workspace-migration-runner-v2/interfaces/workspace-migration-runner-action-handler-service.interface';
import { PageLayoutTabEntity } from 'src/engine/core-modules/page-layout/entities/page-layout-tab.entity';
import { AllFlatEntityMaps } from 'src/engine/metadata-modules/flat-entity/types/all-flat-entity-maps.type';
import { addFlatEntityToFlatEntityMapsOrThrow } from 'src/engine/metadata-modules/flat-entity/utils/add-flat-entity-to-flat-entity-maps-or-throw.util';
import { CreatePageLayoutTabAction } from 'src/engine/workspace-manager/workspace-migration-v2/workspace-migration-builder-v2/builders/page-layout-tab/types/workspace-migration-page-layout-tab-action-v2.type';
import { WorkspaceMigrationActionRunnerArgs } from 'src/engine/workspace-manager/workspace-migration-v2/workspace-migration-runner-v2/types/workspace-migration-action-runner-args.type';
@Injectable()
export class CreatePageLayoutTabActionHandlerService extends WorkspaceMigrationRunnerActionHandler(
'create_page_layout_tab',
) {
constructor() {
super();
}
optimisticallyApplyActionOnAllFlatEntityMaps({
action,
allFlatEntityMaps,
}: OptimisticallyApplyActionOnAllFlatEntityMapsArgs<CreatePageLayoutTabAction>): Partial<AllFlatEntityMaps> {
const { flatPageLayoutTabMaps } = allFlatEntityMaps;
const { flatEntity } = action;
const updatedFlatPageLayoutTabMaps = addFlatEntityToFlatEntityMapsOrThrow({
flatEntity,
flatEntityMaps: flatPageLayoutTabMaps,
});
return {
flatPageLayoutTabMaps: updatedFlatPageLayoutTabMaps,
};
}
async executeForMetadata(
context: WorkspaceMigrationActionRunnerArgs<CreatePageLayoutTabAction>,
): Promise<void> {
const { action, queryRunner, workspaceId } = context;
const { flatEntity } = action;
const pageLayoutTabRepository =
queryRunner.manager.getRepository<PageLayoutTabEntity>(
PageLayoutTabEntity,
);
await pageLayoutTabRepository.insert({
...flatEntity,
workspaceId,
});
}
async executeForWorkspaceSchema(
_context: WorkspaceMigrationActionRunnerArgs<CreatePageLayoutTabAction>,
): Promise<void> {
return;
}
}
@@ -0,0 +1,59 @@
import { Injectable } from '@nestjs/common';
import {
OptimisticallyApplyActionOnAllFlatEntityMapsArgs,
WorkspaceMigrationRunnerActionHandler,
} from 'src/engine/workspace-manager/workspace-migration-v2/workspace-migration-runner-v2/interfaces/workspace-migration-runner-action-handler-service.interface';
import { PageLayoutTabEntity } from 'src/engine/core-modules/page-layout/entities/page-layout-tab.entity';
import { AllFlatEntityMaps } from 'src/engine/metadata-modules/flat-entity/types/all-flat-entity-maps.type';
import { deleteFlatEntityFromFlatEntityMapsOrThrow } from 'src/engine/metadata-modules/flat-entity/utils/delete-flat-entity-from-flat-entity-maps-or-throw.util';
import { DeletePageLayoutTabAction } from 'src/engine/workspace-manager/workspace-migration-v2/workspace-migration-builder-v2/builders/page-layout-tab/types/workspace-migration-page-layout-tab-action-v2.type';
import { WorkspaceMigrationActionRunnerArgs } from 'src/engine/workspace-manager/workspace-migration-v2/workspace-migration-runner-v2/types/workspace-migration-action-runner-args.type';
@Injectable()
export class DeletePageLayoutTabActionHandlerService extends WorkspaceMigrationRunnerActionHandler(
'delete_page_layout_tab',
) {
constructor() {
super();
}
optimisticallyApplyActionOnAllFlatEntityMaps({
action,
allFlatEntityMaps,
}: OptimisticallyApplyActionOnAllFlatEntityMapsArgs<DeletePageLayoutTabAction>): Partial<AllFlatEntityMaps> {
const { flatPageLayoutTabMaps } = allFlatEntityMaps;
const { flatEntityId } = action;
const updatedFlatPageLayoutTabMaps =
deleteFlatEntityFromFlatEntityMapsOrThrow({
entityToDeleteId: flatEntityId,
flatEntityMaps: flatPageLayoutTabMaps,
});
return {
flatPageLayoutTabMaps: updatedFlatPageLayoutTabMaps,
};
}
async executeForMetadata(
context: WorkspaceMigrationActionRunnerArgs<DeletePageLayoutTabAction>,
): Promise<void> {
const { action, queryRunner, workspaceId } = context;
const { flatEntityId } = action;
const pageLayoutTabRepository =
queryRunner.manager.getRepository<PageLayoutTabEntity>(
PageLayoutTabEntity,
);
await pageLayoutTabRepository.delete({ id: flatEntityId, workspaceId });
}
async executeForWorkspaceSchema(
_context: WorkspaceMigrationActionRunnerArgs<DeletePageLayoutTabAction>,
): Promise<void> {
return;
}
}
@@ -0,0 +1,74 @@
import { Injectable } from '@nestjs/common';
import {
OptimisticallyApplyActionOnAllFlatEntityMapsArgs,
WorkspaceMigrationRunnerActionHandler,
} from 'src/engine/workspace-manager/workspace-migration-v2/workspace-migration-runner-v2/interfaces/workspace-migration-runner-action-handler-service.interface';
import { PageLayoutTabEntity } from 'src/engine/core-modules/page-layout/entities/page-layout-tab.entity';
import { AllFlatEntityMaps } from 'src/engine/metadata-modules/flat-entity/types/all-flat-entity-maps.type';
import { findFlatEntityByIdInFlatEntityMapsOrThrow } from 'src/engine/metadata-modules/flat-entity/utils/find-flat-entity-by-id-in-flat-entity-maps-or-throw.util';
import { replaceFlatEntityInFlatEntityMapsOrThrow } from 'src/engine/metadata-modules/flat-entity/utils/replace-flat-entity-in-flat-entity-maps-or-throw.util';
import { UpdatePageLayoutTabAction } from 'src/engine/workspace-manager/workspace-migration-v2/workspace-migration-builder-v2/builders/page-layout-tab/types/workspace-migration-page-layout-tab-action-v2.type';
import { WorkspaceMigrationActionRunnerArgs } from 'src/engine/workspace-manager/workspace-migration-v2/workspace-migration-runner-v2/types/workspace-migration-action-runner-args.type';
import { fromFlatEntityPropertiesUpdatesToPartialFlatEntity } from 'src/engine/workspace-manager/workspace-migration-v2/workspace-migration-runner-v2/utils/from-flat-entity-properties-updates-to-partial-flat-entity';
@Injectable()
export class UpdatePageLayoutTabActionHandlerService extends WorkspaceMigrationRunnerActionHandler(
'update_page_layout_tab',
) {
optimisticallyApplyActionOnAllFlatEntityMaps({
action,
allFlatEntityMaps,
}: OptimisticallyApplyActionOnAllFlatEntityMapsArgs<UpdatePageLayoutTabAction>): Partial<AllFlatEntityMaps> {
const { flatPageLayoutTabMaps } = allFlatEntityMaps;
const { flatEntityId, flatEntityUpdates } = action;
const existingPageLayoutTab = findFlatEntityByIdInFlatEntityMapsOrThrow({
flatEntityId,
flatEntityMaps: flatPageLayoutTabMaps,
});
const updatedPageLayoutTab = {
...existingPageLayoutTab,
...fromFlatEntityPropertiesUpdatesToPartialFlatEntity({
updates: flatEntityUpdates,
}),
};
const updatedFlatPageLayoutTabMaps =
replaceFlatEntityInFlatEntityMapsOrThrow({
flatEntity: updatedPageLayoutTab,
flatEntityMaps: flatPageLayoutTabMaps,
});
return {
flatPageLayoutTabMaps: updatedFlatPageLayoutTabMaps,
};
}
async executeForMetadata(
context: WorkspaceMigrationActionRunnerArgs<UpdatePageLayoutTabAction>,
): Promise<void> {
const { action, queryRunner, workspaceId } = context;
const { flatEntityId, flatEntityUpdates } = action;
const pageLayoutTabRepository =
queryRunner.manager.getRepository<PageLayoutTabEntity>(
PageLayoutTabEntity,
);
await pageLayoutTabRepository.update(
{ id: flatEntityId, workspaceId },
fromFlatEntityPropertiesUpdatesToPartialFlatEntity({
updates: flatEntityUpdates,
}),
);
}
async executeForWorkspaceSchema(
_context: WorkspaceMigrationActionRunnerArgs<UpdatePageLayoutTabAction>,
): Promise<void> {
return;
}
}
@@ -4,6 +4,9 @@ import { WorkspaceSchemaManagerModule } from 'src/engine/twenty-orm/workspace-sc
import { CreateAgentActionHandlerService } from 'src/engine/workspace-manager/workspace-migration-v2/workspace-migration-runner-v2/action-handlers/agent/services/create-agent-action-handler.service';
import { DeleteAgentActionHandlerService } from 'src/engine/workspace-manager/workspace-migration-v2/workspace-migration-runner-v2/action-handlers/agent/services/delete-agent-action-handler.service';
import { UpdateAgentActionHandlerService } from 'src/engine/workspace-manager/workspace-migration-v2/workspace-migration-runner-v2/action-handlers/agent/services/update-agent-action-handler.service';
import { CreatePageLayoutTabActionHandlerService } from 'src/engine/workspace-manager/workspace-migration-v2/workspace-migration-runner-v2/action-handlers/page-layout-tab/services/create-page-layout-tab-action-handler.service';
import { DeletePageLayoutTabActionHandlerService } from 'src/engine/workspace-manager/workspace-migration-v2/workspace-migration-runner-v2/action-handlers/page-layout-tab/services/delete-page-layout-tab-action-handler.service';
import { UpdatePageLayoutTabActionHandlerService } from 'src/engine/workspace-manager/workspace-migration-v2/workspace-migration-runner-v2/action-handlers/page-layout-tab/services/update-page-layout-tab-action-handler.service';
import { CreateCronTriggerActionHandlerService } from 'src/engine/workspace-manager/workspace-migration-v2/workspace-migration-runner-v2/action-handlers/cron-trigger/services/create-cron-trigger-action-handler.service';
import { DeleteCronTriggerActionHandlerService } from 'src/engine/workspace-manager/workspace-migration-v2/workspace-migration-runner-v2/action-handlers/cron-trigger/services/delete-cron-trigger-action-handler.service';
import { UpdateCronTriggerActionHandlerService } from 'src/engine/workspace-manager/workspace-migration-v2/workspace-migration-runner-v2/action-handlers/cron-trigger/services/update-cron-trigger-action-handler.service';
@@ -100,6 +103,10 @@ import { UpdateViewActionHandlerService } from 'src/engine/workspace-manager/wor
CreateAgentActionHandlerService,
UpdateAgentActionHandlerService,
DeleteAgentActionHandlerService,
CreatePageLayoutTabActionHandlerService,
UpdatePageLayoutTabActionHandlerService,
DeletePageLayoutTabActionHandlerService,
],
})
export class WorkspaceSchemaMigrationRunnerActionHandlersModule {}