From 0f06fccdeea8f762998ec18fbc16042afae90df4 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Rapha=C3=ABl=20Bosi?=
<71827178+bosiraphael@users.noreply.github.com>
Date: Fri, 31 Jul 2026 15:12:19 +0200
Subject: [PATCH] Make page layout tab layoutMode diffable and default
standalone pages to vertical list (#23596)
Reported on Discord: an app declared a `STANDALONE_PAGE` layout with one
`FRONT_COMPONENT` widget and got a small bordered card instead of a
full-bleed page, and setting `layoutMode` afterwards changed nothing.
Two bugs:
- `pageLayoutTab.layoutMode` was `toCompare: false`, so it was written
once at create and never diffed again. Changing it in a manifest and
redeploying was a silent no-op, and `updatePageLayoutTab(layoutMode:)`
was accepted by the API then dropped by the runner's update sanitizer.
- A manifest tab that omits `layoutMode` defaulted to `GRID` regardless
of page layout type, and a `GRID` tab always renders its widgets as
cards on a 12-column grid. Standalone pages now default to
`VERTICAL_LIST`, where a lone widget owns the tab.
Also fixes the SDK scaffolder (`twenty add page-layout` emitted a tab
with no `position`, which does not typecheck) and the docs claim that a
single widget is always full-bleed.
Worth knowing for review: this does not migrate workspaces holding
legacy `CANVAS` tabs. The standard-app sync only runs against a fresh
schema, so those rows stay `CANVAS` and keep rendering correctly through
the derived presentation.
---
.../src/page-layouts/main-page.page-layout.ts | 2 +-
.../extend/apps/layout/page-layouts.mdx | 3 +-
.../get-page-layout-base-file.spec.ts | 18 +++++-
.../entity/entity-page-layout-template.ts | 15 ++++-
...niversal-flat-page-layout-tab.util.spec.ts | 53 +++++++++++++++++-
...-to-universal-flat-page-layout-tab.util.ts | 14 ++++-
...-all-universal-flat-entity-maps.service.ts | 8 +++
...ompare-and-stringify.constant.spec.ts.snap | 1 +
...configuration-by-metadata-name.constant.ts | 2 +-
...ge-layout-widget-validator.service.spec.ts | 56 ++++++++++++++++++-
...layout-tab-update.integration-spec.ts.snap | 15 +++++
...page-layout-tab-update.integration-spec.ts | 10 ++++
...-one-page-layout-tab-query-factory.util.ts | 2 +
13 files changed, 186 insertions(+), 13 deletions(-)
diff --git a/packages/create-twenty-app/src/constants/template/src/page-layouts/main-page.page-layout.ts b/packages/create-twenty-app/src/constants/template/src/page-layouts/main-page.page-layout.ts
index eea21670dc..2301f49c8a 100644
--- a/packages/create-twenty-app/src/constants/template/src/page-layouts/main-page.page-layout.ts
+++ b/packages/create-twenty-app/src/constants/template/src/page-layouts/main-page.page-layout.ts
@@ -18,7 +18,7 @@ export default definePageLayout({
title: 'Overview',
position: 0,
icon: 'IconApps',
- layoutMode: PageLayoutTabLayoutMode.CANVAS,
+ layoutMode: PageLayoutTabLayoutMode.VERTICAL_LIST,
widgets: [
{
universalIdentifier: MAIN_PAGE_WIDGET_UNIVERSAL_IDENTIFIER,
diff --git a/packages/twenty-docs/developers/extend/apps/layout/page-layouts.mdx b/packages/twenty-docs/developers/extend/apps/layout/page-layouts.mdx
index 76f494e517..9f8f0dd368 100644
--- a/packages/twenty-docs/developers/extend/apps/layout/page-layouts.mdx
+++ b/packages/twenty-docs/developers/extend/apps/layout/page-layouts.mdx
@@ -53,7 +53,8 @@ export default definePageLayout({
- `type` is one of `'RECORD_INDEX'`, `'RECORD_PAGE'`, `'DASHBOARD'` or `'STANDALONE_PAGE'`. Use `'RECORD_PAGE'` to customize the detail view of a specific object.
- `objectUniversalIdentifier` specifies which object this layout applies to.
-- Each `tab` defines a section of the page with a `title`, `position`, and `layoutMode` (`VERTICAL_LIST` for record pages, `GRID` for dashboards). A tab holding a single widget renders it full-bleed automatically; with several widgets they stack as cards.
+- Each `tab` defines a section of the page with a `title`, `position`, and `layoutMode`: `VERTICAL_LIST` for record pages and standalone pages, `GRID` for dashboards. In a `VERTICAL_LIST` tab, a single widget renders full-bleed and owns the whole tab; with several widgets they stack as cards. A `GRID` tab always lays its widgets out as cards on a 12-column grid, whatever their number, so pick `VERTICAL_LIST` when you want one widget to fill the page.
+- Set `layoutMode` explicitly. Omitting it gives you `VERTICAL_LIST` on a `STANDALONE_PAGE` and `GRID` everywhere else, which is rarely what you want on a record page.
- Each `widget` inside a tab can render a [front component](/developers/extend/apps/layout/front-components), a relation list, or other built-in widget types.
- `position` on tabs controls their order. Use higher values (e.g., 50) to place custom tabs after built-in ones.
diff --git a/packages/twenty-sdk/src/cli/utilities/entity/__tests__/get-page-layout-base-file.spec.ts b/packages/twenty-sdk/src/cli/utilities/entity/__tests__/get-page-layout-base-file.spec.ts
index 067988f9ae..337cd60782 100644
--- a/packages/twenty-sdk/src/cli/utilities/entity/__tests__/get-page-layout-base-file.spec.ts
+++ b/packages/twenty-sdk/src/cli/utilities/entity/__tests__/get-page-layout-base-file.spec.ts
@@ -9,17 +9,28 @@ describe('getPageLayoutBaseFile', () => {
type: PageLayoutType.STANDALONE_PAGE,
});
- expect(result).toContain(
- "import { definePageLayout, PageLayoutType } from 'twenty-sdk/define';",
- );
+ expect(result).toContain("} from 'twenty-sdk/define';");
+ expect(result).toContain('definePageLayout,');
expect(result).toContain('export default definePageLayout({');
expect(result).toContain("name: 'my-layout'");
expect(result).toContain('type: PageLayoutType.STANDALONE_PAGE');
expect(result).toContain("title: 'Overview'");
+ expect(result).toContain('position: 0');
expect(result).toContain('widgets: []');
expect(result).toContain('tabs: [');
});
+ it('should render a standalone page tab in VERTICAL_LIST so a lone widget owns the page', () => {
+ const result = getPageLayoutBaseFile({
+ name: 'my-layout',
+ type: PageLayoutType.STANDALONE_PAGE,
+ });
+
+ expect(result).toContain(
+ 'layoutMode: PageLayoutTabLayoutMode.VERTICAL_LIST',
+ );
+ });
+
it('should render proper file with DASHBOARD type', () => {
const result = getPageLayoutBaseFile({
name: 'my-dashboard',
@@ -27,6 +38,7 @@ describe('getPageLayoutBaseFile', () => {
});
expect(result).toContain('type: PageLayoutType.DASHBOARD');
+ expect(result).toContain('layoutMode: PageLayoutTabLayoutMode.GRID');
});
it('should generate valid UUIDs for layout and tab', () => {
diff --git a/packages/twenty-sdk/src/cli/utilities/entity/entity-page-layout-template.ts b/packages/twenty-sdk/src/cli/utilities/entity/entity-page-layout-template.ts
index 62b214ddc8..7e4dd289a6 100644
--- a/packages/twenty-sdk/src/cli/utilities/entity/entity-page-layout-template.ts
+++ b/packages/twenty-sdk/src/cli/utilities/entity/entity-page-layout-template.ts
@@ -1,4 +1,4 @@
-import { type PageLayoutType } from 'twenty-shared/types';
+import { PageLayoutTabLayoutMode, PageLayoutType } from 'twenty-shared/types';
import { v4 as uuidv4 } from 'uuid';
export const getPageLayoutBaseFile = ({
@@ -8,7 +8,16 @@ export const getPageLayoutBaseFile = ({
name: string;
type: PageLayoutType;
}) => {
- return `import { definePageLayout, PageLayoutType } from 'twenty-sdk/define';
+ const layoutMode =
+ type === PageLayoutType.DASHBOARD
+ ? PageLayoutTabLayoutMode.GRID
+ : PageLayoutTabLayoutMode.VERTICAL_LIST;
+
+ return `import {
+ definePageLayout,
+ PageLayoutTabLayoutMode,
+ PageLayoutType,
+} from 'twenty-sdk/define';
export default definePageLayout({
universalIdentifier: '${uuidv4()}',
@@ -18,6 +27,8 @@ export default definePageLayout({
{
universalIdentifier: '${uuidv4()}',
title: 'Overview',
+ position: 0,
+ layoutMode: PageLayoutTabLayoutMode.${layoutMode},
widgets: [],
},
],
diff --git a/packages/twenty-server/src/engine/core-modules/application/application-manifest/converters/__tests__/from-page-layout-tab-manifest-to-universal-flat-page-layout-tab.util.spec.ts b/packages/twenty-server/src/engine/core-modules/application/application-manifest/converters/__tests__/from-page-layout-tab-manifest-to-universal-flat-page-layout-tab.util.spec.ts
index 942c92532a..f67e21eaac 100644
--- a/packages/twenty-server/src/engine/core-modules/application/application-manifest/converters/__tests__/from-page-layout-tab-manifest-to-universal-flat-page-layout-tab.util.spec.ts
+++ b/packages/twenty-server/src/engine/core-modules/application/application-manifest/converters/__tests__/from-page-layout-tab-manifest-to-universal-flat-page-layout-tab.util.spec.ts
@@ -1,4 +1,4 @@
-import { PageLayoutTabLayoutMode } from 'twenty-shared/types';
+import { PageLayoutTabLayoutMode, PageLayoutType } from 'twenty-shared/types';
import { fromPageLayoutTabManifestToUniversalFlatPageLayoutTab } from 'src/engine/core-modules/application/application-manifest/converters/from-page-layout-tab-manifest-to-universal-flat-page-layout-tab.util';
@@ -15,6 +15,7 @@ describe('fromPageLayoutTabManifestToUniversalFlatPageLayoutTab', () => {
position: 0,
},
pageLayoutUniversalIdentifier,
+ pageLayoutType: undefined,
applicationUniversalIdentifier,
now,
});
@@ -43,6 +44,7 @@ describe('fromPageLayoutTabManifestToUniversalFlatPageLayoutTab', () => {
layoutMode: PageLayoutTabLayoutMode.VERTICAL_LIST,
},
pageLayoutUniversalIdentifier,
+ pageLayoutType: undefined,
applicationUniversalIdentifier,
now,
});
@@ -52,4 +54,53 @@ describe('fromPageLayoutTabManifestToUniversalFlatPageLayoutTab', () => {
expect(result.icon).toBe('IconLayout');
expect(result.layoutMode).toBe(PageLayoutTabLayoutMode.VERTICAL_LIST);
});
+
+ it('should default a standalone page tab to VERTICAL_LIST', () => {
+ const result = fromPageLayoutTabManifestToUniversalFlatPageLayoutTab({
+ pageLayoutTabManifest: {
+ universalIdentifier: 'tab-uuid-3',
+ title: 'Overview',
+ position: 0,
+ },
+ pageLayoutUniversalIdentifier,
+ pageLayoutType: PageLayoutType.STANDALONE_PAGE,
+ applicationUniversalIdentifier,
+ now,
+ });
+
+ expect(result.layoutMode).toBe(PageLayoutTabLayoutMode.VERTICAL_LIST);
+ });
+
+ it('should default a dashboard tab to GRID', () => {
+ const result = fromPageLayoutTabManifestToUniversalFlatPageLayoutTab({
+ pageLayoutTabManifest: {
+ universalIdentifier: 'tab-uuid-4',
+ title: 'Overview',
+ position: 0,
+ },
+ pageLayoutUniversalIdentifier,
+ pageLayoutType: PageLayoutType.DASHBOARD,
+ applicationUniversalIdentifier,
+ now,
+ });
+
+ expect(result.layoutMode).toBe(PageLayoutTabLayoutMode.GRID);
+ });
+
+ it('should keep an explicit layoutMode on a standalone page tab', () => {
+ const result = fromPageLayoutTabManifestToUniversalFlatPageLayoutTab({
+ pageLayoutTabManifest: {
+ universalIdentifier: 'tab-uuid-5',
+ title: 'Overview',
+ position: 0,
+ layoutMode: PageLayoutTabLayoutMode.GRID,
+ },
+ pageLayoutUniversalIdentifier,
+ pageLayoutType: PageLayoutType.STANDALONE_PAGE,
+ applicationUniversalIdentifier,
+ now,
+ });
+
+ expect(result.layoutMode).toBe(PageLayoutTabLayoutMode.GRID);
+ });
});
diff --git a/packages/twenty-server/src/engine/core-modules/application/application-manifest/converters/from-page-layout-tab-manifest-to-universal-flat-page-layout-tab.util.ts b/packages/twenty-server/src/engine/core-modules/application/application-manifest/converters/from-page-layout-tab-manifest-to-universal-flat-page-layout-tab.util.ts
index bb821dba59..a28f6fe378 100644
--- a/packages/twenty-server/src/engine/core-modules/application/application-manifest/converters/from-page-layout-tab-manifest-to-universal-flat-page-layout-tab.util.ts
+++ b/packages/twenty-server/src/engine/core-modules/application/application-manifest/converters/from-page-layout-tab-manifest-to-universal-flat-page-layout-tab.util.ts
@@ -1,16 +1,21 @@
-import { type PageLayoutTabManifest } from 'twenty-shared/application';
-import { PageLayoutTabLayoutMode } from 'twenty-shared/types';
+import {
+ type PageLayoutManifest,
+ type PageLayoutTabManifest,
+} from 'twenty-shared/application';
+import { PageLayoutTabLayoutMode, PageLayoutType } from 'twenty-shared/types';
import { type UniversalFlatPageLayoutTab } from 'src/engine/workspace-manager/workspace-migration/universal-flat-entity/types/universal-flat-page-layout-tab.type';
export const fromPageLayoutTabManifestToUniversalFlatPageLayoutTab = ({
pageLayoutTabManifest,
pageLayoutUniversalIdentifier,
+ pageLayoutType,
applicationUniversalIdentifier,
now,
}: {
pageLayoutTabManifest: PageLayoutTabManifest;
pageLayoutUniversalIdentifier: string;
+ pageLayoutType: PageLayoutManifest['type'] | undefined;
applicationUniversalIdentifier: string;
now: string;
}): UniversalFlatPageLayoutTab => {
@@ -22,7 +27,10 @@ export const fromPageLayoutTabManifestToUniversalFlatPageLayoutTab = ({
pageLayoutUniversalIdentifier,
icon: pageLayoutTabManifest.icon ?? null,
layoutMode:
- pageLayoutTabManifest.layoutMode ?? PageLayoutTabLayoutMode.GRID,
+ pageLayoutTabManifest.layoutMode ??
+ (pageLayoutType === PageLayoutType.STANDALONE_PAGE
+ ? PageLayoutTabLayoutMode.VERTICAL_LIST
+ : PageLayoutTabLayoutMode.GRID),
isActive: true,
isSystemSideEffect: false,
widgetUniversalIdentifiers: [],
diff --git a/packages/twenty-server/src/engine/core-modules/application/application-manifest/services/compute-application-manifest-all-universal-flat-entity-maps.service.ts b/packages/twenty-server/src/engine/core-modules/application/application-manifest/services/compute-application-manifest-all-universal-flat-entity-maps.service.ts
index cdf2fb5e18..102432d308 100644
--- a/packages/twenty-server/src/engine/core-modules/application/application-manifest/services/compute-application-manifest-all-universal-flat-entity-maps.service.ts
+++ b/packages/twenty-server/src/engine/core-modules/application/application-manifest/services/compute-application-manifest-all-universal-flat-entity-maps.service.ts
@@ -526,6 +526,7 @@ export class ComputeApplicationManifestAllUniversalFlatEntityMapsService {
pageLayoutTabManifest,
pageLayoutUniversalIdentifier:
pageLayoutManifest.universalIdentifier,
+ pageLayoutType: pageLayoutManifest.type,
applicationUniversalIdentifier,
now,
}),
@@ -560,12 +561,19 @@ export class ComputeApplicationManifestAllUniversalFlatEntityMapsService {
);
}
+ const referencedPageLayoutManifest = manifest.pageLayouts?.find(
+ (pageLayoutManifest) =>
+ pageLayoutManifest.universalIdentifier ===
+ pageLayoutTabManifest.pageLayoutUniversalIdentifier,
+ );
+
addUniversalFlatEntityToUniversalFlatEntityMapsThroughMutationOrThrow({
universalFlatEntity:
fromPageLayoutTabManifestToUniversalFlatPageLayoutTab({
pageLayoutTabManifest,
pageLayoutUniversalIdentifier:
pageLayoutTabManifest.pageLayoutUniversalIdentifier,
+ pageLayoutType: referencedPageLayoutManifest?.type,
applicationUniversalIdentifier,
now,
}),
diff --git a/packages/twenty-server/src/engine/metadata-modules/flat-entity/constant/__tests__/__snapshots__/all-universal-flat-entity-properties-to-compare-and-stringify.constant.spec.ts.snap b/packages/twenty-server/src/engine/metadata-modules/flat-entity/constant/__tests__/__snapshots__/all-universal-flat-entity-properties-to-compare-and-stringify.constant.spec.ts.snap
index 03446b1c6d..e5997fd1eb 100644
--- a/packages/twenty-server/src/engine/metadata-modules/flat-entity/constant/__tests__/__snapshots__/all-universal-flat-entity-properties-to-compare-and-stringify.constant.spec.ts.snap
+++ b/packages/twenty-server/src/engine/metadata-modules/flat-entity/constant/__tests__/__snapshots__/all-universal-flat-entity-properties-to-compare-and-stringify.constant.spec.ts.snap
@@ -213,6 +213,7 @@ exports[`ALL_UNIVERSAL_FLAT_ENTITY_PROPERTIES_TO_COMPARE_AND_STRINGIFY should ma
"position",
"deletedAt",
"icon",
+ "layoutMode",
"isActive",
"overrides",
],
diff --git a/packages/twenty-server/src/engine/metadata-modules/flat-entity/constant/all-entity-properties-configuration-by-metadata-name.constant.ts b/packages/twenty-server/src/engine/metadata-modules/flat-entity/constant/all-entity-properties-configuration-by-metadata-name.constant.ts
index 62d2245a98..3605088521 100644
--- a/packages/twenty-server/src/engine/metadata-modules/flat-entity/constant/all-entity-properties-configuration-by-metadata-name.constant.ts
+++ b/packages/twenty-server/src/engine/metadata-modules/flat-entity/constant/all-entity-properties-configuration-by-metadata-name.constant.ts
@@ -1116,7 +1116,7 @@ export const ALL_ENTITY_PROPERTIES_CONFIGURATION_BY_METADATA_NAME = {
universalProperty: 'pageLayoutUniversalIdentifier',
},
layoutMode: {
- toCompare: false,
+ toCompare: true,
toStringify: false,
universalProperty: undefined,
},
diff --git a/packages/twenty-server/src/engine/workspace-manager/workspace-migration/workspace-migration-builder/validators/services/__tests__/flat-page-layout-widget-validator.service.spec.ts b/packages/twenty-server/src/engine/workspace-manager/workspace-migration/workspace-migration-builder/validators/services/__tests__/flat-page-layout-widget-validator.service.spec.ts
index 35d26a0f9c..76e15b5f78 100644
--- a/packages/twenty-server/src/engine/workspace-manager/workspace-migration/workspace-migration-builder/validators/services/__tests__/flat-page-layout-widget-validator.service.spec.ts
+++ b/packages/twenty-server/src/engine/workspace-manager/workspace-migration/workspace-migration-builder/validators/services/__tests__/flat-page-layout-widget-validator.service.spec.ts
@@ -6,6 +6,7 @@ import { createEmptyFlatEntityMaps } from 'src/engine/metadata-modules/flat-enti
import { FlatPageLayoutWidgetTypeValidatorService } from 'src/engine/metadata-modules/flat-page-layout-widget/services/flat-page-layout-widget-type-validator.service';
import { type FlatPageLayoutWidget } from 'src/engine/metadata-modules/flat-page-layout-widget/types/flat-page-layout-widget.type';
import { PageLayoutTabExceptionCode } from 'src/engine/metadata-modules/page-layout-tab/exceptions/page-layout-tab.exception';
+import { PageLayoutWidgetExceptionCode } from 'src/engine/metadata-modules/page-layout-widget/exceptions/page-layout-widget.exception';
import { type UniversalFlatPageLayoutTab } from 'src/engine/workspace-manager/workspace-migration/universal-flat-entity/types/universal-flat-page-layout-tab.type';
import { FlatPageLayoutWidgetValidatorService } from 'src/engine/workspace-manager/workspace-migration/workspace-migration-builder/validators/services/flat-page-layout-widget-validator.service';
@@ -18,12 +19,21 @@ const WIDGET_UNIVERSAL_IDENTIFIER = '00000000-0000-0000-0000-000000000111';
const tab = (
universalIdentifier = EXISTING_TAB_UNIVERSAL_IDENTIFIER,
+ layoutMode = PageLayoutTabLayoutMode.VERTICAL_LIST,
): UniversalFlatPageLayoutTab =>
({
universalIdentifier,
- layoutMode: PageLayoutTabLayoutMode.VERTICAL_LIST,
+ layoutMode,
}) as unknown as UniversalFlatPageLayoutTab;
+const GRID_POSITION = {
+ layoutMode: PageLayoutTabLayoutMode.GRID,
+ row: 0,
+ column: 0,
+ rowSpan: 4,
+ columnSpan: 4,
+};
+
const widget = (
universalIdentifier = WIDGET_UNIVERSAL_IDENTIFIER,
pageLayoutTabUniversalIdentifier = EXISTING_TAB_UNIVERSAL_IDENTIFIER,
@@ -142,5 +152,49 @@ describe('FlatPageLayoutWidgetValidatorService', () => {
result.flatEntityMinimalInformation.pageLayoutTabUniversalIdentifier,
).toBe(DESTINATION_TAB_UNIVERSAL_IDENTIFIER);
});
+
+ it('rejects a position whose layout mode does not match its tab', async () => {
+ const result = await service.validateFlatPageLayoutWidgetUpdate(
+ buildUpdateArgs({
+ update: { position: GRID_POSITION },
+ }),
+ );
+
+ expect(result.errors.map((error) => error.code)).toContain(
+ PageLayoutWidgetExceptionCode.INVALID_PAGE_LAYOUT_WIDGET_DATA,
+ );
+ });
+
+ it('accepts a position whose layout mode matches a tab already flipped in the same build', async () => {
+ const result = await service.validateFlatPageLayoutWidgetUpdate(
+ buildUpdateArgs({
+ update: { position: GRID_POSITION },
+ tabs: [
+ tab(
+ EXISTING_TAB_UNIVERSAL_IDENTIFIER,
+ PageLayoutTabLayoutMode.GRID,
+ ),
+ ],
+ }),
+ );
+
+ expect(result.errors).toEqual([]);
+ });
+
+ it('accepts a null position against a tab of any layout mode', async () => {
+ const result = await service.validateFlatPageLayoutWidgetUpdate(
+ buildUpdateArgs({
+ update: { position: null },
+ tabs: [
+ tab(
+ EXISTING_TAB_UNIVERSAL_IDENTIFIER,
+ PageLayoutTabLayoutMode.GRID,
+ ),
+ ],
+ }),
+ );
+
+ expect(result.errors).toEqual([]);
+ });
});
});
diff --git a/packages/twenty-server/test/integration/metadata/suites/page-layout-tab/__snapshots__/successful-page-layout-tab-update.integration-spec.ts.snap b/packages/twenty-server/test/integration/metadata/suites/page-layout-tab/__snapshots__/successful-page-layout-tab-update.integration-spec.ts.snap
index d3d8920704..58895eaed7 100644
--- a/packages/twenty-server/test/integration/metadata/suites/page-layout-tab/__snapshots__/successful-page-layout-tab-update.integration-spec.ts.snap
+++ b/packages/twenty-server/test/integration/metadata/suites/page-layout-tab/__snapshots__/successful-page-layout-tab-update.integration-spec.ts.snap
@@ -1,10 +1,24 @@
// Jest Snapshot v1, https://jestjs.io/docs/snapshot-testing
+exports[`Page layout tab update should succeed should update page layout tab layout mode 1`] = `
+{
+ "createdAt": Any,
+ "deletedAt": null,
+ "id": Any,
+ "layoutMode": "VERTICAL_LIST",
+ "pageLayoutId": Any,
+ "position": 0,
+ "title": "Original Tab Title",
+ "updatedAt": Any,
+}
+`;
+
exports[`Page layout tab update should succeed should update page layout tab position 1`] = `
{
"createdAt": Any,
"deletedAt": null,
"id": Any,
+ "layoutMode": "GRID",
"pageLayoutId": Any,
"position": 10,
"title": "Original Tab Title",
@@ -17,6 +31,7 @@ exports[`Page layout tab update should succeed should update page layout tab tit
"createdAt": Any,
"deletedAt": null,
"id": Any,
+ "layoutMode": "GRID",
"pageLayoutId": Any,
"position": 0,
"title": "Updated Tab Title",
diff --git a/packages/twenty-server/test/integration/metadata/suites/page-layout-tab/successful-page-layout-tab-update.integration-spec.ts b/packages/twenty-server/test/integration/metadata/suites/page-layout-tab/successful-page-layout-tab-update.integration-spec.ts
index 8da8c76f7d..7b8c72a03d 100644
--- a/packages/twenty-server/test/integration/metadata/suites/page-layout-tab/successful-page-layout-tab-update.integration-spec.ts
+++ b/packages/twenty-server/test/integration/metadata/suites/page-layout-tab/successful-page-layout-tab-update.integration-spec.ts
@@ -8,11 +8,13 @@ import {
type EachTestingContext,
eachTestingContextFilter,
} from 'twenty-shared/testing';
+import { PageLayoutTabLayoutMode } from 'twenty-shared/types';
type TestContext = {
input: {
title?: string;
position?: number;
+ layoutMode?: PageLayoutTabLayoutMode;
};
};
@@ -33,6 +35,14 @@ const SUCCESSFUL_TEST_CASES: EachTestingContext[] = [
},
},
},
+ {
+ title: 'update page layout tab layout mode',
+ context: {
+ input: {
+ layoutMode: PageLayoutTabLayoutMode.VERTICAL_LIST,
+ },
+ },
+ },
];
describe('Page layout tab update should succeed', () => {
diff --git a/packages/twenty-server/test/integration/metadata/suites/page-layout-tab/utils/update-one-page-layout-tab-query-factory.util.ts b/packages/twenty-server/test/integration/metadata/suites/page-layout-tab/utils/update-one-page-layout-tab-query-factory.util.ts
index 23f7b12525..de0b927b19 100644
--- a/packages/twenty-server/test/integration/metadata/suites/page-layout-tab/utils/update-one-page-layout-tab-query-factory.util.ts
+++ b/packages/twenty-server/test/integration/metadata/suites/page-layout-tab/utils/update-one-page-layout-tab-query-factory.util.ts
@@ -11,6 +11,7 @@ const DEFAULT_PAGE_LAYOUT_TAB_GQL_FIELDS = `
id
title
position
+ layoutMode
pageLayoutId
createdAt
updatedAt
@@ -34,6 +35,7 @@ export const updateOnePageLayoutTabQueryFactory = ({
title: input.title,
position: input.position,
icon: input.icon,
+ layoutMode: input.layoutMode,
},
},
});