diff --git a/src/admin/components/elements/SearchFilter/index.tsx b/src/admin/components/elements/SearchFilter/index.tsx index dfb5bb702..b2a2f5ef4 100644 --- a/src/admin/components/elements/SearchFilter/index.tsx +++ b/src/admin/components/elements/SearchFilter/index.tsx @@ -5,7 +5,7 @@ import { Props } from './types'; import Search from '../../icons/Search'; import useDebounce from '../../../hooks/useDebounce'; import { useSearchParams } from '../../utilities/SearchParams'; -import { Where } from '../../../../types'; +import { Where, WhereField } from '../../../../types'; import './index.scss'; @@ -23,47 +23,44 @@ const SearchFilter: React.FC = (props) => { const params = useSearchParams(); const history = useHistory(); - const [search, setSearch] = useState(() => params?.where?.[fieldName]?.like || ''); + const [search, setSearch] = useState(''); + const [previousSearch, setPreviousSearch] = useState(''); const placeholder = useRef(`Search by ${fieldLabel}`); const debouncedSearch = useDebounce(search, 300); useEffect(() => { - if (debouncedSearch || params?.where) { - let newWhere = listSearchableFields?.length > 0 ? { - ...(typeof params?.where === 'object' ? params.where : {}), - or: [ - { - [fieldName]: { + const newWhere: Where = { ...typeof params?.where === 'object' ? params.where as Where : {} }; + const fieldNamesToSearch = [fieldName, ...(listSearchableFields || []).map(({ name }) => name)]; + + fieldNamesToSearch.forEach((fieldNameToSearch) => { + const hasOrQuery = Array.isArray(newWhere.or); + const existingFieldSearchIndex = hasOrQuery ? newWhere.or.findIndex((condition) => { + return (condition?.[fieldNameToSearch] as WhereField)?.like; + }) : -1; + + if (debouncedSearch) { + if (!hasOrQuery) newWhere.or = []; + + if (existingFieldSearchIndex > -1) { + (newWhere.or[existingFieldSearchIndex][fieldNameToSearch] as WhereField).like = debouncedSearch; + } else { + newWhere.or.push({ + [fieldNameToSearch]: { like: debouncedSearch, }, - }, - ...listSearchableFields.reduce[]>((prev, curr) => { - return [ - ...prev, - { - [curr.name]: { - like: debouncedSearch, - }, - }, - ]; - }, []), - ], - } : { - ...(typeof params?.where === 'object' ? params.where : {}), - [fieldName]: { - like: debouncedSearch, - }, - }; - - if (!debouncedSearch) { - newWhere = undefined; + }); + } + } else if (existingFieldSearchIndex > -1) { + newWhere.or.splice(existingFieldSearchIndex, 1); } + }); + if (debouncedSearch !== previousSearch) { if (handleChange) handleChange(newWhere as Where); - if (modifySearchQuery && queryString.stringify(params?.where) !== queryString.stringify(newWhere)) { + if (modifySearchQuery) { history.replace({ search: queryString.stringify({ ...params, @@ -71,9 +68,10 @@ const SearchFilter: React.FC = (props) => { where: newWhere, }), }); + setPreviousSearch(debouncedSearch); } } - }, [debouncedSearch, history, fieldName, params, handleChange, modifySearchQuery, listSearchableFields]); + }, [debouncedSearch, previousSearch, history, fieldName, params, handleChange, modifySearchQuery, listSearchableFields]); useEffect(() => { if (listSearchableFields?.length > 0) { diff --git a/src/admin/components/elements/WhereBuilder/index.tsx b/src/admin/components/elements/WhereBuilder/index.tsx index 0fd47cef8..63052f448 100644 --- a/src/admin/components/elements/WhereBuilder/index.tsx +++ b/src/admin/components/elements/WhereBuilder/index.tsx @@ -62,11 +62,25 @@ const WhereBuilder: React.FC = (props) => { const [reducedFields] = useState(() => reduceFields(collection.fields)); useThrottledEffect(() => { - const currentParams = queryString.parse(history.location.search, { ignoreQueryPrefix: true, depth: 10 }); + const currentParams = queryString.parse(history.location.search, { ignoreQueryPrefix: true, depth: 10 }) as { where: Where }; + + const paramsToKeep = typeof currentParams?.where === 'object' && 'or' in currentParams.where ? currentParams.where.or.reduce((keptParams, param) => { + const newParam = { ...param }; + if (param.and) { + delete newParam.and; + } + return [ + ...keptParams, + newParam, + ]; + }, []) : []; const newWhereQuery = { ...typeof currentParams?.where === 'object' ? currentParams.where : {}, - or: conditions, + or: [ + ...conditions, + ...paramsToKeep, + ], }; if (handleChange) handleChange(newWhereQuery as Where); diff --git a/src/types/index.ts b/src/types/index.ts index 7bfd57a1b..405bf595e 100644 --- a/src/types/index.ts +++ b/src/types/index.ts @@ -23,9 +23,9 @@ export type WhereField = { } export type Where = { + [key: string]: WhereField | Where[] or?: Where[] and?: Where[] - [key: string]: Where[] | WhereField } // eslint-disable-next-line @typescript-eslint/no-explicit-any diff --git a/test/fields/e2e.spec.ts b/test/fields/e2e.spec.ts index f311012a9..e05a1efa1 100644 --- a/test/fields/e2e.spec.ts +++ b/test/fields/e2e.spec.ts @@ -107,6 +107,8 @@ describe('fields', () => { await page.locator('.tabs-field__tab-button:has-text("Tab with Array")').click(); await page.locator('.tabs-field__tab-button:has-text("Tab with Row")').click(); + await wait(100); + await expect(page.locator('#field-textInRow')).toHaveValue(textInRowValue); await expect(page.locator('#field-numberInRow')).toHaveValue(numberInRowValue); });