feat: #1001 - builds a way to allow list view to search multiple fields

* make textfields searchable

* shorten namings in placeholder function

* chore: finishes listSearchableFields

Co-authored-by: Christian Reichart <christian.reichart@camperboys.com>
This commit is contained in:
James Mikrut
2022-09-12 16:38:02 -07:00
committed by GitHub
parent d5ccd45b53
commit a1083727ef
10 changed files with 101 additions and 18 deletions

View File

@@ -1,6 +1,6 @@
import React, { useState } from 'react';
import AnimateHeight from 'react-animate-height';
import { fieldAffectsData } from '../../../../fields/config/types';
import { FieldAffectingData, fieldAffectsData } from '../../../../fields/config/types';
import SearchFilter from '../SearchFilter';
import ColumnSelector from '../ColumnSelector';
import WhereBuilder from '../WhereBuilder';
@@ -29,6 +29,7 @@ const ListControls: React.FC<Props> = (props) => {
fields,
admin: {
useAsTitle,
listSearchableFields,
},
},
} = props;
@@ -37,6 +38,7 @@ const ListControls: React.FC<Props> = (props) => {
const shouldInitializeWhereOpened = validateWhereQuery(params?.where);
const [titleField] = useState(() => fields.find((field) => fieldAffectsData(field) && field.name === useAsTitle));
const [textFieldsToBeSearched] = useState(listSearchableFields ? () => fields.filter((field) => fieldAffectsData(field) && listSearchableFields.includes(field.name)) as FieldAffectingData[] : null);
const [visibleDrawer, setVisibleDrawer] = useState<'where' | 'sort' | 'columns'>(shouldInitializeWhereOpened ? 'where' : undefined);
return (
@@ -47,6 +49,7 @@ const ListControls: React.FC<Props> = (props) => {
handleChange={handleWhereChange}
modifySearchQuery={modifySearchQuery}
fieldLabel={titleField && titleField.label ? titleField.label : undefined}
listSearchableFields={textFieldsToBeSearched}
/>
<div className={`${baseClass}__buttons`}>
<div className={`${baseClass}__buttons-wrap`}>

View File

@@ -1,4 +1,4 @@
import React, { useEffect, useState } from 'react';
import React, { useEffect, useRef, useState } from 'react';
import { useHistory } from 'react-router-dom';
import queryString from 'qs';
import { Props } from './types';
@@ -16,6 +16,7 @@ const SearchFilter: React.FC<Props> = (props) => {
fieldName = 'id',
fieldLabel = 'ID',
modifySearchQuery = true,
listSearchableFields,
handleChange,
} = props;
@@ -24,11 +25,32 @@ const SearchFilter: React.FC<Props> = (props) => {
const [search, setSearch] = useState(() => params?.where?.[fieldName]?.like || '');
const placeholder = useRef(`Search by ${fieldLabel}`);
const debouncedSearch = useDebounce(search, 300);
useEffect(() => {
if (debouncedSearch !== params?.where?.[fieldName]?.like) {
const newWhere = {
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,
@@ -36,12 +58,12 @@ const SearchFilter: React.FC<Props> = (props) => {
};
if (!debouncedSearch) {
delete newWhere[fieldName];
newWhere = undefined;
}
if (handleChange) handleChange(newWhere as Where);
if (modifySearchQuery && params?.where?.[fieldName]?.like !== newWhere?.[fieldName]?.like) {
if (modifySearchQuery && queryString.stringify(params?.where) !== queryString.stringify(newWhere)) {
history.replace({
search: queryString.stringify({
...params,
@@ -51,13 +73,24 @@ const SearchFilter: React.FC<Props> = (props) => {
});
}
}
}, [debouncedSearch, history, fieldName, params, handleChange, modifySearchQuery]);
}, [debouncedSearch, history, fieldName, params, handleChange, modifySearchQuery, listSearchableFields]);
useEffect(() => {
if (listSearchableFields?.length > 0) {
placeholder.current = listSearchableFields.reduce<string>((prev, curr, i) => {
if (i === listSearchableFields.length - 1) {
return `${prev} or ${curr.label || curr.name}`;
}
return `${prev}, ${curr.label || curr.name}`;
}, placeholder.current);
}
}, [listSearchableFields]);
return (
<div className={baseClass}>
<input
className={`${baseClass}__input`}
placeholder={`Search by ${fieldLabel}`}
placeholder={placeholder.current}
type="text"
value={search || ''}
onChange={(e) => setSearch(e.target.value)}

View File

@@ -1,8 +1,10 @@
import { FieldAffectingData } from '../../../../fields/config/types';
import { Where } from '../../../../types';
export type Props = {
fieldName?: string,
fieldLabel?: string,
modifySearchQuery?: boolean
listSearchableFields?: FieldAffectingData[]
handleChange?: (where: Where) => void
}