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:
committed by
GitHub
parent
f079eced8a
commit
ec34e64261
@@ -26,8 +26,9 @@ import { useEffectEvent } from '../../../hooks/useEffectEvent.js'
|
|||||||
import { useTranslation } from '../../../providers/Translation/index.js'
|
import { useTranslation } from '../../../providers/Translation/index.js'
|
||||||
import { Button } from '../../Button/index.js'
|
import { Button } from '../../Button/index.js'
|
||||||
import { ReactSelect } from '../../ReactSelect/index.js'
|
import { ReactSelect } from '../../ReactSelect/index.js'
|
||||||
import './index.scss'
|
|
||||||
import { DefaultFilter } from './DefaultFilter/index.js'
|
import { DefaultFilter } from './DefaultFilter/index.js'
|
||||||
|
import { getOperatorValueTypes } from './validOperators.js'
|
||||||
|
import './index.scss'
|
||||||
|
|
||||||
const baseClass = 'condition'
|
const baseClass = 'condition'
|
||||||
|
|
||||||
@@ -103,12 +104,25 @@ export const Condition: React.FC<Props> = (props) => {
|
|||||||
|
|
||||||
const handleOperatorChange = useCallback(
|
const handleOperatorChange = useCallback(
|
||||||
async (operator: Option<Operator>) => {
|
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({
|
await updateCondition({
|
||||||
andIndex,
|
andIndex,
|
||||||
field: reducedField,
|
field: reducedField,
|
||||||
operator: operator.value,
|
operator: operator.value,
|
||||||
orIndex,
|
orIndex,
|
||||||
value,
|
value: isValidValue ? value : undefined,
|
||||||
})
|
})
|
||||||
},
|
},
|
||||||
[andIndex, reducedField, orIndex, updateCondition, value],
|
[andIndex, reducedField, orIndex, updateCondition, value],
|
||||||
|
|||||||
@@ -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',
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -413,7 +413,6 @@ describe('List View', () => {
|
|||||||
await expect(whereBuilder.locator('.condition__value input')).toHaveValue('')
|
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 () => {
|
test('should remove condition from URL when value is cleared', async () => {
|
||||||
await page.goto(postsUrl.list)
|
await page.goto(postsUrl.list)
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user