@salesforcedevs/dx-components 1.3.57-alpha.9 → 1.3.62-alpha01
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 +5 -3
- package/src/assets/icons/salesforcebrand-sprite/svg/symbols.svg +118 -7
- package/src/assets/svg/privacyicon.png +0 -0
- package/src/modules/dx/cardBlogPost/cardBlogPost.html +3 -3
- package/src/modules/dx/cardBlogPost/cardBlogPost.ts +18 -3
- package/src/modules/dx/cardCallout/cardCallout.ts +7 -0
- package/src/modules/dx/cardContent/cardContent.css +5 -0
- package/src/modules/dx/cardContent/cardContent.html +12 -6
- package/src/modules/dx/cardContent/cardContent.ts +39 -7
- package/src/modules/dx/cardDocs/cardDocs.html +6 -2
- package/src/modules/dx/cardDocs/cardDocs.ts +47 -0
- package/src/modules/dx/cardExpanded/cardExpanded.css +15 -5
- package/src/modules/dx/cardExpanded/cardExpanded.html +9 -5
- package/src/modules/dx/cardExpanded/cardExpanded.ts +24 -8
- package/src/modules/dx/cardNews/cardNews.ts +1 -0
- package/src/modules/dx/cardTrial/cardTrial.html +5 -1
- package/src/modules/dx/cardTrial/cardTrial.ts +40 -1
- package/src/modules/dx/cardTrialExpanded/cardTrialExpanded.css +10 -0
- package/src/modules/dx/cardTrialExpanded/cardTrialExpanded.html +16 -10
- package/src/modules/dx/cardTrialExpanded/cardTrialExpanded.ts +43 -1
- package/src/modules/dx/codeBlock/codeBlock.ts +19 -4
- package/src/modules/dx/dropdown/dropdown.html +2 -4
- package/src/modules/dx/dropdown/dropdown.ts +2 -7
- package/src/modules/dx/dropdownOption/dropdownOption.ts +11 -21
- package/src/modules/dx/feature/feature.html +1 -0
- package/src/modules/dx/feature/feature.ts +13 -0
- package/src/modules/dx/featuredContentHeader/featuredContentHeader.ts +116 -2
- package/src/modules/dx/footer/footer.css +9 -0
- package/src/modules/dx/footer/footer.html +6 -0
- package/src/modules/dx/footer/footer.ts +7 -14
- package/src/modules/dx/footer/links.ts +5 -0
- package/src/modules/dx/footerOption/footerOption.ts +12 -4
- package/src/modules/dx/groupText/groupText.ts +8 -14
- package/src/modules/dx/headerMobileNavMenuOption/headerMobileNavMenuOption.ts +8 -0
- package/src/modules/dx/headerNav/headerNav.html +1 -0
- package/src/modules/dx/headerNav/headerNav.ts +4 -0
- package/src/modules/dx/mainContentHeader/mainContentHeader.html +2 -2
- package/src/modules/dx/mainContentHeader/mainContentHeader.ts +21 -6
- package/src/modules/dx/modal/modal.html +1 -1
- package/src/modules/dx/modal/modal.ts +6 -1
- package/src/modules/dx/pagination/pagination.ts +5 -10
- package/src/modules/dx/scrollManager/scrollManager.ts +14 -9
- package/src/modules/dx/searchResults/coveo.css +32 -31
- package/src/modules/dx/searchResults/searchResults.ts +11 -0
- package/src/modules/dx/tab/tab.ts +14 -3
- package/src/modules/dx/tabPanelItem/tabPanelItem.html +1 -1
- package/src/modules/dx/tbidAvatarButton/tbidAvatarButton.ts +26 -16
- package/src/modules/dx/toc/toc.ts +24 -7
- package/src/modules/dx/treeItem/treeItem.ts +24 -7
- package/src/modules/dxBaseElements/headerBase/headerBase.ts +10 -8
- package/src/modules/dxUtils/normalizers/normalizers.ts +1 -3
|
@@ -1,21 +1,41 @@
|
|
|
1
1
|
import { api } from "lwc";
|
|
2
2
|
import { ArchiveCard } from "dxBaseElements/archiveCard";
|
|
3
3
|
import cx from "classnames";
|
|
4
|
+
import ImageAndLabel from "../imageAndLabel";
|
|
5
|
+
import { toJson } from "dxUtils/normalizers";
|
|
4
6
|
|
|
5
7
|
export default class ExpandedCard extends ArchiveCard {
|
|
6
8
|
@api body!: string;
|
|
7
9
|
@api date: string | null = null;
|
|
8
10
|
@api topics: Array<string> = [];
|
|
9
|
-
@api authorLabel?: string | null = null;
|
|
10
|
-
@api authorImgSrc?: string | null = null;
|
|
11
11
|
@api length?: string;
|
|
12
|
+
@api
|
|
13
|
+
get authors() {
|
|
14
|
+
if (this._authors && this._authors.length) {
|
|
15
|
+
return this._authors!.map((author, index) => ({
|
|
16
|
+
...author,
|
|
17
|
+
imgSrc: !this.mobile ? author.image_src : "",
|
|
18
|
+
key: index
|
|
19
|
+
}));
|
|
20
|
+
}
|
|
21
|
+
return undefined;
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
set authors(value: any) {
|
|
25
|
+
if (value !== "undefined") {
|
|
26
|
+
this._authors = (toJson(value) as Array<any>)?.filter(
|
|
27
|
+
(author) => author.name
|
|
28
|
+
);
|
|
29
|
+
}
|
|
30
|
+
}
|
|
31
|
+
private _authors?: Array<ImageAndLabel>;
|
|
12
32
|
|
|
13
33
|
private get isBlog(): boolean {
|
|
14
34
|
return this.contentType === "blog";
|
|
15
35
|
}
|
|
16
36
|
|
|
17
37
|
private get hasAuthor(): boolean {
|
|
18
|
-
return
|
|
38
|
+
return this.authors?.length;
|
|
19
39
|
}
|
|
20
40
|
|
|
21
41
|
private get renderAuthor(): boolean {
|
|
@@ -27,17 +47,13 @@ export default class ExpandedCard extends ArchiveCard {
|
|
|
27
47
|
}
|
|
28
48
|
|
|
29
49
|
private get renderDot(): boolean {
|
|
30
|
-
return !!(
|
|
50
|
+
return !!(this.renderLength && this.date);
|
|
31
51
|
}
|
|
32
52
|
|
|
33
53
|
private get hasTopics(): boolean {
|
|
34
54
|
return !!this.topics?.length;
|
|
35
55
|
}
|
|
36
56
|
|
|
37
|
-
private get authorImage(): string {
|
|
38
|
-
return !this.mobile && this.authorImgSrc ? this.authorImgSrc : "";
|
|
39
|
-
}
|
|
40
|
-
|
|
41
57
|
private get containerClass(): string {
|
|
42
58
|
return cx("card-container", this.mobile && "card-mobile");
|
|
43
59
|
}
|
|
@@ -3,6 +3,7 @@
|
|
|
3
3
|
if:true={hasTwoButtons}
|
|
4
4
|
open={_modalOpen}
|
|
5
5
|
ontogglemodal={toggleModal}
|
|
6
|
+
onclosemodal={closeModal}
|
|
6
7
|
>
|
|
7
8
|
<dx-card-trial-expanded
|
|
8
9
|
badge-background-color={badgeBackgroundColor}
|
|
@@ -21,7 +22,8 @@
|
|
|
21
22
|
target={target}
|
|
22
23
|
terms={terms}
|
|
23
24
|
title={title}
|
|
24
|
-
|
|
25
|
+
type-badge-value={modalTypeBadgeValue}
|
|
26
|
+
type-badge-dark={modalTypeBadgeDark}
|
|
25
27
|
></dx-card-trial-expanded>
|
|
26
28
|
</dx-modal>
|
|
27
29
|
<div class="recommended-container" if:true={recommended}>
|
|
@@ -69,6 +71,7 @@
|
|
|
69
71
|
size="large"
|
|
70
72
|
href={buttonOneHref}
|
|
71
73
|
variant="primary"
|
|
74
|
+
target={buttonOneTarget}
|
|
72
75
|
font="sans"
|
|
73
76
|
icon-symbol={buttonOneIcon}
|
|
74
77
|
icon-size={buttonOneIconSize}
|
|
@@ -82,6 +85,7 @@
|
|
|
82
85
|
href={buttonOneHref}
|
|
83
86
|
variant="primary"
|
|
84
87
|
font="sans"
|
|
88
|
+
target={buttonOneTarget}
|
|
85
89
|
icon-symbol={buttonOneIcon}
|
|
86
90
|
icon-size={buttonOneIconSize}
|
|
87
91
|
>
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import { LightningElement, api } from "lwc";
|
|
2
2
|
import cx from "classnames";
|
|
3
3
|
import { toJson } from "dxUtils/normalizers";
|
|
4
|
+
import { track } from "dxUtils/analytics";
|
|
4
5
|
|
|
5
6
|
export default class CardTrial extends LightningElement {
|
|
6
7
|
@api badgeBackgroundColor?: string = "indigo-vibrant-90";
|
|
@@ -34,6 +35,8 @@ export default class CardTrial extends LightningElement {
|
|
|
34
35
|
@api typeBadgeColor?: string;
|
|
35
36
|
@api typeBadgeSize?: string = "default";
|
|
36
37
|
@api typeBadgeDark?: boolean = false;
|
|
38
|
+
@api modalTypeBadgeValue?: string;
|
|
39
|
+
@api modalTypeBadgeDark?: boolean;
|
|
37
40
|
|
|
38
41
|
@api
|
|
39
42
|
get details() {
|
|
@@ -71,6 +74,10 @@ export default class CardTrial extends LightningElement {
|
|
|
71
74
|
return this.hasButtons ? "menu" : "link";
|
|
72
75
|
}
|
|
73
76
|
|
|
77
|
+
get buttonOneTarget() {
|
|
78
|
+
return this.isExternalURL(this.buttonOneHref) ? "_blank" : null;
|
|
79
|
+
}
|
|
80
|
+
|
|
74
81
|
private _details!: string[];
|
|
75
82
|
private _modalDetails!: [{ title: string; subtitle: string }];
|
|
76
83
|
private _modalOpen = false;
|
|
@@ -93,10 +100,42 @@ export default class CardTrial extends LightningElement {
|
|
|
93
100
|
this._modalOpen = !this._modalOpen;
|
|
94
101
|
}
|
|
95
102
|
|
|
96
|
-
private
|
|
103
|
+
private closeModal() {
|
|
104
|
+
this._modalOpen = false;
|
|
105
|
+
}
|
|
106
|
+
|
|
107
|
+
private handleClick(e: PointerEvent) {
|
|
97
108
|
// card is clickable only if it doesn't contain buttons (for accessibility reasons)
|
|
98
109
|
if (!this.hasButtons) {
|
|
99
110
|
window.location.assign(this.href);
|
|
111
|
+
if (this.href.includes("signup")) {
|
|
112
|
+
this.handleSignUpClick(e);
|
|
113
|
+
}
|
|
114
|
+
}
|
|
115
|
+
}
|
|
116
|
+
|
|
117
|
+
private handleSignUpClick(e: PointerEvent) {
|
|
118
|
+
const payload = {
|
|
119
|
+
click_text: this.label,
|
|
120
|
+
element_title: "dx-button",
|
|
121
|
+
element_type: "card",
|
|
122
|
+
click_url: this.href,
|
|
123
|
+
content_category: "cta"
|
|
124
|
+
};
|
|
125
|
+
track(e.currentTarget!, "custEv_signupStart", payload);
|
|
126
|
+
track(e.currentTarget!, "custEv_linkClick", payload);
|
|
127
|
+
}
|
|
128
|
+
|
|
129
|
+
private isExternalURL(url: string | undefined): boolean {
|
|
130
|
+
if (!url) {
|
|
131
|
+
return false;
|
|
132
|
+
}
|
|
133
|
+
|
|
134
|
+
try {
|
|
135
|
+
const value = new URL(url);
|
|
136
|
+
return value.host !== window.location.host;
|
|
137
|
+
} catch (e) {
|
|
138
|
+
return false;
|
|
100
139
|
}
|
|
101
140
|
}
|
|
102
141
|
}
|
|
@@ -19,6 +19,11 @@
|
|
|
19
19
|
pointer-events: all;
|
|
20
20
|
}
|
|
21
21
|
|
|
22
|
+
.badge-container {
|
|
23
|
+
display: flex;
|
|
24
|
+
justify-content: space-between;
|
|
25
|
+
}
|
|
26
|
+
|
|
22
27
|
.badge-main {
|
|
23
28
|
--dx-c-icon-badge-icon-size: var(--dx-g-spacing-mlg);
|
|
24
29
|
--dx-c-icon-badge-size: var(--dx-g-spacing-2xl);
|
|
@@ -138,6 +143,11 @@ dx-button {
|
|
|
138
143
|
color: white;
|
|
139
144
|
}
|
|
140
145
|
|
|
146
|
+
.bullet-list .bullet {
|
|
147
|
+
padding-left: 1.39571429em;
|
|
148
|
+
text-indent: -1.39571429em;
|
|
149
|
+
}
|
|
150
|
+
|
|
141
151
|
@media screen and (max-width: 768px) {
|
|
142
152
|
.container {
|
|
143
153
|
max-width: 550px;
|
|
@@ -10,14 +10,21 @@
|
|
|
10
10
|
Close
|
|
11
11
|
</dx-button>
|
|
12
12
|
</div>
|
|
13
|
-
<div class="content-container">
|
|
13
|
+
<div class="content-container" tabindex="0" onkeydown={handleKeyDown}>
|
|
14
14
|
<div class="col-one">
|
|
15
|
-
<
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
15
|
+
<div class="badge-container">
|
|
16
|
+
<dx-icon-badge
|
|
17
|
+
class="badge-main"
|
|
18
|
+
background-color={badgeBackgroundColor}
|
|
19
|
+
symbol={badgeSymbol}
|
|
20
|
+
sprite={badgeSprite}
|
|
21
|
+
></dx-icon-badge>
|
|
22
|
+
<dx-type-badge
|
|
23
|
+
if:true={typeBadgeValue}
|
|
24
|
+
value={typeBadgeValue}
|
|
25
|
+
dark={typeBadgeDark}
|
|
26
|
+
></dx-type-badge>
|
|
27
|
+
</div>
|
|
21
28
|
<dx-card-title
|
|
22
29
|
class="title-main"
|
|
23
30
|
href={href}
|
|
@@ -31,6 +38,7 @@
|
|
|
31
38
|
class="button-cta"
|
|
32
39
|
size="large"
|
|
33
40
|
href={href}
|
|
41
|
+
onclick={handleSignUpClick}
|
|
34
42
|
variant="primary"
|
|
35
43
|
font="sans"
|
|
36
44
|
icon-symbol={buttonIcon}
|
|
@@ -72,9 +80,7 @@
|
|
|
72
80
|
for:each={colTwoItem.bullets}
|
|
73
81
|
for:item="bullet"
|
|
74
82
|
>
|
|
75
|
-
<li key={
|
|
76
|
-
{bullet}
|
|
77
|
-
</li>
|
|
83
|
+
<li key={bullet} class="bullet">{bullet}</li>
|
|
78
84
|
</template>
|
|
79
85
|
</ul>
|
|
80
86
|
</div>
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import { LightningElement, api } from "lwc";
|
|
2
2
|
import { toJson } from "dxUtils/normalizers";
|
|
3
|
+
import { track } from "dxUtils/analytics";
|
|
3
4
|
|
|
4
5
|
export default class CardTrial extends LightningElement {
|
|
5
6
|
@api badgeBackgroundColor?: string = "indigo-vibrant-90";
|
|
@@ -16,6 +17,8 @@ export default class CardTrial extends LightningElement {
|
|
|
16
17
|
@api target?: string;
|
|
17
18
|
@api terms!: string;
|
|
18
19
|
@api title!: string;
|
|
20
|
+
@api typeBadgeValue?: string;
|
|
21
|
+
@api typeBadgeDark?: boolean = false;
|
|
19
22
|
|
|
20
23
|
@api
|
|
21
24
|
get details() {
|
|
@@ -37,6 +40,13 @@ export default class CardTrial extends LightningElement {
|
|
|
37
40
|
private _colTwoDetails!: string[];
|
|
38
41
|
private stickyCloseObserver!: IntersectionObserver;
|
|
39
42
|
|
|
43
|
+
connectedCallback(): void {
|
|
44
|
+
this.template.addEventListener(
|
|
45
|
+
"keydown",
|
|
46
|
+
this.handleKeyDown.bind(this)
|
|
47
|
+
);
|
|
48
|
+
}
|
|
49
|
+
|
|
40
50
|
renderedCallback(): void {
|
|
41
51
|
this.observeStickyClose();
|
|
42
52
|
}
|
|
@@ -61,7 +71,39 @@ export default class CardTrial extends LightningElement {
|
|
|
61
71
|
}
|
|
62
72
|
}
|
|
63
73
|
|
|
74
|
+
private handleKeyDown(event: KeyboardEvent): void {
|
|
75
|
+
if (event.key === "Escape") {
|
|
76
|
+
this.handleModalClose();
|
|
77
|
+
}
|
|
78
|
+
}
|
|
79
|
+
|
|
80
|
+
private handleModalToggle() {
|
|
81
|
+
this.dispatchEvent(
|
|
82
|
+
new CustomEvent("togglemodal", {
|
|
83
|
+
bubbles: true
|
|
84
|
+
})
|
|
85
|
+
);
|
|
86
|
+
}
|
|
87
|
+
|
|
64
88
|
private handleModalClose() {
|
|
65
|
-
this.dispatchEvent(
|
|
89
|
+
this.dispatchEvent(
|
|
90
|
+
new CustomEvent("closemodal", {
|
|
91
|
+
bubbles: true
|
|
92
|
+
})
|
|
93
|
+
);
|
|
94
|
+
}
|
|
95
|
+
|
|
96
|
+
private handleSignUpClick(e: PointerEvent) {
|
|
97
|
+
if (this.href.includes("signup")) {
|
|
98
|
+
const payload = {
|
|
99
|
+
click_text: this.buttonCta,
|
|
100
|
+
element_title: "dx-button",
|
|
101
|
+
element_type: "card",
|
|
102
|
+
click_url: this.href,
|
|
103
|
+
content_category: "cta"
|
|
104
|
+
};
|
|
105
|
+
track(e.currentTarget!, "custEv_signupStart", payload);
|
|
106
|
+
track(e.currentTarget!, "custEv_linkClick", payload);
|
|
107
|
+
}
|
|
66
108
|
}
|
|
67
109
|
}
|
|
@@ -174,6 +174,15 @@ export default class CodeBlock extends LightningElement {
|
|
|
174
174
|
this.selectedLanguageLabel = this.selectedLanguage.label;
|
|
175
175
|
this.selectedLanguageId = this.selectedLanguage.id;
|
|
176
176
|
this.formatCodeBlock();
|
|
177
|
+
|
|
178
|
+
gtmTrack(newLang, "custEv_ctaLinkClick", {
|
|
179
|
+
event: "custEv_ctaLinkClick",
|
|
180
|
+
click_text: newLang.detail,
|
|
181
|
+
element_title: "dx-dropdown",
|
|
182
|
+
click_url: this.selectedLanguageId,
|
|
183
|
+
element_type: "link",
|
|
184
|
+
content_category: "code block"
|
|
185
|
+
});
|
|
177
186
|
}
|
|
178
187
|
|
|
179
188
|
/**
|
|
@@ -181,8 +190,11 @@ export default class CodeBlock extends LightningElement {
|
|
|
181
190
|
* https://github.com/storybookjs/storybook/issues/13529
|
|
182
191
|
*/
|
|
183
192
|
async copySource(event: any) {
|
|
184
|
-
gtmTrack(event.target, "
|
|
185
|
-
|
|
193
|
+
gtmTrack(event.target, "custEv_iconClick", {
|
|
194
|
+
click_text: this.copyBtnText,
|
|
195
|
+
element_type: "icon",
|
|
196
|
+
element_title: "dx-icon",
|
|
197
|
+
content_category: "code block"
|
|
186
198
|
});
|
|
187
199
|
|
|
188
200
|
try {
|
|
@@ -206,8 +218,11 @@ export default class CodeBlock extends LightningElement {
|
|
|
206
218
|
this.theme = this.theme === DARK ? LIGHT : DARK;
|
|
207
219
|
setLocalStorageData(LOCAL_STORAGE_KEY, this.theme);
|
|
208
220
|
|
|
209
|
-
gtmTrack(event.target, "
|
|
210
|
-
|
|
221
|
+
gtmTrack(event.target, "custEv_iconClick", {
|
|
222
|
+
click_text: this.updateThemeBtnText,
|
|
223
|
+
element_type: "icon",
|
|
224
|
+
element_title: "dx-icon",
|
|
225
|
+
content_category: "code block"
|
|
211
226
|
});
|
|
212
227
|
}
|
|
213
228
|
|
|
@@ -21,9 +21,8 @@
|
|
|
21
21
|
>
|
|
22
22
|
<template for:each={options} for:item="option" for:index="index">
|
|
23
23
|
<dx-dropdown-option
|
|
24
|
-
suppress-gtm-nav-headings={suppressGtmNavHeadings}
|
|
25
24
|
analytics-event={analyticsEvent}
|
|
26
|
-
analytics-
|
|
25
|
+
analytics-payload={analyticsPayload}
|
|
27
26
|
active={option.active}
|
|
28
27
|
key-value={option.keyValue}
|
|
29
28
|
if:false={option.options}
|
|
@@ -44,9 +43,8 @@
|
|
|
44
43
|
<span class="menu_heading">{option.label}</span>
|
|
45
44
|
<template for:each={option.options} for:item="suboption">
|
|
46
45
|
<dx-dropdown-option
|
|
47
|
-
suppress-gtm-nav-headings={suppressGTMNavHeadings}
|
|
48
46
|
analytics-event={analyticsEvent}
|
|
49
|
-
analytics-
|
|
47
|
+
analytics-payload={analyticsPayload}
|
|
50
48
|
active={suboption.active}
|
|
51
49
|
key={suboption.id}
|
|
52
50
|
key-value={suboption.keyValue}
|
|
@@ -38,13 +38,8 @@ export default class Dropdown extends LightningElement {
|
|
|
38
38
|
@api variant: DropdownVariant = "base";
|
|
39
39
|
|
|
40
40
|
// props forwarded to dropdown option
|
|
41
|
-
@api analyticsEvent
|
|
42
|
-
@api
|
|
43
|
-
elementType: "dropdown",
|
|
44
|
-
destinationType: "internal",
|
|
45
|
-
ctaClick: true
|
|
46
|
-
};
|
|
47
|
-
@api suppressGtmNavHeadings?: boolean = false;
|
|
41
|
+
@api analyticsEvent?: string;
|
|
42
|
+
@api analyticsPayload?: AnalyticsPayload;
|
|
48
43
|
|
|
49
44
|
@api
|
|
50
45
|
get options() {
|
|
@@ -9,12 +9,11 @@ import { track } from "dxUtils/analytics";
|
|
|
9
9
|
|
|
10
10
|
export default class DropdownOption extends LightningElement {
|
|
11
11
|
@api option!: OptionWithNested;
|
|
12
|
-
@api suppressGtmNavHeadings: boolean = false;
|
|
13
12
|
@api keyValue!: string;
|
|
14
13
|
@api active: boolean = false;
|
|
15
14
|
@api navItemLabel: String | null = null;
|
|
16
15
|
@api analyticsEvent: string | null = null;
|
|
17
|
-
@api
|
|
16
|
+
@api analyticsPayload?: AnalyticsPayload | undefined;
|
|
18
17
|
@api indexPosition: number = 0;
|
|
19
18
|
@api variant: DropdownVariant = "base";
|
|
20
19
|
|
|
@@ -43,25 +42,16 @@ export default class DropdownOption extends LightningElement {
|
|
|
43
42
|
new CustomEvent("select", { detail: this.keyValue })
|
|
44
43
|
);
|
|
45
44
|
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
if (!this.suppressGtmNavHeadings) {
|
|
58
|
-
payload.navHeading = navHeading;
|
|
59
|
-
payload.navSubHeading = navSubHeading;
|
|
60
|
-
payload.pageLocation = window.location.pathname;
|
|
61
|
-
}
|
|
62
|
-
|
|
63
|
-
if (this.analyticsEvent && e.currentTarget) {
|
|
64
|
-
track(e.currentTarget, this.analyticsEvent, payload);
|
|
45
|
+
if (this.analyticsEvent && this.analyticsPayload && e.currentTarget) {
|
|
46
|
+
track(e.currentTarget, this.analyticsEvent, {
|
|
47
|
+
...this.analyticsPayload,
|
|
48
|
+
click_text: this.option.label,
|
|
49
|
+
click_url: this.option.link?.href,
|
|
50
|
+
element_type: this.analyticsPayload?.element_type || "dropdown",
|
|
51
|
+
...(this.analyticsPayload?.nav_type
|
|
52
|
+
? { nav_item: this.option.label }
|
|
53
|
+
: {})
|
|
54
|
+
});
|
|
65
55
|
}
|
|
66
56
|
}
|
|
67
57
|
}
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import { LightningElement, api } from "lwc";
|
|
2
|
+
import { track } from "dxUtils/analytics";
|
|
2
3
|
|
|
3
4
|
export default class Feature extends LightningElement {
|
|
4
5
|
@api label!: string;
|
|
@@ -31,4 +32,16 @@ export default class Feature extends LightningElement {
|
|
|
31
32
|
get iconSymbol(): string {
|
|
32
33
|
return this.isExternalLink ? "new_window" : "";
|
|
33
34
|
}
|
|
35
|
+
|
|
36
|
+
handleClick(event: Event) {
|
|
37
|
+
const payload = {
|
|
38
|
+
click_text: this.buttonLabel,
|
|
39
|
+
element_title: "dx-button",
|
|
40
|
+
click_url: this.buttonHref,
|
|
41
|
+
element_type: "button",
|
|
42
|
+
content_category: "cta"
|
|
43
|
+
};
|
|
44
|
+
track(event.target!, "custEv_ctaButtonClick", payload);
|
|
45
|
+
track(event.target!, "custEv_linkClick", payload);
|
|
46
|
+
}
|
|
34
47
|
}
|
|
@@ -4,6 +4,7 @@ import { LightningSlotElement } from "typings/custom";
|
|
|
4
4
|
import { isSlotEmpty } from "dxUtils/slot";
|
|
5
5
|
import { toJson } from "dxUtils/normalizers";
|
|
6
6
|
import { ImageAndLabel } from "../imageAndLabel";
|
|
7
|
+
import { track } from "dxUtils/analytics";
|
|
7
8
|
import svgs from "./svgs";
|
|
8
9
|
|
|
9
10
|
export default class FeaturedContentHeader extends LightningElement {
|
|
@@ -32,14 +33,19 @@ export default class FeaturedContentHeader extends LightningElement {
|
|
|
32
33
|
private _authors?: Array<ImageAndLabel>;
|
|
33
34
|
private isSlotEmpty: boolean = true;
|
|
34
35
|
private isLinkHovered: boolean = false;
|
|
35
|
-
|
|
36
|
+
private progressPodcastPlayed = {
|
|
37
|
+
percent25: false,
|
|
38
|
+
percent50: false,
|
|
39
|
+
percent75: false,
|
|
40
|
+
percent100: false
|
|
41
|
+
};
|
|
36
42
|
// ! Move this map away from the component and probably the filter too.
|
|
37
43
|
@api
|
|
38
44
|
get authors() {
|
|
39
45
|
if (this._authors && this._authors.length) {
|
|
40
46
|
return this._authors!.map((author, index) => ({
|
|
41
47
|
...author,
|
|
42
|
-
imgSrc: author.
|
|
48
|
+
imgSrc: author.image_src,
|
|
43
49
|
key: index
|
|
44
50
|
}));
|
|
45
51
|
}
|
|
@@ -103,6 +109,57 @@ export default class FeaturedContentHeader extends LightningElement {
|
|
|
103
109
|
|
|
104
110
|
private onSlotChange(e: LightningSlotElement): void {
|
|
105
111
|
this.isSlotEmpty = isSlotEmpty(e);
|
|
112
|
+
const slot = e.target;
|
|
113
|
+
const slotElements = slot.assignedElements();
|
|
114
|
+
|
|
115
|
+
if (slotElements.length) {
|
|
116
|
+
const slotContentElement = slotElements[0];
|
|
117
|
+
const playerElement = slotContentElement.shadowRoot.querySelector(
|
|
118
|
+
"audio"
|
|
119
|
+
) as HTMLAudioElement;
|
|
120
|
+
if (playerElement) {
|
|
121
|
+
playerElement.addEventListener("play", (event: Event) => {
|
|
122
|
+
const playerState = this.handlePlayerState(playerElement);
|
|
123
|
+
this.trackAnalytics(
|
|
124
|
+
event,
|
|
125
|
+
"play",
|
|
126
|
+
playerState.timePlayed,
|
|
127
|
+
playerState.percentagePlayed
|
|
128
|
+
);
|
|
129
|
+
});
|
|
130
|
+
|
|
131
|
+
playerElement.addEventListener("pause", (event: Event) => {
|
|
132
|
+
const playerState = this.handlePlayerState(playerElement);
|
|
133
|
+
this.trackAnalytics(
|
|
134
|
+
event,
|
|
135
|
+
"pause",
|
|
136
|
+
playerState.timePlayed,
|
|
137
|
+
playerState.percentagePlayed
|
|
138
|
+
);
|
|
139
|
+
});
|
|
140
|
+
|
|
141
|
+
playerElement.addEventListener("timeupdate", (event: Event) => {
|
|
142
|
+
const playerState = this.handlePlayerState(playerElement);
|
|
143
|
+
if (
|
|
144
|
+
(playerState.percentagePlayed === 25 &&
|
|
145
|
+
!this.progressPodcastPlayed.percent25) ||
|
|
146
|
+
(playerState.percentagePlayed === 50 &&
|
|
147
|
+
!this.progressPodcastPlayed.percent50) ||
|
|
148
|
+
(playerState.percentagePlayed === 75 &&
|
|
149
|
+
!this.progressPodcastPlayed.percent75) ||
|
|
150
|
+
(playerState.percentagePlayed === 100 &&
|
|
151
|
+
!this.progressPodcastPlayed.percent100)
|
|
152
|
+
) {
|
|
153
|
+
this.trackAnalytics(
|
|
154
|
+
event,
|
|
155
|
+
"progress",
|
|
156
|
+
playerState.timePlayed,
|
|
157
|
+
playerState.percentagePlayed
|
|
158
|
+
);
|
|
159
|
+
}
|
|
160
|
+
});
|
|
161
|
+
}
|
|
162
|
+
}
|
|
106
163
|
}
|
|
107
164
|
|
|
108
165
|
renderedCallback(): void {
|
|
@@ -119,4 +176,61 @@ export default class FeaturedContentHeader extends LightningElement {
|
|
|
119
176
|
}
|
|
120
177
|
}
|
|
121
178
|
}
|
|
179
|
+
|
|
180
|
+
private trackAnalytics(
|
|
181
|
+
event: Event,
|
|
182
|
+
action: "play" | "pause" | "progress",
|
|
183
|
+
timePlayed: number,
|
|
184
|
+
percentagePlayed: number
|
|
185
|
+
) {
|
|
186
|
+
let trackEvent = null;
|
|
187
|
+
switch (action) {
|
|
188
|
+
case "play":
|
|
189
|
+
trackEvent = "custEv_podcastPlay";
|
|
190
|
+
break;
|
|
191
|
+
case "pause":
|
|
192
|
+
trackEvent = "custEv_podcastPause";
|
|
193
|
+
break;
|
|
194
|
+
case "progress":
|
|
195
|
+
trackEvent = "custEv_podcastProgress";
|
|
196
|
+
break;
|
|
197
|
+
default:
|
|
198
|
+
trackEvent = null;
|
|
199
|
+
}
|
|
200
|
+
|
|
201
|
+
if (!trackEvent) {
|
|
202
|
+
return;
|
|
203
|
+
}
|
|
204
|
+
|
|
205
|
+
track(event.target!, trackEvent, {
|
|
206
|
+
media_name: this.title,
|
|
207
|
+
media_action: action,
|
|
208
|
+
media_episode: this.href,
|
|
209
|
+
media_percentage_played: percentagePlayed,
|
|
210
|
+
media_seconds_played: timePlayed,
|
|
211
|
+
media_type: "podcast"
|
|
212
|
+
});
|
|
213
|
+
|
|
214
|
+
if (Math.trunc(percentagePlayed) === 25) {
|
|
215
|
+
this.progressPodcastPlayed.percent25 = true;
|
|
216
|
+
} else if (Math.trunc(percentagePlayed) === 50) {
|
|
217
|
+
this.progressPodcastPlayed.percent50 = true;
|
|
218
|
+
} else if (Math.trunc(percentagePlayed) === 75) {
|
|
219
|
+
this.progressPodcastPlayed.percent75 = true;
|
|
220
|
+
} else if (Math.trunc(percentagePlayed) === 100) {
|
|
221
|
+
this.progressPodcastPlayed.percent100 = true;
|
|
222
|
+
}
|
|
223
|
+
}
|
|
224
|
+
|
|
225
|
+
private handlePlayerState(player: HTMLAudioElement) {
|
|
226
|
+
let timePlayed = 0;
|
|
227
|
+
let percentagePlayed = 0;
|
|
228
|
+
if (player) {
|
|
229
|
+
timePlayed = player.currentTime / 1000;
|
|
230
|
+
percentagePlayed = Math.trunc(
|
|
231
|
+
(player.currentTime * 100) / player.duration
|
|
232
|
+
);
|
|
233
|
+
}
|
|
234
|
+
return { timePlayed, percentagePlayed };
|
|
235
|
+
}
|
|
122
236
|
}
|
|
@@ -44,6 +44,11 @@ footer.signup-variant-no-signup {
|
|
|
44
44
|
color: var(--dx-g-blue-vibrant-20);
|
|
45
45
|
}
|
|
46
46
|
|
|
47
|
+
.term-icon {
|
|
48
|
+
width: 35px;
|
|
49
|
+
margin: 0 var(--dx-g-spacing-xs);
|
|
50
|
+
}
|
|
51
|
+
|
|
47
52
|
/* TOP */
|
|
48
53
|
|
|
49
54
|
.content-container_top {
|
|
@@ -402,4 +407,8 @@ footer.signup-variant-no-signup {
|
|
|
402
407
|
.subscription dx-input {
|
|
403
408
|
width: 100%;
|
|
404
409
|
}
|
|
410
|
+
|
|
411
|
+
.term-icon {
|
|
412
|
+
margin-left: 0;
|
|
413
|
+
}
|
|
405
414
|
}
|
|
@@ -139,6 +139,12 @@
|
|
|
139
139
|
</template>
|
|
140
140
|
<template if:false={term.onclick}>
|
|
141
141
|
<a href={term.href} key={term.label} rel={term.rel}>
|
|
142
|
+
<img
|
|
143
|
+
if:true={term.img}
|
|
144
|
+
class="term-icon"
|
|
145
|
+
src={term.img}
|
|
146
|
+
alt="Footer Term Icon"
|
|
147
|
+
/>
|
|
142
148
|
{term.label}
|
|
143
149
|
</a>
|
|
144
150
|
</template>
|