From 0696290af4dd8bfa48f78ae0d6d798cbbd35d2a1 Mon Sep 17 00:00:00 2001 From: Weiko Date: Wed, 22 Apr 2026 17:28:29 +0200 Subject: [PATCH] fix(page-layout): hide deactivated fields from FIELDS widget and layout editor (#19984) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit ## Context - The FIELDS widget resolved every viewField against objectMetadataItem.fields, which includes deactivated field metadata — so fields deactivated after being added to a view kept rendering on records. - Same leak existed in the layout editor: deactivated fields appeared as toggleable hidden viewFields, and newly-deactivated object fields were auto-proposed via the "missing fields" flow. ## Fix - pre-filter objectMetadataItem.fields to field.isActive at each entry point (useFieldsWidgetGroups, useFieldsWidgetEditorGroupsData, useFieldsWidgetHiddenFields) and inside buildDefaultFieldsWidgetGroups for the no-view fallback. --- .../hooks/useFieldsWidgetEditorGroupsData.ts | 12 ++++++++---- .../widgets/fields/hooks/useFieldsWidgetGroups.ts | 8 ++++++-- .../fields/hooks/useFieldsWidgetHiddenFields.ts | 8 ++++++-- .../fields/utils/buildDefaultFieldsWidgetGroups.ts | 14 ++++++++------ 4 files changed, 28 insertions(+), 14 deletions(-) diff --git a/packages/twenty-front/src/modules/page-layout/widgets/fields/hooks/useFieldsWidgetEditorGroupsData.ts b/packages/twenty-front/src/modules/page-layout/widgets/fields/hooks/useFieldsWidgetEditorGroupsData.ts index 1555d53db6..b9a57804df 100644 --- a/packages/twenty-front/src/modules/page-layout/widgets/fields/hooks/useFieldsWidgetEditorGroupsData.ts +++ b/packages/twenty-front/src/modules/page-layout/widgets/fields/hooks/useFieldsWidgetEditorGroupsData.ts @@ -49,8 +49,12 @@ export const useFieldsWidgetEditorGroupsData = ({ return { groups: [], ungroupedFields: [], editorMode: 'ungrouped' }; } + const activeFields = objectMetadataItem.fields.filter( + (field) => field.isActive, + ); + const eligibleFieldMetadataIds = new Set( - objectMetadataItem.fields + activeFields .filter((field) => isFieldMetadataEligibleForFieldsWidget({ fieldName: field.name, @@ -74,7 +78,7 @@ export const useFieldsWidgetEditorGroupsData = ({ let globalIndex = startGlobalIndex; let position = startPosition; - return objectMetadataItem.fields + return activeFields .filter( (field) => !existingFieldMetadataIds.has(field.id) && @@ -105,7 +109,7 @@ export const useFieldsWidgetEditorGroupsData = ({ const fields: FieldsWidgetGroupField[] = groupFields .map((viewField) => { - const fieldMetadataItem = objectMetadataItem.fields.find( + const fieldMetadataItem = activeFields.find( (f) => f.id === viewField.fieldMetadataId, ); @@ -160,7 +164,7 @@ export const useFieldsWidgetEditorGroupsData = ({ const fields = [...view.viewFields] .sort((a, b) => a.position - b.position) .map((viewField) => { - const fieldMetadataItem = objectMetadataItem.fields.find( + const fieldMetadataItem = activeFields.find( (f) => f.id === viewField.fieldMetadataId, ); diff --git a/packages/twenty-front/src/modules/page-layout/widgets/fields/hooks/useFieldsWidgetGroups.ts b/packages/twenty-front/src/modules/page-layout/widgets/fields/hooks/useFieldsWidgetGroups.ts index 2bd936e8e7..72fa368f7b 100644 --- a/packages/twenty-front/src/modules/page-layout/widgets/fields/hooks/useFieldsWidgetGroups.ts +++ b/packages/twenty-front/src/modules/page-layout/widgets/fields/hooks/useFieldsWidgetGroups.ts @@ -37,6 +37,10 @@ export const useFieldsWidgetGroups = ({ return { groups: [], displayMode: 'grouped' }; } + const activeFields = objectMetadataItem.fields.filter( + (field) => field.isActive, + ); + if (isDefined(view) && isNonEmptyArray(view.viewFieldGroups)) { const sortedGroups = view.viewFieldGroups.toSorted( (a, b) => a.position - b.position, @@ -54,7 +58,7 @@ export const useFieldsWidgetGroups = ({ const fields: FieldsWidgetGroupField[] = groupFields .filter((field) => field.isVisible) .map((viewField) => { - const fieldMetadataItem = objectMetadataItem.fields.find( + const fieldMetadataItem = activeFields.find( (f) => f.id === viewField.fieldMetadataId, ); @@ -93,7 +97,7 @@ export const useFieldsWidgetGroups = ({ .sort((a, b) => a.position - b.position) .filter((viewField) => viewField.isVisible) .map((viewField) => { - const fieldMetadataItem = objectMetadataItem.fields.find( + const fieldMetadataItem = activeFields.find( (f) => f.id === viewField.fieldMetadataId, ); diff --git a/packages/twenty-front/src/modules/page-layout/widgets/fields/hooks/useFieldsWidgetHiddenFields.ts b/packages/twenty-front/src/modules/page-layout/widgets/fields/hooks/useFieldsWidgetHiddenFields.ts index d31cd1588b..8c4ffe1e91 100644 --- a/packages/twenty-front/src/modules/page-layout/widgets/fields/hooks/useFieldsWidgetHiddenFields.ts +++ b/packages/twenty-front/src/modules/page-layout/widgets/fields/hooks/useFieldsWidgetHiddenFields.ts @@ -27,11 +27,15 @@ export const useFieldsWidgetHiddenFields = ({ return []; } + const activeFields = objectMetadataItem.fields.filter( + (field) => field.isActive, + ); + if (isDefined(view) && isNonEmptyArray(view.viewFieldGroups)) { const groups: FieldsWidgetGroup[] = view.viewFieldGroups.map((group) => { const fields: FieldsWidgetGroupField[] = (group.viewFields ?? []) .map((viewField) => { - const fieldMetadataItem = objectMetadataItem.fields.find( + const fieldMetadataItem = activeFields.find( (f) => f.id === viewField.fieldMetadataId, ); @@ -67,7 +71,7 @@ export const useFieldsWidgetHiddenFields = ({ .sort((a, b) => a.position - b.position) .filter((viewField) => !viewField.isVisible) .map((viewField) => { - const fieldMetadataItem = objectMetadataItem.fields.find( + const fieldMetadataItem = activeFields.find( (f) => f.id === viewField.fieldMetadataId, ); diff --git a/packages/twenty-front/src/modules/page-layout/widgets/fields/utils/buildDefaultFieldsWidgetGroups.ts b/packages/twenty-front/src/modules/page-layout/widgets/fields/utils/buildDefaultFieldsWidgetGroups.ts index e2cf1ff9ea..f1be26ef80 100644 --- a/packages/twenty-front/src/modules/page-layout/widgets/fields/utils/buildDefaultFieldsWidgetGroups.ts +++ b/packages/twenty-front/src/modules/page-layout/widgets/fields/utils/buildDefaultFieldsWidgetGroups.ts @@ -11,12 +11,14 @@ export const buildDefaultFieldsWidgetGroups = ({ fields: FieldMetadataItem[]; labelIdentifierFieldMetadataItemId: string | undefined; }): FieldsWidgetGroup[] => { - const eligibleFields = fields.filter((field) => - isFieldMetadataEligibleForFieldsWidget({ - fieldName: field.name, - fieldType: field.type, - isLabelIdentifierField: field.id === labelIdentifierFieldMetadataItemId, - }), + const eligibleFields = fields.filter( + (field) => + field.isActive && + isFieldMetadataEligibleForFieldsWidget({ + fieldName: field.name, + fieldType: field.type, + isLabelIdentifierField: field.id === labelIdentifierFieldMetadataItemId, + }), ); const standardFields = eligibleFields.filter((field) => !field.isCustom);