From 8b2447a624ad1af706793cc4761ab62cec2e6526 Mon Sep 17 00:00:00 2001 From: Marie <51697796+ijreilly@users.noreply.github.com> Date: Thu, 2 Oct 2025 16:14:51 +0200 Subject: [PATCH] [Fix] Cannot remove any field filter (#14813) Fixes https://github.com/twentyhq/twenty/issues/14766 To reproduce 1. create a view with a any field filter and save it. After, remove any field filter clicking on the X on the chip. No "Update view" shows. 2. now add another regular filter to the view and save it. Now remove any field filter clicking on the X on the chip and remove the regular filter you just added. Now "Update view" shows, click it and refresh the page. Any field filter still shows There were two problems 1. UpdateViewButtonGroup is in charge of showing "Update View" button. But is never mounted if shouldExpandViewBar is falsy. shouldExpandViewBar was not considering viewAnyFieldFilterDifferentFromCurrentAnyFieldFilter so even if any field filter had changed, UpdateViewButtonGroup still wasn't going to show "Update view" button because it wasn't mounted 2. At save time, we added anyFieldFilterValue to the mutation payload if ``` ...(view.anyFieldFilterValue && { anyFieldFilterValue: view.anyFieldFilterValue, }), ```, but in JS an empty string evaluates to falsy. --- .../modules/views/components/ViewBarDetails.tsx | 1 + ...ieldFilterDifferentFromCurrentAnyFieldFilter.ts | 5 ++++- .../views/utils/convertUpdateViewInputToCore.ts | 14 ++++++++------ 3 files changed, 13 insertions(+), 7 deletions(-) diff --git a/packages/twenty-front/src/modules/views/components/ViewBarDetails.tsx b/packages/twenty-front/src/modules/views/components/ViewBarDetails.tsx index 329a879a23..cec9a9d540 100644 --- a/packages/twenty-front/src/modules/views/components/ViewBarDetails.tsx +++ b/packages/twenty-front/src/modules/views/components/ViewBarDetails.tsx @@ -204,6 +204,7 @@ export const ViewBarDetails = ({ viewFiltersAreDifferentFromRecordFilters || viewSortsAreDifferentFromRecordSorts || viewFilterGroupsAreDifferentFromRecordFilterGroups || + viewAnyFieldFilterDifferentFromCurrentAnyFieldFilter || ((currentRecordSorts.length > 0 || currentRecordFilters.length > 0 || currentRecordFilterGroups.length > 0) && diff --git a/packages/twenty-front/src/modules/views/hooks/useIsViewAnyFieldFilterDifferentFromCurrentAnyFieldFilter.ts b/packages/twenty-front/src/modules/views/hooks/useIsViewAnyFieldFilterDifferentFromCurrentAnyFieldFilter.ts index 0442fe17b7..4927631cdb 100644 --- a/packages/twenty-front/src/modules/views/hooks/useIsViewAnyFieldFilterDifferentFromCurrentAnyFieldFilter.ts +++ b/packages/twenty-front/src/modules/views/hooks/useIsViewAnyFieldFilterDifferentFromCurrentAnyFieldFilter.ts @@ -1,6 +1,7 @@ import { anyFieldFilterValueComponentState } from '@/object-record/record-filter/states/anyFieldFilterValueComponentState'; import { useRecoilComponentValue } from '@/ui/utilities/state/component-state/hooks/useRecoilComponentValue'; import { useGetCurrentViewOnly } from '@/views/hooks/useGetCurrentViewOnly'; +import { isDefined } from 'twenty-shared/utils'; import { compareNonEmptyStrings } from '~/utils/compareNonEmptyStrings'; export const useIsViewAnyFieldFilterDifferentFromCurrentAnyFieldFilter = () => { @@ -12,7 +13,9 @@ export const useIsViewAnyFieldFilterDifferentFromCurrentAnyFieldFilter = () => { const viewAnyFieldFilterValue = currentView?.anyFieldFilterValue; const viewAnyFieldFilterDifferentFromCurrentAnyFieldFilter = - !compareNonEmptyStrings(viewAnyFieldFilterValue, anyFieldFilterValue); + anyFieldFilterValue === '' + ? isDefined(viewAnyFieldFilterValue) + : !compareNonEmptyStrings(viewAnyFieldFilterValue, anyFieldFilterValue); return { viewAnyFieldFilterDifferentFromCurrentAnyFieldFilter }; }; diff --git a/packages/twenty-front/src/modules/views/utils/convertUpdateViewInputToCore.ts b/packages/twenty-front/src/modules/views/utils/convertUpdateViewInputToCore.ts index 1be12990c8..8fd11ebab9 100644 --- a/packages/twenty-front/src/modules/views/utils/convertUpdateViewInputToCore.ts +++ b/packages/twenty-front/src/modules/views/utils/convertUpdateViewInputToCore.ts @@ -24,19 +24,21 @@ export const convertUpdateViewInputToCore = ( ...(view.icon && { icon: view.icon }), ...(isDefined(view.position) && { position: view.position }), ...(isDefined(view.isCompact) && { isCompact: view.isCompact }), - ...(view.kanbanAggregateOperation && { + ...(isDefined(view.kanbanAggregateOperation) && { kanbanAggregateOperation: view.kanbanAggregateOperation, }), - ...(view.kanbanAggregateOperationFieldMetadataId && { + ...(isDefined(view.kanbanAggregateOperationFieldMetadataId) && { kanbanAggregateOperationFieldMetadataId: view.kanbanAggregateOperationFieldMetadataId, }), - ...(view.anyFieldFilterValue && { + ...(isDefined(view.anyFieldFilterValue) && { anyFieldFilterValue: view.anyFieldFilterValue, }), - ...(convertedKey && { key: convertedKey }), - ...(convertedOpenRecordIn && { openRecordIn: convertedOpenRecordIn }), - ...(convertedType && { type: convertedType }), + ...(isDefined(convertedKey) && { key: convertedKey }), + ...(isDefined(convertedOpenRecordIn) && { + openRecordIn: convertedOpenRecordIn, + }), + ...(isDefined(convertedType) && { type: convertedType }), ...(isDefined(view.calendarLayout) && { calendarLayout: view.calendarLayout, }),