Skip to content

Commit da34484

Browse files
committed
fix(ga): issue #606 - search inconsistent
1 parent 78eb4d3 commit da34484

File tree

9 files changed

+1420
-208
lines changed

9 files changed

+1420
-208
lines changed

package.json

+1-1
Original file line numberDiff line numberDiff line change
@@ -25,7 +25,7 @@
2525
"jest": "29.7.0",
2626
"jest-sonar": "0.2.16",
2727
"prettier": "3.3.3",
28-
"pretty-quick": "3.3.1",
28+
"pretty-quick": "4.0.0",
2929
"rimraf": "5.0.10",
3030
"ts-jest": "29.2.4",
3131
"ts-node": "10.9.2",

packages/core/package.json

+3-3
Original file line numberDiff line numberDiff line change
@@ -21,10 +21,10 @@
2121
"watch": "tsc --watch"
2222
},
2323
"dependencies": {
24-
"@sap/bas-sdk": "3.8.8",
24+
"@sap/bas-sdk": "3.8.9",
2525
"@sap/guided-answers-extension-types": "workspace:*",
26-
"axios": "1.6.8",
27-
"xss": "1.0.14"
26+
"axios": "1.7.4",
27+
"xss": "1.0.15"
2828
},
2929
"files": [
3030
"LICENSE",

packages/core/src/guided-answers-api.ts

+1
Original file line numberDiff line numberDiff line change
@@ -173,6 +173,7 @@ async function getTrees(host: string, queryOptions?: GuidedAnswersQueryOptions):
173173
const url = `${host}${TREE_PATH}${query}${urlGetParamString}`;
174174
const response: AxiosResponse<GuidedAnswerTreeSearchResult> = await axios.get<GuidedAnswerTreeSearchResult>(url);
175175
const searchResult = response.data;
176+
176177
if (!Array.isArray(searchResult?.trees)) {
177178
throw Error(
178179
`Query result from call '${url}' does not contain property 'trees' as array. Received response: '${searchResult}'`

packages/ide-extension/package.json

+6-6
Original file line numberDiff line numberDiff line change
@@ -82,13 +82,13 @@
8282
"devDependencies": {
8383
"@sap/guided-answers-extension-core": "workspace:*",
8484
"@sap/guided-answers-extension-types": "workspace:*",
85-
"@types/uuid": "9.0.7",
86-
"@types/vscode": "1.74.1",
87-
"@vscode/vsce": "2.22.0",
88-
"applicationinsights": "2.9.2",
89-
"esbuild": "0.19.11",
85+
"@types/uuid": "10.0.0",
86+
"@types/vscode": "1.92.0",
87+
"@vscode/vsce": "3.0.0",
88+
"applicationinsights": "3.2.2",
89+
"esbuild": "0.23.1",
9090
"esbuild-plugin-copy": "2.1.1",
91-
"uuid": "9.0.1",
91+
"uuid": "10.0.0",
9292
"vscode-uri": "3.0.8"
9393
},
9494
"galleryBanner": {

packages/webapp/package.json

+2-2
Original file line numberDiff line numberDiff line change
@@ -45,14 +45,14 @@
4545
"react-redux": "8.1.2",
4646
"redux": "4.2.1",
4747
"redux-mock-store": "1.5.4",
48-
"uuid": "9.0.1"
48+
"uuid": "10.0.0"
4949
},
5050
"dependencies": {
5151
"@fluentui/react": "8.114.2",
5252
"@fluentui/react-focus": "8.8.37",
5353
"@fluentui/style-utilities": "8.10.1",
5454
"@fluentui/utilities": "8.13.23",
55-
"@sap-ux/ui-components": "1.15.12",
55+
"@sap-ux/ui-components": "1.17.5",
5656
"react-copy-to-clipboard": "5.1.0",
5757
"react-infinite-scroll-component": "6.1.0"
5858
}

packages/webapp/src/webview/state/reducers.ts

+1
Original file line numberDiff line numberDiff line change
@@ -145,6 +145,7 @@ function updateGuidedAnswerTreesReducer(newState: AppState, action: UpdateGuided
145145
}
146146
delete newState.activeGuidedAnswer;
147147
newState.activeScreen = 'SEARCH';
148+
148149
return newState;
149150
}
150151

packages/webapp/src/webview/ui/components/App/App.tsx

+23-12
Original file line numberDiff line numberDiff line change
@@ -1,21 +1,25 @@
11
import type { ReactElement } from 'react';
2-
import React, { useEffect } from 'react';
2+
import React, { useEffect, useState } from 'react';
33
import { useSelector } from 'react-redux';
4+
import i18next from 'i18next';
5+
6+
import InfiniteScroll from 'react-infinite-scroll-component';
7+
import { SpinnerSize } from '@fluentui/react';
8+
import { FocusZone, FocusZoneDirection } from '@fluentui/react-focus';
9+
import { initIcons, UILoader, UIIcon, UiIcons } from '@sap-ux/ui-components';
10+
411
import type { AppState } from '../../../types';
512
import { actions } from '../../../state';
13+
614
import { GuidedAnswerNode } from '../GuidedAnswerNode';
715
import { Header } from '../Header';
816
import { ErrorScreen } from '../ErrorScreen';
917
import { FiltersRibbon } from '../Header/Filters';
10-
import { FocusZone, FocusZoneDirection } from '@fluentui/react-focus';
11-
import './App.scss';
12-
import { initIcons, UILoader, UIIcon, UiIcons } from '@sap-ux/ui-components';
13-
import InfiniteScroll from 'react-infinite-scroll-component';
14-
import { SpinnerSize } from '@fluentui/react';
15-
import i18next from 'i18next';
1618
import { TreeItemBottomSection } from '../TreeItemBottomSection';
1719
import { HomeGrid } from '../HomeGrid';
1820

21+
import './App.scss';
22+
1923
initIcons();
2024

2125
/**
@@ -25,6 +29,8 @@ initIcons();
2529
*/
2630
export function App(): ReactElement {
2731
const appState = useSelector<AppState, AppState>((state) => state);
32+
const [hasMore, setHasMore] = useState(true);
33+
2834
useEffect(() => {
2935
const resultsContainer = document.getElementById('results-container');
3036
if (!resultsContainer) {
@@ -50,8 +56,16 @@ export function App(): ReactElement {
5056
};
5157
}, []);
5258

59+
useEffect(() => {
60+
// appState.pageSize
61+
62+
const isMore =
63+
appState.guidedAnswerTreeSearchResult.trees.length < appState.guidedAnswerTreeSearchResult.resultSize;
64+
setHasMore(isMore);
65+
}, [appState.guidedAnswerTreeSearchResult.trees]);
66+
5367
function fetchData() {
54-
if (appState.guidedAnswerTreeSearchResult.resultSize > appState.pageSize) {
68+
if (hasMore) {
5569
actions.searchTree({
5670
query: appState.query,
5771
filters: {
@@ -97,10 +111,7 @@ export function App(): ReactElement {
97111
dataLength={appState.guidedAnswerTreeSearchResult.trees.length} //This is important field to render the next data
98112
next={fetchData}
99113
loader={<UILoader id="loading-indicator" size={SpinnerSize.large} />}
100-
hasMore={
101-
appState.guidedAnswerTreeSearchResult.trees.length <
102-
appState.guidedAnswerTreeSearchResult.resultSize
103-
}>
114+
hasMore={hasMore}>
104115
{appState.guidedAnswerTreeSearchResult.trees.map((tree) => {
105116
return (
106117
<li key={`tree-item-${tree.TITLE}`} className="tree-item">

packages/webapp/src/webview/ui/components/Header/SearchField/SearchField.tsx

+44-22
Original file line numberDiff line numberDiff line change
@@ -1,35 +1,57 @@
1-
import React from 'react';
1+
import React, { useCallback } from 'react';
2+
import type { ChangeEvent } from 'react';
23
import { useSelector } from 'react-redux';
3-
import type { AppState } from '../../../../types';
4-
import { actions } from '../../../../state';
4+
55
import { UISearchBox } from '@sap-ux/ui-components';
66

7+
import type { AppState } from '../../../../types';
8+
import { actions } from '../../../../state';
79
import { Filters } from '../Filters';
810

9-
let timer: NodeJS.Timeout;
11+
const SEARCH_TIMEOUT = 250;
12+
1013
/**
1114
*
1215
* @returns An input field
1316
*/
1417
export function SearchField() {
1518
const appState = useSelector<AppState, AppState>((state) => state);
1619

17-
const onChange = (value: string): void => {
18-
clearTimeout(timer);
19-
actions.setQueryValue(value);
20-
timer = setTimeout(() => {
21-
actions.searchTree({
22-
query: value,
23-
filters: {
24-
product: appState.selectedProductFilters,
25-
component: appState.selectedComponentFilters
26-
},
27-
paging: {
28-
responseSize: appState.pageSize,
29-
offset: 0
30-
}
31-
});
32-
}, 100);
20+
const debounce = (fn: Function, delay = SEARCH_TIMEOUT) => {
21+
let timeoutId: ReturnType<typeof setTimeout>;
22+
return function (this: any, ...args: any[]) {
23+
clearTimeout(timeoutId);
24+
timeoutId = setTimeout(() => fn.apply(this, args), delay);
25+
};
26+
};
27+
28+
const debounceSearch = useCallback(
29+
debounce(
30+
(newSearchTerm: string) =>
31+
actions.searchTree({
32+
query: newSearchTerm,
33+
filters: {
34+
product: appState.selectedProductFilters,
35+
component: appState.selectedComponentFilters
36+
},
37+
paging: {
38+
responseSize: appState.pageSize,
39+
offset: 0
40+
}
41+
}),
42+
SEARCH_TIMEOUT
43+
),
44+
[]
45+
);
46+
47+
const onClearSearchTerm = (): void => {
48+
actions.setQueryValue('');
49+
debounceSearch('');
50+
};
51+
52+
const onChangeSearchTerm = (_?: ChangeEvent<HTMLInputElement> | undefined, newSearchTerm = ''): void => {
53+
actions.setQueryValue(newSearchTerm);
54+
debounceSearch(newSearchTerm);
3355
};
3456

3557
return (
@@ -40,8 +62,8 @@ export function SearchField() {
4062
readOnly={appState.networkStatus === 'LOADING'}
4163
placeholder="Search Guided Answers"
4264
id="search-field"
43-
onClear={() => onChange('')}
44-
onChange={(e: any) => onChange(e?.target?.value || '')}></UISearchBox>
65+
onClear={onClearSearchTerm}
66+
onChange={onChangeSearchTerm}></UISearchBox>
4567
{appState.activeScreen === 'SEARCH' && <Filters />}
4668
</div>
4769
);

0 commit comments

Comments
 (0)