Skip to content

Commit

Permalink
[Enhancement #552] Implement text input debounce in faceted search.
Browse files Browse the repository at this point in the history
  • Loading branch information
ledsoft committed Oct 21, 2024
1 parent 434f5da commit bd1b22c
Show file tree
Hide file tree
Showing 6 changed files with 52 additions and 17 deletions.
18 changes: 18 additions & 0 deletions package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

1 change: 1 addition & 0 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -59,6 +59,7 @@
"redux-thunk": "^2.4.2",
"resolve": "1.22.2",
"simple-xpath-position": "^2.0.2",
"use-debounce": "^10.0.4",
"uuid": "^10.0.0",
"whatwg-fetch": "3.6.2",
"whatwg-mimetype": "3.0.0"
Expand Down
3 changes: 1 addition & 2 deletions src/action/SearchActions.ts
Original file line number Diff line number Diff line change
Expand Up @@ -56,7 +56,6 @@ export function removeSearchListener() {
* Timer to delay search requests as user is still typing.
*/
let updateSearchTimer: ReturnType<typeof setTimeout> | null = null;
const updateSearchDelay = 400; // ms

/**
* Change the search criteria and trigger a new search.
Expand Down Expand Up @@ -85,7 +84,7 @@ export function updateSearchFilter(searchString: string) {
updateSearchTimer = setTimeout(() => {
updateSearchTimer = null;
dispatch(searchEverything());
}, updateSearchDelay);
}, Constants.SEARCH_DEBOUNCE_DELAY);
return Promise.resolve();
}
};
Expand Down
41 changes: 26 additions & 15 deletions src/component/search/facet/FacetedSearch.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@ import VocabularyFacet from "./VocabularyFacet";
import SimplePagination from "../../dashboard/widget/lastcommented/SimplePagination";
import Constants from "../../../util/Constants";
import TermStateFacet from "./TermStateFacet";
import { useDebouncedCallback } from "use-debounce";

function aggregateSearchParams(params: { [key: string]: SearchParam }) {
return Object.entries(params)
Expand Down Expand Up @@ -62,37 +63,47 @@ const FacetedSearch: React.FC = () => {
const dispatch: ThunkDispatch = useDispatch();
const [page, setPage] = useState(0);
const [params, setParams] = useState(INITIAL_STATE);
const [results, setResults] =
React.useState<FacetedSearchResult[] | null>(null);

const onChange = (value: SearchParam) => {
const change = {};
change[value.property] = value;
setParams({ ...params, ...change });
setPage(0);
if (value.matchType === MatchType.IRI || value.value[0].length === 0) {
runSearch({ ...params, ...change }, page);
} else {
debouncedSearch({ ...params, ...change }, page);
}
};
const onPageChange = (page: number) => {
setPage(page);
runSearch(params, page);
};
const [results, setResults] =
React.useState<FacetedSearchResult[] | null>(null);
const runSearch = React.useCallback(
(params: SearchParam[]) => {
(params: {}, page: number) => {
const sp = aggregateSearchParams(params);
if (sp.length === 0) {
setPage(0);
setResults(null);
return;
}
trackPromise(
dispatch(
executeFacetedTermSearch(params, {
executeFacetedTermSearch(sp, {
page,
size: Constants.DEFAULT_PAGE_SIZE,
})
),
"faceted-search"
).then((res) => setResults(res));
},
[page, dispatch, setResults]
[dispatch, setPage, setResults]
);
React.useEffect(() => {
const sp = aggregateSearchParams(params);
if (sp.length === 0) {
setPage(0);
setResults(null);
return;
}
runSearch(sp);
}, [params, runSearch]);
const debouncedSearch = useDebouncedCallback((params: {}, page: number) => {
runSearch(params, page);
}, Constants.SEARCH_DEBOUNCE_DELAY);

return (
<div id="faceted-search" className="relative">
Expand Down Expand Up @@ -146,7 +157,7 @@ const FacetedSearch: React.FC = () => {
{results && (
<SimplePagination
page={page}
setPage={setPage}
setPage={onPageChange}
pageSize={Constants.LAST_COMMENTED_ASSET_LIMIT}
itemCount={
results.length === 0 ? 0 : Constants.LAST_COMMENTED_ASSET_LIMIT
Expand Down
4 changes: 4 additions & 0 deletions src/component/search/facet/__tests__/FacetedSearch.test.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,10 @@ jest.mock("../FacetedSearchResultItem", () => () => (
jest.mock("../TermTypeFacet", () => () => <div>Term type selector</div>);
jest.mock("../VocabularyFacet", () => () => <div>Vocabulary selector</div>);
jest.mock("../TextFacet", () => () => <div>Text facet</div>);
jest.mock("use-debounce", () => ({
...jest.requireActual("use-debounce"),
useDebouncedCallback: jest.fn().mockImplementation((arg) => arg),
}));

describe("FacetedSearch", () => {
let fakeDispatch: ThunkDispatch;
Expand Down
2 changes: 2 additions & 0 deletions src/util/Constants.ts
Original file line number Diff line number Diff line change
Expand Up @@ -119,6 +119,8 @@ const constants = {
WORKSPACE_EDITABLE_CONTEXT_PARAM: "edit-context",
TIMESTAMP_PARAM_FORMAT: "yyyyMMdd'T'HHmmss'Z'",
FTS_SNIPPET_TEXT_SIZE: 250,
// Search debounce delay in milliseconds
SEARCH_DEBOUNCE_DELAY: 400,

// Size of page fetched from server
DEFAULT_PAGE_SIZE: 100,
Expand Down

0 comments on commit bd1b22c

Please sign in to comment.