From 96426cca5407960f9d80cb8909be6f0567f4cf1e Mon Sep 17 00:00:00 2001 From: Jarvis Raymond Date: Wed, 8 Feb 2023 14:35:03 -0600 Subject: [PATCH 01/17] feat(healSearchDebounce): Initial commit --- src/Discovery/Discovery.tsx | 19 +++++++++++++++++-- 1 file changed, 17 insertions(+), 2 deletions(-) diff --git a/src/Discovery/Discovery.tsx b/src/Discovery/Discovery.tsx index 6e8a8b6304..d6b81e37cf 100644 --- a/src/Discovery/Discovery.tsx +++ b/src/Discovery/Discovery.tsx @@ -1,4 +1,5 @@ import React, { useState, useEffect, ReactNode } from 'react'; +import { debounce } from 'lodash'; import * as JsSearch from 'js-search'; import { Tag, Popover, Space, Collapse, Button, Dropdown, Menu, Pagination, Tooltip, @@ -337,8 +338,22 @@ const Discovery: React.FunctionComponent = (props: Props) => { setVisibleResources(filteredResources); }; - useEffect(doSearchFilterSort, - [props.searchTerm, + const debounceDelayInMilliseconds = 500; + const [executedSearches, setExecutedSearches] = useState(0); + const initialSearchesWithoutDebounce = 2; + useEffect( + () => { + // Execute searches initially without debounce on page load + if (executedSearches < initialSearchesWithoutDebounce) { + console.log('no debounce'); + setExecutedSearches(executedSearches + 1); + return doSearchFilterSort(); + } + console.log('with debounce'); + // Otherwise debounce the calls + return debounce(doSearchFilterSort, debounceDelayInMilliseconds); + }, [ + props.searchTerm, props.accessSortDirection, props.studies, props.pagination, From 43f0aedf9c26a95887c971ea5e6aad78d59f943d Mon Sep 17 00:00:00 2001 From: Jarvis Raymond Date: Thu, 9 Feb 2023 10:15:55 -0600 Subject: [PATCH 02/17] feat(healSearchDebounce): Wrote unit test and organized code --- src/Discovery/Discovery.tsx | 18 ++-------- .../DebounceSearch/DebounceSearch.test.jsx | 33 +++++++++++++++++++ .../Utils/DebounceSearch/DebounceSearch.tsx | 14 ++++++++ 3 files changed, 50 insertions(+), 15 deletions(-) create mode 100644 src/Discovery/Utils/DebounceSearch/DebounceSearch.test.jsx create mode 100644 src/Discovery/Utils/DebounceSearch/DebounceSearch.tsx diff --git a/src/Discovery/Discovery.tsx b/src/Discovery/Discovery.tsx index d6b81e37cf..1678d591c5 100644 --- a/src/Discovery/Discovery.tsx +++ b/src/Discovery/Discovery.tsx @@ -1,5 +1,5 @@ import React, { useState, useEffect, ReactNode } from 'react'; -import { debounce } from 'lodash'; +import { DebounceSearch } from './Utils/DebounceSearch/DebounceSearch'; import * as JsSearch from 'js-search'; import { Tag, Popover, Space, Collapse, Button, Dropdown, Menu, Pagination, Tooltip, @@ -278,6 +278,7 @@ const Discovery: React.FunctionComponent = (props: Props) => { const { config } = props; const [jsSearch, setJsSearch] = useState(null); + const [executedSearches, setExecutedSearches] = useState(0); const [accessibilityFilterVisible, setAccessibilityFilterVisible] = useState(false); const [modalVisible, setModalVisible] = useState(false); const [filtersVisible, setFiltersVisible] = useState(false); @@ -338,21 +339,8 @@ const Discovery: React.FunctionComponent = (props: Props) => { setVisibleResources(filteredResources); }; - const debounceDelayInMilliseconds = 500; - const [executedSearches, setExecutedSearches] = useState(0); - const initialSearchesWithoutDebounce = 2; useEffect( - () => { - // Execute searches initially without debounce on page load - if (executedSearches < initialSearchesWithoutDebounce) { - console.log('no debounce'); - setExecutedSearches(executedSearches + 1); - return doSearchFilterSort(); - } - console.log('with debounce'); - // Otherwise debounce the calls - return debounce(doSearchFilterSort, debounceDelayInMilliseconds); - }, [ + DebounceSearch(doSearchFilterSort, executedSearches, setExecutedSearches), [ props.searchTerm, props.accessSortDirection, props.studies, diff --git a/src/Discovery/Utils/DebounceSearch/DebounceSearch.test.jsx b/src/Discovery/Utils/DebounceSearch/DebounceSearch.test.jsx new file mode 100644 index 0000000000..a9a9837b25 --- /dev/null +++ b/src/Discovery/Utils/DebounceSearch/DebounceSearch.test.jsx @@ -0,0 +1,33 @@ +import { DebounceSearch } from './DebounceSearch'; +import { debounce } from 'lodash'; + +jest.mock('lodash', () => { + return { + debounce: jest.fn(func => func), + }; +}); + +describe('DebounceSearch', () => { + let doSearchFilterSort, setExecutedSearches; + beforeEach(() => { + doSearchFilterSort = jest.fn(); + setExecutedSearches = jest.fn(); + }); + + it('executes the doSearchFilterSort function immediately the first two times it is called', () => { + let executedSearches = 0; + DebounceSearch(doSearchFilterSort, executedSearches, setExecutedSearches); + expect(doSearchFilterSort).toHaveBeenCalledTimes(1); + expect(setExecutedSearches).toHaveBeenCalledTimes(1); + executedSearches = 1; + DebounceSearch(doSearchFilterSort, executedSearches, setExecutedSearches); + expect(doSearchFilterSort).toHaveBeenCalledTimes(2); + expect(setExecutedSearches).toHaveBeenCalledWith(2); + }); + + it('debounces the doSearchFilterSort function after the first two calls', () => { + let executedSearches = 2; + DebounceSearch(doSearchFilterSort, executedSearches, setExecutedSearches); + expect(debounce).toHaveBeenCalledWith(doSearchFilterSort, 500); + }); +}); diff --git a/src/Discovery/Utils/DebounceSearch/DebounceSearch.tsx b/src/Discovery/Utils/DebounceSearch/DebounceSearch.tsx new file mode 100644 index 0000000000..829c511651 --- /dev/null +++ b/src/Discovery/Utils/DebounceSearch/DebounceSearch.tsx @@ -0,0 +1,14 @@ +import { debounce } from 'lodash'; + +export const DebounceSearch = (doSearchFilterSort, executedSearches, setExecutedSearches) => { + const debounceDelayInMilliseconds = 500; + const initialSearchesWithoutDebounce = 2; + + // Execute searches initially without debounce to decrease page load time + if (executedSearches < initialSearchesWithoutDebounce) { + setExecutedSearches(executedSearches + 1); + return doSearchFilterSort(); + } + // Otherwise debounce the calls + return debounce(doSearchFilterSort, debounceDelayInMilliseconds); + } From c75f83a40c62c4959f51c40593db54fbf3827ee4 Mon Sep 17 00:00:00 2001 From: Jarvis Raymond Date: Thu, 9 Feb 2023 10:28:17 -0600 Subject: [PATCH 03/17] feat(healSearchDebounce): Ran eslint on changed files --- src/Discovery/Discovery.tsx | 2 +- .../DebounceSearch/DebounceSearch.test.jsx | 15 ++++++------- .../Utils/DebounceSearch/DebounceSearch.tsx | 22 ++++++++++--------- 3 files changed, 20 insertions(+), 19 deletions(-) diff --git a/src/Discovery/Discovery.tsx b/src/Discovery/Discovery.tsx index 1678d591c5..aaf0953e0f 100644 --- a/src/Discovery/Discovery.tsx +++ b/src/Discovery/Discovery.tsx @@ -1,5 +1,4 @@ import React, { useState, useEffect, ReactNode } from 'react'; -import { DebounceSearch } from './Utils/DebounceSearch/DebounceSearch'; import * as JsSearch from 'js-search'; import { Tag, Popover, Space, Collapse, Button, Dropdown, Menu, Pagination, Tooltip, @@ -20,6 +19,7 @@ import { } from '@ant-design/icons'; import Checkbox from 'antd/lib/checkbox/Checkbox'; import MenuItem from 'antd/lib/menu/MenuItem'; +import DebounceSearch from './Utils/DebounceSearch/DebounceSearch'; import { DiscoveryConfig } from './DiscoveryConfig'; import './Discovery.css'; import DiscoverySummary from './DiscoverySummary'; diff --git a/src/Discovery/Utils/DebounceSearch/DebounceSearch.test.jsx b/src/Discovery/Utils/DebounceSearch/DebounceSearch.test.jsx index a9a9837b25..8b480a76d5 100644 --- a/src/Discovery/Utils/DebounceSearch/DebounceSearch.test.jsx +++ b/src/Discovery/Utils/DebounceSearch/DebounceSearch.test.jsx @@ -1,14 +1,13 @@ -import { DebounceSearch } from './DebounceSearch'; import { debounce } from 'lodash'; +import { DebounceSearch } from './DebounceSearch'; -jest.mock('lodash', () => { - return { - debounce: jest.fn(func => func), - }; -}); +jest.mock('lodash', () => ({ + debounce: jest.fn((func) => func), +})); describe('DebounceSearch', () => { - let doSearchFilterSort, setExecutedSearches; + let doSearchFilterSort; let + setExecutedSearches; beforeEach(() => { doSearchFilterSort = jest.fn(); setExecutedSearches = jest.fn(); @@ -26,7 +25,7 @@ describe('DebounceSearch', () => { }); it('debounces the doSearchFilterSort function after the first two calls', () => { - let executedSearches = 2; + const executedSearches = 2; DebounceSearch(doSearchFilterSort, executedSearches, setExecutedSearches); expect(debounce).toHaveBeenCalledWith(doSearchFilterSort, 500); }); diff --git a/src/Discovery/Utils/DebounceSearch/DebounceSearch.tsx b/src/Discovery/Utils/DebounceSearch/DebounceSearch.tsx index 829c511651..bae3434069 100644 --- a/src/Discovery/Utils/DebounceSearch/DebounceSearch.tsx +++ b/src/Discovery/Utils/DebounceSearch/DebounceSearch.tsx @@ -1,14 +1,16 @@ import { debounce } from 'lodash'; -export const DebounceSearch = (doSearchFilterSort, executedSearches, setExecutedSearches) => { - const debounceDelayInMilliseconds = 500; - const initialSearchesWithoutDebounce = 2; +const DebounceSearch = (doSearchFilterSort, executedSearches, setExecutedSearches) => { + const debounceDelayInMilliseconds = 500; + const initialSearchesWithoutDebounce = 2; - // Execute searches initially without debounce to decrease page load time - if (executedSearches < initialSearchesWithoutDebounce) { - setExecutedSearches(executedSearches + 1); - return doSearchFilterSort(); - } - // Otherwise debounce the calls - return debounce(doSearchFilterSort, debounceDelayInMilliseconds); + // Execute searches initially without debounce to decrease page load time + if (executedSearches < initialSearchesWithoutDebounce) { + setExecutedSearches(executedSearches + 1); + return doSearchFilterSort(); } + // Otherwise debounce the calls + return debounce(doSearchFilterSort, debounceDelayInMilliseconds); +}; + +export default DebounceSearch; From 8ebc9354d3b2625e27c4cf3e679e5832b87fdd24 Mon Sep 17 00:00:00 2001 From: Jarvis Raymond Date: Thu, 9 Feb 2023 10:42:24 -0600 Subject: [PATCH 04/17] feat(healSearchDebounce): Changed import of DebounceSearch for Jest test --- src/Discovery/Utils/DebounceSearch/DebounceSearch.test.jsx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Discovery/Utils/DebounceSearch/DebounceSearch.test.jsx b/src/Discovery/Utils/DebounceSearch/DebounceSearch.test.jsx index 8b480a76d5..c59b8104a6 100644 --- a/src/Discovery/Utils/DebounceSearch/DebounceSearch.test.jsx +++ b/src/Discovery/Utils/DebounceSearch/DebounceSearch.test.jsx @@ -1,5 +1,5 @@ import { debounce } from 'lodash'; -import { DebounceSearch } from './DebounceSearch'; +import DebounceSearch from './DebounceSearch'; jest.mock('lodash', () => ({ debounce: jest.fn((func) => func), From ac65aed82947c370cb85d3e0c6046ec731de6f2a Mon Sep 17 00:00:00 2001 From: Jarvis Raymond Date: Thu, 9 Feb 2023 16:20:27 -0600 Subject: [PATCH 05/17] test(addReactTestingLibrary): Refactored and separated out code so tests can be written and so debouncing works --- src/Discovery/Discovery.tsx | 59 +++++++------------ .../Utils/DebounceSearch/DebounceSearch.tsx | 5 ++ .../DebounceSearch/doSearchFilterSort.js | 40 +++++++++++++ 3 files changed, 67 insertions(+), 37 deletions(-) create mode 100644 src/Discovery/Utils/DebounceSearch/doSearchFilterSort.js diff --git a/src/Discovery/Discovery.tsx b/src/Discovery/Discovery.tsx index aaf0953e0f..0700dd1241 100644 --- a/src/Discovery/Discovery.tsx +++ b/src/Discovery/Discovery.tsx @@ -1,4 +1,4 @@ -import React, { useState, useEffect, ReactNode } from 'react'; +import React, { useState, useEffect, ReactNode, useCallback, useMemo } from 'react'; import * as JsSearch from 'js-search'; import { Tag, Popover, Space, Collapse, Button, Dropdown, Menu, Pagination, Tooltip, @@ -29,7 +29,9 @@ import DiscoveryListView from './DiscoveryListView'; import DiscoveryAdvancedSearchPanel from './DiscoveryAdvancedSearchPanel'; import { ReduxDiscoveryActionBar, ReduxDiscoveryDetails } from './reduxer'; import DiscoveryMDSSearch from './DiscoveryMDSSearch'; +import { debounce, throttle } from 'lodash'; import DiscoveryAccessibilityLinks from './DiscoveryAccessibilityLinks'; +import doSearchFilterSort from './Utils/DebounceSearch/doSearchFilterSort'; export const accessibleFieldName = '__accessible'; @@ -300,47 +302,30 @@ const Discovery: React.FunctionComponent = (props: Props) => { props.onSearchChange(value); }; - const doSearchFilterSort = () => { - let filteredResources = props.studies; - if (jsSearch && props.searchTerm) { - filteredResources = jsSearch.search(props.searchTerm); - } - filteredResources = filterByTags( - filteredResources, - props.selectedTags, - config, - ); - if (config.features.advSearchFilters && config.features.advSearchFilters.enabled) { - filteredResources = filterByAdvSearch( - filteredResources, - filterState, - config, - filterMultiSelectionLogic, - ); - } - if (props.config.features.authorization.enabled) { - filteredResources = filteredResources.filter( - (resource) => props.accessFilters[resource[accessibleFieldName]], - ); - } + const debounceDelayInMilliseconds = 500; + const initialSearchesWithoutDebounce = 2; + //const dbs = useCallback(debounce(doSearchFilterSort, 500),[]); + + // THIS WORKS BUT ONLY ON PREVIOUS VERSION OF SEARCH TERM + // const dbs = useMemo(() => (debounce(doSearchFilterSort, 250)),[visibleResources]); + const dbs = useMemo(() => (debounce(doSearchFilterSort, 500)),[]); - filteredResources = filteredResources.sort( - (a, b) => { - if (props.accessSortDirection === AccessSortDirection.DESCENDING) { - return a[accessibleFieldName] - b[accessibleFieldName]; - } if (props.accessSortDirection === AccessSortDirection.ASCENDING) { - return b[accessibleFieldName] - a[accessibleFieldName]; - } - return 0; - }, - ); - setVisibleResources(filteredResources); - }; useEffect( - DebounceSearch(doSearchFilterSort, executedSearches, setExecutedSearches), [ + ()=>{ + const parametersForDoSearchFilterSort = [props, jsSearch, config, setVisibleResources, filterByTags, filterByAdvSearch, filterState, filterMultiSelectionLogic, accessibleFieldName, AccessSortDirection]; + // Execute searches initially without debounce to decrease page load time + if (executedSearches < initialSearchesWithoutDebounce) { + setExecutedSearches(executedSearches + 1); + return doSearchFilterSort(...parametersForDoSearchFilterSort ) ; + } + // Otherwise debounce the calls + // return debounce(doSearchFilterSort, debounceDelayInMilliseconds); + dbs(...parametersForDoSearchFilterSort); + return; + }, [ props.searchTerm, props.accessSortDirection, props.studies, diff --git a/src/Discovery/Utils/DebounceSearch/DebounceSearch.tsx b/src/Discovery/Utils/DebounceSearch/DebounceSearch.tsx index bae3434069..a08127356f 100644 --- a/src/Discovery/Utils/DebounceSearch/DebounceSearch.tsx +++ b/src/Discovery/Utils/DebounceSearch/DebounceSearch.tsx @@ -1,4 +1,9 @@ import { debounce } from 'lodash'; +import { useCallback } from 'react'; + + +const dbs = useCallback(debounce(doSearchFilterSort, debounceDelayInMilliseconds),[]); + const DebounceSearch = (doSearchFilterSort, executedSearches, setExecutedSearches) => { const debounceDelayInMilliseconds = 500; diff --git a/src/Discovery/Utils/DebounceSearch/doSearchFilterSort.js b/src/Discovery/Utils/DebounceSearch/doSearchFilterSort.js new file mode 100644 index 0000000000..e09991defb --- /dev/null +++ b/src/Discovery/Utils/DebounceSearch/doSearchFilterSort.js @@ -0,0 +1,40 @@ +const doSearchFilterSort = (props, jsSearch, config, setVisibleResources, filterByTags, filterByAdvSearch, filterState, filterMultiSelectionLogic, accessibleFieldName, AccessSortDirection ) => { + console.log('called doSearchFilterSort with ',props.studies, ' and search term', props.searchTerm); + let filteredResources = props.studies; + if (jsSearch && props.searchTerm) { + filteredResources = jsSearch.search(props.searchTerm); + } + filteredResources = filterByTags( + filteredResources, + props.selectedTags, + config, + ); + + if (config.features.advSearchFilters && config.features.advSearchFilters.enabled) { + filteredResources = filterByAdvSearch( + filteredResources, + filterState, + config, + filterMultiSelectionLogic, + ); + } + + if (props.config.features.authorization.enabled) { + filteredResources = filteredResources.filter( + (resource) => props.accessFilters[resource[accessibleFieldName]], + ); + } + + filteredResources = filteredResources.sort( + (a, b) => { + if (props.accessSortDirection === AccessSortDirection.DESCENDING) { + return a[accessibleFieldName] - b[accessibleFieldName]; + } if (props.accessSortDirection === AccessSortDirection.ASCENDING) { + return b[accessibleFieldName] - a[accessibleFieldName]; + } + return 0; + }, + ); + setVisibleResources(filteredResources); + }; + export default doSearchFilterSort; From 6cfb52f7e4b78b9d7c239a49ba98a4b2894943d7 Mon Sep 17 00:00:00 2001 From: Jarvis Raymond Date: Fri, 10 Feb 2023 08:40:47 -0600 Subject: [PATCH 06/17] feat(healSearchDebounce): Renamed function dbs to debounceSearch for clarity --- src/Discovery/Discovery.tsx | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/Discovery/Discovery.tsx b/src/Discovery/Discovery.tsx index 0700dd1241..dc703f7cd7 100644 --- a/src/Discovery/Discovery.tsx +++ b/src/Discovery/Discovery.tsx @@ -310,7 +310,7 @@ const Discovery: React.FunctionComponent = (props: Props) => { // THIS WORKS BUT ONLY ON PREVIOUS VERSION OF SEARCH TERM // const dbs = useMemo(() => (debounce(doSearchFilterSort, 250)),[visibleResources]); - const dbs = useMemo(() => (debounce(doSearchFilterSort, 500)),[]); + const debounceSearch = useMemo(() => (debounce(doSearchFilterSort, 500)),[]); useEffect( @@ -323,7 +323,7 @@ const Discovery: React.FunctionComponent = (props: Props) => { } // Otherwise debounce the calls // return debounce(doSearchFilterSort, debounceDelayInMilliseconds); - dbs(...parametersForDoSearchFilterSort); + debounceSearch(...parametersForDoSearchFilterSort); return; }, [ props.searchTerm, From c16dd59ffac47b90b3509d136cb3693f3f01b414 Mon Sep 17 00:00:00 2001 From: Jarvis Raymond Date: Fri, 10 Feb 2023 15:00:43 -0600 Subject: [PATCH 07/17] feat(healSearchDebounce): Renamed organized functions only used for search into a search folder and authored a test for doDebounceSearch --- src/Discovery/Discovery.tsx | 102 ++---------------- .../DebounceSearch/DebounceSearch.test.jsx | 32 ------ .../Utils/DebounceSearch/DebounceSearch.tsx | 21 ---- .../Utils/Search/doDebounceSearch.test.jsx | 74 +++++++++++++ .../Utils/Search/doDebounceSearch.tsx | 74 +++++++++++++ .../doSearchFilterSort.js | 5 +- .../Utils/Search/filterByAdvSearch.ts | 63 +++++++++++ src/Discovery/Utils/Search/filterByTags.ts | 12 +++ 8 files changed, 236 insertions(+), 147 deletions(-) delete mode 100644 src/Discovery/Utils/DebounceSearch/DebounceSearch.test.jsx delete mode 100644 src/Discovery/Utils/DebounceSearch/DebounceSearch.tsx create mode 100644 src/Discovery/Utils/Search/doDebounceSearch.test.jsx create mode 100644 src/Discovery/Utils/Search/doDebounceSearch.tsx rename src/Discovery/Utils/{DebounceSearch => Search}/doSearchFilterSort.js (87%) create mode 100644 src/Discovery/Utils/Search/filterByAdvSearch.ts create mode 100644 src/Discovery/Utils/Search/filterByTags.ts diff --git a/src/Discovery/Discovery.tsx b/src/Discovery/Discovery.tsx index dc703f7cd7..2f97676c3d 100644 --- a/src/Discovery/Discovery.tsx +++ b/src/Discovery/Discovery.tsx @@ -19,9 +19,8 @@ import { } from '@ant-design/icons'; import Checkbox from 'antd/lib/checkbox/Checkbox'; import MenuItem from 'antd/lib/menu/MenuItem'; -import DebounceSearch from './Utils/DebounceSearch/DebounceSearch'; +import doDebounceSearch from './Utils/Search/doDebounceSearch'; import { DiscoveryConfig } from './DiscoveryConfig'; -import './Discovery.css'; import DiscoverySummary from './DiscoverySummary'; import DiscoveryTagViewer from './DiscoveryTagViewer'; import DiscoveryDropdownTagViewer from './DiscoveryDropdownTagViewer'; @@ -29,9 +28,10 @@ import DiscoveryListView from './DiscoveryListView'; import DiscoveryAdvancedSearchPanel from './DiscoveryAdvancedSearchPanel'; import { ReduxDiscoveryActionBar, ReduxDiscoveryDetails } from './reduxer'; import DiscoveryMDSSearch from './DiscoveryMDSSearch'; -import { debounce, throttle } from 'lodash'; +import { debounce } from 'lodash'; import DiscoveryAccessibilityLinks from './DiscoveryAccessibilityLinks'; -import doSearchFilterSort from './Utils/DebounceSearch/doSearchFilterSort'; +import doSearchFilterSort from './Utils/Search/doSearchFilterSort'; +import './Discovery.css'; export const accessibleFieldName = '__accessible'; @@ -180,75 +180,10 @@ const highlightSearchTerm = (value: string, searchTerm: string, highlighClassNam }; }; -const filterByTags = (studies: any[], selectedTags: any, config: DiscoveryConfig): any[] => { - // if no tags selected, show all studies - if (Object.values(selectedTags).every((selected) => !selected)) { - return studies; - } - const tagField = config.minimalFieldMapping.tagsListFieldName; - return studies.filter((study) => study[tagField]?.some((tag) => selectedTags[tag.name])); -}; - interface FilterState { [key: string]: { [value: string]: boolean } } -const filterByAdvSearch = (studies: any[], advSearchFilterState: FilterState, config: DiscoveryConfig, filterMultiSelectionLogic: string): any[] => { - // if no filters active, show all studies - const noFiltersActive = Object.values(advSearchFilterState).every((selectedValues) => { - if (Object.values(selectedValues).length === 0) { - return true; - } - if (Object.values(selectedValues).every((selected) => !selected)) { - return true; - } - return false; - }); - if (noFiltersActive) { - return studies; - } - - // Combine within filters as AND - if (filterMultiSelectionLogic === 'AND') { - return studies.filter((study) => Object.keys(advSearchFilterState).every((filterName) => { - const filterValues = Object.keys(advSearchFilterState[filterName]); - // Handle the edge case where no values in this filter are selected - if (filterValues.length === 0) { - return true; - } - if (!config.features.advSearchFilters) { - return false; - } - const studyFilters = study[config.features.advSearchFilters.field]; - if (!studyFilters || !studyFilters.length) { - return false; - } - - const studyFilterValues = studyFilters.filter(({ key }) => key === filterName) - .map(({ value }) => value); - return filterValues.every((value) => studyFilterValues.includes(value)); - })); - } - - // Combine within filters as OR - return studies.filter((study) => Object.keys(advSearchFilterState).some((filterName) => { - const filterValues = Object.keys(advSearchFilterState[filterName]); - // Handle the edge case where no values in this filter are selected - if (filterValues.length === 0) { - return true; - } - if (!config.features.advSearchFilters) { - return false; - } - const studyFilters = study[config.features.advSearchFilters.field]; - if (!studyFilters || !studyFilters.length) { - return false; - } - - return studyFilters.some(({ key, value }) => key === filterName && filterValues.includes(value)); - })); -}; - export interface DiscoveryResource { [accessibleFieldName]: AccessLevel, [any: string]: any, @@ -278,9 +213,8 @@ interface Props { const Discovery: React.FunctionComponent = (props: Props) => { const { config } = props; - const [jsSearch, setJsSearch] = useState(null); - const [executedSearches, setExecutedSearches] = useState(0); + const [executedSearchesCount, setExecutedSearchesCount] = useState(0); const [accessibilityFilterVisible, setAccessibilityFilterVisible] = useState(false); const [modalVisible, setModalVisible] = useState(false); const [filtersVisible, setFiltersVisible] = useState(false); @@ -302,30 +236,12 @@ const Discovery: React.FunctionComponent = (props: Props) => { props.onSearchChange(value); }; - - - const debounceDelayInMilliseconds = 500; - const initialSearchesWithoutDebounce = 2; - //const dbs = useCallback(debounce(doSearchFilterSort, 500),[]); - - // THIS WORKS BUT ONLY ON PREVIOUS VERSION OF SEARCH TERM - // const dbs = useMemo(() => (debounce(doSearchFilterSort, 250)),[visibleResources]); - const debounceSearch = useMemo(() => (debounce(doSearchFilterSort, 500)),[]); - + const memoizedDebouncedSearch = useMemo(() => (debounce(doSearchFilterSort, 500)),[]); + const parametersForDoSearchFilterSort = [props, jsSearch, config, setVisibleResources, + filterState, filterMultiSelectionLogic, accessibleFieldName, AccessSortDirection]; useEffect( - ()=>{ - const parametersForDoSearchFilterSort = [props, jsSearch, config, setVisibleResources, filterByTags, filterByAdvSearch, filterState, filterMultiSelectionLogic, accessibleFieldName, AccessSortDirection]; - // Execute searches initially without debounce to decrease page load time - if (executedSearches < initialSearchesWithoutDebounce) { - setExecutedSearches(executedSearches + 1); - return doSearchFilterSort(...parametersForDoSearchFilterSort ) ; - } - // Otherwise debounce the calls - // return debounce(doSearchFilterSort, debounceDelayInMilliseconds); - debounceSearch(...parametersForDoSearchFilterSort); - return; - }, [ + ()=> doDebounceSearch(parametersForDoSearchFilterSort, memoizedDebouncedSearch, executedSearchesCount, setExecutedSearchesCount), [ props.searchTerm, props.accessSortDirection, props.studies, diff --git a/src/Discovery/Utils/DebounceSearch/DebounceSearch.test.jsx b/src/Discovery/Utils/DebounceSearch/DebounceSearch.test.jsx deleted file mode 100644 index c59b8104a6..0000000000 --- a/src/Discovery/Utils/DebounceSearch/DebounceSearch.test.jsx +++ /dev/null @@ -1,32 +0,0 @@ -import { debounce } from 'lodash'; -import DebounceSearch from './DebounceSearch'; - -jest.mock('lodash', () => ({ - debounce: jest.fn((func) => func), -})); - -describe('DebounceSearch', () => { - let doSearchFilterSort; let - setExecutedSearches; - beforeEach(() => { - doSearchFilterSort = jest.fn(); - setExecutedSearches = jest.fn(); - }); - - it('executes the doSearchFilterSort function immediately the first two times it is called', () => { - let executedSearches = 0; - DebounceSearch(doSearchFilterSort, executedSearches, setExecutedSearches); - expect(doSearchFilterSort).toHaveBeenCalledTimes(1); - expect(setExecutedSearches).toHaveBeenCalledTimes(1); - executedSearches = 1; - DebounceSearch(doSearchFilterSort, executedSearches, setExecutedSearches); - expect(doSearchFilterSort).toHaveBeenCalledTimes(2); - expect(setExecutedSearches).toHaveBeenCalledWith(2); - }); - - it('debounces the doSearchFilterSort function after the first two calls', () => { - const executedSearches = 2; - DebounceSearch(doSearchFilterSort, executedSearches, setExecutedSearches); - expect(debounce).toHaveBeenCalledWith(doSearchFilterSort, 500); - }); -}); diff --git a/src/Discovery/Utils/DebounceSearch/DebounceSearch.tsx b/src/Discovery/Utils/DebounceSearch/DebounceSearch.tsx deleted file mode 100644 index a08127356f..0000000000 --- a/src/Discovery/Utils/DebounceSearch/DebounceSearch.tsx +++ /dev/null @@ -1,21 +0,0 @@ -import { debounce } from 'lodash'; -import { useCallback } from 'react'; - - -const dbs = useCallback(debounce(doSearchFilterSort, debounceDelayInMilliseconds),[]); - - -const DebounceSearch = (doSearchFilterSort, executedSearches, setExecutedSearches) => { - const debounceDelayInMilliseconds = 500; - const initialSearchesWithoutDebounce = 2; - - // Execute searches initially without debounce to decrease page load time - if (executedSearches < initialSearchesWithoutDebounce) { - setExecutedSearches(executedSearches + 1); - return doSearchFilterSort(); - } - // Otherwise debounce the calls - return debounce(doSearchFilterSort, debounceDelayInMilliseconds); -}; - -export default DebounceSearch; diff --git a/src/Discovery/Utils/Search/doDebounceSearch.test.jsx b/src/Discovery/Utils/Search/doDebounceSearch.test.jsx new file mode 100644 index 0000000000..8c0356871c --- /dev/null +++ b/src/Discovery/Utils/Search/doDebounceSearch.test.jsx @@ -0,0 +1,74 @@ +import doDebounceSearch from "./doDebounceSearch"; +import doSearchFilterSort from "./doSearchFilterSort"; + +jest.mock("./doSearchFilterSort"); + +describe("doDebounceSearch", () => { + let parametersForDoSearchFilterSort; + let memoizedDebouncedSearch; + let executedSearchesCount; + let setExecutedSearchesCount; + let result; + + beforeEach(() => { + parametersForDoSearchFilterSort = [1, 2, 3]; + memoizedDebouncedSearch = jest.fn(); + executedSearchesCount = 0; + setExecutedSearchesCount = jest.fn(); + + result = doDebounceSearch( + parametersForDoSearchFilterSort, + memoizedDebouncedSearch, + executedSearchesCount, + setExecutedSearchesCount + ); + }); + + afterEach(() => { + jest.clearAllMocks(); + }); + + it("should call doSearchFilterSort initially without debouncing", () => { + executedSearchesCount = 1; + doDebounceSearch( + parametersForDoSearchFilterSort, + memoizedDebouncedSearch, + executedSearchesCount, + setExecutedSearchesCount + ); + expect(doSearchFilterSort).toHaveBeenCalledWith(...parametersForDoSearchFilterSort); + expect(memoizedDebouncedSearch).not.toHaveBeenCalled(); + }); + + it("should debounce calls after the initial 2 calls", () => { + executedSearchesCount = 2; + doDebounceSearch( + parametersForDoSearchFilterSort, + memoizedDebouncedSearch, + executedSearchesCount, + setExecutedSearchesCount + ); + expect(doSearchFilterSort).not.toHaveBeenCalled(); + expect(memoizedDebouncedSearch).toHaveBeenCalledWith(...parametersForDoSearchFilterSort); + }); + + it("should increment the executedSearchesCount by 1 after each call", () => { + executedSearchesCount = 1; + doDebounceSearch( + parametersForDoSearchFilterSort, + memoizedDebouncedSearch, + executedSearchesCount, + setExecutedSearchesCount + ); + expect(setExecutedSearchesCount).toHaveBeenCalledWith(2); + + executedSearchesCount = 2; + doDebounceSearch( + parametersForDoSearchFilterSort, + memoizedDebouncedSearch, + executedSearchesCount, + setExecutedSearchesCount + ); + expect(setExecutedSearchesCount).toHaveBeenCalledWith(3); + }); +}); diff --git a/src/Discovery/Utils/Search/doDebounceSearch.tsx b/src/Discovery/Utils/Search/doDebounceSearch.tsx new file mode 100644 index 0000000000..8c0356871c --- /dev/null +++ b/src/Discovery/Utils/Search/doDebounceSearch.tsx @@ -0,0 +1,74 @@ +import doDebounceSearch from "./doDebounceSearch"; +import doSearchFilterSort from "./doSearchFilterSort"; + +jest.mock("./doSearchFilterSort"); + +describe("doDebounceSearch", () => { + let parametersForDoSearchFilterSort; + let memoizedDebouncedSearch; + let executedSearchesCount; + let setExecutedSearchesCount; + let result; + + beforeEach(() => { + parametersForDoSearchFilterSort = [1, 2, 3]; + memoizedDebouncedSearch = jest.fn(); + executedSearchesCount = 0; + setExecutedSearchesCount = jest.fn(); + + result = doDebounceSearch( + parametersForDoSearchFilterSort, + memoizedDebouncedSearch, + executedSearchesCount, + setExecutedSearchesCount + ); + }); + + afterEach(() => { + jest.clearAllMocks(); + }); + + it("should call doSearchFilterSort initially without debouncing", () => { + executedSearchesCount = 1; + doDebounceSearch( + parametersForDoSearchFilterSort, + memoizedDebouncedSearch, + executedSearchesCount, + setExecutedSearchesCount + ); + expect(doSearchFilterSort).toHaveBeenCalledWith(...parametersForDoSearchFilterSort); + expect(memoizedDebouncedSearch).not.toHaveBeenCalled(); + }); + + it("should debounce calls after the initial 2 calls", () => { + executedSearchesCount = 2; + doDebounceSearch( + parametersForDoSearchFilterSort, + memoizedDebouncedSearch, + executedSearchesCount, + setExecutedSearchesCount + ); + expect(doSearchFilterSort).not.toHaveBeenCalled(); + expect(memoizedDebouncedSearch).toHaveBeenCalledWith(...parametersForDoSearchFilterSort); + }); + + it("should increment the executedSearchesCount by 1 after each call", () => { + executedSearchesCount = 1; + doDebounceSearch( + parametersForDoSearchFilterSort, + memoizedDebouncedSearch, + executedSearchesCount, + setExecutedSearchesCount + ); + expect(setExecutedSearchesCount).toHaveBeenCalledWith(2); + + executedSearchesCount = 2; + doDebounceSearch( + parametersForDoSearchFilterSort, + memoizedDebouncedSearch, + executedSearchesCount, + setExecutedSearchesCount + ); + expect(setExecutedSearchesCount).toHaveBeenCalledWith(3); + }); +}); diff --git a/src/Discovery/Utils/DebounceSearch/doSearchFilterSort.js b/src/Discovery/Utils/Search/doSearchFilterSort.js similarity index 87% rename from src/Discovery/Utils/DebounceSearch/doSearchFilterSort.js rename to src/Discovery/Utils/Search/doSearchFilterSort.js index e09991defb..d2fc7c1ac1 100644 --- a/src/Discovery/Utils/DebounceSearch/doSearchFilterSort.js +++ b/src/Discovery/Utils/Search/doSearchFilterSort.js @@ -1,4 +1,7 @@ -const doSearchFilterSort = (props, jsSearch, config, setVisibleResources, filterByTags, filterByAdvSearch, filterState, filterMultiSelectionLogic, accessibleFieldName, AccessSortDirection ) => { +import filterByTags from "./filterByTags"; +import filterByAdvSearch from "./filterByAdvSearch" + +const doSearchFilterSort = (props, jsSearch, config, setVisibleResources, filterState, filterMultiSelectionLogic, accessibleFieldName, AccessSortDirection ) => { console.log('called doSearchFilterSort with ',props.studies, ' and search term', props.searchTerm); let filteredResources = props.studies; if (jsSearch && props.searchTerm) { diff --git a/src/Discovery/Utils/Search/filterByAdvSearch.ts b/src/Discovery/Utils/Search/filterByAdvSearch.ts new file mode 100644 index 0000000000..d0a77a8e69 --- /dev/null +++ b/src/Discovery/Utils/Search/filterByAdvSearch.ts @@ -0,0 +1,63 @@ +import { DiscoveryConfig } from '../../DiscoveryConfig'; + +interface FilterState { + [key: string]: { [value: string]: boolean } + } + +const filterByAdvSearch = (studies: any[], advSearchFilterState: FilterState, config: DiscoveryConfig, filterMultiSelectionLogic: string): any[] => { + // if no filters active, show all studies + const noFiltersActive = Object.values(advSearchFilterState).every((selectedValues) => { + if (Object.values(selectedValues).length === 0) { + return true; + } + if (Object.values(selectedValues).every((selected) => !selected)) { + return true; + } + return false; + }); + if (noFiltersActive) { + return studies; + } + + // Combine within filters as AND + if (filterMultiSelectionLogic === 'AND') { + return studies.filter((study) => Object.keys(advSearchFilterState).every((filterName) => { + const filterValues = Object.keys(advSearchFilterState[filterName]); + // Handle the edge case where no values in this filter are selected + if (filterValues.length === 0) { + return true; + } + if (!config.features.advSearchFilters) { + return false; + } + const studyFilters = study[config.features.advSearchFilters.field]; + if (!studyFilters || !studyFilters.length) { + return false; + } + + const studyFilterValues = studyFilters.filter(({ key }) => key === filterName) + .map(({ value }) => value); + return filterValues.every((value) => studyFilterValues.includes(value)); + })); + } + + // Combine within filters as OR + return studies.filter((study) => Object.keys(advSearchFilterState).some((filterName) => { + const filterValues = Object.keys(advSearchFilterState[filterName]); + // Handle the edge case where no values in this filter are selected + if (filterValues.length === 0) { + return true; + } + if (!config.features.advSearchFilters) { + return false; + } + const studyFilters = study[config.features.advSearchFilters.field]; + if (!studyFilters || !studyFilters.length) { + return false; + } + + return studyFilters.some(({ key, value }) => key === filterName && filterValues.includes(value)); + })); + }; + + export default filterByAdvSearch; diff --git a/src/Discovery/Utils/Search/filterByTags.ts b/src/Discovery/Utils/Search/filterByTags.ts new file mode 100644 index 0000000000..8018a62d19 --- /dev/null +++ b/src/Discovery/Utils/Search/filterByTags.ts @@ -0,0 +1,12 @@ +import { DiscoveryConfig } from '../../DiscoveryConfig'; + +const filterByTags = (studies: any[], selectedTags: any, config: DiscoveryConfig): any[] => { + // if no tags selected, show all studies + if (Object.values(selectedTags).every((selected) => !selected)) { + return studies; + } + const tagField = config.minimalFieldMapping.tagsListFieldName; + return studies.filter((study) => study[tagField]?.some((tag) => selectedTags[tag.name])); + }; + + export default filterByTags; From 7296e9ff57769d032fb8ce8c271a2ca389625bb2 Mon Sep 17 00:00:00 2001 From: Jarvis Raymond Date: Fri, 10 Feb 2023 15:20:12 -0600 Subject: [PATCH 08/17] feat(healSearchDebounce): Created test for doDebounceSearch.ts --- .../Utils/Search/doDebounceSearch.test.jsx | 74 ---------------- .../Utils/Search/doDebounceSearch.test.ts | 37 ++++++++ .../Utils/Search/doDebounceSearch.tsx | 85 +++---------------- ...rchFilterSort.js => doSearchFilterSort.ts} | 0 4 files changed, 50 insertions(+), 146 deletions(-) delete mode 100644 src/Discovery/Utils/Search/doDebounceSearch.test.jsx create mode 100644 src/Discovery/Utils/Search/doDebounceSearch.test.ts rename src/Discovery/Utils/Search/{doSearchFilterSort.js => doSearchFilterSort.ts} (100%) diff --git a/src/Discovery/Utils/Search/doDebounceSearch.test.jsx b/src/Discovery/Utils/Search/doDebounceSearch.test.jsx deleted file mode 100644 index 8c0356871c..0000000000 --- a/src/Discovery/Utils/Search/doDebounceSearch.test.jsx +++ /dev/null @@ -1,74 +0,0 @@ -import doDebounceSearch from "./doDebounceSearch"; -import doSearchFilterSort from "./doSearchFilterSort"; - -jest.mock("./doSearchFilterSort"); - -describe("doDebounceSearch", () => { - let parametersForDoSearchFilterSort; - let memoizedDebouncedSearch; - let executedSearchesCount; - let setExecutedSearchesCount; - let result; - - beforeEach(() => { - parametersForDoSearchFilterSort = [1, 2, 3]; - memoizedDebouncedSearch = jest.fn(); - executedSearchesCount = 0; - setExecutedSearchesCount = jest.fn(); - - result = doDebounceSearch( - parametersForDoSearchFilterSort, - memoizedDebouncedSearch, - executedSearchesCount, - setExecutedSearchesCount - ); - }); - - afterEach(() => { - jest.clearAllMocks(); - }); - - it("should call doSearchFilterSort initially without debouncing", () => { - executedSearchesCount = 1; - doDebounceSearch( - parametersForDoSearchFilterSort, - memoizedDebouncedSearch, - executedSearchesCount, - setExecutedSearchesCount - ); - expect(doSearchFilterSort).toHaveBeenCalledWith(...parametersForDoSearchFilterSort); - expect(memoizedDebouncedSearch).not.toHaveBeenCalled(); - }); - - it("should debounce calls after the initial 2 calls", () => { - executedSearchesCount = 2; - doDebounceSearch( - parametersForDoSearchFilterSort, - memoizedDebouncedSearch, - executedSearchesCount, - setExecutedSearchesCount - ); - expect(doSearchFilterSort).not.toHaveBeenCalled(); - expect(memoizedDebouncedSearch).toHaveBeenCalledWith(...parametersForDoSearchFilterSort); - }); - - it("should increment the executedSearchesCount by 1 after each call", () => { - executedSearchesCount = 1; - doDebounceSearch( - parametersForDoSearchFilterSort, - memoizedDebouncedSearch, - executedSearchesCount, - setExecutedSearchesCount - ); - expect(setExecutedSearchesCount).toHaveBeenCalledWith(2); - - executedSearchesCount = 2; - doDebounceSearch( - parametersForDoSearchFilterSort, - memoizedDebouncedSearch, - executedSearchesCount, - setExecutedSearchesCount - ); - expect(setExecutedSearchesCount).toHaveBeenCalledWith(3); - }); -}); diff --git a/src/Discovery/Utils/Search/doDebounceSearch.test.ts b/src/Discovery/Utils/Search/doDebounceSearch.test.ts new file mode 100644 index 0000000000..27fefd2402 --- /dev/null +++ b/src/Discovery/Utils/Search/doDebounceSearch.test.ts @@ -0,0 +1,37 @@ +import doDebounceSearch from "./doDebounceSearch"; +import doSearchFilterSort from "./doSearchFilterSort"; + +jest.mock("./doSearchFilterSort"); + +describe("doDebounceSearch", () => { + let memoizedDebouncedSearch; + let setExecutedSearchesCount; + beforeEach(() => { + memoizedDebouncedSearch = jest.fn(() => {}); + setExecutedSearchesCount = jest.fn(() => {}); + }); + + afterEach(() => { + jest.clearAllMocks(); + }); + + it("should execute doSearchFilterSort initially without debouncing", () => { + doDebounceSearch([1, 2, 3], memoizedDebouncedSearch, 0, setExecutedSearchesCount); + expect(doSearchFilterSort).toHaveBeenCalledWith(1, 2, 3); + expect(memoizedDebouncedSearch).not.toHaveBeenCalled(); + expect(setExecutedSearchesCount).toHaveBeenCalledWith(1); + + jest.clearAllMocks(); + doDebounceSearch([4, 5, 6], memoizedDebouncedSearch, 1, setExecutedSearchesCount); + expect(doSearchFilterSort).toHaveBeenCalledWith(4, 5, 6); + expect(memoizedDebouncedSearch).not.toHaveBeenCalled(); + expect(setExecutedSearchesCount).toHaveBeenCalledWith(2); + }); + + it("should debounce the doSearchFilterSort call when executedSearchesCount >= 2", () => { + doDebounceSearch([1, 2, 3], memoizedDebouncedSearch, 2, setExecutedSearchesCount); + expect(doSearchFilterSort).not.toHaveBeenCalled(); + expect(memoizedDebouncedSearch).toHaveBeenCalledWith(1, 2, 3); + expect(setExecutedSearchesCount).not.toHaveBeenCalled(); + }); +}); diff --git a/src/Discovery/Utils/Search/doDebounceSearch.tsx b/src/Discovery/Utils/Search/doDebounceSearch.tsx index 8c0356871c..33b1009b3f 100644 --- a/src/Discovery/Utils/Search/doDebounceSearch.tsx +++ b/src/Discovery/Utils/Search/doDebounceSearch.tsx @@ -1,74 +1,15 @@ -import doDebounceSearch from "./doDebounceSearch"; import doSearchFilterSort from "./doSearchFilterSort"; -jest.mock("./doSearchFilterSort"); - -describe("doDebounceSearch", () => { - let parametersForDoSearchFilterSort; - let memoizedDebouncedSearch; - let executedSearchesCount; - let setExecutedSearchesCount; - let result; - - beforeEach(() => { - parametersForDoSearchFilterSort = [1, 2, 3]; - memoizedDebouncedSearch = jest.fn(); - executedSearchesCount = 0; - setExecutedSearchesCount = jest.fn(); - - result = doDebounceSearch( - parametersForDoSearchFilterSort, - memoizedDebouncedSearch, - executedSearchesCount, - setExecutedSearchesCount - ); - }); - - afterEach(() => { - jest.clearAllMocks(); - }); - - it("should call doSearchFilterSort initially without debouncing", () => { - executedSearchesCount = 1; - doDebounceSearch( - parametersForDoSearchFilterSort, - memoizedDebouncedSearch, - executedSearchesCount, - setExecutedSearchesCount - ); - expect(doSearchFilterSort).toHaveBeenCalledWith(...parametersForDoSearchFilterSort); - expect(memoizedDebouncedSearch).not.toHaveBeenCalled(); - }); - - it("should debounce calls after the initial 2 calls", () => { - executedSearchesCount = 2; - doDebounceSearch( - parametersForDoSearchFilterSort, - memoizedDebouncedSearch, - executedSearchesCount, - setExecutedSearchesCount - ); - expect(doSearchFilterSort).not.toHaveBeenCalled(); - expect(memoizedDebouncedSearch).toHaveBeenCalledWith(...parametersForDoSearchFilterSort); - }); - - it("should increment the executedSearchesCount by 1 after each call", () => { - executedSearchesCount = 1; - doDebounceSearch( - parametersForDoSearchFilterSort, - memoizedDebouncedSearch, - executedSearchesCount, - setExecutedSearchesCount - ); - expect(setExecutedSearchesCount).toHaveBeenCalledWith(2); - - executedSearchesCount = 2; - doDebounceSearch( - parametersForDoSearchFilterSort, - memoizedDebouncedSearch, - executedSearchesCount, - setExecutedSearchesCount - ); - expect(setExecutedSearchesCount).toHaveBeenCalledWith(3); - }); -}); +const doDebounceSearch = (parametersForDoSearchFilterSort, memoizedDebouncedSearch, executedSearchesCount, setExecutedSearchesCount) => { + const debounceDelayInMilliseconds = 500; + const initialSearchesWithoutDebounce = 2; + // Execute searches initially without debounce to decrease page load time + if (executedSearchesCount < initialSearchesWithoutDebounce) { + setExecutedSearchesCount(executedSearchesCount + 1); + return doSearchFilterSort(...parametersForDoSearchFilterSort ) ; + } + // Otherwise debounce the calls + // return debounce(doSearchFilterSort, debounceDelayInMilliseconds); + return memoizedDebouncedSearch(...parametersForDoSearchFilterSort); +} +export default doDebounceSearch; diff --git a/src/Discovery/Utils/Search/doSearchFilterSort.js b/src/Discovery/Utils/Search/doSearchFilterSort.ts similarity index 100% rename from src/Discovery/Utils/Search/doSearchFilterSort.js rename to src/Discovery/Utils/Search/doSearchFilterSort.ts From 9c32e4bc99974db7580ada4be4e332aed4c4ad95 Mon Sep 17 00:00:00 2001 From: Jarvis Raymond Date: Fri, 10 Feb 2023 15:28:46 -0600 Subject: [PATCH 09/17] test(addReactTestingLibrary): Removed console.log --- src/Discovery/Utils/Search/doSearchFilterSort.ts | 1 - 1 file changed, 1 deletion(-) diff --git a/src/Discovery/Utils/Search/doSearchFilterSort.ts b/src/Discovery/Utils/Search/doSearchFilterSort.ts index d2fc7c1ac1..70bc8c515e 100644 --- a/src/Discovery/Utils/Search/doSearchFilterSort.ts +++ b/src/Discovery/Utils/Search/doSearchFilterSort.ts @@ -2,7 +2,6 @@ import filterByTags from "./filterByTags"; import filterByAdvSearch from "./filterByAdvSearch" const doSearchFilterSort = (props, jsSearch, config, setVisibleResources, filterState, filterMultiSelectionLogic, accessibleFieldName, AccessSortDirection ) => { - console.log('called doSearchFilterSort with ',props.studies, ' and search term', props.searchTerm); let filteredResources = props.studies; if (jsSearch && props.searchTerm) { filteredResources = jsSearch.search(props.searchTerm); From b77a49e2c298cb60e76767c466a9962f5a2fda2c Mon Sep 17 00:00:00 2001 From: Jarvis Raymond Date: Thu, 23 Feb 2023 09:26:48 -0600 Subject: [PATCH 10/17] feat(healSearchDebounce): Converted JS function to TS and changed array to object to avoid needing spread operator --- src/Discovery/Discovery.tsx | 18 +++- .../Utils/Search/doDebounceSearch.tsx | 27 +++--- .../Utils/Search/doSearchFilterSort.ts | 82 +++++++++++-------- 3 files changed, 77 insertions(+), 50 deletions(-) diff --git a/src/Discovery/Discovery.tsx b/src/Discovery/Discovery.tsx index e07e13cd05..735a719e99 100644 --- a/src/Discovery/Discovery.tsx +++ b/src/Discovery/Discovery.tsx @@ -237,10 +237,20 @@ const Discovery: React.FunctionComponent = (props: Props) => { props.onSearchChange(value); }; - const memoizedDebouncedSearch = useMemo(() => (debounce(doSearchFilterSort, 500)),[]); - const parametersForDoSearchFilterSort = [props, jsSearch, config, setVisibleResources, - filterState, filterMultiSelectionLogic, accessibleFieldName, AccessSortDirection]; - + const memoizedDebouncedSearch = useMemo( + () => debounce(doSearchFilterSort, 500), + [] + ); + const parametersForDoSearchFilterSort = { + props, + jsSearch, + config, + setVisibleResources, + filterState, + filterMultiSelectionLogic, + accessibleFieldName, + AccessSortDirection, + }; useEffect( ()=> doDebounceSearch(parametersForDoSearchFilterSort, memoizedDebouncedSearch, executedSearchesCount, setExecutedSearchesCount), [ props.searchTerm, diff --git a/src/Discovery/Utils/Search/doDebounceSearch.tsx b/src/Discovery/Utils/Search/doDebounceSearch.tsx index 33b1009b3f..b150dd8289 100644 --- a/src/Discovery/Utils/Search/doDebounceSearch.tsx +++ b/src/Discovery/Utils/Search/doDebounceSearch.tsx @@ -1,15 +1,20 @@ -import doSearchFilterSort from "./doSearchFilterSort"; +import doSearchFilterSort from './doSearchFilterSort'; -const doDebounceSearch = (parametersForDoSearchFilterSort, memoizedDebouncedSearch, executedSearchesCount, setExecutedSearchesCount) => { +const doDebounceSearch = ( + parametersForDoSearchFilterSort: any[], + memoizedDebouncedSearch: (...args: any[]) => void, + executedSearchesCount: number, + setExecutedSearchesCount: (count: number) => void +) => { const debounceDelayInMilliseconds = 500; const initialSearchesWithoutDebounce = 2; - // Execute searches initially without debounce to decrease page load time - if (executedSearchesCount < initialSearchesWithoutDebounce) { - setExecutedSearchesCount(executedSearchesCount + 1); - return doSearchFilterSort(...parametersForDoSearchFilterSort ) ; - } - // Otherwise debounce the calls - // return debounce(doSearchFilterSort, debounceDelayInMilliseconds); - return memoizedDebouncedSearch(...parametersForDoSearchFilterSort); -} + // Execute searches initially without debounce to decrease page load time + if (executedSearchesCount < initialSearchesWithoutDebounce) { + setExecutedSearchesCount(executedSearchesCount + 1); + return doSearchFilterSort(parametersForDoSearchFilterSort); + } + // Otherwise debounce the calls + // return debounce(doSearchFilterSort, debounceDelayInMilliseconds); + return memoizedDebouncedSearch(parametersForDoSearchFilterSort); +}; export default doDebounceSearch; diff --git a/src/Discovery/Utils/Search/doSearchFilterSort.ts b/src/Discovery/Utils/Search/doSearchFilterSort.ts index 70bc8c515e..646637b0fb 100644 --- a/src/Discovery/Utils/Search/doSearchFilterSort.ts +++ b/src/Discovery/Utils/Search/doSearchFilterSort.ts @@ -1,42 +1,54 @@ -import filterByTags from "./filterByTags"; -import filterByAdvSearch from "./filterByAdvSearch" +import filterByTags from './filterByTags'; +import filterByAdvSearch from './filterByAdvSearch'; -const doSearchFilterSort = (props, jsSearch, config, setVisibleResources, filterState, filterMultiSelectionLogic, accessibleFieldName, AccessSortDirection ) => { - let filteredResources = props.studies; - if (jsSearch && props.searchTerm) { - filteredResources = jsSearch.search(props.searchTerm); - } - filteredResources = filterByTags( +const doSearchFilterSort = (parametersForDoSearchFilterSort) => { + const { + props, + jsSearch, + config, + setVisibleResources, + filterState, + filterMultiSelectionLogic, + accessibleFieldName, + AccessSortDirection, + } = parametersForDoSearchFilterSort; + let filteredResources = props.studies; + if (jsSearch && props.searchTerm) { + filteredResources = jsSearch.search(props.searchTerm); + } + filteredResources = filterByTags( + filteredResources, + props.selectedTags, + config + ); + + if ( + config.features.advSearchFilters && + config.features.advSearchFilters.enabled + ) { + filteredResources = filterByAdvSearch( filteredResources, - props.selectedTags, + filterState, config, + filterMultiSelectionLogic ); + } - if (config.features.advSearchFilters && config.features.advSearchFilters.enabled) { - filteredResources = filterByAdvSearch( - filteredResources, - filterState, - config, - filterMultiSelectionLogic, - ); - } + if (props.config.features.authorization.enabled) { + filteredResources = filteredResources.filter( + (resource) => props.accessFilters[resource[accessibleFieldName]] + ); + } - if (props.config.features.authorization.enabled) { - filteredResources = filteredResources.filter( - (resource) => props.accessFilters[resource[accessibleFieldName]], - ); + filteredResources = filteredResources.sort((a, b) => { + if (props.accessSortDirection === AccessSortDirection.DESCENDING) { + return a[accessibleFieldName] - b[accessibleFieldName]; } - - filteredResources = filteredResources.sort( - (a, b) => { - if (props.accessSortDirection === AccessSortDirection.DESCENDING) { - return a[accessibleFieldName] - b[accessibleFieldName]; - } if (props.accessSortDirection === AccessSortDirection.ASCENDING) { - return b[accessibleFieldName] - a[accessibleFieldName]; - } - return 0; - }, - ); - setVisibleResources(filteredResources); - }; - export default doSearchFilterSort; + if (props.accessSortDirection === AccessSortDirection.ASCENDING) { + return b[accessibleFieldName] - a[accessibleFieldName]; + } + return 0; + }); + setVisibleResources(filteredResources); +}; +export default doSearchFilterSort; From d2e87907bfd06f8a98122a43a072e81ea7c24fdc Mon Sep 17 00:00:00 2001 From: Jarvis Raymond Date: Thu, 23 Feb 2023 09:55:10 -0600 Subject: [PATCH 11/17] feat(healSearchDebounce): Ran eslint on changed files --- src/Discovery/Discovery.tsx | 106 +++++++++--------- .../Utils/Search/doDebounceSearch.test.ts | 12 +- .../Utils/Search/doDebounceSearch.tsx | 5 +- .../Utils/Search/doSearchFilterSort.ts | 10 +- .../Utils/Search/filterByAdvSearch.ts | 76 ++++++------- src/Discovery/Utils/Search/filterByTags.ts | 16 +-- 6 files changed, 114 insertions(+), 111 deletions(-) diff --git a/src/Discovery/Discovery.tsx b/src/Discovery/Discovery.tsx index 735a719e99..e88df3aa62 100644 --- a/src/Discovery/Discovery.tsx +++ b/src/Discovery/Discovery.tsx @@ -1,4 +1,6 @@ -import React, { useState, useEffect, ReactNode, useCallback, useMemo } from 'react'; +import React, { + useState, useEffect, ReactNode, useMemo, +} from 'react'; import * as JsSearch from 'js-search'; import { Tag, Popover, Space, Collapse, Button, Dropdown, Menu, Pagination, Tooltip, @@ -19,6 +21,8 @@ import { } from '@ant-design/icons'; import Checkbox from 'antd/lib/checkbox/Checkbox'; import MenuItem from 'antd/lib/menu/MenuItem'; +import { debounce } from 'lodash'; +import { JsxElement } from 'typescript'; import doDebounceSearch from './Utils/Search/doDebounceSearch'; import { DiscoveryConfig } from './DiscoveryConfig'; import DiscoverySummary from './DiscoverySummary'; @@ -28,11 +32,9 @@ import DiscoveryListView from './DiscoveryListView'; import DiscoveryAdvancedSearchPanel from './DiscoveryAdvancedSearchPanel'; import { ReduxDiscoveryActionBar, ReduxDiscoveryDetails } from './reduxer'; import DiscoveryMDSSearch from './DiscoveryMDSSearch'; -import { debounce } from 'lodash'; import DiscoveryAccessibilityLinks from './DiscoveryAccessibilityLinks'; import doSearchFilterSort from './Utils/Search/doSearchFilterSort'; import './Discovery.css'; -import { JsxElement } from 'typescript'; export const accessibleFieldName = '__accessible'; @@ -109,54 +111,54 @@ const accessibleDataFilterToggle = () => { export const renderFieldContent = (content: any, contentType: 'string' | 'paragraphs' | 'number' | 'link' | 'tags' = 'string', config: DiscoveryConfig): React.ReactNode => { switch (contentType) { - case 'string': - if (Array.isArray(content)) { - return content.join(', '); - } - return content; - case 'number': - if (Array.isArray(content)) { - return content.join(', '); - } - return content.toLocaleString(); - case 'paragraphs': - return content.split('\n').map((paragraph, i) =>

{paragraph}

); - case 'link': + case 'string': + if (Array.isArray(content)) { + return content.join(', '); + } + return content; + case 'number': + if (Array.isArray(content)) { + return content.join(', '); + } + return content.toLocaleString(); + case 'paragraphs': + return content.split('\n').map((paragraph, i) =>

{paragraph}

); + case 'link': + return ( + ev.stopPropagation()} + onKeyPress={(ev) => ev.stopPropagation()} + href={content} + target='_blank' + rel='noreferrer' + > + {content} + + ); + case 'tags': + if (!content || !content.map) { + return null; + } + return content.map(({ name, category }) => { + const color = getTagColor(category, config); return ( - ev.stopPropagation()} - onKeyPress={(ev) => ev.stopPropagation()} - href={content} - target='_blank' - rel='noreferrer' + - {content} - + {name} + ); - case 'tags': - if (!content || !content.map) { - return null; - } - return content.map(({ name, category }) => { - const color = getTagColor(category, config); - return ( - - {name} - - ); - }); - default: - throw new Error(`Unrecognized content type ${contentType}. Check the 'study_page_fields' section of the Discovery config.`); + }); + default: + throw new Error(`Unrecognized content type ${contentType}. Check the 'study_page_fields' section of the Discovery config.`); } }; @@ -237,9 +239,10 @@ const Discovery: React.FunctionComponent = (props: Props) => { props.onSearchChange(value); }; + const debouncingDelayInMilliseconds = 500; const memoizedDebouncedSearch = useMemo( - () => debounce(doSearchFilterSort, 500), - [] + () => debounce(doSearchFilterSort, debouncingDelayInMilliseconds), + [], ); const parametersForDoSearchFilterSort = { props, @@ -251,8 +254,9 @@ const Discovery: React.FunctionComponent = (props: Props) => { accessibleFieldName, AccessSortDirection, }; + useEffect( - ()=> doDebounceSearch(parametersForDoSearchFilterSort, memoizedDebouncedSearch, executedSearchesCount, setExecutedSearchesCount), [ + () => doDebounceSearch(parametersForDoSearchFilterSort, memoizedDebouncedSearch, executedSearchesCount, setExecutedSearchesCount), [ props.searchTerm, props.accessSortDirection, props.studies, diff --git a/src/Discovery/Utils/Search/doDebounceSearch.test.ts b/src/Discovery/Utils/Search/doDebounceSearch.test.ts index 27fefd2402..85cadd9f15 100644 --- a/src/Discovery/Utils/Search/doDebounceSearch.test.ts +++ b/src/Discovery/Utils/Search/doDebounceSearch.test.ts @@ -1,9 +1,9 @@ -import doDebounceSearch from "./doDebounceSearch"; -import doSearchFilterSort from "./doSearchFilterSort"; +import doDebounceSearch from './doDebounceSearch'; +import doSearchFilterSort from './doSearchFilterSort'; -jest.mock("./doSearchFilterSort"); +jest.mock('./doSearchFilterSort'); -describe("doDebounceSearch", () => { +describe('doDebounceSearch', () => { let memoizedDebouncedSearch; let setExecutedSearchesCount; beforeEach(() => { @@ -15,7 +15,7 @@ describe("doDebounceSearch", () => { jest.clearAllMocks(); }); - it("should execute doSearchFilterSort initially without debouncing", () => { + it('should execute doSearchFilterSort initially without debouncing', () => { doDebounceSearch([1, 2, 3], memoizedDebouncedSearch, 0, setExecutedSearchesCount); expect(doSearchFilterSort).toHaveBeenCalledWith(1, 2, 3); expect(memoizedDebouncedSearch).not.toHaveBeenCalled(); @@ -28,7 +28,7 @@ describe("doDebounceSearch", () => { expect(setExecutedSearchesCount).toHaveBeenCalledWith(2); }); - it("should debounce the doSearchFilterSort call when executedSearchesCount >= 2", () => { + it('should debounce the doSearchFilterSort call when executedSearchesCount >= 2', () => { doDebounceSearch([1, 2, 3], memoizedDebouncedSearch, 2, setExecutedSearchesCount); expect(doSearchFilterSort).not.toHaveBeenCalled(); expect(memoizedDebouncedSearch).toHaveBeenCalledWith(1, 2, 3); diff --git a/src/Discovery/Utils/Search/doDebounceSearch.tsx b/src/Discovery/Utils/Search/doDebounceSearch.tsx index b150dd8289..13f701c698 100644 --- a/src/Discovery/Utils/Search/doDebounceSearch.tsx +++ b/src/Discovery/Utils/Search/doDebounceSearch.tsx @@ -1,12 +1,11 @@ import doSearchFilterSort from './doSearchFilterSort'; const doDebounceSearch = ( - parametersForDoSearchFilterSort: any[], + parametersForDoSearchFilterSort: {}, memoizedDebouncedSearch: (...args: any[]) => void, executedSearchesCount: number, - setExecutedSearchesCount: (count: number) => void + setExecutedSearchesCount: (count: number) => void, ) => { - const debounceDelayInMilliseconds = 500; const initialSearchesWithoutDebounce = 2; // Execute searches initially without debounce to decrease page load time if (executedSearchesCount < initialSearchesWithoutDebounce) { diff --git a/src/Discovery/Utils/Search/doSearchFilterSort.ts b/src/Discovery/Utils/Search/doSearchFilterSort.ts index 646637b0fb..b4e7badbdd 100644 --- a/src/Discovery/Utils/Search/doSearchFilterSort.ts +++ b/src/Discovery/Utils/Search/doSearchFilterSort.ts @@ -19,24 +19,24 @@ const doSearchFilterSort = (parametersForDoSearchFilterSort) => { filteredResources = filterByTags( filteredResources, props.selectedTags, - config + config, ); if ( - config.features.advSearchFilters && - config.features.advSearchFilters.enabled + config.features.advSearchFilters + && config.features.advSearchFilters.enabled ) { filteredResources = filterByAdvSearch( filteredResources, filterState, config, - filterMultiSelectionLogic + filterMultiSelectionLogic, ); } if (props.config.features.authorization.enabled) { filteredResources = filteredResources.filter( - (resource) => props.accessFilters[resource[accessibleFieldName]] + (resource) => props.accessFilters[resource[accessibleFieldName]], ); } diff --git a/src/Discovery/Utils/Search/filterByAdvSearch.ts b/src/Discovery/Utils/Search/filterByAdvSearch.ts index d0a77a8e69..5e9eedb6dd 100644 --- a/src/Discovery/Utils/Search/filterByAdvSearch.ts +++ b/src/Discovery/Utils/Search/filterByAdvSearch.ts @@ -5,44 +5,23 @@ interface FilterState { } const filterByAdvSearch = (studies: any[], advSearchFilterState: FilterState, config: DiscoveryConfig, filterMultiSelectionLogic: string): any[] => { - // if no filters active, show all studies - const noFiltersActive = Object.values(advSearchFilterState).every((selectedValues) => { - if (Object.values(selectedValues).length === 0) { - return true; - } - if (Object.values(selectedValues).every((selected) => !selected)) { - return true; - } - return false; - }); - if (noFiltersActive) { - return studies; + // if no filters active, show all studies + const noFiltersActive = Object.values(advSearchFilterState).every((selectedValues) => { + if (Object.values(selectedValues).length === 0) { + return true; } - - // Combine within filters as AND - if (filterMultiSelectionLogic === 'AND') { - return studies.filter((study) => Object.keys(advSearchFilterState).every((filterName) => { - const filterValues = Object.keys(advSearchFilterState[filterName]); - // Handle the edge case where no values in this filter are selected - if (filterValues.length === 0) { - return true; - } - if (!config.features.advSearchFilters) { - return false; - } - const studyFilters = study[config.features.advSearchFilters.field]; - if (!studyFilters || !studyFilters.length) { - return false; - } - - const studyFilterValues = studyFilters.filter(({ key }) => key === filterName) - .map(({ value }) => value); - return filterValues.every((value) => studyFilterValues.includes(value)); - })); + if (Object.values(selectedValues).every((selected) => !selected)) { + return true; } + return false; + }); + if (noFiltersActive) { + return studies; + } - // Combine within filters as OR - return studies.filter((study) => Object.keys(advSearchFilterState).some((filterName) => { + // Combine within filters as AND + if (filterMultiSelectionLogic === 'AND') { + return studies.filter((study) => Object.keys(advSearchFilterState).every((filterName) => { const filterValues = Object.keys(advSearchFilterState[filterName]); // Handle the edge case where no values in this filter are selected if (filterValues.length === 0) { @@ -56,8 +35,29 @@ const filterByAdvSearch = (studies: any[], advSearchFilterState: FilterState, co return false; } - return studyFilters.some(({ key, value }) => key === filterName && filterValues.includes(value)); + const studyFilterValues = studyFilters.filter(({ key }) => key === filterName) + .map(({ value }) => value); + return filterValues.every((value) => studyFilterValues.includes(value)); })); - }; + } + + // Combine within filters as OR + return studies.filter((study) => Object.keys(advSearchFilterState).some((filterName) => { + const filterValues = Object.keys(advSearchFilterState[filterName]); + // Handle the edge case where no values in this filter are selected + if (filterValues.length === 0) { + return true; + } + if (!config.features.advSearchFilters) { + return false; + } + const studyFilters = study[config.features.advSearchFilters.field]; + if (!studyFilters || !studyFilters.length) { + return false; + } + + return studyFilters.some(({ key, value }) => key === filterName && filterValues.includes(value)); + })); +}; - export default filterByAdvSearch; +export default filterByAdvSearch; diff --git a/src/Discovery/Utils/Search/filterByTags.ts b/src/Discovery/Utils/Search/filterByTags.ts index 8018a62d19..3f1c125f23 100644 --- a/src/Discovery/Utils/Search/filterByTags.ts +++ b/src/Discovery/Utils/Search/filterByTags.ts @@ -1,12 +1,12 @@ import { DiscoveryConfig } from '../../DiscoveryConfig'; const filterByTags = (studies: any[], selectedTags: any, config: DiscoveryConfig): any[] => { - // if no tags selected, show all studies - if (Object.values(selectedTags).every((selected) => !selected)) { - return studies; - } - const tagField = config.minimalFieldMapping.tagsListFieldName; - return studies.filter((study) => study[tagField]?.some((tag) => selectedTags[tag.name])); - }; + // if no tags selected, show all studies + if (Object.values(selectedTags).every((selected) => !selected)) { + return studies; + } + const tagField = config.minimalFieldMapping.tagsListFieldName; + return studies.filter((study) => study[tagField]?.some((tag) => selectedTags[tag.name])); +}; - export default filterByTags; +export default filterByTags; From 1b900cd28a35b384fbe75c4c87404cb5a3d004c8 Mon Sep 17 00:00:00 2001 From: Jarvis Raymond Date: Thu, 23 Feb 2023 10:33:45 -0600 Subject: [PATCH 12/17] feat(healSearchDebounce): Fixed TS errors --- src/Discovery/Discovery.tsx | 8 +++----- src/Discovery/Utils/Search/doSearchFilterSort.ts | 15 ++++++++++++++- 2 files changed, 17 insertions(+), 6 deletions(-) diff --git a/src/Discovery/Discovery.tsx b/src/Discovery/Discovery.tsx index e88df3aa62..19c11af376 100644 --- a/src/Discovery/Discovery.tsx +++ b/src/Discovery/Discovery.tsx @@ -3,7 +3,7 @@ import React, { } from 'react'; import * as JsSearch from 'js-search'; import { - Tag, Popover, Space, Collapse, Button, Dropdown, Menu, Pagination, Tooltip, + Tag, Popover, Space, Collapse, Button, Dropdown, Pagination, Tooltip, } from 'antd'; import { LockOutlined, @@ -20,9 +20,7 @@ import { MinusCircleOutlined, } from '@ant-design/icons'; import Checkbox from 'antd/lib/checkbox/Checkbox'; -import MenuItem from 'antd/lib/menu/MenuItem'; import { debounce } from 'lodash'; -import { JsxElement } from 'typescript'; import doDebounceSearch from './Utils/Search/doDebounceSearch'; import { DiscoveryConfig } from './DiscoveryConfig'; import DiscoverySummary from './DiscoverySummary'; @@ -183,7 +181,7 @@ const highlightSearchTerm = (value: string, searchTerm: string, highlighClassNam }; }; -interface FilterState { +export interface FilterState { [key: string]: { [value: string]: boolean } } @@ -193,7 +191,7 @@ export interface DiscoveryResource { tags?: { name: string, category: string }[] } -interface Props { +export interface Props { config: DiscoveryConfig, studies: DiscoveryResource[], studyRegistrationValidationField: string, diff --git a/src/Discovery/Utils/Search/doSearchFilterSort.ts b/src/Discovery/Utils/Search/doSearchFilterSort.ts index b4e7badbdd..d8e2b07fad 100644 --- a/src/Discovery/Utils/Search/doSearchFilterSort.ts +++ b/src/Discovery/Utils/Search/doSearchFilterSort.ts @@ -1,7 +1,20 @@ import filterByTags from './filterByTags'; import filterByAdvSearch from './filterByAdvSearch'; +import { Props, FilterState, AccessSortDirection } from '../../Discovery'; +import { DiscoveryConfig } from '../../DiscoveryConfig'; -const doSearchFilterSort = (parametersForDoSearchFilterSort) => { +interface ParametersForDoSearchFilterSort { + props: Props, + jsSearch: any, + config: DiscoveryConfig, + setVisibleResources: (...args: any[]) => void, + filterState: FilterState, + filterMultiSelectionLogic: string, + accessibleFieldName: string, + AccessSortDirection: AccessSortDirection, + +} +const doSearchFilterSort = (parametersForDoSearchFilterSort: ParametersForDoSearchFilterSort) => { const { props, jsSearch, From 38540b4a8b71d5380a58bd927e57fea581eb37c3 Mon Sep 17 00:00:00 2001 From: Jarvis Raymond Date: Thu, 23 Feb 2023 10:52:24 -0600 Subject: [PATCH 13/17] feat(healSearchDebounce): Formatted code --- src/Discovery/Utils/Search/doSearchFilterSort.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Discovery/Utils/Search/doSearchFilterSort.ts b/src/Discovery/Utils/Search/doSearchFilterSort.ts index d8e2b07fad..47fa28cdf0 100644 --- a/src/Discovery/Utils/Search/doSearchFilterSort.ts +++ b/src/Discovery/Utils/Search/doSearchFilterSort.ts @@ -12,8 +12,8 @@ interface ParametersForDoSearchFilterSort { filterMultiSelectionLogic: string, accessibleFieldName: string, AccessSortDirection: AccessSortDirection, - } + const doSearchFilterSort = (parametersForDoSearchFilterSort: ParametersForDoSearchFilterSort) => { const { props, From d98faa65cf91495fdb1ce4a83702e64648ee8178 Mon Sep 17 00:00:00 2001 From: Jarvis Raymond Date: Thu, 23 Feb 2023 13:54:10 -0600 Subject: [PATCH 14/17] feat(healSearchDebounce): Removed old comment --- src/Discovery/Utils/Search/doDebounceSearch.tsx | 1 - 1 file changed, 1 deletion(-) diff --git a/src/Discovery/Utils/Search/doDebounceSearch.tsx b/src/Discovery/Utils/Search/doDebounceSearch.tsx index 13f701c698..1c22ccc6df 100644 --- a/src/Discovery/Utils/Search/doDebounceSearch.tsx +++ b/src/Discovery/Utils/Search/doDebounceSearch.tsx @@ -13,7 +13,6 @@ const doDebounceSearch = ( return doSearchFilterSort(parametersForDoSearchFilterSort); } // Otherwise debounce the calls - // return debounce(doSearchFilterSort, debounceDelayInMilliseconds); return memoizedDebouncedSearch(parametersForDoSearchFilterSort); }; export default doDebounceSearch; From df74c73d8339a6328a25faa00821fde6fb2c74e4 Mon Sep 17 00:00:00 2001 From: Jarvis Raymond Date: Thu, 23 Feb 2023 14:22:53 -0600 Subject: [PATCH 15/17] feat(healSearchDebounce): Refactored test to use a test object --- src/Discovery/Utils/Search/doDebounceSearch.test.ts | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/src/Discovery/Utils/Search/doDebounceSearch.test.ts b/src/Discovery/Utils/Search/doDebounceSearch.test.ts index 85cadd9f15..afcae0f215 100644 --- a/src/Discovery/Utils/Search/doDebounceSearch.test.ts +++ b/src/Discovery/Utils/Search/doDebounceSearch.test.ts @@ -16,22 +16,22 @@ describe('doDebounceSearch', () => { }); it('should execute doSearchFilterSort initially without debouncing', () => { - doDebounceSearch([1, 2, 3], memoizedDebouncedSearch, 0, setExecutedSearchesCount); - expect(doSearchFilterSort).toHaveBeenCalledWith(1, 2, 3); + doDebounceSearch({test:"test"}, memoizedDebouncedSearch, 0, setExecutedSearchesCount); + expect(doSearchFilterSort).toHaveBeenCalledWith({test:"test"}); expect(memoizedDebouncedSearch).not.toHaveBeenCalled(); expect(setExecutedSearchesCount).toHaveBeenCalledWith(1); jest.clearAllMocks(); - doDebounceSearch([4, 5, 6], memoizedDebouncedSearch, 1, setExecutedSearchesCount); - expect(doSearchFilterSort).toHaveBeenCalledWith(4, 5, 6); + doDebounceSearch({test:"test2"}, memoizedDebouncedSearch, 1, setExecutedSearchesCount); + expect(doSearchFilterSort).toHaveBeenCalledWith({test:"test2"}); expect(memoizedDebouncedSearch).not.toHaveBeenCalled(); expect(setExecutedSearchesCount).toHaveBeenCalledWith(2); }); it('should debounce the doSearchFilterSort call when executedSearchesCount >= 2', () => { - doDebounceSearch([1, 2, 3], memoizedDebouncedSearch, 2, setExecutedSearchesCount); + doDebounceSearch({test:"test3"}, memoizedDebouncedSearch, 2, setExecutedSearchesCount); expect(doSearchFilterSort).not.toHaveBeenCalled(); - expect(memoizedDebouncedSearch).toHaveBeenCalledWith(1, 2, 3); + expect(memoizedDebouncedSearch).toHaveBeenCalledWith({test:"test3"}); expect(setExecutedSearchesCount).not.toHaveBeenCalled(); }); }); From 1ab5a85f36f33622a0333f6fa0701c57cf5adc68 Mon Sep 17 00:00:00 2001 From: Jarvis Raymond Date: Thu, 9 Mar 2023 08:41:26 -0600 Subject: [PATCH 16/17] feat(healSearchDebounce): Removed duplicated code, added import for FilterState in doSearchFilterSort.ts --- src/Discovery/Utils/Search/filterByAdvSearch.ts | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/src/Discovery/Utils/Search/filterByAdvSearch.ts b/src/Discovery/Utils/Search/filterByAdvSearch.ts index 5e9eedb6dd..7b16506927 100644 --- a/src/Discovery/Utils/Search/filterByAdvSearch.ts +++ b/src/Discovery/Utils/Search/filterByAdvSearch.ts @@ -1,8 +1,5 @@ import { DiscoveryConfig } from '../../DiscoveryConfig'; - -interface FilterState { - [key: string]: { [value: string]: boolean } - } +import { FilterState } from '../../Discovery'; const filterByAdvSearch = (studies: any[], advSearchFilterState: FilterState, config: DiscoveryConfig, filterMultiSelectionLogic: string): any[] => { // if no filters active, show all studies From 5940e63cc100a5613a4cc13d8f74478bb5651fbf Mon Sep 17 00:00:00 2001 From: Jarvis Raymond Date: Thu, 9 Mar 2023 09:17:59 -0600 Subject: [PATCH 17/17] feat(healSearchDebounce): ran eslint and fixed imports for doSearchFilterSort --- src/Discovery/Utils/Search/doDebounceSearch.test.ts | 12 ++++++------ src/Discovery/Utils/Search/doSearchFilterSort.ts | 1 - 2 files changed, 6 insertions(+), 7 deletions(-) diff --git a/src/Discovery/Utils/Search/doDebounceSearch.test.ts b/src/Discovery/Utils/Search/doDebounceSearch.test.ts index afcae0f215..a52a73bf25 100644 --- a/src/Discovery/Utils/Search/doDebounceSearch.test.ts +++ b/src/Discovery/Utils/Search/doDebounceSearch.test.ts @@ -16,22 +16,22 @@ describe('doDebounceSearch', () => { }); it('should execute doSearchFilterSort initially without debouncing', () => { - doDebounceSearch({test:"test"}, memoizedDebouncedSearch, 0, setExecutedSearchesCount); - expect(doSearchFilterSort).toHaveBeenCalledWith({test:"test"}); + doDebounceSearch({ test: 'test' }, memoizedDebouncedSearch, 0, setExecutedSearchesCount); + expect(doSearchFilterSort).toHaveBeenCalledWith({ test: 'test' }); expect(memoizedDebouncedSearch).not.toHaveBeenCalled(); expect(setExecutedSearchesCount).toHaveBeenCalledWith(1); jest.clearAllMocks(); - doDebounceSearch({test:"test2"}, memoizedDebouncedSearch, 1, setExecutedSearchesCount); - expect(doSearchFilterSort).toHaveBeenCalledWith({test:"test2"}); + doDebounceSearch({ test: 'test2' }, memoizedDebouncedSearch, 1, setExecutedSearchesCount); + expect(doSearchFilterSort).toHaveBeenCalledWith({ test: 'test2' }); expect(memoizedDebouncedSearch).not.toHaveBeenCalled(); expect(setExecutedSearchesCount).toHaveBeenCalledWith(2); }); it('should debounce the doSearchFilterSort call when executedSearchesCount >= 2', () => { - doDebounceSearch({test:"test3"}, memoizedDebouncedSearch, 2, setExecutedSearchesCount); + doDebounceSearch({ test: 'test3' }, memoizedDebouncedSearch, 2, setExecutedSearchesCount); expect(doSearchFilterSort).not.toHaveBeenCalled(); - expect(memoizedDebouncedSearch).toHaveBeenCalledWith({test:"test3"}); + expect(memoizedDebouncedSearch).toHaveBeenCalledWith({ test: 'test3' }); expect(setExecutedSearchesCount).not.toHaveBeenCalled(); }); }); diff --git a/src/Discovery/Utils/Search/doSearchFilterSort.ts b/src/Discovery/Utils/Search/doSearchFilterSort.ts index 47fa28cdf0..1343f83dbc 100644 --- a/src/Discovery/Utils/Search/doSearchFilterSort.ts +++ b/src/Discovery/Utils/Search/doSearchFilterSort.ts @@ -23,7 +23,6 @@ const doSearchFilterSort = (parametersForDoSearchFilterSort: ParametersForDoSear filterState, filterMultiSelectionLogic, accessibleFieldName, - AccessSortDirection, } = parametersForDoSearchFilterSort; let filteredResources = props.studies; if (jsSearch && props.searchTerm) {