f7aab2e988
## Context Fixes #23065. App-manifest dashboard `RECORD_TABLE` widgets could not reference a view by universal identifier. `RecordTableConfiguration.viewId` was typed as a plain `string`, so `FormatRecordSerializedRelationProperties` (which only renames properties branded with `SerializedRelation`) left it as `viewId` in the manifest type. As a result the manifest rejected `viewUniversalIdentifier`, and the widget could not be made portable across workspaces the way `FIELDS` widgets already are. ## Changes - `RecordTableConfiguration.viewId` is now `SerializedRelation | null` (was `string`), matching `FieldsConfiguration`. This makes the manifest type surface `viewUniversalIdentifier` instead of `viewId`. - `RecordTableConfigurationDTO.viewId` retyped to match. - Forward converter (`fromPageLayoutWidgetConfigurationToUniversalConfiguration`): the `RECORD_TABLE` case now emits the `viewUniversalIdentifier` key instead of `viewId`, since the branded property is renamed in the universal type. Now consistent with the `FIELDS` case (uses `| null`). - Reverse converter (`fromUniversalConfigurationToFlatPageLayoutWidgetConfiguration`): the `RECORD_TABLE` case now reads `viewUniversalIdentifier` and resolves it back to a concrete `viewId`. Frontend readers need no change: `SerializedRelation` is a runtime string, so the existing `typeof === 'string'` guards and `as string` casts still hold. ## Migration None needed. The persisted `pageLayoutWidget.configuration` still stores a concrete `viewId`; `universalConfiguration` (which carries `viewUniversalIdentifier`) is computed on the fly from it and never persisted. Only the manifest/universal representation changes, so there is no stored data in the old shape to backfill. ## Verification - `nx typecheck twenty-server` and `nx typecheck twenty-front`: pass - oxlint + oxfmt on the changed files: clean - End-to-end against a server built from this branch: built a minimal app declaring a view (by `universalIdentifier`) and a `DASHBOARD` page layout with a `RECORD_TABLE` widget referencing that view via `viewUniversalIdentifier`, then installed it. The manifest carried `viewUniversalIdentifier`, and the installed `pageLayoutWidget.configuration.viewId` resolved to the concrete workspace view id. <!-- This is an auto-generated description by cubic. --> <a href="https://cubic.dev/pr/twentyhq/twenty/pull/23634?utm_source=github" target="_blank" rel="noopener noreferrer" data-no-image-dialog="true"><picture><source media="(prefers-color-scheme: dark)" srcset="https://www.cubic.dev/buttons/review-in-cubic-dark.svg"><source media="(prefers-color-scheme: light)" srcset="https://www.cubic.dev/buttons/review-in-cubic-light.svg"><img alt="Review in cubic" src="https://www.cubic.dev/buttons/review-in-cubic-dark.svg"></picture></a> <!-- End of auto-generated description by cubic. -->