@salesforcedevs/dx-components 1.3.91-version-picker-alpha → 1.3.92-alpha-001-localstorage

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.3.91-version-picker-alpha",
3
+ "version": "1.3.92-alpha-001-localstorage",
4
4
  "description": "DX Lightning web components",
5
5
  "license": "MIT",
6
6
  "engines": {
@@ -24,14 +24,14 @@ export default class Audio extends LightningElement {
24
24
  );
25
25
  }
26
26
 
27
- private trackClick(e: Event, clickType: string) {
27
+ private trackClick(e: Event, eventType: string, action: string) {
28
28
  const audioElement = this.template.querySelector(
29
29
  "audio"
30
30
  ) as HTMLMediaElement;
31
31
 
32
32
  const payload = {
33
- event: "custEv_blogAudioPlay",
34
- media_action: clickType,
33
+ event: eventType,
34
+ media_action: action,
35
35
  media_name: this.postName,
36
36
  media_percentage_played: (
37
37
  (audioElement!.currentTime * 100) /
@@ -44,12 +44,12 @@ export default class Audio extends LightningElement {
44
44
  }
45
45
 
46
46
  private trackPlay(e: Event) {
47
- this.trackClick(e, "play");
47
+ this.trackClick(e, "custEv_blogAudioPlay", "play");
48
48
  }
49
49
  private trackEnded(e: Event) {
50
- this.trackClick(e, "complete");
50
+ this.trackClick(e, "custEv_blogAudioComplete", "complete");
51
51
  }
52
52
  private trackPause(e: Event) {
53
- this.trackClick(e, "pause");
53
+ this.trackClick(e, "custEv_blogAudioPause", "pause");
54
54
  }
55
55
  }
@@ -8,7 +8,9 @@
8
8
  part="container"
9
9
  >
10
10
  <div class={textContainerClassName}>
11
- <h3 class="dx-text-display-4">{title}</h3>
11
+ <h3 class="dx-text-display-4">
12
+ <dx-formatted-rich-text value={title}></dx-formatted-rich-text>
13
+ </h3>
12
14
  <p>{body}</p>
13
15
  <div class="cta">
14
16
  <dx-button if:true={hasLargeButton} size="large">
@@ -13,6 +13,7 @@ import { track } from "dxUtils/analytics";
13
13
 
14
14
  export default class CardNews extends LightningElement {
15
15
  @api backgroundColor?: string = "indigo-vibrant-40";
16
+ @api title!: string;
16
17
  @api body!: string;
17
18
  @api buttonText?: string = "";
18
19
  @api buttonType!: CardNewsButtonType;
@@ -26,7 +27,6 @@ export default class CardNews extends LightningElement {
26
27
  @api imgPlacement?: CardNewsImagePlacement = "top";
27
28
  @api imgVerticalAlign?: CardNewsImageVerticalAlignment | null = null;
28
29
  @api target?: string | null = null;
29
- @api title!: string;
30
30
  @api textContainerWidth?: CardNewsTextContainerSize = "small";
31
31
 
32
32
  private get style(): string {
@@ -0,0 +1,3 @@
1
+ <template>
2
+ <div class="container" lwc:dom="manual"></div>
3
+ </template>
@@ -0,0 +1,17 @@
1
+ import { LightningElement, api } from "lwc";
2
+ import { sanitizeHtml } from "dxUtils/sanitizeHtml";
3
+
4
+ export default class FormattedRichText extends LightningElement {
5
+ @api value!: string;
6
+
7
+ private get sanitizedValue(): string {
8
+ return sanitizeHtml(this.value);
9
+ }
10
+ renderedCallback() {
11
+ const containerEl = this.template.querySelector(".container");
12
+
13
+ if (containerEl) {
14
+ containerEl.innerHTML = this.sanitizedValue;
15
+ }
16
+ }
17
+ }
@@ -17,8 +17,10 @@ export const restoreScroll = () => {
17
17
  if (scrollUnlocked) {
18
18
  return;
19
19
  }
20
- document.body.scrollTop = document.documentElement.scrollTop =
21
- window.history.state?.scroll?.value;
20
+ const value = window.history.state?.scroll?.value;
21
+ if (value) {
22
+ document.body.scrollTop = document.documentElement.scrollTop = value;
23
+ }
22
24
  };
23
25
 
24
26
  export default class ScrollManager extends LightningElement {
@@ -1,7 +1,10 @@
1
1
  import { LightningElement, api, track } from "lwc";
2
2
  import type * as CoveoSDK from "coveo-search-ui";
3
3
  import { track as trackGTM } from "dxUtils/analytics";
4
- import { CONTENT_TYPE_LABELS } from "dxConstants/contentTypes";
4
+ import {
5
+ CONTENT_TYPE_LABELS,
6
+ CONTENT_TYPE_ICONS
7
+ } from "dxConstants/contentTypes";
5
8
  import { getContentTypeColorVariables } from "dxUtils/contentTypes";
6
9
 
7
10
  interface CoveoSearch {
@@ -19,9 +22,7 @@ interface CoveoSearch {
19
22
 
20
23
  declare const Coveo: CoveoSearch;
21
24
 
22
- function getPaginationState(
23
- event: CoveoSDK.IQuerySuccessEventArgs
24
- ): {
25
+ function getPaginationState(event: CoveoSDK.IQuerySuccessEventArgs): {
25
26
  numberOfPages: number;
26
27
  currentPage: number;
27
28
  } {
@@ -67,6 +68,25 @@ const resultsTemplatesInnerHtml = `
67
68
  </script>
68
69
  `;
69
70
 
71
+ const buildTemplateHelperBadge = (value: string) => {
72
+ const style = getContentTypeColorVariables(value);
73
+ const label = CONTENT_TYPE_LABELS[value];
74
+ const { iconSprite, iconSymbol } = CONTENT_TYPE_ICONS[value];
75
+ return `
76
+ <div style="${style}" class="dx-badge">
77
+ <svg
78
+ aria-hidden="true"
79
+ style="display: inline; margin-bottom: 1px; fill: var(--color); height: var(--dx-g-icon-size-xs); width: var(--dx-g-icon-size-xs);"
80
+ xmlns="http://www.w3.org/2000/svg"
81
+ part="svg"
82
+ >
83
+ <use xlink:href="/assets/icons/${iconSprite}-sprite/svg/symbols.svg#${iconSymbol}"></use>
84
+ </svg>
85
+ <span>${label}</span>
86
+ </div>
87
+ `;
88
+ };
89
+
70
90
  export default class SearchResults extends LightningElement {
71
91
  @api coveoOrganizationId!: string;
72
92
  @api coveoPublicAccessToken!: string;
@@ -179,11 +199,7 @@ export default class SearchResults extends LightningElement {
179
199
 
180
200
  Coveo.TemplateHelpers.registerTemplateHelper(
181
201
  "badge",
182
- (value: string) => {
183
- const style = getContentTypeColorVariables(value);
184
- const label = CONTENT_TYPE_LABELS[value];
185
- return `<div style="${style}" class="dx-badge"><span>${label}</span></div>`;
186
- }
202
+ buildTemplateHelperBadge
187
203
  );
188
204
 
189
205
  Coveo.init(this.root);
@@ -76,6 +76,7 @@
76
76
  selected={result.selected}
77
77
  title-highlights={result.titleHighlights}
78
78
  title={result.title}
79
+ select={result.select}
79
80
  ></dx-sidebar-search-result>
80
81
  </template>
81
82
  <dx-empty-state
@@ -6,6 +6,7 @@ import {
6
6
  Unsubscribe,
7
7
  ResultsPerPage,
8
8
  SearchBox,
9
+ buildInteractiveResult,
9
10
  buildResultList,
10
11
  buildResultsPerPage,
11
12
  buildSearchBox,
@@ -23,6 +24,7 @@ import {
23
24
  SidebarSearchResult
24
25
  } from "typings/custom";
25
26
 
27
+ const RESULT_CLICK_LOCAL_STORAGE_KEY = "dx-sidebar-search-result-click";
26
28
  export const SESSION_KEY = "dx-sidebar-search-state";
27
29
 
28
30
  const DEFAULT_RESULT_COUNT = 20;
@@ -86,7 +88,7 @@ export default class SidebarSearch extends LightningElement {
86
88
  private _coveoAdvancedQueryConfig!: { [key: string]: any };
87
89
  private dropdownRequestedOpen: boolean = false;
88
90
  private recentSearches: Option[] = [];
89
- private unsubscribeFromResultList: Unsubscribe = () => {};
91
+ private unsubscribeFromResultList: Unsubscribe = () => { };
90
92
  private resultList: ResultList | null = null;
91
93
  private resultsPerPage: ResultsPerPage | null = null;
92
94
  private preloadedState?: SearchAppState;
@@ -137,6 +139,7 @@ export default class SidebarSearch extends LightningElement {
137
139
  if (this.hasCorrectCoveoConfig && !this.engine) {
138
140
  this.initializeUserSession();
139
141
  this.initializeCoveo();
142
+ this.syncAnalytics();
140
143
  } else if (!this.hasCorrectCoveoConfig) {
141
144
  console.error(
142
145
  "Incorrect coveo search configuration provided. All coveo configuration attributes must be defined.",
@@ -242,16 +245,25 @@ export default class SidebarSearch extends LightningElement {
242
245
  }
243
246
  };
244
247
 
248
+ private syncAnalytics = () => {
249
+ const storedResult = window.localStorage.getItem(RESULT_CLICK_LOCAL_STORAGE_KEY);
250
+ if (storedResult) {
251
+ const interactiveResult = buildInteractiveResult(this.engine!, {
252
+ options: { result: JSON.parse(storedResult) }
253
+ });
254
+ interactiveResult.cancelPendingSelect();
255
+ interactiveResult.select();
256
+ window.localStorage.removeItem(RESULT_CLICK_LOCAL_STORAGE_KEY);
257
+ }
258
+ }
259
+
245
260
  private onResultListChange = () => {
246
261
  if (!this.resultList) {
247
262
  return;
248
263
  }
249
264
 
250
- const {
251
- isLoading,
252
- firstSearchExecuted,
253
- results
254
- } = this.resultList.state;
265
+ const { isLoading, firstSearchExecuted, results } =
266
+ this.resultList.state;
255
267
 
256
268
  if ((!firstSearchExecuted && !isLoading) || !this.value) {
257
269
  // coveo search is firing off some unwanted payloads on startup
@@ -289,15 +301,17 @@ export default class SidebarSearch extends LightningElement {
289
301
  engine.dispatch(registerSearchQueryAction);
290
302
  }
291
303
 
292
- private normalizeCoveoResult = ({
293
- clickUri,
294
- excerpt,
295
- excerptHighlights,
296
- raw: { sfhtml_url__c },
297
- title,
298
- titleHighlights,
299
- uniqueId
300
- }: Result): SidebarSearchResult => {
304
+ private normalizeCoveoResult = (result: Result): SidebarSearchResult => {
305
+ const {
306
+ clickUri,
307
+ excerpt,
308
+ excerptHighlights,
309
+ raw: { sfhtml_url__c },
310
+ title,
311
+ titleHighlights,
312
+ uniqueId
313
+ } = result;
314
+
301
315
  // discussion about this normalization here: https://salesforce-internal.slack.com/archives/C020S6784JX/p1639506238376600
302
316
 
303
317
  let pathname, queryParam;
@@ -348,7 +362,8 @@ export default class SidebarSearch extends LightningElement {
348
362
  excerptHighlights,
349
363
  uniqueId,
350
364
  href,
351
- selected: isSelected
365
+ selected: isSelected,
366
+ select: () => window.localStorage.setItem(RESULT_CLICK_LOCAL_STORAGE_KEY, result),
352
367
  };
353
368
  };
354
369
 
@@ -389,10 +404,10 @@ export default class SidebarSearch extends LightningElement {
389
404
  }
390
405
 
391
406
  private updateRecentSearches = () =>
392
- (this.recentSearches = UserRecentSearches.get().map((item: string) => ({
393
- id: item,
394
- label: item
395
- })));
407
+ (this.recentSearches = UserRecentSearches.get().map((item: string) => ({
408
+ id: item,
409
+ label: item
410
+ })));
396
411
 
397
412
  private dispatchSidebarSearchChange(searchTerm: string | undefined): void {
398
413
  this.dispatchEvent(
@@ -1,5 +1,5 @@
1
1
  <template>
2
- <a class={className} href={href}>
2
+ <a class={className} href={href} onclick={select}>
3
3
  <span class="title search-text">
4
4
  <template for:each={titleChunks} for:item="chunk">
5
5
  <span class={chunk.class} key={chunk.id}>{chunk.value}</span>
@@ -55,6 +55,7 @@ export default class SidebarSearchResult extends LightningElement {
55
55
  @api selected!: boolean;
56
56
  @api title!: string;
57
57
  @api titleHighlights!: CoveoHighlights;
58
+ @api select!: Function;
58
59
 
59
60
  private get titleChunks() {
60
61
  return toChunks(this.title, this.titleHighlights);
@@ -25,7 +25,6 @@ dx-tree:not(:last-child) {
25
25
  }
26
26
 
27
27
  .mobile-header {
28
- box-sizing: content-box;
29
28
  display: flex;
30
29
  line-height: var(--dx-g-spacing-xl);
31
30
  margin-bottom: 12px;
@@ -114,8 +113,10 @@ dx-tree:not(:last-child) {
114
113
  background-color: #dddbda;
115
114
  }
116
115
 
116
+ /* This class checks if an element with container class has an elemnt with container-mobile class and
117
+ must not contain any collapsed class and finally must have a mobile-header class (to which this css will be applied) */
117
118
  .container.container-mobile:not(.collapsed) .mobile-header {
118
- background-color: #F3F3F3;
119
+ background-color: var(--dx-g-gray-95);
119
120
  }
120
121
 
121
122
  .container.container-mobile .header-title {
@@ -26,6 +26,7 @@
26
26
  --height: var(--dx-g-spacing-mlg);
27
27
  }
28
28
 
29
+ svg,
29
30
  dx-icon {
30
31
  margin-right: var(--dx-g-spacing-sm);
31
32
  }
@@ -0,0 +1,8 @@
1
+ export function sanitizeHtml(str: string) {
2
+ const allowedTags = ["a", "b", "em", "br", "strong"];
3
+ const pattern = new RegExp(
4
+ `<(/?(?!${allowedTags.join("|")})\\b[^>]*?)>`,
5
+ "gi"
6
+ );
7
+ return str.replace(pattern, "");
8
+ }