backfill widget position from gridPosition (phase 1 of gridPosition removal) (#20032)
## Context
Phase 1 of removing the legacy `gridPosition` field from
`PageLayoutWidget` in favor of the new `position` discriminated union
(`grid` / `vertical-list` / `canvas`). This PR is purely additive —
`gridPosition` is still required and read everywhere; we just guarantee
that every widget now also has a non-null `position` so a follow-up PR
can drop `gridPosition` cleanly.
## Changes
- **Slow instance command**
`BackfillPageLayoutWidgetPositionSlowInstanceCommand` (2.1.0):
for every `core.pageLayoutWidget` row where `position IS NULL`, copies
`gridPosition`
into `position` with `layoutMode: 'GRID'`. Historically only grid
widgets used
`gridPosition`, so a single SQL update covers every existing row.
- **`PageLayoutDuplicationService`**: when duplicating a widget, also
forwards
`originalWidget.position` (was previously only forwarding
`gridPosition`).
- **Frontend default layouts** (10 `Default*PageLayout.ts` files): added
a `position`
sibling to every widget, matching the parent tab's `layoutMode` —
`VERTICAL_LIST` widgets
get `{ layoutMode, index }`, `CANVAS` widgets get `{ layoutMode }`
<img width="338" height="226" alt="Screenshot 2026-04-24 at 16 23 17"
src="https://github.com/user-attachments/assets/c3319318-f1b8-4271-96b4-196b209a1f5e"
/>
This commit is contained in:
+5
-1
@@ -39,7 +39,11 @@ export class CreatePageLayoutWidgetInput {
|
||||
@IsOptional()
|
||||
objectMetadataId?: string | null;
|
||||
|
||||
@Field(() => GridPositionInput, { nullable: false })
|
||||
@Field(() => GridPositionInput, {
|
||||
nullable: false,
|
||||
deprecationReason:
|
||||
'Use `position` instead. Will be removed in a future release.',
|
||||
})
|
||||
@ValidateNested()
|
||||
@Type(() => GridPositionInput)
|
||||
gridPosition: GridPositionInput;
|
||||
|
||||
+4
-1
@@ -48,7 +48,10 @@ export class UpdatePageLayoutWidgetWithIdInput {
|
||||
@IsOptional()
|
||||
objectMetadataId: string | null;
|
||||
|
||||
@Field(() => GridPositionInput)
|
||||
@Field(() => GridPositionInput, {
|
||||
deprecationReason:
|
||||
'Use `position` instead. Will be removed in a future release.',
|
||||
})
|
||||
@ValidateNested()
|
||||
@Type(() => GridPositionInput)
|
||||
@IsNotEmpty()
|
||||
|
||||
+5
-1
@@ -42,7 +42,11 @@ export class UpdatePageLayoutWidgetInput {
|
||||
@IsOptional()
|
||||
objectMetadataId?: string | null;
|
||||
|
||||
@Field(() => GridPositionInput, { nullable: true })
|
||||
@Field(() => GridPositionInput, {
|
||||
nullable: true,
|
||||
deprecationReason:
|
||||
'Use `position` instead. Will be removed in a future release.',
|
||||
})
|
||||
@ValidateNested()
|
||||
@Type(() => GridPositionInput)
|
||||
@IsOptional()
|
||||
|
||||
+5
-1
@@ -56,7 +56,11 @@ export class PageLayoutWidgetDTO {
|
||||
@Field(() => UUIDScalarType, { nullable: true })
|
||||
objectMetadataId?: string;
|
||||
|
||||
@Field(() => GridPositionDTO, { nullable: false })
|
||||
@Field(() => GridPositionDTO, {
|
||||
nullable: false,
|
||||
deprecationReason:
|
||||
'Use `position` instead. Will be removed in a future release.',
|
||||
})
|
||||
gridPosition: GridPositionDTO;
|
||||
|
||||
@Field(() => PageLayoutWidgetPositionUnion, { nullable: true })
|
||||
|
||||
+1
@@ -325,6 +325,7 @@ export class PageLayoutDuplicationService {
|
||||
createPageLayoutWidgetInput: {
|
||||
title: originalWidget.title,
|
||||
gridPosition: originalWidget.gridPosition,
|
||||
position: originalWidget.position ?? undefined,
|
||||
type: originalWidget.type,
|
||||
objectMetadataId: originalWidget.objectMetadataId,
|
||||
configuration: originalWidget.configuration,
|
||||
|
||||
Reference in New Issue
Block a user