[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.
This commit is contained in:
Marie
2025-10-02 16:14:51 +02:00
committed by GitHub
parent 98544a2479
commit 8b2447a624
3 changed files with 13 additions and 7 deletions
@@ -204,6 +204,7 @@ export const ViewBarDetails = ({
viewFiltersAreDifferentFromRecordFilters ||
viewSortsAreDifferentFromRecordSorts ||
viewFilterGroupsAreDifferentFromRecordFilterGroups ||
viewAnyFieldFilterDifferentFromCurrentAnyFieldFilter ||
((currentRecordSorts.length > 0 ||
currentRecordFilters.length > 0 ||
currentRecordFilterGroups.length > 0) &&
@@ -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 };
};
@@ -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,
}),