@salesforcedevs/dx-components 0.16.0 → 0.17.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/lwc.config.json CHANGED
@@ -26,7 +26,7 @@
26
26
  "dx/featuredContentHeader",
27
27
  "dx/featureGrid",
28
28
  "dx/featuresList",
29
- "dx/feedbackBanner",
29
+ "dx/banner",
30
30
  "dx/footer",
31
31
  "dx/newsletterForm",
32
32
  "dx/formattedDateTime",
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@salesforcedevs/dx-components",
3
- "version": "0.16.0",
3
+ "version": "0.17.0",
4
4
  "description": "DX Lightning web components",
5
5
  "license": "MIT",
6
6
  "engines": {
@@ -29,5 +29,5 @@
29
29
  "@types/debounce": "^1.2.0",
30
30
  "@types/lodash.get": "^4.4.6"
31
31
  },
32
- "gitHead": "27aac9b260986d3bd145401c4ce66594314c74e9"
32
+ "gitHead": "b7a26c9e46cee9298b3ebc7cbea85930320b83a0"
33
33
  }
@@ -0,0 +1,31 @@
1
+ import Banner from "dx/banner";
2
+ import { createRenderComponent } from "utils/tests";
3
+
4
+ const TAG = "dx-banner";
5
+ const render = createRenderComponent(TAG, Banner);
6
+
7
+ describe(TAG, () => {
8
+ it("renders banner component", () => {
9
+ const element = render();
10
+
11
+ const innerContainer = element.shadowRoot.querySelectorAll(
12
+ ".container_inner"
13
+ );
14
+
15
+ expect(innerContainer).not.toBeNull();
16
+
17
+ return expect(element).toBeAccessible();
18
+ });
19
+
20
+ it("renders custom banner markup in the banner", () => {
21
+ const element = render({ bannerMarkup: "Give feedback about our new site" });
22
+
23
+ const bannerContainer = element.shadowRoot.querySelector(
24
+ ".info-container"
25
+ );
26
+
27
+ return Promise.resolve().then(() => {
28
+ expect(bannerContainer.innerHTML).toContain('Give feedback about our new site')
29
+ });
30
+ });
31
+ });
@@ -1,7 +1,7 @@
1
1
  @import "helpers/reset";
2
2
  @import "helpers/text";
3
3
 
4
- .feedback {
4
+ .container {
5
5
  --primary-color: var(--dx-g-cloud-blue-vibrant-50);
6
6
  --secondary-color: var(--dx-g-cloud-blue-vibrant-40);
7
7
 
@@ -21,26 +21,26 @@
21
21
  );
22
22
  }
23
23
 
24
- .feedback_inner {
24
+ .container_inner {
25
25
  height: 100%;
26
26
  display: flex;
27
- align-items: center;
28
27
  background: var(--primary-color);
29
28
  padding: var(--dx-g-spacing-xs) var(--dx-g-spacing-sm);
30
29
  color: white;
31
30
  font-weight: bold;
32
31
  }
33
32
 
34
- .feedback a {
33
+ .container a {
35
34
  text-decoration: underline;
36
35
  transition: var(--dx-g-transition-hue-1x);
37
36
  margin-right: 4px;
38
37
  }
39
38
 
40
- .feedback a:hover {
39
+ .container a:hover {
41
40
  opacity: 0.8;
42
41
  }
43
42
 
44
- .feedback dx-icon {
43
+ .container dx-icon {
45
44
  margin-right: var(--dx-g-spacing-sm);
45
+ margin-top:var( --dx-g-spacing-2xs)
46
46
  }
@@ -0,0 +1,13 @@
1
+ <template>
2
+ <div class="container">
3
+ <div class="container_inner dx-text-body-4">
4
+ <dx-icon symbol="announcement"></dx-icon>
5
+ <!--
6
+ NOTE: Here we are rendering mark up using lwc:dom & innerHTML
7
+ option instead of slots because the html markup will come as a
8
+ property to the component from a configuration
9
+ -->
10
+ <div lwc:dom="manual" class="info-container"></div>
11
+ </div>
12
+ </div>
13
+ </template>
@@ -0,0 +1,14 @@
1
+ import { LightningElement, api } from "lwc";
2
+
3
+ export default class Banner extends LightningElement {
4
+ @api bannerMarkup =
5
+ '<span><a href="https://forms.gle/TdSyKFPHXoBx7seM9" target="blank">Share your feedback</a>about our new site.</span>';
6
+
7
+ renderedCallback(){
8
+ const container = this.template.querySelector(".info-container");
9
+ if(container){
10
+ // eslint-disable-next-line @lwc/lwc/no-inner-html
11
+ container.innerHTML = this.bannerMarkup
12
+ }
13
+ }
14
+ }
@@ -21,6 +21,7 @@
21
21
  >
22
22
  <template for:each={options} for:item="option">
23
23
  <dx-dropdown-option
24
+ analytics-event={analyticsEvent}
24
25
  active={option.active}
25
26
  key-value={option.keyValue}
26
27
  if:false={option.options}
@@ -39,6 +40,7 @@
39
40
  <span class="menu_heading">{option.label}</span>
40
41
  <template for:each={option.options} for:item="suboption">
41
42
  <dx-dropdown-option
43
+ analytics-event={analyticsEvent}
42
44
  active={suboption.active}
43
45
  key={suboption.id}
44
46
  key-value={suboption.keyValue}
@@ -29,8 +29,10 @@ export default class Dropdown extends LightningElement {
29
29
  @api small?: boolean = false;
30
30
  @api openOnHover?: boolean = false; // dropdown opens/closes with hover
31
31
  @api width?: string | null = null;
32
- @api fullWidth?: boolean | null;
33
- @api navItemLabel: string | null = null;
32
+ @api fullWidth?: boolean | null; @api navItemLabel: string | null = null;
33
+
34
+ // props forwarded to dropdown option
35
+ @api analyticsEvent: string | null = null
34
36
 
35
37
  @api
36
38
  get options() {
@@ -1,6 +1,7 @@
1
1
  import DropdownOption from "dx/dropdownOption";
2
2
  import { createRenderComponent } from "utils/tests";
3
3
  import { MOCK_BUTTON_PROPS, MOCK_LINK_PROPS } from "./mockProps";
4
+ import * as instrumentation from "dx/instrumentation";
4
5
 
5
6
  const TAG = "dx-dropdown-option";
6
7
  const render = createRenderComponent(TAG, DropdownOption);
@@ -13,6 +14,10 @@ const appendToMenu = (element: HTMLElement) => {
13
14
  };
14
15
 
15
16
  describe(TAG, () => {
17
+ beforeEach(() => {
18
+ jest.clearAllMocks();
19
+ });
20
+
16
21
  it("renders a button by default", () => {
17
22
  const component = render(MOCK_BUTTON_PROPS);
18
23
  expect(component.shadowRoot.querySelector("button")).not.toBeNull();
@@ -23,8 +28,8 @@ describe(TAG, () => {
23
28
 
24
29
  it("renders the correct label, description, and img", () => {
25
30
  const component = render(MOCK_BUTTON_PROPS);
26
- const label = component.shadowRoot.querySelector(".option_label")
27
- .textContent;
31
+ const label =
32
+ component.shadowRoot.querySelector(".option_label").textContent;
28
33
  expect(label).toEqual(MOCK_BUTTON_PROPS.option.label);
29
34
 
30
35
  const description = component.shadowRoot.querySelector(
@@ -79,4 +84,29 @@ describe(TAG, () => {
79
84
 
80
85
  expect(onClickMock).toBeCalled();
81
86
  });
87
+
88
+ it("fires analytics when given an analytics event", () => {
89
+ const track = jest.spyOn(instrumentation, "track");
90
+
91
+ const component = render({
92
+ ...MOCK_BUTTON_PROPS,
93
+ analyticsEvent: "mock"
94
+ });
95
+
96
+ const option = component.shadowRoot.querySelector(".option");
97
+ option.click();
98
+
99
+ expect(track).toHaveBeenCalledTimes(1);
100
+ });
101
+
102
+ it("doesn't fire analytics when not given an analytics event", () => {
103
+ const track = jest.spyOn(instrumentation, "track");
104
+
105
+ const component = render(MOCK_BUTTON_PROPS);
106
+
107
+ const option = component.shadowRoot.querySelector(".option");
108
+ option.click();
109
+
110
+ expect(track).not.toHaveBeenCalled();
111
+ });
82
112
  });
@@ -8,6 +8,7 @@ export default class DropdownOption extends LightningElement {
8
8
  @api keyValue!: string;
9
9
  @api active: boolean = false;
10
10
  @api navItemLabel: String | null = null;
11
+ @api analyticsEvent: string | null = null;
11
12
 
12
13
  @api focus() {
13
14
  const option = this.template.querySelector(".option");
@@ -26,11 +27,13 @@ export default class DropdownOption extends LightningElement {
26
27
  new CustomEvent("select", { detail: this.keyValue })
27
28
  );
28
29
 
29
- track(e.currentTarget, "custEv_topNavLinkClick", {
30
- navHeading: this.navItemLabel || undefined,
31
- navSubHeading: this.option.label || undefined,
32
- clickText: this.keyValue || undefined,
33
- pageLocation: window.location.pathname || undefined
34
- });
30
+ if (this.analyticsEvent && e.currentTarget) {
31
+ track(e.currentTarget, this.analyticsEvent, {
32
+ navHeading: this.navItemLabel || undefined,
33
+ navSubHeading: this.option.label || undefined,
34
+ clickText: this.keyValue || undefined,
35
+ pageLocation: window.location.pathname || undefined
36
+ });
37
+ }
35
38
  }
36
39
  }
@@ -25,8 +25,9 @@ img {
25
25
  }
26
26
 
27
27
  .size-small img {
28
+ max-width: 250px;
29
+ min-width: unset;
28
30
  width: calc(100% - 40px);
29
- min-width: calc(100% - 40px);
30
31
  }
31
32
 
32
33
  .text {
@@ -14,6 +14,12 @@ import { track } from "dx/instrumentation";
14
14
  const createNewsletterSignupHref = (email: string): string =>
15
15
  `/newsletter?subscriberEmail=${email}`;
16
16
 
17
+ const ANALYTICS_INFO = {
18
+ itemTitle: "Newsletter Sign Up Footer",
19
+ elementType: "button",
20
+ destinationType: "internal",
21
+ ctaClick: true
22
+ };
17
23
  export default class Footer extends LightningElement {
18
24
  @api locale: string | null = null;
19
25
  @api
@@ -85,7 +91,13 @@ export default class Footer extends LightningElement {
85
91
 
86
92
  private onSubmitEmail = async (e: CustomEvent) => {
87
93
  const href = createNewsletterSignupHref(e.detail);
88
- track(e.currentTarget, "custEv_newsletterSubscriptionStart");
94
+
95
+ track(e.currentTarget, "custEv_ctaButtonClick", {
96
+ ...ANALYTICS_INFO,
97
+ clickText: e.detail,
98
+ clickUrl: href,
99
+ });
100
+
89
101
  window.location.assign(href);
90
102
  };
91
103
 
@@ -9,23 +9,20 @@ import {
9
9
  mockPropsNoNavigation
10
10
  } from "./mockProps";
11
11
  import { track } from "dx/instrumentation";
12
+ import { ANALYTICS_INFO } from "utils/headerBase";
12
13
 
13
14
  const TAG = "dx-header";
14
15
  const render = createRenderComponent(TAG, Header);
15
16
 
16
17
  jest.mock("dx/instrumentation");
17
18
 
18
- const GTM_EVENT_NAME = "custEv_signupStart";
19
- const SIGN_UP_LABEL = "Sign Up";
20
-
21
19
  describe("dx-header", () => {
22
20
  it("renders", () => {
23
21
  const subtitle = "testsubtitle";
24
22
  const element = render({ ...mockPropsDevelopers, subtitle });
25
23
  const subtitleEl = element.shadowRoot.querySelector(".subtitle");
26
- const buttons: Array<HTMLElement> = element.shadowRoot.querySelectorAll(
27
- "dx-button"
28
- );
24
+ const buttons: Array<HTMLElement> =
25
+ element.shadowRoot.querySelectorAll("dx-button");
29
26
  const dropdown = element.shadowRoot.querySelector("dx-dropdown");
30
27
  const headerEl = element.shadowRoot.querySelector("dx-header-nav");
31
28
 
@@ -88,9 +85,8 @@ describe("dx-header", () => {
88
85
  ...mockPropsDevelopers,
89
86
  versions: JSON.stringify([version])
90
87
  });
91
- const dropdown: Dropdown = element.shadowRoot.querySelector(
92
- "dx-dropdown"
93
- );
88
+ const dropdown: Dropdown =
89
+ element.shadowRoot.querySelector("dx-dropdown");
94
90
  expect(dropdown).not.toBeNull();
95
91
  expect(dropdown.options).toHaveLength(1);
96
92
 
@@ -180,9 +176,8 @@ describe("dx-header", () => {
180
176
  bailLabel: "test",
181
177
  signupLink: "/"
182
178
  });
183
- const buttons: Array<Button> = element.shadowRoot.querySelectorAll(
184
- "dx-button"
185
- );
179
+ const buttons: Array<Button> =
180
+ element.shadowRoot.querySelectorAll("dx-button");
186
181
 
187
182
  expect(buttons[0].href).toEqual("/");
188
183
  expect(buttons[2].href).toEqual("test");
@@ -194,26 +189,48 @@ describe("dx-header", () => {
194
189
  subtitle: mockPropsDevelopers.subtitle,
195
190
  navItems: mockPropsDevelopers.navItems
196
191
  });
197
- const headerSearch = element.shadowRoot.querySelector(
198
- "dx-header-search"
199
- );
192
+ const headerSearch =
193
+ element.shadowRoot.querySelector("dx-header-search");
200
194
 
201
195
  expect(headerSearch).toBeNull();
202
196
  return expect(element).toBeAccessible();
203
197
  });
204
198
 
205
- it("signup button track is beign called", () => {
199
+ it("signup button track is being called", () => {
206
200
  const element = render(mockPropsDevelopers);
207
201
 
208
- const button: HTMLElement = element.shadowRoot.querySelector(
209
- "dx-button"
210
- );
202
+ const button: HTMLElement =
203
+ element.shadowRoot.querySelector("dx-button");
211
204
 
212
205
  button.click();
213
206
 
214
207
  expect(track).toBeCalledTimes(1);
215
- expect(track).toBeCalledWith(button, GTM_EVENT_NAME, {
216
- clickText: SIGN_UP_LABEL
208
+ expect(track).toBeCalledWith(button, "custEv_signupStart", {
209
+ ...ANALYTICS_INFO,
210
+ clickUrl: "/sign-up"
217
211
  });
218
212
  });
213
+
214
+ it("hides signup button when signupLink property is empty", () => {
215
+ const updatedMockPropsDevelopers = {
216
+ ...mockPropsDevelopers,
217
+ signupLink: ""
218
+ };
219
+ const element = render(updatedMockPropsDevelopers);
220
+ const signupButtonContainer: HTMLElement =
221
+ element.shadowRoot.querySelector(".header-login-signup");
222
+ expect(signupButtonContainer).toBeNull();
223
+ });
224
+
225
+ it("hides banner when banner markup is empty", () => {
226
+ const bannerMarkup = "";
227
+ const updatedMockPropsDevelopers = {
228
+ ...mockPropsDevelopers,
229
+ bannerMarkup
230
+ };
231
+ const element = render(updatedMockPropsDevelopers);
232
+ const bannerElement: HTMLElement =
233
+ element.shadowRoot.querySelector("dx-banner");
234
+ expect(bannerElement).toBeNull();
235
+ });
219
236
  });
@@ -37,6 +37,7 @@ const versions = JSON.stringify([
37
37
  export const mockPropsDevelopers = {
38
38
  navItems: JSON.stringify(mockNavDevelopers),
39
39
  subtitle: "Developers",
40
+ signupLink: "/sign-up",
40
41
  ...coveoConfig
41
42
  };
42
43
 
@@ -45,15 +46,22 @@ export const mockPropsNoNavigation = {
45
46
  ...coveoConfig
46
47
  };
47
48
 
49
+ export const mockPropsDevWebsite = {
50
+ version: "1",
51
+ versions,
52
+ ...coveoConfig,
53
+ signupLink: "/sign-up",
54
+ bannerMarkup:
55
+ '<span><a href="https://forms.gle/TdSyKFPHXoBx7seM9" target="blank">Share your feedback</a>about our new site.</span>'
56
+ };
57
+
48
58
  export const mockPropsEmployees = {
49
59
  bailHref: "/quip-dev-center",
50
60
  bailLabel: "Quip Development Center",
51
61
  brand: "employees",
52
62
  navItems: JSON.stringify(mockNavEmployees),
53
63
  subtitle: "Employees",
54
- version: "1",
55
- versions,
56
- ...coveoConfig
64
+ ...mockPropsDevWebsite
57
65
  };
58
66
 
59
67
  export const mockPropsMarketing = {
@@ -62,9 +70,7 @@ export const mockPropsMarketing = {
62
70
  brand: "marketing",
63
71
  navItems: JSON.stringify(mockNavMarketing),
64
72
  subtitle: "Marketing",
65
- version: "1",
66
- versions,
67
- ...coveoConfig
73
+ ...mockPropsDevWebsite
68
74
  };
69
75
 
70
76
  export const mockPropsPartners = {
@@ -73,9 +79,7 @@ export const mockPropsPartners = {
73
79
  brand: "partners",
74
80
  navItems: JSON.stringify(mockNavPartners),
75
81
  subtitle: "Partners",
76
- version: "1",
77
- versions,
78
- ...coveoConfig
82
+ ...mockPropsDevWebsite
79
83
  };
80
84
 
81
85
  export const mockPropsCommerce = {
@@ -84,9 +88,7 @@ export const mockPropsCommerce = {
84
88
  brand: "commerce",
85
89
  navItems: JSON.stringify(mockNavCommerce),
86
90
  subtitle: "Commerce",
87
- version: "1",
88
- versions,
89
- ...coveoConfig
91
+ ...mockPropsDevWebsite
90
92
  };
91
93
 
92
94
  export const mockPropsSales = {
@@ -95,9 +97,7 @@ export const mockPropsSales = {
95
97
  brand: "sales",
96
98
  navItems: JSON.stringify(mockNavSales),
97
99
  subtitle: "Sales",
98
- version: "1",
99
- versions,
100
- ...coveoConfig
100
+ ...mockPropsDevWebsite
101
101
  };
102
102
 
103
103
  export const mockPropsSuccess = {
@@ -106,9 +106,7 @@ export const mockPropsSuccess = {
106
106
  brand: "success",
107
107
  navItems: JSON.stringify(mockNavSuccess),
108
108
  subtitle: "Success",
109
- version: "1",
110
- versions,
111
- ...coveoConfig
109
+ ...mockPropsDevWebsite
112
110
  };
113
111
 
114
112
  export const mockPropsIntegration = {
@@ -117,9 +115,7 @@ export const mockPropsIntegration = {
117
115
  brand: "integration",
118
116
  navItems: JSON.stringify(mockNavIntegration),
119
117
  subtitle: "Integration",
120
- version: "1",
121
- versions,
122
- ...coveoConfig
118
+ ...mockPropsDevWebsite
123
119
  };
124
120
 
125
121
  export const mockPropsPlatform = {
@@ -128,9 +124,7 @@ export const mockPropsPlatform = {
128
124
  brand: "platform",
129
125
  navItems: JSON.stringify(mockNavPlatform),
130
126
  subtitle: "Platform",
131
- version: "1",
132
- versions,
133
- ...coveoConfig
127
+ ...mockPropsDevWebsite
134
128
  };
135
129
 
136
130
  export const mockPropsIndustries = {
@@ -139,9 +133,7 @@ export const mockPropsIndustries = {
139
133
  brand: "industries",
140
134
  navItems: JSON.stringify(mockNavIndustries),
141
135
  subtitle: "Industries",
142
- version: "1",
143
- versions,
144
- ...coveoConfig
136
+ ...mockPropsDevWebsite
145
137
  };
146
138
 
147
139
  export const mockPropsLearning = {
@@ -150,9 +142,7 @@ export const mockPropsLearning = {
150
142
  brand: "learning",
151
143
  navItems: JSON.stringify(mockNavLearning),
152
144
  subtitle: "Learning",
153
- version: "1",
154
- versions,
155
- ...coveoConfig
145
+ ...mockPropsDevWebsite
156
146
  };
157
147
 
158
148
  export const mockPropsService = {
@@ -161,9 +151,7 @@ export const mockPropsService = {
161
151
  brand: "service",
162
152
  navItems: JSON.stringify(mockNavService),
163
153
  subtitle: "Service",
164
- version: "1",
165
- versions,
166
- ...coveoConfig
154
+ ...mockPropsDevWebsite
167
155
  };
168
156
 
169
157
  export const mockPropsAnalytics = {
@@ -172,7 +160,5 @@ export const mockPropsAnalytics = {
172
160
  brand: "analytics",
173
161
  navItems: JSON.stringify(mockNavAnalytics),
174
162
  subtitle: "Analytics",
175
- version: "1",
176
- versions,
177
- ...coveoConfig
163
+ ...mockPropsDevWebsite
178
164
  };
@@ -1,7 +1,10 @@
1
1
  <template>
2
2
  <dx-brand-theme-provider brand={brand}>
3
3
  <header class={className}>
4
- <dx-feedback-banner></dx-feedback-banner>
4
+ <dx-banner
5
+ if:true={bannerMarkup}
6
+ banner-markup={bannerMarkup}
7
+ ></dx-banner>
5
8
  <div class="header_l1">
6
9
  <dx-breadcrumbs
7
10
  title={title}
@@ -82,6 +82,8 @@ const headerStoryGenerator = (
82
82
  bail-label="Quip Development Center"
83
83
  brand="${brand}"
84
84
  breadcrumbs="${mockProps.breadcrumbs}"
85
+ signup-link="${mockProps.signupLink}"
86
+ banner-markup="${mockProps.bannerMarkup}"
85
87
  ></dx-header>`;
86
88
 
87
89
  // ALL STORIES
@@ -140,3 +142,31 @@ export const Service = () =>
140
142
  headerStoryGenerator(mockPropsService, "service", "Service");
141
143
  export const Analytics = () =>
142
144
  headerStoryGenerator(mockPropsAnalytics, "analytics", "Analytics");
145
+
146
+ export const MarketingWithoutSignup = () =>
147
+ headerStoryGenerator(
148
+ { ...mockPropsMarketing, signupLink: "" },
149
+ "marketing",
150
+ "Marketing"
151
+ );
152
+
153
+ export const MarketingWithCustomBannerText = () =>
154
+ headerStoryGenerator(
155
+ {
156
+ ...mockPropsMarketing,
157
+ bannerMarkup:
158
+ 'Salesforce Subscription Management API ("the API") is available as a developer preview. The API is not generally available unless or until Salesforce announces its general availability in documentation or in press releases or public statements. All components of the API including request names, parameters, objects, and fields are subject to change or deprecation at any time, with or without notice. Do not use the API with real data or in a production environment.'
159
+ },
160
+ "marketing",
161
+ "Marketing"
162
+ );
163
+
164
+ export const MarketingWithoutBanner = () =>
165
+ headerStoryGenerator(
166
+ {
167
+ ...mockPropsMarketing,
168
+ bannerMarkup: ""
169
+ },
170
+ "marketing",
171
+ "Marketing"
172
+ );
@@ -10,12 +10,15 @@ export default class Header extends HeaderBase {
10
10
  get breadcrumbs() {
11
11
  return this._breadcrumbs;
12
12
  }
13
+
13
14
  set breadcrumbs(value) {
14
15
  this._breadcrumbs = toJson(value);
15
16
  }
16
17
 
17
18
  private get showSignup(): boolean {
18
- return (this.mobile && !this.isSearchOpen) || !this.mobile;
19
+ return this.signupLink
20
+ ? (this.mobile && !this.isSearchOpen) || !this.mobile
21
+ : false;
19
22
  }
20
23
 
21
24
  protected mobileBreakpoint(): string {
@@ -13,6 +13,7 @@
13
13
 
14
14
  <!-- DESKTOP "MORE CONTENT" NAV ITEM -->
15
15
  <dx-dropdown
16
+ analytics-event="custEv_topNavLinkClick"
16
17
  if:true={navItem.options}
17
18
  nav-item-label={navItem.label}
18
19
  open-on-hover
@@ -2,6 +2,18 @@ import { LightningElement, api } from "lwc";
2
2
  import { track } from "dx/instrumentation";
3
3
  import { CountryOptions, CheckboxTextSet } from "typings/custom";
4
4
 
5
+ const ANALYTICS_INFO = {
6
+ itemTitle: "newsletter sign up submit",
7
+ formName: "newsletter",
8
+ formType: "newsletter",
9
+ method: "email",
10
+ destinationType: "internal",
11
+ clickText: "Subscribe Now",
12
+ clickUrl: "/newsletter/success",
13
+ elementType: "button",
14
+ ctaClick: true
15
+ };
16
+
5
17
  export default class Form extends LightningElement {
6
18
  @api checkboxTextSet: string = "";
7
19
  @api countries: string = "";
@@ -134,16 +146,13 @@ export default class Form extends LightningElement {
134
146
  submitButtonEl.textContent = "...Processing request";
135
147
 
136
148
  try {
137
- const res = await fetch(
138
- "/pages/pardot/footer_optin",
139
- {
140
- method: "POST",
141
- headers: {
142
- "Content-Type": "application/json"
143
- },
144
- body: JSON.stringify(formData)
145
- }
146
- );
149
+ const res = await fetch("/pages/pardot/footer_optin", {
150
+ method: "POST",
151
+ headers: {
152
+ "Content-Type": "application/json"
153
+ },
154
+ body: JSON.stringify(formData)
155
+ });
147
156
 
148
157
  if (!res.ok) {
149
158
  throw new Error(errorMsg);
@@ -156,7 +165,7 @@ export default class Form extends LightningElement {
156
165
  }
157
166
 
158
167
  // GTM event
159
- track(submitButtonEl, "custEv_newsletterSubscription");
168
+ track(submitButtonEl, "custEv_formCompletion", ANALYTICS_INFO);
160
169
 
161
170
  window.location.assign("/newsletter/success");
162
171
  } catch (error) {
@@ -18,7 +18,14 @@ const VALID_BRANDS = [
18
18
  "service",
19
19
  "success"
20
20
  ];
21
- const SIGN_UP_LABEL = "Sign Up";
21
+
22
+ export const ANALYTICS_INFO = {
23
+ clickText: "Sign Up",
24
+ itemTitle: "Sign Up Header Button",
25
+ elementType: "button",
26
+ destinationType: "internal",
27
+ ctaClick: true
28
+ };
22
29
 
23
30
  export abstract class HeaderBase extends LightningElement {
24
31
  @api bailHref?: string | null = null;
@@ -33,6 +40,9 @@ export abstract class HeaderBase extends LightningElement {
33
40
  @api subtitle!: string;
34
41
  @api title: string = "Salesforce";
35
42
  @api version?: string | null = null;
43
+ @api bannerMarkup =
44
+ '<span><a href="https://forms.gle/TdSyKFPHXoBx7seM9" target="blank">Share your feedback</a>about our new site.</span>';
45
+
36
46
 
37
47
  @api
38
48
  get navItems() {
@@ -182,7 +192,8 @@ export abstract class HeaderBase extends LightningElement {
182
192
 
183
193
  private handleSignUpClick(e: PointerEvent) {
184
194
  track(e.currentTarget!, "custEv_signupStart", {
185
- clickText: SIGN_UP_LABEL
195
+ ...ANALYTICS_INFO,
196
+ clickUrl: this.signupLink,
186
197
  });
187
198
  }
188
199
 
@@ -1,19 +0,0 @@
1
- import FeedbackBanner from "dx/feedbackBanner";
2
- import { createRenderComponent } from "utils/tests";
3
-
4
- const TAG = "dx-feedback-banner";
5
- const render = createRenderComponent(TAG, FeedbackBanner);
6
-
7
- describe(TAG, () => {
8
- it("renders a single dx-button component", () => {
9
- const element = render();
10
-
11
- const innerContainer = element.shadowRoot.querySelectorAll(
12
- ".feedback_inner"
13
- );
14
-
15
- expect(innerContainer).not.toBeNull();
16
-
17
- return expect(element).toBeAccessible();
18
- });
19
- });
@@ -1,13 +0,0 @@
1
- <template>
2
- <div class="feedback">
3
- <div class="feedback_inner dx-text-body-4">
4
- <dx-icon symbol="announcement"></dx-icon>
5
- <span>
6
- <a href="https://forms.gle/TdSyKFPHXoBx7seM9" target="blank">
7
- Share your feedback
8
- </a>
9
- about our new site.
10
- </span>
11
- </div>
12
- </div>
13
- </template>
@@ -1,3 +0,0 @@
1
- import { LightningElement } from "lwc";
2
-
3
- export default class FeedbackBanner extends LightningElement {}