scaffold record page layout + fields view when adding an object (#19977)
## Summary
Extends `yarn twenty add` → **Object** so it scaffolds a complete record
page out
of the box:
- A **record-page-fields view** (`<name>-record-page-fields.ts`,
FIELDS_WIDGET)
pre-populated with the `name` field plus the auto-generated default
fields (`createdAt`,
`updatedAt`, `createdBy`, `updatedBy`) — the default-field entries are
emitted as
`generateDefaultFieldUniversalIdentifier({ objectUniversalIdentifier,
fieldName: '...' })`
calls rather than pre-computed UUIDs, so the generated file
double-serves as
documentation for the public util.
- A **record page layout** (`<name>-record-page-layout.ts`) with a Home
tab whose Fields
widget points at the new view (via `viewUniversalIdentifier`), plus a
Timeline tab.
- The companion prompt now covers all three artefacts (was view + nav
menu item).
Fix: Server-side, renames `viewId` → `viewUniversalIdentifier` on the
universal-flat FIELDS
widget configuration so it is consistent with other universal-flat
references. The DB-side
DTO keeps `viewId` (now typed as `SerializedRelation`), and the
conversion utils map
between the two.
<img width="337" height="349" alt="Screenshot 2026-04-22 at 15 40 22"
src="https://github.com/user-attachments/assets/59e36540-1761-46b0-808d-648c68604268"
/>
This commit is contained in:
+1
-1
@@ -295,7 +295,7 @@ export const fromPageLayoutWidgetConfigurationToUniversalConfiguration = ({
|
||||
return {
|
||||
...rest,
|
||||
newFieldDefaultVisibility,
|
||||
viewId: viewUniversalIdentifier,
|
||||
viewUniversalIdentifier,
|
||||
};
|
||||
}
|
||||
|
||||
|
||||
+14
-8
@@ -40,17 +40,23 @@ export const validateFieldsFlatPageLayoutWidgetForCreation = (
|
||||
return errors;
|
||||
}
|
||||
|
||||
const viewId = (
|
||||
universalConfiguration as { configurationType: string; viewId?: unknown }
|
||||
).viewId;
|
||||
const viewUniversalIdentifier = (
|
||||
universalConfiguration as {
|
||||
configurationType: string;
|
||||
viewUniversalIdentifier?: unknown;
|
||||
}
|
||||
).viewUniversalIdentifier;
|
||||
|
||||
if (isDefined(viewId) && viewId !== null) {
|
||||
if (typeof viewId !== 'string' || !uuidValidate(viewId)) {
|
||||
if (isDefined(viewUniversalIdentifier) && viewUniversalIdentifier !== null) {
|
||||
if (
|
||||
typeof viewUniversalIdentifier !== 'string' ||
|
||||
!uuidValidate(viewUniversalIdentifier)
|
||||
) {
|
||||
errors.push({
|
||||
code: PageLayoutWidgetExceptionCode.INVALID_PAGE_LAYOUT_WIDGET_DATA,
|
||||
message: t`Invalid viewId for fields widget "${widgetTitle}". Expected a valid UUID`,
|
||||
userFriendlyMessage: msg`Invalid viewId for fields widget`,
|
||||
value: viewId,
|
||||
message: t`Invalid viewUniversalIdentifier for fields widget "${widgetTitle}". Expected a valid UUID`,
|
||||
userFriendlyMessage: msg`Invalid viewUniversalIdentifier for fields widget`,
|
||||
value: viewUniversalIdentifier,
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
+1
-1
@@ -89,7 +89,7 @@ export const computeFlatDefaultRecordPageLayoutToCreate = ({
|
||||
const universalConfiguration = isFieldsWidget
|
||||
? {
|
||||
configurationType: WidgetConfigurationType.FIELDS,
|
||||
viewId: recordPageFieldsView.universalIdentifier,
|
||||
viewUniversalIdentifier: recordPageFieldsView.universalIdentifier,
|
||||
}
|
||||
: {
|
||||
configurationType:
|
||||
|
||||
+5
-2
@@ -7,7 +7,10 @@ import {
|
||||
IsOptional,
|
||||
IsUUID,
|
||||
} from 'class-validator';
|
||||
import { type FieldsConfiguration } from 'twenty-shared/types';
|
||||
import {
|
||||
type FieldsConfiguration,
|
||||
type SerializedRelation,
|
||||
} from 'twenty-shared/types';
|
||||
|
||||
import { WidgetConfigurationType } from 'src/engine/metadata-modules/page-layout-widget/enums/widget-configuration-type.type';
|
||||
|
||||
@@ -21,7 +24,7 @@ export class FieldsConfigurationDTO implements FieldsConfiguration {
|
||||
@Field(() => String, { nullable: true })
|
||||
@IsOptional()
|
||||
@IsUUID()
|
||||
viewId: string | null;
|
||||
viewId: SerializedRelation | null;
|
||||
|
||||
@Field(() => Boolean, { nullable: true })
|
||||
@IsOptional()
|
||||
|
||||
Reference in New Issue
Block a user