From 435e21d23fa79d307bacf17bdd6d67d5a673e523 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Rapha=C3=ABl=20Bosi?= <71827178+bosiraphael@users.noreply.github.com> Date: Wed, 25 Feb 2026 15:01:50 +0100 Subject: [PATCH] [FRONT COMPONENTS] Serialize relation between widget and front component (#18228) This allows us to define page layout widgets of type front component in an app with the front component universal identifier. --- ...ny-or-all-flat-entity-maps-cache.module.ts | 2 ++ .../flat-page-layout-widget.module.ts | 2 ++ ...at-page-layout-widget-map-cache.service.ts | 13 ++++++++ ...-flat-page-layout-widget-to-create.util.ts | 4 +++ ...uration-to-universal-configuration.util.ts | 25 ++++++++++++++- ...-entity-to-flat-page-layout-widget.util.ts | 3 ++ ...e-layout-widget-to-update-or-throw.util.ts | 4 +++ .../dtos/front-component-configuration.dto.ts | 7 ++-- .../services/page-layout-widget.service.ts | 6 ++++ .../page-layout-duplication.service.ts | 6 ++++ .../services/page-layout-update.service.ts | 14 ++++++++ ...ge-layout-widget-action-handler.service.ts | 1 + ...ge-layout-widget-action-handler.service.ts | 2 ++ ...t-page-layout-widget-configuration.util.ts | 32 ++++++++++++++++++- .../page-layout-widget-configuration.type.ts | 2 +- 15 files changed, 118 insertions(+), 5 deletions(-) diff --git a/packages/twenty-server/src/engine/metadata-modules/flat-entity/services/workspace-many-or-all-flat-entity-maps-cache.module.ts b/packages/twenty-server/src/engine/metadata-modules/flat-entity/services/workspace-many-or-all-flat-entity-maps-cache.module.ts index e44f7925a1..db20232c9c 100644 --- a/packages/twenty-server/src/engine/metadata-modules/flat-entity/services/workspace-many-or-all-flat-entity-maps-cache.module.ts +++ b/packages/twenty-server/src/engine/metadata-modules/flat-entity/services/workspace-many-or-all-flat-entity-maps-cache.module.ts @@ -3,6 +3,7 @@ import { TypeOrmModule } from '@nestjs/typeorm'; import { ApplicationEntity } from 'src/engine/core-modules/application/application.entity'; import { FieldMetadataEntity } from 'src/engine/metadata-modules/field-metadata/field-metadata.entity'; +import { FrontComponentEntity } from 'src/engine/metadata-modules/front-component/entities/front-component.entity'; import { WorkspaceManyOrAllFlatEntityMapsCacheService } from 'src/engine/metadata-modules/flat-entity/services/workspace-many-or-all-flat-entity-maps-cache.service'; import { WorkspaceFlatFieldMetadataMapCacheService } from 'src/engine/metadata-modules/flat-field-metadata/services/workspace-flat-field-metadata-map-cache.service'; import { WorkspaceFlatIndexMapCacheService } from 'src/engine/metadata-modules/flat-index-metadata/services/workspace-flat-index-map-cache.service'; @@ -56,6 +57,7 @@ import { WorkspaceCacheModule } from 'src/engine/workspace-cache/workspace-cache RowLevelPermissionPredicateGroupEntity, ApplicationEntity, RoleEntity, + FrontComponentEntity, ]), ], providers: [ diff --git a/packages/twenty-server/src/engine/metadata-modules/flat-page-layout-widget/flat-page-layout-widget.module.ts b/packages/twenty-server/src/engine/metadata-modules/flat-page-layout-widget/flat-page-layout-widget.module.ts index 2556259802..1cfc697817 100644 --- a/packages/twenty-server/src/engine/metadata-modules/flat-page-layout-widget/flat-page-layout-widget.module.ts +++ b/packages/twenty-server/src/engine/metadata-modules/flat-page-layout-widget/flat-page-layout-widget.module.ts @@ -5,6 +5,7 @@ import { ApplicationEntity } from 'src/engine/core-modules/application/applicati import { FieldMetadataEntity } from 'src/engine/metadata-modules/field-metadata/field-metadata.entity'; import { FlatPageLayoutWidgetTypeValidatorService } from 'src/engine/metadata-modules/flat-page-layout-widget/services/flat-page-layout-widget-type-validator.service'; import { WorkspaceFlatPageLayoutWidgetMapCacheService } from 'src/engine/metadata-modules/flat-page-layout-widget/services/workspace-flat-page-layout-widget-map-cache.service'; +import { FrontComponentEntity } from 'src/engine/metadata-modules/front-component/entities/front-component.entity'; import { ObjectMetadataEntity } from 'src/engine/metadata-modules/object-metadata/object-metadata.entity'; import { PageLayoutTabEntity } from 'src/engine/metadata-modules/page-layout-tab/entities/page-layout-tab.entity'; import { PageLayoutWidgetEntity } from 'src/engine/metadata-modules/page-layout-widget/entities/page-layout-widget.entity'; @@ -18,6 +19,7 @@ import { ViewEntity } from 'src/engine/metadata-modules/view/entities/view.entit PageLayoutTabEntity, ObjectMetadataEntity, FieldMetadataEntity, + FrontComponentEntity, ViewEntity, ]), ], diff --git a/packages/twenty-server/src/engine/metadata-modules/flat-page-layout-widget/services/workspace-flat-page-layout-widget-map-cache.service.ts b/packages/twenty-server/src/engine/metadata-modules/flat-page-layout-widget/services/workspace-flat-page-layout-widget-map-cache.service.ts index e6835d4426..17fa17c916 100644 --- a/packages/twenty-server/src/engine/metadata-modules/flat-page-layout-widget/services/workspace-flat-page-layout-widget-map-cache.service.ts +++ b/packages/twenty-server/src/engine/metadata-modules/flat-page-layout-widget/services/workspace-flat-page-layout-widget-map-cache.service.ts @@ -10,6 +10,7 @@ import { FieldMetadataEntity } from 'src/engine/metadata-modules/field-metadata/ import { createEmptyFlatEntityMaps } from 'src/engine/metadata-modules/flat-entity/constant/create-empty-flat-entity-maps.constant'; import { FlatPageLayoutWidgetMaps } from 'src/engine/metadata-modules/flat-page-layout-widget/types/flat-page-layout-widget-maps.type'; import { fromPageLayoutWidgetEntityToFlatPageLayoutWidget } from 'src/engine/metadata-modules/flat-page-layout-widget/utils/from-page-layout-widget-entity-to-flat-page-layout-widget.util'; +import { FrontComponentEntity } from 'src/engine/metadata-modules/front-component/entities/front-component.entity'; import { ObjectMetadataEntity } from 'src/engine/metadata-modules/object-metadata/object-metadata.entity'; import { PageLayoutTabEntity } from 'src/engine/metadata-modules/page-layout-tab/entities/page-layout-tab.entity'; import { PageLayoutWidgetEntity } from 'src/engine/metadata-modules/page-layout-widget/entities/page-layout-widget.entity'; @@ -32,6 +33,8 @@ export class WorkspaceFlatPageLayoutWidgetMapCacheService extends WorkspaceCache private readonly objectMetadataRepository: Repository, @InjectRepository(FieldMetadataEntity) private readonly fieldMetadataRepository: Repository, + @InjectRepository(FrontComponentEntity) + private readonly frontComponentRepository: Repository, @InjectRepository(ViewEntity) private readonly viewRepository: Repository, ) { @@ -47,6 +50,7 @@ export class WorkspaceFlatPageLayoutWidgetMapCacheService extends WorkspaceCache pageLayoutTabs, objectMetadatas, fieldMetadatas, + frontComponents, views, ] = await Promise.all([ this.pageLayoutWidgetRepository.find({ @@ -73,6 +77,11 @@ export class WorkspaceFlatPageLayoutWidgetMapCacheService extends WorkspaceCache select: ['id', 'universalIdentifier'], withDeleted: true, }), + this.frontComponentRepository.find({ + where: { workspaceId }, + select: ['id', 'universalIdentifier'], + withDeleted: true, + }), this.viewRepository.find({ where: { workspaceId }, select: ['id', 'universalIdentifier'], @@ -89,6 +98,9 @@ export class WorkspaceFlatPageLayoutWidgetMapCacheService extends WorkspaceCache const fieldMetadataUniversalIdentifierById = Object.fromEntries( createIdToUniversalIdentifierMap(fieldMetadatas), ); + const frontComponentUniversalIdentifierById = Object.fromEntries( + createIdToUniversalIdentifierMap(frontComponents), + ); const viewUniversalIdentifierById = Object.fromEntries( createIdToUniversalIdentifierMap(views), ); @@ -103,6 +115,7 @@ export class WorkspaceFlatPageLayoutWidgetMapCacheService extends WorkspaceCache pageLayoutTabIdToUniversalIdentifierMap, objectMetadataIdToUniversalIdentifierMap, fieldMetadataUniversalIdentifierById, + frontComponentUniversalIdentifierById, viewUniversalIdentifierById, }); diff --git a/packages/twenty-server/src/engine/metadata-modules/flat-page-layout-widget/utils/from-create-page-layout-widget-input-to-flat-page-layout-widget-to-create.util.ts b/packages/twenty-server/src/engine/metadata-modules/flat-page-layout-widget/utils/from-create-page-layout-widget-input-to-flat-page-layout-widget-to-create.util.ts index 9cdca5db77..1d1a4fe87a 100644 --- a/packages/twenty-server/src/engine/metadata-modules/flat-page-layout-widget/utils/from-create-page-layout-widget-input-to-flat-page-layout-widget-to-create.util.ts +++ b/packages/twenty-server/src/engine/metadata-modules/flat-page-layout-widget/utils/from-create-page-layout-widget-input-to-flat-page-layout-widget-to-create.util.ts @@ -19,6 +19,7 @@ export type FromCreatePageLayoutWidgetInputToFlatPageLayoutWidgetToCreateArgs = | 'flatPageLayoutTabMaps' | 'flatObjectMetadataMaps' | 'flatFieldMetadataMaps' + | 'flatFrontComponentMaps' | 'flatViewFieldGroupMaps' | 'flatViewMaps' >; @@ -30,6 +31,7 @@ export const fromCreatePageLayoutWidgetInputToFlatPageLayoutWidgetToCreate = ({ flatPageLayoutTabMaps, flatObjectMetadataMaps, flatFieldMetadataMaps, + flatFrontComponentMaps, flatViewFieldGroupMaps, flatViewMaps, }: FromCreatePageLayoutWidgetInputToFlatPageLayoutWidgetToCreateArgs): FlatPageLayoutWidget => { @@ -82,6 +84,8 @@ export const fromCreatePageLayoutWidgetInputToFlatPageLayoutWidgetToCreate = ({ configuration: createPageLayoutWidgetInput.configuration, fieldMetadataUniversalIdentifierById: flatFieldMetadataMaps.universalIdentifierById, + frontComponentUniversalIdentifierById: + flatFrontComponentMaps.universalIdentifierById, viewFieldGroupUniversalIdentifierById: flatViewFieldGroupMaps.universalIdentifierById, viewUniversalIdentifierById: flatViewMaps.universalIdentifierById, diff --git a/packages/twenty-server/src/engine/metadata-modules/flat-page-layout-widget/utils/from-page-layout-widget-configuration-to-universal-configuration.util.ts b/packages/twenty-server/src/engine/metadata-modules/flat-page-layout-widget/utils/from-page-layout-widget-configuration-to-universal-configuration.util.ts index 93e2005be7..c3bacdc926 100644 --- a/packages/twenty-server/src/engine/metadata-modules/flat-page-layout-widget/utils/from-page-layout-widget-configuration-to-universal-configuration.util.ts +++ b/packages/twenty-server/src/engine/metadata-modules/flat-page-layout-widget/utils/from-page-layout-widget-configuration-to-universal-configuration.util.ts @@ -73,12 +73,14 @@ const convertChartFilterToUniversalFilter = ({ export const fromPageLayoutWidgetConfigurationToUniversalConfiguration = ({ configuration, fieldMetadataUniversalIdentifierById, + frontComponentUniversalIdentifierById = {}, viewFieldGroupUniversalIdentifierById = {}, viewUniversalIdentifierById = {}, shouldThrowOnMissingIdentifier = false, }: { configuration: PageLayoutWidgetConfiguration; fieldMetadataUniversalIdentifierById: Partial>; + frontComponentUniversalIdentifierById?: Partial>; viewFieldGroupUniversalIdentifierById?: Partial>; viewUniversalIdentifierById?: Partial>; shouldThrowOnMissingIdentifier?: boolean; @@ -326,6 +328,28 @@ export const fromPageLayoutWidgetConfigurationToUniversalConfiguration = ({ }; } + case WidgetConfigurationType.FRONT_COMPONENT: { + const { frontComponentId, ...rest } = configuration; + + const frontComponentUniversalIdentifier: string | null = + frontComponentUniversalIdentifierById[frontComponentId] ?? null; + + if ( + !isDefined(frontComponentUniversalIdentifier) && + shouldThrowOnMissingIdentifier + ) { + throw new FlatEntityMapsException( + `Front component universal identifier not found for id: ${frontComponentId}`, + FlatEntityMapsExceptionCode.RELATION_UNIVERSAL_IDENTIFIER_NOT_FOUND, + ); + } + + return { + ...rest, + frontComponentUniversalIdentifier, + }; + } + case WidgetConfigurationType.VIEW: case WidgetConfigurationType.FIELD: case WidgetConfigurationType.TIMELINE: @@ -338,7 +362,6 @@ export const fromPageLayoutWidgetConfigurationToUniversalConfiguration = ({ case WidgetConfigurationType.WORKFLOW: case WidgetConfigurationType.WORKFLOW_VERSION: case WidgetConfigurationType.WORKFLOW_RUN: - case WidgetConfigurationType.FRONT_COMPONENT: case WidgetConfigurationType.IFRAME: case WidgetConfigurationType.STANDALONE_RICH_TEXT: return configuration; diff --git a/packages/twenty-server/src/engine/metadata-modules/flat-page-layout-widget/utils/from-page-layout-widget-entity-to-flat-page-layout-widget.util.ts b/packages/twenty-server/src/engine/metadata-modules/flat-page-layout-widget/utils/from-page-layout-widget-entity-to-flat-page-layout-widget.util.ts index be0b68a819..db8f9cac22 100644 --- a/packages/twenty-server/src/engine/metadata-modules/flat-page-layout-widget/utils/from-page-layout-widget-entity-to-flat-page-layout-widget.util.ts +++ b/packages/twenty-server/src/engine/metadata-modules/flat-page-layout-widget/utils/from-page-layout-widget-entity-to-flat-page-layout-widget.util.ts @@ -12,6 +12,7 @@ import { type FromEntityToFlatEntityArgs } from 'src/engine/workspace-cache/type type FromPageLayoutWidgetEntityToFlatPageLayoutWidgetArgs = FromEntityToFlatEntityArgs<'pageLayoutWidget'> & { fieldMetadataUniversalIdentifierById: Partial>; + frontComponentUniversalIdentifierById?: Partial>; viewFieldGroupUniversalIdentifierById?: Partial>; viewUniversalIdentifierById?: Partial>; }; @@ -22,6 +23,7 @@ export const fromPageLayoutWidgetEntityToFlatPageLayoutWidget = ({ pageLayoutTabIdToUniversalIdentifierMap, objectMetadataIdToUniversalIdentifierMap, fieldMetadataUniversalIdentifierById, + frontComponentUniversalIdentifierById, viewFieldGroupUniversalIdentifierById, viewUniversalIdentifierById, }: FromPageLayoutWidgetEntityToFlatPageLayoutWidgetArgs): FlatPageLayoutWidget => { @@ -74,6 +76,7 @@ export const fromPageLayoutWidgetEntityToFlatPageLayoutWidget = ({ fromPageLayoutWidgetConfigurationToUniversalConfiguration({ configuration: pageLayoutWidgetEntityWithoutRelations.configuration, fieldMetadataUniversalIdentifierById, + frontComponentUniversalIdentifierById, viewFieldGroupUniversalIdentifierById, viewUniversalIdentifierById, }); diff --git a/packages/twenty-server/src/engine/metadata-modules/flat-page-layout-widget/utils/from-update-page-layout-widget-input-to-flat-page-layout-widget-to-update-or-throw.util.ts b/packages/twenty-server/src/engine/metadata-modules/flat-page-layout-widget/utils/from-update-page-layout-widget-input-to-flat-page-layout-widget-to-update-or-throw.util.ts index 7045ee5481..dd5c40d1c7 100644 --- a/packages/twenty-server/src/engine/metadata-modules/flat-page-layout-widget/utils/from-update-page-layout-widget-input-to-flat-page-layout-widget-to-update-or-throw.util.ts +++ b/packages/twenty-server/src/engine/metadata-modules/flat-page-layout-widget/utils/from-update-page-layout-widget-input-to-flat-page-layout-widget-to-update-or-throw.util.ts @@ -30,6 +30,7 @@ export const fromUpdatePageLayoutWidgetInputToFlatPageLayoutWidgetToUpdateOrThro flatPageLayoutWidgetMaps, flatObjectMetadataMaps, flatFieldMetadataMaps, + flatFrontComponentMaps, flatViewFieldGroupMaps, flatViewMaps, }: { @@ -39,6 +40,7 @@ export const fromUpdatePageLayoutWidgetInputToFlatPageLayoutWidgetToUpdateOrThro AllFlatEntityMaps, | 'flatObjectMetadataMaps' | 'flatFieldMetadataMaps' + | 'flatFrontComponentMaps' | 'flatViewFieldGroupMaps' | 'flatViewMaps' >): FlatPageLayoutWidget => { @@ -102,6 +104,8 @@ export const fromUpdatePageLayoutWidgetInputToFlatPageLayoutWidgetToUpdateOrThro configuration: flatPageLayoutWidgetToUpdate.configuration, fieldMetadataUniversalIdentifierById: flatFieldMetadataMaps.universalIdentifierById, + frontComponentUniversalIdentifierById: + flatFrontComponentMaps.universalIdentifierById, viewFieldGroupUniversalIdentifierById: flatViewFieldGroupMaps.universalIdentifierById, viewUniversalIdentifierById: flatViewMaps.universalIdentifierById, diff --git a/packages/twenty-server/src/engine/metadata-modules/page-layout-widget/dtos/front-component-configuration.dto.ts b/packages/twenty-server/src/engine/metadata-modules/page-layout-widget/dtos/front-component-configuration.dto.ts index 284420f0eb..b8de1a452d 100644 --- a/packages/twenty-server/src/engine/metadata-modules/page-layout-widget/dtos/front-component-configuration.dto.ts +++ b/packages/twenty-server/src/engine/metadata-modules/page-layout-widget/dtos/front-component-configuration.dto.ts @@ -1,7 +1,10 @@ import { Field, ObjectType } from '@nestjs/graphql'; import { IsIn, IsNotEmpty, IsUUID } from 'class-validator'; -import { type FrontComponentConfiguration } from 'twenty-shared/types'; +import { + type FrontComponentConfiguration, + type SerializedRelation, +} from 'twenty-shared/types'; import { UUIDScalarType } from 'src/engine/api/graphql/workspace-schema-builder/graphql-types/scalars'; import { WidgetConfigurationType } from 'src/engine/metadata-modules/page-layout-widget/enums/widget-configuration-type.type'; @@ -18,5 +21,5 @@ export class FrontComponentConfigurationDTO @Field(() => UUIDScalarType) @IsNotEmpty() @IsUUID() - frontComponentId: string; + frontComponentId: SerializedRelation; } diff --git a/packages/twenty-server/src/engine/metadata-modules/page-layout-widget/services/page-layout-widget.service.ts b/packages/twenty-server/src/engine/metadata-modules/page-layout-widget/services/page-layout-widget.service.ts index af1c9fb4e4..324c09ba1b 100644 --- a/packages/twenty-server/src/engine/metadata-modules/page-layout-widget/services/page-layout-widget.service.ts +++ b/packages/twenty-server/src/engine/metadata-modules/page-layout-widget/services/page-layout-widget.service.ts @@ -243,6 +243,7 @@ export class PageLayoutWidgetService { flatPageLayoutTabMaps, flatObjectMetadataMaps, flatFieldMetadataMaps, + flatFrontComponentMaps, flatViewFieldGroupMaps, flatViewMaps, } = @@ -253,6 +254,7 @@ export class PageLayoutWidgetService { 'flatPageLayoutTabMaps', 'flatObjectMetadataMaps', 'flatFieldMetadataMaps', + 'flatFrontComponentMaps', 'flatViewFieldGroupMaps', 'flatViewMaps', ], @@ -267,6 +269,7 @@ export class PageLayoutWidgetService { flatPageLayoutTabMaps, flatObjectMetadataMaps, flatFieldMetadataMaps, + flatFrontComponentMaps, flatViewFieldGroupMaps, flatViewMaps, }); @@ -327,6 +330,7 @@ export class PageLayoutWidgetService { const { flatObjectMetadataMaps: existingFlatObjectMetadataMaps, flatFieldMetadataMaps: existingFlatFieldMetadataMaps, + flatFrontComponentMaps: existingFlatFrontComponentMaps, flatViewFieldGroupMaps: existingFlatViewFieldGroupMaps, flatViewMaps: existingFlatViewMaps, } = await this.workspaceManyOrAllFlatEntityMapsCacheService.getOrRecomputeManyOrAllFlatEntityMaps( @@ -335,6 +339,7 @@ export class PageLayoutWidgetService { flatMapsKeys: [ 'flatObjectMetadataMaps', 'flatFieldMetadataMaps', + 'flatFrontComponentMaps', 'flatViewFieldGroupMaps', 'flatViewMaps', ], @@ -369,6 +374,7 @@ export class PageLayoutWidgetService { flatPageLayoutWidgetMaps: existingFlatPageLayoutWidgetMaps, flatObjectMetadataMaps: existingFlatObjectMetadataMaps, flatFieldMetadataMaps: existingFlatFieldMetadataMaps, + flatFrontComponentMaps: existingFlatFrontComponentMaps, flatViewFieldGroupMaps: existingFlatViewFieldGroupMaps, flatViewMaps: existingFlatViewMaps, }); diff --git a/packages/twenty-server/src/engine/metadata-modules/page-layout/services/page-layout-duplication.service.ts b/packages/twenty-server/src/engine/metadata-modules/page-layout/services/page-layout-duplication.service.ts index 2d8a4ce31f..a7a366ba30 100644 --- a/packages/twenty-server/src/engine/metadata-modules/page-layout/services/page-layout-duplication.service.ts +++ b/packages/twenty-server/src/engine/metadata-modules/page-layout/services/page-layout-duplication.service.ts @@ -52,6 +52,7 @@ export class PageLayoutDuplicationService { flatPageLayoutWidgetMaps, flatObjectMetadataMaps, flatFieldMetadataMaps, + flatFrontComponentMaps, flatViewFieldGroupMaps, flatViewMaps, } = await this.getPageLayoutFlatEntityMaps(workspaceId); @@ -116,6 +117,7 @@ export class PageLayoutDuplicationService { flatPageLayoutTabMaps: optimisticFlatPageLayoutTabMaps, flatObjectMetadataMaps, flatFieldMetadataMaps, + flatFrontComponentMaps, flatViewFieldGroupMaps, flatViewMaps, }); @@ -185,6 +187,7 @@ export class PageLayoutDuplicationService { 'flatPageLayoutWidgetMaps', 'flatObjectMetadataMaps', 'flatFieldMetadataMaps', + 'flatFrontComponentMaps', 'flatViewFieldGroupMaps', 'flatViewMaps', ], @@ -296,6 +299,7 @@ export class PageLayoutDuplicationService { flatPageLayoutTabMaps, flatObjectMetadataMaps, flatFieldMetadataMaps, + flatFrontComponentMaps, flatViewFieldGroupMaps, flatViewMaps, }: { @@ -309,6 +313,7 @@ export class PageLayoutDuplicationService { flatPageLayoutTabMaps: AllFlatEntityMaps['flatPageLayoutTabMaps']; flatObjectMetadataMaps: AllFlatEntityMaps['flatObjectMetadataMaps']; flatFieldMetadataMaps: AllFlatEntityMaps['flatFieldMetadataMaps']; + flatFrontComponentMaps: AllFlatEntityMaps['flatFrontComponentMaps']; flatViewFieldGroupMaps: AllFlatEntityMaps['flatViewFieldGroupMaps']; flatViewMaps: AllFlatEntityMaps['flatViewMaps']; }): FlatPageLayoutWidget[] { @@ -330,6 +335,7 @@ export class PageLayoutDuplicationService { flatPageLayoutTabMaps, flatObjectMetadataMaps, flatFieldMetadataMaps, + flatFrontComponentMaps, flatViewFieldGroupMaps, flatViewMaps, }), diff --git a/packages/twenty-server/src/engine/metadata-modules/page-layout/services/page-layout-update.service.ts b/packages/twenty-server/src/engine/metadata-modules/page-layout/services/page-layout-update.service.ts index 1498e06cc6..695396cf85 100644 --- a/packages/twenty-server/src/engine/metadata-modules/page-layout/services/page-layout-update.service.ts +++ b/packages/twenty-server/src/engine/metadata-modules/page-layout/services/page-layout-update.service.ts @@ -119,6 +119,7 @@ export class PageLayoutUpdateService { const { flatObjectMetadataMaps, flatFieldMetadataMaps, + flatFrontComponentMaps, flatViewFieldGroupMaps, flatViewMaps, } = @@ -128,6 +129,7 @@ export class PageLayoutUpdateService { flatMapsKeys: [ 'flatObjectMetadataMaps', 'flatFieldMetadataMaps', + 'flatFrontComponentMaps', 'flatViewFieldGroupMaps', 'flatViewMaps', ], @@ -154,6 +156,7 @@ export class PageLayoutUpdateService { workspaceCustomApplicationUniversalIdentifier: workspaceCustomFlatApplication.universalIdentifier, flatFieldMetadataMaps, + flatFrontComponentMaps, flatViewFieldGroupMaps, flatViewMaps, }); @@ -367,6 +370,7 @@ export class PageLayoutUpdateService { workspaceCustomApplicationId, workspaceCustomApplicationUniversalIdentifier, flatFieldMetadataMaps, + flatFrontComponentMaps, flatViewFieldGroupMaps, flatViewMaps, }: { @@ -378,6 +382,7 @@ export class PageLayoutUpdateService { AllFlatEntityMaps, | 'flatObjectMetadataMaps' | 'flatFieldMetadataMaps' + | 'flatFrontComponentMaps' | 'flatViewFieldGroupMaps' | 'flatViewMaps' | 'flatPageLayoutTabMaps' @@ -402,6 +407,7 @@ export class PageLayoutUpdateService { workspaceCustomApplicationId, workspaceCustomApplicationUniversalIdentifier, flatFieldMetadataMaps, + flatFrontComponentMaps, flatViewFieldGroupMaps, flatViewMaps, }); @@ -427,6 +433,7 @@ export class PageLayoutUpdateService { workspaceCustomApplicationId, workspaceCustomApplicationUniversalIdentifier, flatFieldMetadataMaps, + flatFrontComponentMaps, flatViewFieldGroupMaps, flatViewMaps, }: { @@ -439,6 +446,7 @@ export class PageLayoutUpdateService { AllFlatEntityMaps, | 'flatObjectMetadataMaps' | 'flatFieldMetadataMaps' + | 'flatFrontComponentMaps' | 'flatViewFieldGroupMaps' | 'flatViewMaps' | 'flatPageLayoutTabMaps' @@ -509,6 +517,8 @@ export class PageLayoutUpdateService { configuration: widgetInput.configuration, fieldMetadataUniversalIdentifierById: flatFieldMetadataMaps.universalIdentifierById, + frontComponentUniversalIdentifierById: + flatFrontComponentMaps.universalIdentifierById, viewFieldGroupUniversalIdentifierById: flatViewFieldGroupMaps.universalIdentifierById, viewUniversalIdentifierById: flatViewMaps.universalIdentifierById, @@ -556,6 +566,8 @@ export class PageLayoutUpdateService { configuration: updatedConfiguration, fieldMetadataUniversalIdentifierById: flatFieldMetadataMaps.universalIdentifierById, + frontComponentUniversalIdentifierById: + flatFrontComponentMaps.universalIdentifierById, viewFieldGroupUniversalIdentifierById: flatViewFieldGroupMaps.universalIdentifierById, viewUniversalIdentifierById: @@ -606,6 +618,8 @@ export class PageLayoutUpdateService { configuration: restoredConfiguration, fieldMetadataUniversalIdentifierById: flatFieldMetadataMaps.universalIdentifierById, + frontComponentUniversalIdentifierById: + flatFrontComponentMaps.universalIdentifierById, viewFieldGroupUniversalIdentifierById: flatViewFieldGroupMaps.universalIdentifierById, viewUniversalIdentifierById: diff --git a/packages/twenty-server/src/engine/workspace-manager/workspace-migration/workspace-migration-runner/action-handlers/page-layout-widget/services/create-page-layout-widget-action-handler.service.ts b/packages/twenty-server/src/engine/workspace-manager/workspace-migration/workspace-migration-runner/action-handlers/page-layout-widget/services/create-page-layout-widget-action-handler.service.ts index 0a8edb372d..c6a563a0f3 100644 --- a/packages/twenty-server/src/engine/workspace-manager/workspace-migration/workspace-migration-runner/action-handlers/page-layout-widget/services/create-page-layout-widget-action-handler.service.ts +++ b/packages/twenty-server/src/engine/workspace-manager/workspace-migration/workspace-migration-runner/action-handlers/page-layout-widget/services/create-page-layout-widget-action-handler.service.ts @@ -42,6 +42,7 @@ export class CreatePageLayoutWidgetActionHandlerService extends WorkspaceMigrati fromUniversalConfigurationToFlatPageLayoutWidgetConfiguration({ universalConfiguration: action.flatEntity.universalConfiguration, flatFieldMetadataMaps: allFlatEntityMaps.flatFieldMetadataMaps, + flatFrontComponentMaps: allFlatEntityMaps.flatFrontComponentMaps, flatViewMaps: allFlatEntityMaps.flatViewMaps, flatViewFieldGroupMaps: allFlatEntityMaps.flatViewFieldGroupMaps, }); diff --git a/packages/twenty-server/src/engine/workspace-manager/workspace-migration/workspace-migration-runner/action-handlers/page-layout-widget/services/update-page-layout-widget-action-handler.service.ts b/packages/twenty-server/src/engine/workspace-manager/workspace-migration/workspace-migration-runner/action-handlers/page-layout-widget/services/update-page-layout-widget-action-handler.service.ts index c52201fb74..b34ffc94fb 100644 --- a/packages/twenty-server/src/engine/workspace-manager/workspace-migration/workspace-migration-runner/action-handlers/page-layout-widget/services/update-page-layout-widget-action-handler.service.ts +++ b/packages/twenty-server/src/engine/workspace-manager/workspace-migration/workspace-migration-runner/action-handlers/page-layout-widget/services/update-page-layout-widget-action-handler.service.ts @@ -50,6 +50,8 @@ export class UpdatePageLayoutWidgetActionHandlerService extends WorkspaceMigrati fromUniversalConfigurationToFlatPageLayoutWidgetConfiguration({ universalConfiguration, flatFieldMetadataMaps: allFlatEntityMaps.flatFieldMetadataMaps, + flatFrontComponentMaps: + allFlatEntityMaps.flatFrontComponentMaps, flatViewMaps: allFlatEntityMaps.flatViewMaps, flatViewFieldGroupMaps: allFlatEntityMaps.flatViewFieldGroupMaps, diff --git a/packages/twenty-server/src/engine/workspace-manager/workspace-migration/workspace-migration-runner/action-handlers/page-layout-widget/services/utils/from-universal-configuration-to-flat-page-layout-widget-configuration.util.ts b/packages/twenty-server/src/engine/workspace-manager/workspace-migration/workspace-migration-runner/action-handlers/page-layout-widget/services/utils/from-universal-configuration-to-flat-page-layout-widget-configuration.util.ts index d372c37477..01933827fd 100644 --- a/packages/twenty-server/src/engine/workspace-manager/workspace-migration/workspace-migration-runner/action-handlers/page-layout-widget/services/utils/from-universal-configuration-to-flat-page-layout-widget-configuration.util.ts +++ b/packages/twenty-server/src/engine/workspace-manager/workspace-migration/workspace-migration-runner/action-handlers/page-layout-widget/services/utils/from-universal-configuration-to-flat-page-layout-widget-configuration.util.ts @@ -70,11 +70,13 @@ const convertUniversalFilterToChartFilter = ({ export const fromUniversalConfigurationToFlatPageLayoutWidgetConfiguration = ({ universalConfiguration, flatFieldMetadataMaps, + flatFrontComponentMaps, flatViewMaps, flatViewFieldGroupMaps, }: { universalConfiguration: FlatPageLayoutWidget['universalConfiguration']; flatFieldMetadataMaps: MetadataFlatEntityMaps<'fieldMetadata'>; + flatFrontComponentMaps: MetadataFlatEntityMaps<'frontComponent'>; flatViewMaps: MetadataFlatEntityMaps<'view'>; flatViewFieldGroupMaps: MetadataFlatEntityMaps<'viewFieldGroup'>; }): FlatPageLayoutWidget['configuration'] => { @@ -310,6 +312,35 @@ export const fromUniversalConfigurationToFlatPageLayoutWidgetConfiguration = ({ return { ...rest, viewId, newFieldDefaultConfiguration }; } + case WidgetConfigurationType.FRONT_COMPONENT: { + const { frontComponentUniversalIdentifier, ...rest } = + universalConfiguration; + + if (!isDefined(frontComponentUniversalIdentifier)) { + throw new FlatEntityMapsException( + `Front component universal identifier is required for FRONT_COMPONENT configuration`, + FlatEntityMapsExceptionCode.ENTITY_NOT_FOUND, + ); + } + + const flatFrontComponent = findFlatEntityByUniversalIdentifier({ + flatEntityMaps: flatFrontComponentMaps, + universalIdentifier: frontComponentUniversalIdentifier, + }); + + if (!isDefined(flatFrontComponent)) { + throw new FlatEntityMapsException( + `Front component not found for universal identifier: ${frontComponentUniversalIdentifier}`, + FlatEntityMapsExceptionCode.ENTITY_NOT_FOUND, + ); + } + + return { + ...rest, + frontComponentId: flatFrontComponent.id, + }; + } + case WidgetConfigurationType.VIEW: case WidgetConfigurationType.FIELD: case WidgetConfigurationType.TIMELINE: @@ -322,7 +353,6 @@ export const fromUniversalConfigurationToFlatPageLayoutWidgetConfiguration = ({ case WidgetConfigurationType.WORKFLOW: case WidgetConfigurationType.WORKFLOW_VERSION: case WidgetConfigurationType.WORKFLOW_RUN: - case WidgetConfigurationType.FRONT_COMPONENT: case WidgetConfigurationType.IFRAME: case WidgetConfigurationType.STANDALONE_RICH_TEXT: return universalConfiguration; diff --git a/packages/twenty-shared/src/types/page-layout/page-layout-widget-configuration.type.ts b/packages/twenty-shared/src/types/page-layout/page-layout-widget-configuration.type.ts index a77b6104c6..87e272c645 100644 --- a/packages/twenty-shared/src/types/page-layout/page-layout-widget-configuration.type.ts +++ b/packages/twenty-shared/src/types/page-layout/page-layout-widget-configuration.type.ts @@ -125,7 +125,7 @@ export type IframeConfiguration = { export type FrontComponentConfiguration = { configurationType: 'FRONT_COMPONENT'; - frontComponentId: string; + frontComponentId: SerializedRelation; }; export type TimelineConfiguration = {