diff --git a/packages/twenty-front/src/modules/page-layout/utils/__tests__/convertPageLayoutToTabLayouts.test.ts b/packages/twenty-front/src/modules/page-layout/utils/__tests__/convertPageLayoutToTabLayouts.test.ts index ed0c8ed72b..029c249372 100644 --- a/packages/twenty-front/src/modules/page-layout/utils/__tests__/convertPageLayoutToTabLayouts.test.ts +++ b/packages/twenty-front/src/modules/page-layout/utils/__tests__/convertPageLayoutToTabLayouts.test.ts @@ -1,9 +1,11 @@ +import { DEFAULT_WIDGET_SIZE } from 'twenty-shared/constants'; import { WIDGET_SIZES } from '@/page-layout/constants/WidgetSizes'; import { type PageLayout } from '@/page-layout/types/PageLayout'; import { convertPageLayoutToTabLayouts } from '@/page-layout/utils/convertPageLayoutToTabLayouts'; import { AggregateOperations, GraphOrderBy, + PageLayoutTabLayoutMode, PageLayoutType, WidgetConfigurationType, WidgetType, @@ -95,6 +97,66 @@ describe('convertPageLayoutToTabLayouts', () => { }); }); + it('should use default widget size when gridPosition is undefined', () => { + const pageLayout: PageLayout = { + id: 'page-layout-1', + name: 'Page Layout 1', + type: PageLayoutType.RECORD_PAGE, + objectMetadataId: 'object-metadata-1', + universalIdentifier: '20202020-0000-0000-0000-000000000001', + tabs: [ + { + id: 'tab-1', + applicationId: '', + isActive: true, + title: 'Tab 1', + position: 0, + pageLayoutId: 'page-layout-1', + widgets: [ + { + __typename: 'PageLayoutWidget', + id: 'widget-no-grid-pos', + applicationId: '', + isActive: true, + pageLayoutTabId: 'tab-1', + title: 'No Grid Position', + type: WidgetType.FRONT_COMPONENT, + configuration: { + configurationType: WidgetConfigurationType.FRONT_COMPONENT, + frontComponentId: 'my-component', + }, + gridPosition: undefined as any, + position: { + __typename: 'PageLayoutWidgetCanvasPosition' as const, + layoutMode: PageLayoutTabLayoutMode.CANVAS, + }, + objectMetadataId: null, + createdAt: '2025-01-01T00:00:00.000Z', + updatedAt: '2025-01-01T00:00:00.000Z', + deletedAt: null, + }, + ], + createdAt: '2025-01-01T00:00:00.000Z', + updatedAt: '2025-01-01T00:00:00.000Z', + deletedAt: null, + }, + ], + createdAt: '2025-01-01T00:00:00.000Z', + updatedAt: '2025-01-01T00:00:00.000Z', + deletedAt: null, + }; + + const result = convertPageLayoutToTabLayouts(pageLayout); + + expect(result['tab-1'].desktop[0]).toMatchObject({ + i: 'widget-no-grid-pos', + x: 0, + y: 0, + w: DEFAULT_WIDGET_SIZE.default.w, + h: DEFAULT_WIDGET_SIZE.default.h, + }); + }); + it('should apply STANDALONE_RICH_TEXT minimum size constraints', () => { const pageLayout: PageLayout = { id: 'page-layout-1', diff --git a/packages/twenty-front/src/modules/page-layout/utils/__tests__/createPendingWidgetPlaceholderLayoutItem.test.ts b/packages/twenty-front/src/modules/page-layout/utils/__tests__/createPendingWidgetPlaceholderLayoutItem.test.ts index 22d6dda77d..1b6f2ab69b 100644 --- a/packages/twenty-front/src/modules/page-layout/utils/__tests__/createPendingWidgetPlaceholderLayoutItem.test.ts +++ b/packages/twenty-front/src/modules/page-layout/utils/__tests__/createPendingWidgetPlaceholderLayoutItem.test.ts @@ -1,4 +1,4 @@ -import { DEFAULT_WIDGET_SIZE } from '@/page-layout/constants/DefaultWidgetSize'; +import { DEFAULT_WIDGET_SIZE } from 'twenty-shared/constants'; import { PENDING_WIDGET_PLACEHOLDER_LAYOUT_KEY } from '@/page-layout/constants/PendingWidgetPlaceholderLayoutKey'; import { createPendingWidgetPlaceholderLayoutItem } from '@/page-layout/utils/createPendingWidgetPlaceholderLayoutItem'; diff --git a/packages/twenty-front/src/modules/page-layout/utils/convertPageLayoutToTabLayouts.ts b/packages/twenty-front/src/modules/page-layout/utils/convertPageLayoutToTabLayouts.ts index f6a02684c0..abd95484b0 100644 --- a/packages/twenty-front/src/modules/page-layout/utils/convertPageLayoutToTabLayouts.ts +++ b/packages/twenty-front/src/modules/page-layout/utils/convertPageLayoutToTabLayouts.ts @@ -1,4 +1,4 @@ -import { DEFAULT_WIDGET_SIZE } from '@/page-layout/constants/DefaultWidgetSize'; +import { DEFAULT_WIDGET_SIZE } from 'twenty-shared/constants'; import { type PageLayout } from '@/page-layout/types/PageLayout'; import { type TabLayouts } from '@/page-layout/types/TabLayouts'; import { getWidgetSize } from '@/page-layout/utils/getWidgetSize'; @@ -45,10 +45,10 @@ export const convertPageLayoutToTabLayouts = ( return { i: widget.id, - x: gridPos.column, - y: gridPos.row, - w: gridPos.columnSpan, - h: gridPos.rowSpan, + x: gridPos?.column ?? 0, + y: gridPos?.row ?? 0, + w: gridPos?.columnSpan ?? DEFAULT_WIDGET_SIZE.default.w, + h: gridPos?.rowSpan ?? DEFAULT_WIDGET_SIZE.default.h, minW, minH, }; diff --git a/packages/twenty-front/src/modules/page-layout/utils/createPendingWidgetPlaceholderLayoutItem.ts b/packages/twenty-front/src/modules/page-layout/utils/createPendingWidgetPlaceholderLayoutItem.ts index fef521c846..88522ac977 100644 --- a/packages/twenty-front/src/modules/page-layout/utils/createPendingWidgetPlaceholderLayoutItem.ts +++ b/packages/twenty-front/src/modules/page-layout/utils/createPendingWidgetPlaceholderLayoutItem.ts @@ -1,4 +1,4 @@ -import { DEFAULT_WIDGET_SIZE } from '@/page-layout/constants/DefaultWidgetSize'; +import { DEFAULT_WIDGET_SIZE } from 'twenty-shared/constants'; import { PENDING_WIDGET_PLACEHOLDER_LAYOUT_KEY } from '@/page-layout/constants/PendingWidgetPlaceholderLayoutKey'; import { type Layout } from 'react-grid-layout'; diff --git a/packages/twenty-front/src/modules/page-layout/utils/getWidgetSize.ts b/packages/twenty-front/src/modules/page-layout/utils/getWidgetSize.ts index 29026ada79..d2bb66c1d1 100644 --- a/packages/twenty-front/src/modules/page-layout/utils/getWidgetSize.ts +++ b/packages/twenty-front/src/modules/page-layout/utils/getWidgetSize.ts @@ -1,4 +1,4 @@ -import { DEFAULT_WIDGET_SIZE } from '@/page-layout/constants/DefaultWidgetSize'; +import { DEFAULT_WIDGET_SIZE } from 'twenty-shared/constants'; import { GRAPH_WIDGET_SIZES } from '@/page-layout/constants/GraphWidgetSizes'; import { type WidgetConfigurationType } from '~/generated-metadata/graphql'; diff --git a/packages/twenty-server/src/engine/core-modules/application/application-manifest/converters/__tests__/from-page-layout-widget-manifest-to-universal-flat-page-layout-widget.util.spec.ts b/packages/twenty-server/src/engine/core-modules/application/application-manifest/converters/__tests__/from-page-layout-widget-manifest-to-universal-flat-page-layout-widget.util.spec.ts index 548b5ab44d..4a958a9d8d 100644 --- a/packages/twenty-server/src/engine/core-modules/application/application-manifest/converters/__tests__/from-page-layout-widget-manifest-to-universal-flat-page-layout-widget.util.spec.ts +++ b/packages/twenty-server/src/engine/core-modules/application/application-manifest/converters/__tests__/from-page-layout-widget-manifest-to-universal-flat-page-layout-widget.util.spec.ts @@ -1,5 +1,7 @@ -import { WidgetType } from 'src/engine/metadata-modules/page-layout-widget/enums/widget-type.enum'; +import { DEFAULT_WIDGET_SIZE } from 'twenty-shared/constants'; + import { fromPageLayoutWidgetManifestToUniversalFlatPageLayoutWidget } from 'src/engine/core-modules/application/application-manifest/converters/from-page-layout-widget-manifest-to-universal-flat-page-layout-widget.util'; +import { WidgetType } from 'src/engine/metadata-modules/page-layout-widget/enums/widget-type.enum'; describe('fromPageLayoutWidgetManifestToUniversalFlatPageLayoutWidget', () => { const now = '2026-01-01T00:00:00.000Z'; @@ -33,8 +35,8 @@ describe('fromPageLayoutWidgetManifestToUniversalFlatPageLayoutWidget', () => { expect(result.gridPosition).toEqual({ row: 0, column: 0, - rowSpan: 1, - columnSpan: 1, + rowSpan: DEFAULT_WIDGET_SIZE.default.h, + columnSpan: DEFAULT_WIDGET_SIZE.default.w, }); expect(result.position).toBeNull(); expect(result.universalConfiguration).toEqual({ @@ -65,8 +67,8 @@ describe('fromPageLayoutWidgetManifestToUniversalFlatPageLayoutWidget', () => { expect(result.gridPosition).toEqual({ row: 0, column: 0, - rowSpan: 1, - columnSpan: 1, + rowSpan: DEFAULT_WIDGET_SIZE.default.h, + columnSpan: DEFAULT_WIDGET_SIZE.default.w, }); expect(result.universalConfiguration).toEqual({ configurationType: 'IFRAME', diff --git a/packages/twenty-server/src/engine/core-modules/application/application-manifest/converters/from-page-layout-widget-manifest-to-universal-flat-page-layout-widget.util.ts b/packages/twenty-server/src/engine/core-modules/application/application-manifest/converters/from-page-layout-widget-manifest-to-universal-flat-page-layout-widget.util.ts index e46876a9c1..9cf78a04b9 100644 --- a/packages/twenty-server/src/engine/core-modules/application/application-manifest/converters/from-page-layout-widget-manifest-to-universal-flat-page-layout-widget.util.ts +++ b/packages/twenty-server/src/engine/core-modules/application/application-manifest/converters/from-page-layout-widget-manifest-to-universal-flat-page-layout-widget.util.ts @@ -1,4 +1,5 @@ import { type PageLayoutWidgetManifest } from 'twenty-shared/application'; +import { DEFAULT_WIDGET_SIZE } from 'twenty-shared/constants'; import { type WidgetType } from 'src/engine/metadata-modules/page-layout-widget/enums/widget-type.enum'; import { type UniversalFlatPageLayoutWidget } from 'src/engine/workspace-manager/workspace-migration/universal-flat-entity/types/universal-flat-page-layout-widget.type'; @@ -27,8 +28,8 @@ export const fromPageLayoutWidgetManifestToUniversalFlatPageLayoutWidget = ({ gridPosition: pageLayoutWidgetManifest.gridPosition ?? { row: 0, column: 0, - rowSpan: 1, - columnSpan: 1, + rowSpan: DEFAULT_WIDGET_SIZE.default.h, + columnSpan: DEFAULT_WIDGET_SIZE.default.w, }, position: null, universalConfiguration: diff --git a/packages/twenty-front/src/modules/page-layout/constants/DefaultWidgetSize.ts b/packages/twenty-shared/src/constants/DefaultWidgetSize.ts similarity index 100% rename from packages/twenty-front/src/modules/page-layout/constants/DefaultWidgetSize.ts rename to packages/twenty-shared/src/constants/DefaultWidgetSize.ts diff --git a/packages/twenty-shared/src/constants/index.ts b/packages/twenty-shared/src/constants/index.ts index 236d0f0eae..8cebf82afd 100644 --- a/packages/twenty-shared/src/constants/index.ts +++ b/packages/twenty-shared/src/constants/index.ts @@ -21,6 +21,7 @@ export { DATE_TYPE_FORMAT } from './DateTypeFormat'; export { DEFAULT_NUMBER_OF_GROUPS_LIMIT } from './DefaultNumberOfGroupsLimit'; export { DEFAULT_RELATIVE_DATE_FILTER_VALUE } from './DefaultRelativeDateFilterValue'; export { DEFAULT_VISIBLE_ADDRESS_SUBFIELDS } from './DefaultVisibleAddressSubfields'; +export { DEFAULT_WIDGET_SIZE } from './DefaultWidgetSize'; export { DOCUMENTATION_BASE_URL } from './DocumentationBaseUrl'; export { DOCUMENTATION_DEFAULT_LANGUAGE } from './DocumentationDefaultLanguage'; export { DOCUMENTATION_DEFAULT_PATH } from './DocumentationDefaultPath';