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. Review in cubic --- .../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, }, }, });