chore: ensures new listSearchableFields works with complex queries

This commit is contained in:
James
2022-09-12 19:40:01 -07:00
parent a1083727ef
commit 4e165cf52e
4 changed files with 48 additions and 34 deletions

View File

@@ -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) {

View File

@@ -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);

View File

@@ -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

View File

@@ -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);
});