fix(ui): resets value in where builder when operator changes (#11136)

### What?
The list filters in the collection view allows invalid queries. If you
enter a value and then change operator, the value will remain even if it
doesn't pass the new value field validation, and an error is thrown.

### Why?
The value isn't reset or revalidated on operator change. It is reset on
field change.

### How?
Resets the value field when the operator changes.

Fixes #10648
This commit is contained in:
Jessica Chowdhury
2025-04-08 14:52:11 +01:00
committed by GitHub
parent f079eced8a
commit ec34e64261
3 changed files with 50 additions and 3 deletions

View File

@@ -26,8 +26,9 @@ import { useEffectEvent } from '../../../hooks/useEffectEvent.js'
import { useTranslation } from '../../../providers/Translation/index.js'
import { Button } from '../../Button/index.js'
import { ReactSelect } from '../../ReactSelect/index.js'
import './index.scss'
import { DefaultFilter } from './DefaultFilter/index.js'
import { getOperatorValueTypes } from './validOperators.js'
import './index.scss'
const baseClass = 'condition'
@@ -103,12 +104,25 @@ export const Condition: React.FC<Props> = (props) => {
const handleOperatorChange = useCallback(
async (operator: Option<Operator>) => {
const operatorValueTypes = getOperatorValueTypes(reducedField.field.type)
const validOperatorValue = operatorValueTypes[operator.value] || 'any'
const isValidValue =
validOperatorValue === 'any' ||
typeof value === validOperatorValue ||
(validOperatorValue === 'boolean' && (value === 'true' || value === 'false'))
if (!isValidValue) {
// if the current value is not valid for the new operator
// reset the value before passing it to updateCondition
setInternalValue(undefined)
}
await updateCondition({
andIndex,
field: reducedField,
operator: operator.value,
orIndex,
value,
value: isValidValue ? value : undefined,
})
},
[andIndex, reducedField, orIndex, updateCondition, value],

View File

@@ -0,0 +1,34 @@
export const getOperatorValueTypes = (fieldType) => {
return {
all: 'any',
contains: 'string',
equals: 'any',
/*
* exists:
* The expected value is boolean, but it's passed as a string ('true' or 'false').
* Need to additionally check if the value is strictly 'true' or 'false' as a string,
* rather than using a direct typeof comparison.
* This is handled as:
* validOperatorValue === 'boolean' && (value === 'true' || value === 'false')
*/
exists: 'boolean',
/*
* greater_than, greater_than_equal, less_than, less_than_equal:
* Used for number and date fields:
* - For date fields, the value is an object (e.g., Mon Feb 17 2025 12:00:00 GMT+0000).
* - For number fields, the value is a string representing the number.
*/
greater_than: fieldType === 'date' ? 'object' : 'string',
greater_than_equal: fieldType === 'date' ? 'object' : 'string',
in: 'any',
intersects: 'any',
less_than: fieldType === 'date' ? 'object' : 'string',
less_than_equal: fieldType === 'date' ? 'object' : 'string',
like: 'string',
near: 'any',
not_equals: 'any',
not_in: 'any',
not_like: 'string',
within: 'any',
}
}

View File

@@ -413,7 +413,6 @@ describe('List View', () => {
await expect(whereBuilder.locator('.condition__value input')).toHaveValue('')
})
// eslint-disable-next-line playwright/expect-expect
test('should remove condition from URL when value is cleared', async () => {
await page.goto(postsUrl.list)