Fix moving a widget to another tab (#19450)

https://github.com/user-attachments/assets/aac81e79-7f2f-4a34-bf68-c76061086821

---------

Co-authored-by: Weiko <corentin@twenty.com>
This commit is contained in:
Baptiste Devessier
2026-04-09 15:59:04 +02:00
committed by GitHub
parent 1e908e5f0f
commit 16e145b036
25 changed files with 415 additions and 132 deletions
@@ -1,7 +1,7 @@
import {
type GridPosition,
type PageLayoutWidgetConditionalDisplay,
type PageLayoutWidgetPosition,
type GridPosition,
} from 'twenty-shared/types';
import { isDefined } from 'twenty-shared/utils';
@@ -110,5 +110,6 @@ export const createStandardPageLayoutWidgetFlatMetadata = ({
deletedAt: null,
conditionalDisplay: conditionalDisplay ?? null,
overrides: null,
universalOverrides: null,
};
};
@@ -34,6 +34,7 @@ export const ALL_JSONB_PROPERTIES_WITH_SERIALIZED_RELATION_BY_METADATA_NAME = {
pageLayoutTab: {},
pageLayoutWidget: {
configuration: 'configuration',
overrides: 'overrides',
},
commandMenuItem: {},
navigationMenuItem: {},
@@ -1,5 +1,6 @@
import { Injectable } from '@nestjs/common';
import { isDefined } from 'twenty-shared/utils';
import { v4 } from 'uuid';
import { WorkspaceMigrationRunnerActionHandler } from 'src/engine/workspace-manager/workspace-migration/workspace-migration-runner/interfaces/workspace-migration-runner-action-handler-service.interface';
@@ -11,6 +12,7 @@ import {
UniversalCreatePageLayoutWidgetAction,
} from 'src/engine/workspace-manager/workspace-migration/workspace-migration-builder/builders/page-layout-widget/types/workspace-migration-page-layout-widget-action.type';
import { fromUniversalConfigurationToFlatPageLayoutWidgetConfiguration } from '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';
import { fromUniversalOverridesToPageLayoutWidgetOverrides } from 'src/engine/workspace-manager/workspace-migration/workspace-migration-runner/action-handlers/page-layout-widget/services/utils/from-universal-overrides-to-page-layout-widget-overrides.util';
import {
WorkspaceMigrationActionRunnerArgs,
WorkspaceMigrationActionRunnerContext,
@@ -47,6 +49,13 @@ export class CreatePageLayoutWidgetActionHandlerService extends WorkspaceMigrati
flatViewFieldGroupMaps: allFlatEntityMaps.flatViewFieldGroupMaps,
});
const overrides = isDefined(action.flatEntity.universalOverrides)
? fromUniversalOverridesToPageLayoutWidgetOverrides({
universalOverrides: action.flatEntity.universalOverrides,
flatPageLayoutTabMaps: allFlatEntityMaps.flatPageLayoutTabMaps,
})
: null;
const emptyUniversalForeignKeyAggregators =
getUniversalFlatEntityEmptyForeignKeyAggregators({
metadataName: 'pageLayoutWidget',
@@ -57,6 +66,7 @@ export class CreatePageLayoutWidgetActionHandlerService extends WorkspaceMigrati
flatEntity: {
...action.flatEntity,
configuration,
overrides,
pageLayoutTabId,
objectMetadataId,
applicationId: flatApplication.id,
@@ -10,6 +10,7 @@ import {
UniversalUpdatePageLayoutWidgetAction,
} from 'src/engine/workspace-manager/workspace-migration/workspace-migration-builder/builders/page-layout-widget/types/workspace-migration-page-layout-widget-action.type';
import { fromUniversalConfigurationToFlatPageLayoutWidgetConfiguration } from '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';
import { fromUniversalOverridesToPageLayoutWidgetOverrides } from 'src/engine/workspace-manager/workspace-migration/workspace-migration-runner/action-handlers/page-layout-widget/services/utils/from-universal-overrides-to-page-layout-widget-overrides.util';
import {
WorkspaceMigrationActionRunnerArgs,
WorkspaceMigrationActionRunnerContext,
@@ -34,14 +35,17 @@ export class UpdatePageLayoutWidgetActionHandlerService extends WorkspaceMigrati
universalIdentifier: action.universalIdentifier,
});
const { universalConfiguration, ...updateWithResolvedForeignKeys } =
resolveUniversalUpdateRelationIdentifiersToIds({
metadataName: 'pageLayoutWidget',
universalUpdate: action.update,
allFlatEntityMaps,
});
const {
universalConfiguration,
universalOverrides,
...updateWithResolvedForeignKeys
} = resolveUniversalUpdateRelationIdentifiersToIds({
metadataName: 'pageLayoutWidget',
universalUpdate: action.update,
allFlatEntityMaps,
});
const update =
const updateWithConfiguration =
universalConfiguration === undefined
? updateWithResolvedForeignKeys
: {
@@ -58,6 +62,19 @@ export class UpdatePageLayoutWidgetActionHandlerService extends WorkspaceMigrati
}),
};
const update =
universalOverrides === undefined
? updateWithConfiguration
: universalOverrides === null
? { ...updateWithConfiguration, overrides: null }
: {
...updateWithConfiguration,
overrides: fromUniversalOverridesToPageLayoutWidgetOverrides({
universalOverrides,
flatPageLayoutTabMaps: allFlatEntityMaps.flatPageLayoutTabMaps,
}),
};
return {
type: 'update',
metadataName: 'pageLayoutWidget',
@@ -0,0 +1,39 @@
import { type FormatRecordSerializedRelationProperties } from 'twenty-shared/types';
import { isDefined } from 'twenty-shared/utils';
import { findFlatEntityByUniversalIdentifierOrThrow } from 'src/engine/metadata-modules/flat-entity/utils/find-flat-entity-by-universal-identifier-or-throw.util';
import { type FlatPageLayoutTabMaps } from 'src/engine/metadata-modules/flat-page-layout-tab/types/flat-page-layout-tab-maps.type';
import { type FlatPageLayoutTab } from 'src/engine/metadata-modules/flat-page-layout-tab/types/flat-page-layout-tab.type';
import { type PageLayoutWidgetOverrides } from 'src/engine/metadata-modules/page-layout-widget/entities/page-layout-widget.entity';
type UniversalPageLayoutWidgetOverrides =
FormatRecordSerializedRelationProperties<PageLayoutWidgetOverrides>;
export const fromUniversalOverridesToPageLayoutWidgetOverrides = ({
universalOverrides,
flatPageLayoutTabMaps,
}: {
universalOverrides: UniversalPageLayoutWidgetOverrides;
flatPageLayoutTabMaps: FlatPageLayoutTabMaps;
}): PageLayoutWidgetOverrides => {
const { pageLayoutTabUniversalIdentifier, ...scalarOverrides } =
universalOverrides;
if (!isDefined(pageLayoutTabUniversalIdentifier)) {
return {
...scalarOverrides,
};
}
const flatPageLayoutTab =
findFlatEntityByUniversalIdentifierOrThrow<FlatPageLayoutTab>({
flatEntityMaps: flatPageLayoutTabMaps,
universalIdentifier: pageLayoutTabUniversalIdentifier,
});
return {
...scalarOverrides,
pageLayoutTabId:
flatPageLayoutTab.id as PageLayoutWidgetOverrides['pageLayoutTabId'],
};
};