diff --git a/packages/payload/src/admin/components/elements/WhereBuilder/Condition/Date/index.tsx b/packages/payload/src/admin/components/elements/WhereBuilder/Condition/Date/index.tsx index 4c3a18eb6c..898bf266c6 100644 --- a/packages/payload/src/admin/components/elements/WhereBuilder/Condition/Date/index.tsx +++ b/packages/payload/src/admin/components/elements/WhereBuilder/Condition/Date/index.tsx @@ -6,9 +6,9 @@ import DatePicker from '../../../DatePicker' const baseClass = 'condition-value-date' -const DateField: React.FC = ({ onChange, value }) => ( +const DateField: React.FC = ({ disabled, onChange, value }) => (
- +
) diff --git a/packages/payload/src/admin/components/elements/WhereBuilder/Condition/Date/types.ts b/packages/payload/src/admin/components/elements/WhereBuilder/Condition/Date/types.ts index 1de7736260..ffd31f406f 100644 --- a/packages/payload/src/admin/components/elements/WhereBuilder/Condition/Date/types.ts +++ b/packages/payload/src/admin/components/elements/WhereBuilder/Condition/Date/types.ts @@ -1,4 +1,5 @@ export type Props = { + disabled?: boolean onChange: () => void value: Date } diff --git a/packages/payload/src/admin/components/elements/WhereBuilder/Condition/Number/index.tsx b/packages/payload/src/admin/components/elements/WhereBuilder/Condition/Number/index.tsx index c81baf6354..c2c37020e6 100644 --- a/packages/payload/src/admin/components/elements/WhereBuilder/Condition/Number/index.tsx +++ b/packages/payload/src/admin/components/elements/WhereBuilder/Condition/Number/index.tsx @@ -7,11 +7,12 @@ import './index.scss' const baseClass = 'condition-value-number' -const NumberField: React.FC = ({ onChange, value }) => { +const NumberField: React.FC = ({ disabled, onChange, value }) => { const { t } = useTranslation('general') return ( onChange(e.target.value)} placeholder={t('enterAValue')} type="number" diff --git a/packages/payload/src/admin/components/elements/WhereBuilder/Condition/Number/types.ts b/packages/payload/src/admin/components/elements/WhereBuilder/Condition/Number/types.ts index ff6e5e78f9..c7571ee2e8 100644 --- a/packages/payload/src/admin/components/elements/WhereBuilder/Condition/Number/types.ts +++ b/packages/payload/src/admin/components/elements/WhereBuilder/Condition/Number/types.ts @@ -1,4 +1,5 @@ export type Props = { + disabled?: boolean onChange: (e: string) => void value: string } diff --git a/packages/payload/src/admin/components/elements/WhereBuilder/Condition/Relationship/index.tsx b/packages/payload/src/admin/components/elements/WhereBuilder/Condition/Relationship/index.tsx index 77b14f5fd5..5113a0a28d 100644 --- a/packages/payload/src/admin/components/elements/WhereBuilder/Condition/Relationship/index.tsx +++ b/packages/payload/src/admin/components/elements/WhereBuilder/Condition/Relationship/index.tsx @@ -16,7 +16,7 @@ const baseClass = 'condition-value-relationship' const maxResultsPerRequest = 10 const RelationshipField: React.FC = (props) => { - const { admin: { isSortable } = {}, hasMany, onChange, relationTo, value } = props + const { admin: { isSortable } = {}, disabled, hasMany, onChange, relationTo, value } = props const { collections, @@ -261,6 +261,7 @@ const RelationshipField: React.FC = (props) => {
{!errorLoading && ( { diff --git a/packages/payload/src/admin/components/elements/WhereBuilder/Condition/Relationship/types.ts b/packages/payload/src/admin/components/elements/WhereBuilder/Condition/Relationship/types.ts index eabbbdef2d..9a9c47aff9 100644 --- a/packages/payload/src/admin/components/elements/WhereBuilder/Condition/Relationship/types.ts +++ b/packages/payload/src/admin/components/elements/WhereBuilder/Condition/Relationship/types.ts @@ -5,6 +5,7 @@ import type { PaginatedDocs } from '../../../../../../database/types' import type { RelationshipField } from '../../../../../../fields/config/types' export type Props = { + disabled?: boolean onChange: (val: unknown) => void value: unknown } & RelationshipField diff --git a/packages/payload/src/admin/components/elements/WhereBuilder/Condition/Select/index.tsx b/packages/payload/src/admin/components/elements/WhereBuilder/Condition/Select/index.tsx index e83afa38f7..89069c26df 100644 --- a/packages/payload/src/admin/components/elements/WhereBuilder/Condition/Select/index.tsx +++ b/packages/payload/src/admin/components/elements/WhereBuilder/Condition/Select/index.tsx @@ -20,6 +20,7 @@ const formatOptions = (options: Option[]): OptionObject[] => }) export const Select: React.FC = ({ + disabled, onChange, operator, options: optionsFromProps, @@ -79,6 +80,7 @@ export const Select: React.FC = ({ return ( ({ ...option, label: getTranslation(option.label, i18n) }))} diff --git a/packages/payload/src/admin/components/elements/WhereBuilder/Condition/Select/types.ts b/packages/payload/src/admin/components/elements/WhereBuilder/Condition/Select/types.ts index 9f10c4a554..6a93d3274b 100644 --- a/packages/payload/src/admin/components/elements/WhereBuilder/Condition/Select/types.ts +++ b/packages/payload/src/admin/components/elements/WhereBuilder/Condition/Select/types.ts @@ -2,6 +2,7 @@ import type { Option } from '../../../../../../fields/config/types' import type { Operator } from '../../../../../../types' export type Props = { + disabled?: boolean onChange: (val: string) => void operator: Operator options: Option[] diff --git a/packages/payload/src/admin/components/elements/WhereBuilder/Condition/Text/index.tsx b/packages/payload/src/admin/components/elements/WhereBuilder/Condition/Text/index.tsx index 0fd3195f77..acf5352ec8 100644 --- a/packages/payload/src/admin/components/elements/WhereBuilder/Condition/Text/index.tsx +++ b/packages/payload/src/admin/components/elements/WhereBuilder/Condition/Text/index.tsx @@ -7,11 +7,12 @@ import './index.scss' const baseClass = 'condition-value-text' -const Text: React.FC = ({ onChange, value }) => { +const Text: React.FC = ({ disabled, onChange, value }) => { const { t } = useTranslation('general') return ( onChange(e.target.value)} placeholder={t('enterAValue')} type="text" diff --git a/packages/payload/src/admin/components/elements/WhereBuilder/Condition/Text/types.ts b/packages/payload/src/admin/components/elements/WhereBuilder/Condition/Text/types.ts index ba61c3750c..03cdc06870 100644 --- a/packages/payload/src/admin/components/elements/WhereBuilder/Condition/Text/types.ts +++ b/packages/payload/src/admin/components/elements/WhereBuilder/Condition/Text/types.ts @@ -1,4 +1,5 @@ export type Props = { + disabled?: boolean onChange: (val: string) => void value: string } diff --git a/packages/payload/src/admin/components/elements/WhereBuilder/Condition/index.tsx b/packages/payload/src/admin/components/elements/WhereBuilder/Condition/index.tsx index 8ec270cb9e..6e088646bb 100644 --- a/packages/payload/src/admin/components/elements/WhereBuilder/Condition/index.tsx +++ b/packages/payload/src/admin/components/elements/WhereBuilder/Condition/index.tsx @@ -26,25 +26,29 @@ const baseClass = 'condition' const Condition: React.FC = (props) => { const { andIndex, dispatch, fields, orIndex, value } = props - const fieldValue = Object.keys(value)[0] - const operatorAndValue = value?.[fieldValue] ? Object.entries(value[fieldValue])[0] : undefined - - const operatorValue = operatorAndValue?.[0] - const queryValue = operatorAndValue?.[1] - + const fieldName = Object.keys(value)[0] const [activeField, setActiveField] = useState(() => - fields.find((field) => fieldValue === field.value), + fields.find((field) => fieldName === field.value), ) + + const operatorAndValue = value?.[fieldName] ? Object.entries(value[fieldName])[0] : undefined + const queryValue = operatorAndValue?.[1] + const operatorValue = operatorAndValue?.[0] + const [internalValue, setInternalValue] = useState(queryValue) + const [internalOperatorField, setInternalOperatorField] = useState(operatorValue) + const debouncedValue = useDebounce(internalValue, 300) useEffect(() => { - const newActiveField = fields.find((field) => fieldValue === field.value) + const newActiveField = fields.find(({ value: name }) => name === fieldName) - if (newActiveField) { + if (newActiveField && newActiveField !== activeField) { setActiveField(newActiveField) + setInternalOperatorField(null) + setInternalValue('') } - }, [fieldValue, fields]) + }, [fieldName, fields, activeField]) useEffect(() => { dispatch({ @@ -73,21 +77,23 @@ const Condition: React.FC = (props) => {
+ isClearable={false} + onChange={(field) => { dispatch({ - andIndex, - field: field?.value || undefined, - orIndex, + andIndex: andIndex, + field: field?.value, + orIndex: orIndex, type: 'update', }) - } + }} options={fields} - value={fields.find((field) => fieldValue === field.value)} + value={fields.find((field) => fieldName === field.value)} />
{ dispatch({ andIndex, @@ -95,9 +101,14 @@ const Condition: React.FC = (props) => { orIndex, type: 'update', }) + setInternalOperatorField(operator.value) }} options={activeField.operators} - value={activeField.operators.find((operator) => operatorValue === operator.value)} + value={ + activeField.operators.find( + (operator) => internalOperatorField === operator.value, + ) || null + } />
@@ -106,6 +117,7 @@ const Condition: React.FC = (props) => { DefaultComponent={ValueComponent} componentProps={{ ...activeField?.props, + disabled: !operatorValue, onChange: setInternalValue, operator: operatorValue, options: valueOptions, diff --git a/packages/payload/src/admin/components/elements/WhereBuilder/reducer.ts b/packages/payload/src/admin/components/elements/WhereBuilder/reducer.ts index 1c41a34148..1e525dcf49 100644 --- a/packages/payload/src/admin/components/elements/WhereBuilder/reducer.ts +++ b/packages/payload/src/admin/components/elements/WhereBuilder/reducer.ts @@ -59,17 +59,17 @@ const reducer = (state: Where[], action: Action): Where[] => { if (field) { newState[orIndex].and[andIndex] = { - [field]: { - [Object.keys(existingCondition)[0]]: Object.values(existingCondition)[0], - }, + [field]: operator ? { [operator]: value } : {}, } } if (value !== undefined) { newState[orIndex].and[andIndex] = { - [existingFieldName]: { - [Object.keys(existingCondition)[0]]: value, - }, + [existingFieldName]: Object.keys(existingCondition)[0] + ? { + [Object.keys(existingCondition)[0]]: value, + } + : {}, } } } diff --git a/test/admin/e2e.spec.ts b/test/admin/e2e.spec.ts index d5d352aa1c..e6fa8e2e65 100644 --- a/test/admin/e2e.spec.ts +++ b/test/admin/e2e.spec.ts @@ -647,6 +647,38 @@ describe('admin', () => { await expect(page.locator(tableRowLocator)).toHaveCount(2) }) + test('resets filter value and operator on field update', async () => { + const { id } = await createPost({ title: 'post1' }) + await createPost({ title: 'post2' }) + + // open the column controls + await page.locator('.list-controls__toggle-columns').click() + await page.locator('.list-controls__toggle-where').click() + await page.waitForSelector('.list-controls__where.rah-static--height-auto') + await page.locator('.where-builder__add-first-filter').click() + + const operatorField = page.locator('.condition__operator') + await operatorField.click() + + const dropdownOperatorOptions = operatorField.locator('.rs__option') + await dropdownOperatorOptions.locator('text=equals').click() + + // execute filter (where ID equals id value) + const valueField = page.locator('.condition__value > input') + await valueField.fill(id) + + const filterField = page.locator('.condition__field') + await filterField.click() + + // select new filter field of Number + const dropdownFieldOptions = filterField.locator('.rs__option') + await dropdownFieldOptions.locator('text=Number').click() + + // expect operator & value field to reset (be empty) + await expect(operatorField.locator('.rs__placeholder')).toContainText('Select a value') + await expect(valueField).toHaveValue('') + }) + test('should accept where query from valid URL where parameter', async () => { await createPost({ title: 'post1' }) await createPost({ title: 'post2' })