Replace newFieldDefaultConfiguration with newFieldDefaultVisibility (#18539)

https://github.com/user-attachments/assets/365092cb-0fe1-44f7-9ae6-c6fc5edb98b2

---------

Co-authored-by: Weiko <corentin@twenty.com>
This commit is contained in:
Baptiste Devessier
2026-03-11 13:14:30 +01:00
committed by GitHub
parent e4e7137660
commit ab5fb1f658
24 changed files with 843 additions and 1096 deletions
@@ -273,7 +273,7 @@ export const fromPageLayoutWidgetConfigurationToUniversalConfiguration = ({
}
case WidgetConfigurationType.FIELDS: {
const { viewId, newFieldDefaultConfiguration, ...rest } = configuration;
const { viewId, newFieldDefaultVisibility, ...rest } = configuration;
let viewUniversalIdentifier: string | null = null;
@@ -291,40 +291,10 @@ export const fromPageLayoutWidgetConfigurationToUniversalConfiguration = ({
}
}
if (!isDefined(newFieldDefaultConfiguration)) {
return {
...rest,
newFieldDefaultConfiguration,
viewId: viewUniversalIdentifier,
};
}
let viewFieldGroupUniversalIdentifier: string | null = null;
if (isDefined(newFieldDefaultConfiguration.viewFieldGroupId)) {
viewFieldGroupUniversalIdentifier =
viewFieldGroupUniversalIdentifierById[
newFieldDefaultConfiguration.viewFieldGroupId
] ?? null;
if (
!isDefined(viewFieldGroupUniversalIdentifier) &&
shouldThrowOnMissingIdentifier
) {
throw new FlatEntityMapsException(
`View field group universal identifier not found for id: ${newFieldDefaultConfiguration.viewFieldGroupId}`,
FlatEntityMapsExceptionCode.RELATION_UNIVERSAL_IDENTIFIER_NOT_FOUND,
);
}
}
return {
...rest,
newFieldDefaultVisibility,
viewId: viewUniversalIdentifier,
newFieldDefaultConfiguration: {
isVisible: newFieldDefaultConfiguration.isVisible,
viewFieldGroupId: viewFieldGroupUniversalIdentifier,
},
};
}
@@ -1,8 +1,8 @@
import { type FlatPageLayoutWidgetMaps } from 'src/engine/metadata-modules/flat-page-layout-widget/types/flat-page-layout-widget-maps.type';
import { type FlatViewFieldGroupMaps } from 'src/engine/metadata-modules/flat-view-field-group/types/flat-view-field-group-maps.type';
import { DEFAULT_VIEW_FIELD_SIZE } from 'src/engine/metadata-modules/flat-view-field/constants/default-view-field-size.constant';
import { type FlatViewFieldMaps } from 'src/engine/metadata-modules/flat-view-field/types/flat-view-field-maps.type';
import { computeFlatViewFieldsFromFieldsWidgets } from 'src/engine/metadata-modules/flat-view-field/utils/compute-flat-view-fields-from-fields-widgets.util';
import { type FlatPageLayoutWidgetMaps } from 'src/engine/metadata-modules/flat-page-layout-widget/types/flat-page-layout-widget-maps.type';
import { type FlatViewFieldGroupMaps } from 'src/engine/metadata-modules/flat-view-field-group/types/flat-view-field-group-maps.type';
import { type FlatViewMaps } from 'src/engine/metadata-modules/flat-view/types/flat-view-maps.type';
import { WidgetConfigurationType } from 'src/engine/metadata-modules/page-layout-widget/enums/widget-configuration-type.type';
import { WidgetType } from 'src/engine/metadata-modules/page-layout-widget/enums/widget-type.enum';
@@ -37,13 +37,24 @@ const buildFlatViewMaps = (
}) as unknown as FlatViewMaps;
const buildFlatViewFieldGroupMaps = (
entries: { id: string; universalIdentifier: string }[] = [],
entries: {
id: string;
universalIdentifier: string;
viewId?: string;
position?: number;
}[] = [],
): FlatViewFieldGroupMaps =>
({
byUniversalIdentifier: Object.fromEntries(
entries.map((entry) => [
entry.universalIdentifier,
{ universalIdentifier: entry.universalIdentifier, id: entry.id },
{
universalIdentifier: entry.universalIdentifier,
id: entry.id,
viewId: entry.viewId ?? VIEW_ID,
position: entry.position ?? 0,
deletedAt: null,
},
]),
),
universalIdentifierById: Object.fromEntries(
@@ -74,14 +85,12 @@ const buildFieldsWidget = ({
objectMetadataUniversalIdentifier = OBJECT_METADATA_UNIVERSAL_IDENTIFIER,
viewId = VIEW_ID,
isVisible = true,
viewFieldGroupId = null as string | null,
deletedAt = null as string | null,
}: {
widgetUniversalIdentifier?: string;
objectMetadataUniversalIdentifier?: string;
viewId?: string | null;
isVisible?: boolean;
viewFieldGroupId?: string | null;
deletedAt?: string | null;
} = {}) => ({
universalIdentifier: widgetUniversalIdentifier,
@@ -91,10 +100,7 @@ const buildFieldsWidget = ({
configuration: {
configurationType: WidgetConfigurationType.FIELDS,
viewId,
newFieldDefaultConfiguration: {
isVisible,
viewFieldGroupId,
},
newFieldDefaultVisibility: isVisible,
},
universalConfiguration: null,
overrides: null,
@@ -478,7 +484,7 @@ describe('computeFlatViewFieldsFromFieldsWidgets', () => {
});
describe('view field group handling', () => {
it('should resolve viewFieldGroupUniversalIdentifier when viewFieldGroupId is set', () => {
it('should resolve to the last view field group when groups exist', () => {
const result = computeFlatViewFieldsFromFieldsWidgets({
fieldsToCreate: [
{
@@ -488,7 +494,7 @@ describe('computeFlatViewFieldsFromFieldsWidgets', () => {
},
],
flatPageLayoutWidgetMaps: buildFlatPageLayoutWidgetMaps([
buildFieldsWidget({ viewFieldGroupId: VIEW_FIELD_GROUP_ID }),
buildFieldsWidget(),
]),
flatViewFieldMaps: buildFlatViewFieldMaps(),
flatViewMaps: buildFlatViewMaps([
@@ -509,7 +515,7 @@ describe('computeFlatViewFieldsFromFieldsWidgets', () => {
);
});
it('should set viewFieldGroupUniversalIdentifier to null when viewFieldGroupId is null', () => {
it('should set viewFieldGroupUniversalIdentifier to null when no groups exist', () => {
const result = computeFlatViewFieldsFromFieldsWidgets({
fieldsToCreate: [
{
@@ -519,7 +525,7 @@ describe('computeFlatViewFieldsFromFieldsWidgets', () => {
},
],
flatPageLayoutWidgetMaps: buildFlatPageLayoutWidgetMaps([
buildFieldsWidget({ viewFieldGroupId: null }),
buildFieldsWidget(),
]),
flatViewFieldMaps: buildFlatViewFieldMaps(),
flatViewMaps: buildFlatViewMaps([
@@ -532,7 +538,7 @@ describe('computeFlatViewFieldsFromFieldsWidgets', () => {
expect(result[0].viewFieldGroupUniversalIdentifier).toBeNull();
});
it('should compute position only from view fields in the same group', () => {
it('should compute position only from view fields in the last group', () => {
const result = computeFlatViewFieldsFromFieldsWidgets({
fieldsToCreate: [
{
@@ -542,7 +548,7 @@ describe('computeFlatViewFieldsFromFieldsWidgets', () => {
},
],
flatPageLayoutWidgetMaps: buildFlatPageLayoutWidgetMaps([
buildFieldsWidget({ viewFieldGroupId: VIEW_FIELD_GROUP_ID }),
buildFieldsWidget(),
]),
flatViewFieldMaps: buildFlatViewFieldMaps([
{
@@ -582,7 +588,7 @@ describe('computeFlatViewFieldsFromFieldsWidgets', () => {
expect(result[0].position).toBe(3);
});
it('should compute position only from ungrouped view fields when viewFieldGroupId is null', () => {
it('should compute position only from ungrouped view fields when no groups exist', () => {
const result = computeFlatViewFieldsFromFieldsWidgets({
fieldsToCreate: [
{
@@ -592,7 +598,7 @@ describe('computeFlatViewFieldsFromFieldsWidgets', () => {
},
],
flatPageLayoutWidgetMaps: buildFlatPageLayoutWidgetMaps([
buildFieldsWidget({ viewFieldGroupId: null }),
buildFieldsWidget(),
]),
flatViewFieldMaps: buildFlatViewFieldMaps([
{
@@ -3,10 +3,10 @@ import { v4 } from 'uuid';
import { type FlatPageLayoutWidgetMaps } from 'src/engine/metadata-modules/flat-page-layout-widget/types/flat-page-layout-widget-maps.type';
import { type FlatPageLayoutWidget } from 'src/engine/metadata-modules/flat-page-layout-widget/types/flat-page-layout-widget.type';
import { type FlatViewFieldGroupMaps } from 'src/engine/metadata-modules/flat-view-field-group/types/flat-view-field-group-maps.type';
import { DEFAULT_VIEW_FIELD_SIZE } from 'src/engine/metadata-modules/flat-view-field/constants/default-view-field-size.constant';
import { type FlatViewFieldMaps } from 'src/engine/metadata-modules/flat-view-field/types/flat-view-field-maps.type';
import { type FlatViewField } from 'src/engine/metadata-modules/flat-view-field/types/flat-view-field.type';
import { type FlatViewFieldGroupMaps } from 'src/engine/metadata-modules/flat-view-field-group/types/flat-view-field-group-maps.type';
import { type FlatViewMaps } from 'src/engine/metadata-modules/flat-view/types/flat-view-maps.type';
import { type FieldsConfigurationDTO } from 'src/engine/metadata-modules/page-layout-widget/dtos/fields-configuration.dto';
import { WidgetConfigurationType } from 'src/engine/metadata-modules/page-layout-widget/enums/widget-configuration-type.type';
@@ -45,9 +45,33 @@ const getMatchingFieldsWidgets = ({
objectMetadataUniversalIdentifier &&
isFieldsWidgetConfiguration(widget.configuration) &&
isDefined(widget.configuration.viewId) &&
isDefined(widget.configuration.newFieldDefaultConfiguration),
isDefined(widget.configuration.newFieldDefaultVisibility),
);
const findLastViewFieldGroupId = ({
viewId,
flatViewFieldGroupMaps,
}: {
viewId: string;
flatViewFieldGroupMaps: FlatViewFieldGroupMaps;
}): string | null => {
const groupsForView = Object.values(
flatViewFieldGroupMaps.byUniversalIdentifier,
)
.filter(isDefined)
.filter((group) => !isDefined(group.deletedAt) && group.viewId === viewId);
if (groupsForView.length === 0) {
return null;
}
const lastGroup = groupsForView.reduce((maxGroup, group) =>
group.position > maxGroup.position ? group : maxGroup,
);
return lastGroup.id;
};
const computeNextPosition = ({
viewId,
viewFieldGroupId,
@@ -127,8 +151,7 @@ export const computeFlatViewFieldsFromFieldsWidgets = ({
const configuration = widget.configuration;
const viewId = configuration.viewId!;
const { isVisible, viewFieldGroupId } =
configuration.newFieldDefaultConfiguration!;
const isVisible = configuration.newFieldDefaultVisibility!;
const viewUniversalIdentifier =
flatViewMaps.universalIdentifierById[viewId] ?? null;
@@ -137,6 +160,11 @@ export const computeFlatViewFieldsFromFieldsWidgets = ({
continue;
}
const viewFieldGroupId = findLastViewFieldGroupId({
viewId,
flatViewFieldGroupMaps,
});
const viewFieldGroupUniversalIdentifier = isDefined(viewFieldGroupId)
? (flatViewFieldGroupMaps.universalIdentifierById[viewFieldGroupId] ??
null)
@@ -1,30 +1,16 @@
import { Field, ObjectType } from '@nestjs/graphql';
import { Type } from 'class-transformer';
import {
IsBoolean,
IsIn,
IsNotEmpty,
IsOptional,
IsUUID,
ValidateNested,
} from 'class-validator';
import { type FieldsConfiguration } from 'twenty-shared/types';
import { WidgetConfigurationType } from 'src/engine/metadata-modules/page-layout-widget/enums/widget-configuration-type.type';
@ObjectType('NewFieldDefaultConfiguration')
export class NewFieldDefaultConfigurationDTO {
@Field(() => Boolean)
@IsBoolean()
isVisible: boolean;
@Field(() => String, { nullable: true })
@IsOptional()
@IsUUID()
viewFieldGroupId: string | null;
}
@ObjectType('FieldsConfiguration')
export class FieldsConfigurationDTO implements FieldsConfiguration {
@Field(() => WidgetConfigurationType)
@@ -37,11 +23,10 @@ export class FieldsConfigurationDTO implements FieldsConfiguration {
@IsUUID()
viewId: string | null;
@Field(() => NewFieldDefaultConfigurationDTO, { nullable: true })
@Field(() => Boolean, { nullable: true })
@IsOptional()
@ValidateNested()
@Type(() => NewFieldDefaultConfigurationDTO)
newFieldDefaultConfiguration: NewFieldDefaultConfigurationDTO | null;
@IsBoolean()
newFieldDefaultVisibility: boolean | null;
@Field(() => Boolean, { nullable: true })
@IsOptional()