Introducing view field group syncable entity (#17867)

## Context
Introduces a new viewFieldGroup entity that allows grouping view fields
into sections (e.g. "General", "Additional", "Other") within a view.

The page layout fields widget needs a way to organize fields into
sections. Today, views have no concept of field grouping. This PR
introduces the viewFieldGroup entity which sits between a view and its
viewFields, enabling section-based organization.

<img width="401" height="724" alt="Layout - V2 (customize visibility)"
src="https://github.com/user-attachments/assets/6376e2ab-44db-42bf-9d2c-758f56f6b548"
/>

---------

Co-authored-by: Charles Bochet <charles@twenty.com>
This commit is contained in:
Weiko
2026-02-11 22:02:58 +01:00
committed by GitHub
parent ed66fbd71b
commit 6aca1dd013
126 changed files with 3593 additions and 115 deletions
@@ -15,6 +15,7 @@ export const ALL_JSONB_PROPERTIES_WITH_SERIALIZED_RELATION_BY_METADATA_NAME = {
view: {},
viewField: {},
viewGroup: {},
viewFieldGroup: {},
viewFilter: {},
viewFilterGroup: {},
index: {},
@@ -202,6 +202,7 @@ export const ALL_UNIVERSAL_METADATA_RELATIONS = {
viewFilters: { metadataName: 'viewFilter' },
viewFilterGroups: { metadataName: 'viewFilterGroup' },
viewGroups: { metadataName: 'viewGroup' },
viewFieldGroups: { metadataName: 'viewFieldGroup' },
// TODO migrate viewSort to v2
viewSorts: null,
},
@@ -224,11 +225,36 @@ export const ALL_UNIVERSAL_METADATA_RELATIONS = {
universalForeignKey: 'viewUniversalIdentifier',
isNullable: false,
},
viewFieldGroup: {
metadataName: 'viewFieldGroup',
foreignKey: 'viewFieldGroupId',
universalFlatEntityForeignKeyAggregator:
'viewFieldUniversalIdentifiers',
universalForeignKey: 'viewFieldGroupUniversalIdentifier',
isNullable: true,
},
workspace: null,
application: null,
},
oneToMany: {},
},
viewFieldGroup: {
manyToOne: {
view: {
metadataName: 'view',
foreignKey: 'viewId',
universalFlatEntityForeignKeyAggregator:
'viewFieldGroupUniversalIdentifiers',
universalForeignKey: 'viewUniversalIdentifier',
isNullable: false,
},
workspace: null,
application: null,
},
oneToMany: {
viewFields: { metadataName: 'viewField' },
},
},
viewFilter: {
manyToOne: {
fieldMetadata: {
@@ -0,0 +1,7 @@
import { type ViewFieldGroupEntity } from 'src/engine/metadata-modules/view-field-group/entities/view-field-group.entity';
import { type UniversalFlatEntityFrom } from 'src/engine/workspace-manager/workspace-migration/universal-flat-entity/types/universal-flat-entity-from.type';
export type UniversalFlatViewFieldGroup = UniversalFlatEntityFrom<
ViewFieldGroupEntity,
'viewFieldGroup'
>;