chore: ensures new listSearchableFields works with complex queries
This commit is contained in:
@@ -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> = (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]: {
|
||||
like: debouncedSearch,
|
||||
},
|
||||
},
|
||||
...listSearchableFields.reduce<Record<string, unknown>[]>((prev, curr) => {
|
||||
return [
|
||||
...prev,
|
||||
{
|
||||
[curr.name]: {
|
||||
like: debouncedSearch,
|
||||
},
|
||||
},
|
||||
];
|
||||
}, []),
|
||||
],
|
||||
} : {
|
||||
...(typeof params?.where === 'object' ? params.where : {}),
|
||||
[fieldName]: {
|
||||
like: debouncedSearch,
|
||||
},
|
||||
};
|
||||
const newWhere: Where = { ...typeof params?.where === 'object' ? params.where as Where : {} };
|
||||
const fieldNamesToSearch = [fieldName, ...(listSearchableFields || []).map(({ name }) => name)];
|
||||
|
||||
if (!debouncedSearch) {
|
||||
newWhere = undefined;
|
||||
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,
|
||||
},
|
||||
});
|
||||
}
|
||||
} 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> = (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) {
|
||||
|
||||
@@ -62,11 +62,25 @@ const WhereBuilder: React.FC<Props> = (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);
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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);
|
||||
});
|
||||
|
||||
Reference in New Issue
Block a user