@salesforcedevs/dx-components 1.28.6 → 1.28.7-alpha.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@salesforcedevs/dx-components",
|
|
3
|
-
"version": "1.28.
|
|
3
|
+
"version": "1.28.7-alpha.0",
|
|
4
4
|
"description": "DX Lightning web components",
|
|
5
5
|
"license": "MIT",
|
|
6
6
|
"engines": {
|
|
@@ -44,5 +44,5 @@
|
|
|
44
44
|
"luxon": "3.4.4",
|
|
45
45
|
"msw": "^2.12.4"
|
|
46
46
|
},
|
|
47
|
-
"gitHead": "
|
|
47
|
+
"gitHead": "fd19dde09113f8458a649b7f5e27fac4db3d2bb5"
|
|
48
48
|
}
|
|
@@ -48,10 +48,6 @@
|
|
|
48
48
|
<dx-sidebar-search
|
|
49
49
|
onchange={onSearchChange}
|
|
50
50
|
onloading={onSearchLoading}
|
|
51
|
-
coveo-organization-id={coveoOrganizationId}
|
|
52
|
-
coveo-public-access-token={coveoPublicAccessToken}
|
|
53
|
-
coveo-search-hub={coveoSearchHub}
|
|
54
|
-
coveo-advanced-query-config={coveoAdvancedQueryConfig}
|
|
55
51
|
></dx-sidebar-search>
|
|
56
52
|
</div>
|
|
57
53
|
<slot name="version-picker"></slot>
|
|
@@ -1,18 +1,18 @@
|
|
|
1
1
|
import cx from "classnames";
|
|
2
2
|
import { api, track } from "lwc";
|
|
3
3
|
import { TreeNode, SidebarSearchResult } from "typings/custom";
|
|
4
|
-
import { getSidebarSearchParams } from "dxUtils/coveo";
|
|
5
4
|
import { toJson } from "dxUtils/normalizers";
|
|
6
5
|
import SidebarSearch from "dx/sidebarSearch";
|
|
7
6
|
import { SidebarBase } from "dxBaseElements/sidebarBase";
|
|
8
7
|
|
|
9
8
|
const MOBILE_SIZE_MATCH = "768px";
|
|
10
9
|
|
|
10
|
+
const getSearchQueryParam = (): string | null =>
|
|
11
|
+
typeof window !== "undefined"
|
|
12
|
+
? new URLSearchParams(window.location.search).get("q")
|
|
13
|
+
: null;
|
|
14
|
+
|
|
11
15
|
export default class Sidebar extends SidebarBase {
|
|
12
|
-
@api coveoOrganizationId!: string;
|
|
13
|
-
@api coveoPublicAccessToken!: string;
|
|
14
|
-
@api coveoSearchHub!: string;
|
|
15
|
-
@api coveoAdvancedQueryConfig!: string;
|
|
16
16
|
@api header: string = "";
|
|
17
17
|
|
|
18
18
|
@api
|
|
@@ -130,7 +130,7 @@ export default class Sidebar extends SidebarBase {
|
|
|
130
130
|
constructor() {
|
|
131
131
|
super();
|
|
132
132
|
|
|
133
|
-
if (
|
|
133
|
+
if (getSearchQueryParam()) {
|
|
134
134
|
this.isSearchLoading = true;
|
|
135
135
|
this.scrollToSelectedSearchResult = true;
|
|
136
136
|
}
|
|
@@ -175,7 +175,7 @@ export default class Sidebar extends SidebarBase {
|
|
|
175
175
|
this.isSearchLoading = e.detail;
|
|
176
176
|
}
|
|
177
177
|
|
|
178
|
-
private onSidebarSearchContentScroll(scrollEvent) {
|
|
178
|
+
private onSidebarSearchContentScroll(scrollEvent: Event) {
|
|
179
179
|
if (this.isSearchLoading) {
|
|
180
180
|
return;
|
|
181
181
|
}
|
|
@@ -1,75 +1,42 @@
|
|
|
1
1
|
import { LightningElement, api } from "lwc";
|
|
2
2
|
import debounce from "debounce";
|
|
3
|
-
import {
|
|
4
|
-
Result,
|
|
5
|
-
ResultList,
|
|
6
|
-
Unsubscribe,
|
|
7
|
-
ResultsPerPage,
|
|
8
|
-
SearchBox,
|
|
9
|
-
buildInteractiveResult,
|
|
10
|
-
buildResultList,
|
|
11
|
-
buildResultsPerPage,
|
|
12
|
-
buildSearchBox,
|
|
13
|
-
loadAdvancedSearchQueryActions,
|
|
14
|
-
SearchEngine,
|
|
15
|
-
SearchAppState,
|
|
16
|
-
loadQueryActions
|
|
17
|
-
} from "@coveo/headless";
|
|
18
|
-
import { buildSearchEngine, getSidebarSearchParams } from "dxUtils/coveo";
|
|
19
3
|
import { RecentSearches } from "dxUtils/recentSearches";
|
|
20
|
-
import { toJson } from "dxUtils/normalizers";
|
|
21
4
|
import {
|
|
22
5
|
Option,
|
|
23
6
|
PopoverRequestCloseType,
|
|
24
7
|
SidebarSearchResult
|
|
25
8
|
} from "typings/custom";
|
|
26
9
|
|
|
27
|
-
const RESULT_CLICK_LOCAL_STORAGE_KEY = "dx-sidebar-search-result-click";
|
|
28
|
-
export const SESSION_KEY = "dx-sidebar-search-state";
|
|
29
|
-
|
|
30
|
-
const DEFAULT_RESULT_COUNT = 20;
|
|
31
10
|
const SEARCH_DEBOUNCE_DELAY = 1200;
|
|
11
|
+
const DATA_CLOUD_SEARCH_PATH = "/data-cloud-search/search";
|
|
32
12
|
|
|
33
13
|
const UserRecentSearches = new RecentSearches();
|
|
34
14
|
|
|
35
|
-
const
|
|
36
|
-
|
|
15
|
+
const getSearchQueryParam = (): string =>
|
|
16
|
+
new URLSearchParams(window.location.search).get("q") ?? "";
|
|
17
|
+
|
|
18
|
+
/**
|
|
19
|
+
* Returns the current page base URL without the last path segment.
|
|
20
|
+
* e.g. https://developer.salesforce.com/docs/atlas.en-us.apexcode.meta/apexcode/apex_dev_guide.htm
|
|
21
|
+
* -> https://developer.salesforce.com/docs/atlas.en-us.apexcode.meta/apexcode
|
|
22
|
+
*/
|
|
23
|
+
const getBaseUrlPath = (): string => {
|
|
24
|
+
const url = window.location.origin + window.location.pathname;
|
|
25
|
+
const lastSlash = url.lastIndexOf("/");
|
|
26
|
+
return lastSlash > 0 ? url.substring(0, lastSlash) : url;
|
|
27
|
+
};
|
|
28
|
+
|
|
29
|
+
/** Data Cloud Search API result item (title, url, matchedText) */
|
|
30
|
+
interface DataCloudSearchResultItem {
|
|
31
|
+
title?: string;
|
|
32
|
+
url?: string;
|
|
33
|
+
matchedText?: string;
|
|
34
|
+
}
|
|
37
35
|
|
|
38
36
|
export default class SidebarSearch extends LightningElement {
|
|
39
|
-
@api coveoOrganizationId!: string;
|
|
40
|
-
@api coveoPublicAccessToken!: string;
|
|
41
|
-
@api coveoSearchHub!: string;
|
|
42
|
-
@api
|
|
43
|
-
get coveoAdvancedQueryConfig(): { [key: string]: any } {
|
|
44
|
-
return this._coveoAdvancedQueryConfig;
|
|
45
|
-
}
|
|
46
|
-
set coveoAdvancedQueryConfig(value) {
|
|
47
|
-
const jsonValue = toJson(value);
|
|
48
|
-
const hasChanged =
|
|
49
|
-
this._coveoAdvancedQueryConfig &&
|
|
50
|
-
Object.entries(jsonValue).some(
|
|
51
|
-
([key, val]: [string, any]) =>
|
|
52
|
-
this._coveoAdvancedQueryConfig[key] !== val
|
|
53
|
-
);
|
|
54
|
-
this._coveoAdvancedQueryConfig = jsonValue;
|
|
55
|
-
|
|
56
|
-
if (hasChanged && this.engine && this.value !== "") {
|
|
57
|
-
this.dispatchOnLoading(true);
|
|
58
|
-
}
|
|
59
|
-
|
|
60
|
-
if (hasChanged && this.engine) {
|
|
61
|
-
// set advanced filters needs access to the latest coveoAdvancedQueryConfig
|
|
62
|
-
this.setAdvancedFilters(this.engine);
|
|
63
|
-
this.submitSearch(true);
|
|
64
|
-
}
|
|
65
|
-
}
|
|
66
|
-
|
|
67
37
|
@api
|
|
68
38
|
public fetchMoreResults() {
|
|
69
|
-
|
|
70
|
-
this.fetchingMoreResults = true;
|
|
71
|
-
this.resultList.fetchMoreResults();
|
|
72
|
-
}
|
|
39
|
+
// Data Cloud Search API does not expose pagination in the same way; no-op
|
|
73
40
|
}
|
|
74
41
|
|
|
75
42
|
@api
|
|
@@ -85,313 +52,98 @@ export default class SidebarSearch extends LightningElement {
|
|
|
85
52
|
this.dropdownRequestedOpen = value;
|
|
86
53
|
}
|
|
87
54
|
|
|
88
|
-
private _coveoAdvancedQueryConfig!: { [key: string]: any };
|
|
89
55
|
private dropdownRequestedOpen: boolean = false;
|
|
90
56
|
private recentSearches: Option[] = [];
|
|
91
|
-
private
|
|
92
|
-
private resultList: ResultList | null = null;
|
|
93
|
-
private resultsPerPage: ResultsPerPage | null = null;
|
|
94
|
-
private preloadedState?: SearchAppState;
|
|
95
|
-
private searchBox: SearchBox | null = null;
|
|
96
|
-
private value?: string = "";
|
|
97
|
-
private engine: SearchEngine | null = null;
|
|
98
|
-
private fetchingMoreResults: boolean = false;
|
|
57
|
+
private value: string = "";
|
|
99
58
|
private didRender = false;
|
|
100
|
-
|
|
101
|
-
private get hasCorrectCoveoConfig(): boolean {
|
|
102
|
-
const coveoConfigurations = [
|
|
103
|
-
this.coveoOrganizationId,
|
|
104
|
-
this.coveoPublicAccessToken,
|
|
105
|
-
this.coveoSearchHub,
|
|
106
|
-
this.coveoAdvancedQueryConfig
|
|
107
|
-
];
|
|
108
|
-
|
|
109
|
-
return coveoConfigurations.every(
|
|
110
|
-
(val) =>
|
|
111
|
-
!!val && (typeof val === "string" || typeof val === "object")
|
|
112
|
-
);
|
|
113
|
-
}
|
|
59
|
+
private dataCloudSearchInitialized: boolean = false;
|
|
114
60
|
|
|
115
61
|
private get isDropdownOpen() {
|
|
116
62
|
return (
|
|
117
63
|
this.dropdownRequestedOpen &&
|
|
118
|
-
this.recentSearches &&
|
|
119
|
-
this.recentSearches.length > 0 &&
|
|
64
|
+
this.recentSearches?.length > 0 &&
|
|
120
65
|
!this.value
|
|
121
66
|
);
|
|
122
67
|
}
|
|
123
68
|
|
|
124
69
|
constructor() {
|
|
125
70
|
super();
|
|
126
|
-
|
|
127
71
|
this.updateRecentSearches();
|
|
128
|
-
this.value =
|
|
129
|
-
}
|
|
130
|
-
|
|
131
|
-
disconnectedCallback() {
|
|
132
|
-
this.unsubscribeFromResultList();
|
|
72
|
+
this.value = getSearchQueryParam();
|
|
133
73
|
}
|
|
134
74
|
|
|
135
75
|
renderedCallback() {
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
this.initializeUserSession();
|
|
141
|
-
this.initializeCoveo();
|
|
142
|
-
} else if (!this.hasCorrectCoveoConfig) {
|
|
143
|
-
console.error(
|
|
144
|
-
"Incorrect coveo search configuration provided. All coveo configuration attributes must be defined.",
|
|
145
|
-
{
|
|
146
|
-
coveoOrganizationId: this.coveoOrganizationId,
|
|
147
|
-
coveoPublicAccessToken: this.coveoPublicAccessToken,
|
|
148
|
-
coveoSearchHub: this.coveoSearchHub,
|
|
149
|
-
coveoAdvancedQueryConfig: this.coveoAdvancedQueryConfig
|
|
150
|
-
}
|
|
151
|
-
);
|
|
152
|
-
}
|
|
153
|
-
|
|
154
|
-
// If this is the first render and there is a search value, trigger
|
|
155
|
-
// term highlighting
|
|
156
|
-
if (!this.didRender && this.value) {
|
|
157
|
-
this.dispatchHighlightedTermChange();
|
|
158
|
-
}
|
|
159
|
-
|
|
160
|
-
this.didRender = true;
|
|
161
|
-
}
|
|
162
|
-
|
|
163
|
-
private initializeUserSession() {
|
|
164
|
-
const stringified = window.sessionStorage.getItem(SESSION_KEY);
|
|
165
|
-
|
|
166
|
-
if (!stringified) {
|
|
167
|
-
return;
|
|
168
|
-
}
|
|
169
|
-
|
|
170
|
-
try {
|
|
171
|
-
const json = JSON.parse(stringified);
|
|
172
|
-
|
|
173
|
-
const hasSameConfig = Object.entries(
|
|
174
|
-
json.coveoAdvancedQueryConfig
|
|
175
|
-
).every(
|
|
176
|
-
([key, value]: [string, any]) =>
|
|
177
|
-
this.coveoAdvancedQueryConfig[key] === value
|
|
178
|
-
);
|
|
179
|
-
const hasSameQuery = json?.state?.query?.q === this.value;
|
|
180
|
-
|
|
181
|
-
if (hasSameConfig && hasSameQuery) {
|
|
182
|
-
this.preloadedState = json?.state;
|
|
183
|
-
} else {
|
|
184
|
-
window.sessionStorage.removeItem(SESSION_KEY);
|
|
76
|
+
if (!this.dataCloudSearchInitialized) {
|
|
77
|
+
this.dataCloudSearchInitialized = true;
|
|
78
|
+
if (!this.didRender && this.value) {
|
|
79
|
+
this.dispatchHighlightedTermChange();
|
|
185
80
|
}
|
|
186
|
-
|
|
187
|
-
console.error(e);
|
|
188
|
-
window.sessionStorage.removeItem(SESSION_KEY);
|
|
189
|
-
}
|
|
190
|
-
}
|
|
191
|
-
|
|
192
|
-
private initializeCoveo = () => {
|
|
193
|
-
try {
|
|
194
|
-
this.engine = buildSearchEngine({
|
|
195
|
-
organizationId: this.coveoOrganizationId,
|
|
196
|
-
publicAccessToken: this.coveoPublicAccessToken,
|
|
197
|
-
searchHub: this.coveoSearchHub,
|
|
198
|
-
preloadedState: this.preloadedState
|
|
199
|
-
});
|
|
200
|
-
} catch (ex) {
|
|
201
|
-
console.error(`Coveo engine failed to initialize (${ex})`);
|
|
202
|
-
}
|
|
203
|
-
|
|
204
|
-
if (!this.engine) {
|
|
205
|
-
console.error("Coveo engine failed to initialize!");
|
|
206
|
-
return;
|
|
207
|
-
}
|
|
208
|
-
|
|
209
|
-
if (this.preloadedState) {
|
|
210
|
-
const actions = loadQueryActions(this.engine);
|
|
211
|
-
this.engine.dispatch(actions.updateQuery({ q: this.value || "" }));
|
|
212
|
-
}
|
|
213
|
-
|
|
214
|
-
this.resultList = buildResultList(this.engine, {
|
|
215
|
-
options: { fieldsToInclude: ["sfhtml_url__c"] }
|
|
216
|
-
});
|
|
217
|
-
|
|
218
|
-
this.resultsPerPage = buildResultsPerPage(this.engine, {
|
|
219
|
-
initialState: {
|
|
220
|
-
numberOfResults: DEFAULT_RESULT_COUNT
|
|
221
|
-
}
|
|
222
|
-
});
|
|
223
|
-
|
|
224
|
-
this.searchBox = buildSearchBox(this.engine, {
|
|
225
|
-
options: { numberOfSuggestions: 3 }
|
|
226
|
-
});
|
|
227
|
-
|
|
228
|
-
this.setAdvancedFilters(this.engine);
|
|
229
|
-
|
|
230
|
-
this.unsubscribeFromResultList = this.resultList?.subscribe(
|
|
231
|
-
this.onResultListChange
|
|
232
|
-
);
|
|
233
|
-
|
|
234
|
-
if (this.value) {
|
|
235
|
-
this.dispatchHighlightedTermChange();
|
|
236
|
-
}
|
|
237
|
-
|
|
238
|
-
if (!this.preloadedState) {
|
|
239
|
-
if (this.value) {
|
|
240
|
-
this.submitSearch();
|
|
241
|
-
} else {
|
|
81
|
+
if (!this.value) {
|
|
242
82
|
this.dispatchOnLoading(false);
|
|
243
83
|
}
|
|
244
84
|
}
|
|
245
|
-
|
|
246
|
-
|
|
247
|
-
};
|
|
248
|
-
|
|
249
|
-
private syncAnalytics = () => {
|
|
250
|
-
const storedResult = window.localStorage.getItem(
|
|
251
|
-
RESULT_CLICK_LOCAL_STORAGE_KEY
|
|
252
|
-
);
|
|
253
|
-
if (storedResult) {
|
|
254
|
-
const interactiveResult = buildInteractiveResult(this.engine!, {
|
|
255
|
-
options: { result: JSON.parse(storedResult) }
|
|
256
|
-
});
|
|
257
|
-
interactiveResult.cancelPendingSelect();
|
|
258
|
-
interactiveResult.select();
|
|
259
|
-
window.localStorage.removeItem(RESULT_CLICK_LOCAL_STORAGE_KEY);
|
|
260
|
-
}
|
|
261
|
-
};
|
|
262
|
-
|
|
263
|
-
private onResultListChange = () => {
|
|
264
|
-
if (!this.resultList) {
|
|
265
|
-
return;
|
|
266
|
-
}
|
|
267
|
-
|
|
268
|
-
const { isLoading, firstSearchExecuted, results } =
|
|
269
|
-
this.resultList.state;
|
|
270
|
-
|
|
271
|
-
if ((!firstSearchExecuted && !isLoading) || !this.value) {
|
|
272
|
-
// coveo search is firing off some unwanted payloads on startup
|
|
273
|
-
return;
|
|
274
|
-
}
|
|
275
|
-
|
|
276
|
-
if (!isLoading) {
|
|
277
|
-
this.dispatchOnChangeEvent(results);
|
|
278
|
-
}
|
|
279
|
-
|
|
280
|
-
if (!this.fetchingMoreResults) {
|
|
281
|
-
this.dispatchOnLoading(isLoading);
|
|
282
|
-
}
|
|
283
|
-
|
|
284
|
-
if (!isLoading && this.fetchingMoreResults) {
|
|
285
|
-
this.fetchingMoreResults = false;
|
|
85
|
+
if (!this.didRender && this.value) {
|
|
86
|
+
this.dispatchHighlightedTermChange();
|
|
286
87
|
}
|
|
287
|
-
|
|
288
|
-
|
|
289
|
-
private setAdvancedFilters(engine: SearchEngine) {
|
|
290
|
-
const aq = Object.entries(this.coveoAdvancedQueryConfig).reduce(
|
|
291
|
-
(result, [key, value]) =>
|
|
292
|
-
`${result}(@${key}=="${normalizeCoveoAdvancedQueryValue(
|
|
293
|
-
value
|
|
294
|
-
)}")`,
|
|
295
|
-
""
|
|
296
|
-
);
|
|
297
|
-
|
|
298
|
-
const registerSearchQueryAction = loadAdvancedSearchQueryActions(
|
|
299
|
-
engine
|
|
300
|
-
).registerAdvancedSearchQueries({
|
|
301
|
-
aq: aq
|
|
302
|
-
});
|
|
303
|
-
|
|
304
|
-
engine.dispatch(registerSearchQueryAction);
|
|
88
|
+
this.didRender = true;
|
|
305
89
|
}
|
|
306
90
|
|
|
307
|
-
private
|
|
308
|
-
|
|
309
|
-
|
|
310
|
-
|
|
311
|
-
|
|
312
|
-
|
|
313
|
-
|
|
314
|
-
|
|
315
|
-
|
|
316
|
-
|
|
317
|
-
|
|
318
|
-
// discussion about this normalization here: https://salesforce-internal.slack.com/archives/C020S6784JX/p1639506238376600
|
|
319
|
-
|
|
320
|
-
let pathname, queryParam;
|
|
321
|
-
if (sfhtml_url__c) {
|
|
322
|
-
pathname = `/docs/${sfhtml_url__c}`;
|
|
323
|
-
} else {
|
|
324
|
-
const isNestedGuide = clickUri.includes("/guide/");
|
|
325
|
-
const url = new URL(clickUri);
|
|
326
|
-
const extension =
|
|
327
|
-
isNestedGuide && !url.pathname?.endsWith(".html")
|
|
328
|
-
? ".html"
|
|
329
|
-
: "";
|
|
330
|
-
pathname = `${url.pathname}${extension}`;
|
|
331
|
-
queryParam = url.search;
|
|
332
|
-
}
|
|
333
|
-
|
|
334
|
-
let href;
|
|
335
|
-
let isSelected = false;
|
|
336
|
-
const isReferenceUrl = clickUri.includes("/references/");
|
|
337
|
-
if (isReferenceUrl) {
|
|
338
|
-
if (queryParam) {
|
|
339
|
-
href = `${pathname}${queryParam}&q=${this.value}`;
|
|
340
|
-
} else {
|
|
341
|
-
href = `${pathname}?q=${this.value}`;
|
|
342
|
-
}
|
|
343
|
-
|
|
344
|
-
//NOTE: This is specific to references related comparison
|
|
345
|
-
const resultHrefWithMetaQuery = `${pathname}${queryParam}`;
|
|
346
|
-
|
|
347
|
-
const urlParams = new URLSearchParams(window.location.search);
|
|
348
|
-
const metaQueryParam = urlParams.get("meta");
|
|
349
|
-
|
|
350
|
-
let currentUrlPathWithQuery = window.location.pathname;
|
|
351
|
-
if (metaQueryParam) {
|
|
352
|
-
currentUrlPathWithQuery = `${currentUrlPathWithQuery}?meta=${metaQueryParam}`;
|
|
353
|
-
}
|
|
354
|
-
|
|
355
|
-
isSelected = resultHrefWithMetaQuery === currentUrlPathWithQuery;
|
|
356
|
-
} else {
|
|
357
|
-
href = `${pathname}?q=${this.value}`;
|
|
358
|
-
isSelected = pathname === window.location.pathname;
|
|
359
|
-
}
|
|
360
|
-
|
|
91
|
+
private normalizeDataCloudResult = (
|
|
92
|
+
item: DataCloudSearchResultItem,
|
|
93
|
+
index: number
|
|
94
|
+
): SidebarSearchResult => {
|
|
95
|
+
const href = item.url ?? "";
|
|
96
|
+
const resultPath = href.startsWith("http")
|
|
97
|
+
? new URL(href).pathname
|
|
98
|
+
: href;
|
|
99
|
+
const isSelected =
|
|
100
|
+
!!resultPath && resultPath === window.location.pathname;
|
|
361
101
|
return {
|
|
362
|
-
title,
|
|
363
|
-
titleHighlights,
|
|
364
|
-
excerpt,
|
|
365
|
-
excerptHighlights,
|
|
366
|
-
uniqueId
|
|
102
|
+
title: item.title ?? "",
|
|
103
|
+
titleHighlights: [],
|
|
104
|
+
excerpt: item.matchedText ?? "",
|
|
105
|
+
excerptHighlights: [],
|
|
106
|
+
uniqueId: href || `result-${index}`,
|
|
367
107
|
href,
|
|
368
108
|
selected: isSelected,
|
|
369
|
-
select: () =>
|
|
370
|
-
window.localStorage.setItem(
|
|
371
|
-
RESULT_CLICK_LOCAL_STORAGE_KEY,
|
|
372
|
-
JSON.stringify(result)
|
|
373
|
-
)
|
|
109
|
+
select: () => {}
|
|
374
110
|
};
|
|
375
111
|
};
|
|
376
112
|
|
|
377
|
-
private
|
|
378
|
-
|
|
379
|
-
|
|
380
|
-
|
|
381
|
-
|
|
382
|
-
|
|
383
|
-
|
|
384
|
-
|
|
113
|
+
private async fetchDataCloudSearch(): Promise<void> {
|
|
114
|
+
const body = {
|
|
115
|
+
searchQuery: this.value.trim(),
|
|
116
|
+
baseUrlPath: getBaseUrlPath()
|
|
117
|
+
};
|
|
118
|
+
try {
|
|
119
|
+
const res = await fetch(DATA_CLOUD_SEARCH_PATH, {
|
|
120
|
+
method: "POST",
|
|
121
|
+
headers: { "Content-Type": "application/json" },
|
|
122
|
+
body: JSON.stringify(body)
|
|
123
|
+
});
|
|
124
|
+
if (!res.ok) {
|
|
125
|
+
throw new Error(`Search API error: ${res.status}`);
|
|
126
|
+
}
|
|
127
|
+
const data = await res.json();
|
|
128
|
+
const rawResults: DataCloudSearchResultItem[] = Array.isArray(data)
|
|
129
|
+
? data
|
|
130
|
+
: data?.results ?? data?.data?.results ?? [];
|
|
131
|
+
const results: SidebarSearchResult[] = rawResults.map(
|
|
132
|
+
this.normalizeDataCloudResult
|
|
133
|
+
);
|
|
134
|
+
this.dispatchChange(results);
|
|
135
|
+
} catch (err) {
|
|
136
|
+
console.error("Data Cloud Search request failed", err);
|
|
137
|
+
this.dispatchChange([]);
|
|
138
|
+
} finally {
|
|
139
|
+
this.dispatchOnLoading(false);
|
|
140
|
+
}
|
|
385
141
|
}
|
|
386
142
|
|
|
387
|
-
private
|
|
388
|
-
this.updateSessionStorage();
|
|
143
|
+
private dispatchChange(results: SidebarSearchResult[]) {
|
|
389
144
|
this.dispatchEvent(
|
|
390
145
|
new CustomEvent("change", {
|
|
391
|
-
detail: {
|
|
392
|
-
results: results.map(this.normalizeCoveoResult),
|
|
393
|
-
value: this.value
|
|
394
|
-
}
|
|
146
|
+
detail: { results, value: this.value }
|
|
395
147
|
})
|
|
396
148
|
);
|
|
397
149
|
}
|
|
@@ -427,19 +179,12 @@ export default class SidebarSearch extends LightningElement {
|
|
|
427
179
|
}
|
|
428
180
|
|
|
429
181
|
private submitSearch = debounce((isSyncingSearchValue = false) => {
|
|
430
|
-
|
|
431
|
-
|
|
432
|
-
|
|
433
|
-
|
|
434
|
-
// When `isSyncingSearchValue` is true, we are submitting in a case
|
|
435
|
-
// where the search box is already synced correctly.
|
|
436
|
-
if (!isSyncingSearchValue) {
|
|
437
|
-
this.dispatchSidebarSearchChange(this.value);
|
|
438
|
-
}
|
|
439
|
-
|
|
440
|
-
this.searchBox.updateText(this.value || "");
|
|
441
|
-
this.searchBox.submit();
|
|
182
|
+
UserRecentSearches.add(this.value);
|
|
183
|
+
this.updateRecentSearches();
|
|
184
|
+
if (!isSyncingSearchValue) {
|
|
185
|
+
this.dispatchSidebarSearchChange(this.value);
|
|
442
186
|
}
|
|
187
|
+
this.fetchDataCloudSearch();
|
|
443
188
|
}, SEARCH_DEBOUNCE_DELAY);
|
|
444
189
|
|
|
445
190
|
private onClickRecentSearch(e: CustomEvent) {
|
|
@@ -461,7 +206,6 @@ export default class SidebarSearch extends LightningElement {
|
|
|
461
206
|
|
|
462
207
|
private onInputChange(e: CustomEvent) {
|
|
463
208
|
this.value = e.detail;
|
|
464
|
-
|
|
465
209
|
this.handleValueChange(false);
|
|
466
210
|
this.dispatchHighlightedTermChange();
|
|
467
211
|
}
|
|
@@ -477,16 +221,10 @@ export default class SidebarSearch extends LightningElement {
|
|
|
477
221
|
private handleValueChange(isSyncingSearchValue = false) {
|
|
478
222
|
if (this.value) {
|
|
479
223
|
this.dispatchOnLoading(true);
|
|
480
|
-
|
|
481
|
-
this.submitSearch(isSyncingSearchValue);
|
|
482
|
-
}
|
|
224
|
+
this.submitSearch(isSyncingSearchValue);
|
|
483
225
|
} else {
|
|
484
|
-
// coveo's reaction to an empty value triggers a return of results
|
|
485
|
-
// bootlegging our own ux here`
|
|
486
226
|
this.dispatchOnLoading(false);
|
|
487
|
-
this.
|
|
488
|
-
// Empty search values are not submitted for search, so we need to manually
|
|
489
|
-
// trigger a search change on our own here
|
|
227
|
+
this.dispatchChange([]);
|
|
490
228
|
this.dispatchSidebarSearchChange(this.value);
|
|
491
229
|
}
|
|
492
230
|
}
|
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
import { LightningElement, api } from "lwc";
|
|
2
2
|
import cx from "classnames";
|
|
3
|
-
import {
|
|
3
|
+
import { HighlightedSections } from "typings/custom";
|
|
4
4
|
|
|
5
|
-
const toChunks = (value: string, highlights:
|
|
5
|
+
const toChunks = (value: string, highlights: HighlightedSections) => {
|
|
6
6
|
if (!highlights || highlights.length < 1) {
|
|
7
7
|
return [
|
|
8
8
|
{
|
|
@@ -51,11 +51,11 @@ const toChunks = (value: string, highlights: CoveoHighlights) => {
|
|
|
51
51
|
|
|
52
52
|
export default class SidebarSearchResult extends LightningElement {
|
|
53
53
|
@api description!: string;
|
|
54
|
-
@api descriptionHighlights!:
|
|
54
|
+
@api descriptionHighlights!: HighlightedSections;
|
|
55
55
|
@api href!: string;
|
|
56
56
|
@api selected!: boolean;
|
|
57
57
|
@api header!: string;
|
|
58
|
-
@api titleHighlights!:
|
|
58
|
+
@api titleHighlights!: HighlightedSections;
|
|
59
59
|
@api select!: Function;
|
|
60
60
|
|
|
61
61
|
private get titleChunks() {
|