@salesforcedevs/dw-components 1.3.148-canary.27 → 1.3.148-canary.28
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 +1 -0
- package/package.json +1 -1
- package/src/modules/dw/j2sCardSequence/j2sCardSequence.css +0 -46
- package/src/modules/dw/j2sCardSequence/j2sCardSequence.html +13 -66
- package/src/modules/dw/j2sCardSequence/j2sCardSequence.ts +33 -156
- package/src/modules/dw/j2sCardSequenceStep/j2sCardSequenceStep.css +47 -0
- package/src/modules/dw/j2sCardSequenceStep/j2sCardSequenceStep.html +59 -0
- package/src/modules/dw/j2sCardSequenceStep/j2sCardSequenceStep.ts +152 -0
- package/src/modules/dw/j2sForm/j2sForm.ts +11 -5
package/lwc.config.json
CHANGED
package/package.json
CHANGED
|
@@ -1,6 +1,4 @@
|
|
|
1
1
|
@import "dxHelpers/reset";
|
|
2
|
-
@import "dxHelpers/text";
|
|
3
|
-
@import "dxHelpers/card";
|
|
4
2
|
|
|
5
3
|
:host {
|
|
6
4
|
--dx-c-button-custom-color: var(--dx-g-blue-vibrant-50);
|
|
@@ -14,47 +12,3 @@
|
|
|
14
12
|
dx-step-sequence {
|
|
15
13
|
scroll-margin-top: var(--dx-g-global-header-height);
|
|
16
14
|
}
|
|
17
|
-
|
|
18
|
-
dx-step-sequence-step:last-child[data-has-primary-action="true"]
|
|
19
|
-
dx-card-step::part(footer-container) {
|
|
20
|
-
background-color: var(--dx-g-indigo-vibrant-95);
|
|
21
|
-
border-radius: 8px;
|
|
22
|
-
margin: 0 30px 30px 30px;
|
|
23
|
-
}
|
|
24
|
-
|
|
25
|
-
[slot="secondary-action-section"] {
|
|
26
|
-
color: var(--dx-g-red-vibrant-50);
|
|
27
|
-
position: relative;
|
|
28
|
-
font-size: var(--dx-g-text-xs, 12px);
|
|
29
|
-
font-family: var(--dx-g-font-sans);
|
|
30
|
-
line-height: 18px;
|
|
31
|
-
text-align: left;
|
|
32
|
-
}
|
|
33
|
-
|
|
34
|
-
.body-container li {
|
|
35
|
-
line-height: var(--dx-g-text-2xl);
|
|
36
|
-
}
|
|
37
|
-
|
|
38
|
-
.body-container p:not(:last-child) {
|
|
39
|
-
padding-bottom: 20px;
|
|
40
|
-
}
|
|
41
|
-
|
|
42
|
-
.body-markup {
|
|
43
|
-
display: block;
|
|
44
|
-
}
|
|
45
|
-
|
|
46
|
-
.final-email-address {
|
|
47
|
-
display: block;
|
|
48
|
-
margin-top: 20px;
|
|
49
|
-
line-height: 24px;
|
|
50
|
-
color: var(--dx-g-blue-vibrant-50);
|
|
51
|
-
}
|
|
52
|
-
|
|
53
|
-
.referral-email-field {
|
|
54
|
-
--dx-c-input-width: 100%;
|
|
55
|
-
}
|
|
56
|
-
|
|
57
|
-
.spinner-container {
|
|
58
|
-
min-height: 200px;
|
|
59
|
-
position: relative;
|
|
60
|
-
}
|
|
@@ -8,73 +8,20 @@
|
|
|
8
8
|
use-history={useHistory}
|
|
9
9
|
>
|
|
10
10
|
<template for:each={stepsData} for:item="stepDatum" for:index="index">
|
|
11
|
-
<dx-step-sequence-step
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
header-text-color={stepDatum.headerData.textColor}
|
|
22
|
-
show-step-number={stepDatum.showStepNumber}
|
|
23
|
-
step-count={stepsData.length}
|
|
11
|
+
<dx-step-sequence-step key={stepDatum.id}>
|
|
12
|
+
<dw-j2s-card-sequence-step
|
|
13
|
+
country-options={countries}
|
|
14
|
+
is-loading={isLoading}
|
|
15
|
+
oncountrychange={handleCountryChange}
|
|
16
|
+
ongetstarted={handleGetStarted}
|
|
17
|
+
onformsubmit={handleFormSubmit}
|
|
18
|
+
recaptcha-token={recaptchaToken}
|
|
19
|
+
selected-country={selectedCountry}
|
|
20
|
+
step-datum={stepDatum}
|
|
24
21
|
step-index={index}
|
|
25
|
-
step-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
<template if:true={isLoading}>
|
|
29
|
-
<div class="spinner-container">
|
|
30
|
-
<dx-spinner
|
|
31
|
-
size="large"
|
|
32
|
-
variant="brand"
|
|
33
|
-
></dx-spinner>
|
|
34
|
-
</div>
|
|
35
|
-
</template>
|
|
36
|
-
<template if:false={isLoading}>
|
|
37
|
-
<span lwc:dom="manual" class="body-markup"></span>
|
|
38
|
-
<template if:true={stepDatum.formData}>
|
|
39
|
-
<dw-j2s-form
|
|
40
|
-
id={stepDatum.formData.formId}
|
|
41
|
-
countries={countries}
|
|
42
|
-
form-metadata={stepDatum.formData}
|
|
43
|
-
incoming-user-info={formIncomingUserInfo}
|
|
44
|
-
onformvaliditychange={handleFormValidityChange}
|
|
45
|
-
recaptcha-token={recaptchaToken}
|
|
46
|
-
>
|
|
47
|
-
<div slot="form-captcha-slot">
|
|
48
|
-
<slot name="captcha-slot"></slot>
|
|
49
|
-
</div>
|
|
50
|
-
</dw-j2s-form>
|
|
51
|
-
</template>
|
|
52
|
-
</template>
|
|
53
|
-
</div>
|
|
54
|
-
<div slot="secondary-action-section">
|
|
55
|
-
<span
|
|
56
|
-
lwc:dom="manual"
|
|
57
|
-
class="secondary-action-markup"
|
|
58
|
-
></span>
|
|
59
|
-
</div>
|
|
60
|
-
<div slot="primary-action-section">
|
|
61
|
-
<dx-button
|
|
62
|
-
if:true={hasPrimaryAction}
|
|
63
|
-
class="primary-action"
|
|
64
|
-
disabled={isJ2sFormInvalid}
|
|
65
|
-
href={primaryActionLink}
|
|
66
|
-
icon-sprite={stepDatum.primaryAction.iconSprite}
|
|
67
|
-
icon-symbol={stepDatum.primaryAction.iconSymbol}
|
|
68
|
-
loading={isLoading}
|
|
69
|
-
onclick={primaryActionHandler}
|
|
70
|
-
size="large"
|
|
71
|
-
target={primaryActionLinkTarget}
|
|
72
|
-
variant={primaryActionVariant}
|
|
73
|
-
>
|
|
74
|
-
{primaryActionText}
|
|
75
|
-
</dx-button>
|
|
76
|
-
</div>
|
|
77
|
-
</dx-card-step>
|
|
22
|
+
step-total-count={stepsData.length}
|
|
23
|
+
user-info={formIncomingUserInfo}
|
|
24
|
+
></dw-j2s-card-sequence-step>
|
|
78
25
|
</dx-step-sequence-step>
|
|
79
26
|
</template>
|
|
80
27
|
</dx-step-sequence>
|
|
@@ -1,9 +1,8 @@
|
|
|
1
1
|
import { api, LightningElement } from "lwc";
|
|
2
2
|
import StepSequence from "dx/stepSequence";
|
|
3
3
|
import { getListWithUuids } from "dxUtils/list";
|
|
4
|
-
import { track } from "dxUtils/analytics";
|
|
5
4
|
import { toJson } from "dxUtils/normalizers";
|
|
6
|
-
import
|
|
5
|
+
import J2sCardSequenceStep from "dw/j2sCardSequenceStep";
|
|
7
6
|
|
|
8
7
|
export type StepDatum = {
|
|
9
8
|
bodyHtml?:
|
|
@@ -69,10 +68,8 @@ export type DrmFormData = {
|
|
|
69
68
|
};
|
|
70
69
|
|
|
71
70
|
export default class J2sCardSequence extends LightningElement {
|
|
72
|
-
_didRenderStaticInnerHtml = false;
|
|
73
71
|
_isDrmLoading = false;
|
|
74
72
|
_isFormSubmitting = false;
|
|
75
|
-
_isJ2sFormInvalid = false;
|
|
76
73
|
_isTbidLoading = false;
|
|
77
74
|
_recaptchaResetTimeoutId: number | null = null;
|
|
78
75
|
_stepsData: StepDatum[] = [];
|
|
@@ -107,11 +104,11 @@ export default class J2sCardSequence extends LightningElement {
|
|
|
107
104
|
});
|
|
108
105
|
}
|
|
109
106
|
|
|
110
|
-
private
|
|
111
|
-
private countries = "[]";
|
|
107
|
+
private countries: any[] = [];
|
|
112
108
|
private currentSequenceStep = 0;
|
|
113
109
|
private formSubmissionFailureState: Partial<DrmFormData> | null = null;
|
|
114
110
|
private recaptchaToken = "";
|
|
111
|
+
private selectedCountry = "";
|
|
115
112
|
private sessionStorageId = "j2s-card-sequence";
|
|
116
113
|
private tbidUserInfo: any; // TODO typings?
|
|
117
114
|
|
|
@@ -125,47 +122,6 @@ export default class J2sCardSequence extends LightningElement {
|
|
|
125
122
|
return Boolean(this.tbidUserInfo);
|
|
126
123
|
}
|
|
127
124
|
|
|
128
|
-
private get isJ2sFormInvalid() {
|
|
129
|
-
return this.currentSequenceStep === 1 ? this._isJ2sFormInvalid : false;
|
|
130
|
-
}
|
|
131
|
-
private set isJ2sFormInvalid(isFormInvalid: boolean) {
|
|
132
|
-
this._isJ2sFormInvalid = isFormInvalid;
|
|
133
|
-
}
|
|
134
|
-
|
|
135
|
-
private get primaryAction() {
|
|
136
|
-
return this.stepsData[this.currentSequenceStep || 0].primaryAction;
|
|
137
|
-
}
|
|
138
|
-
|
|
139
|
-
private get primaryActionLink() {
|
|
140
|
-
const { link } = this.primaryAction;
|
|
141
|
-
return typeof link === "string"
|
|
142
|
-
? link
|
|
143
|
-
: link?.[this.confirmedCountry] || link?.default;
|
|
144
|
-
}
|
|
145
|
-
|
|
146
|
-
private get primaryActionText() {
|
|
147
|
-
const { text } = this.primaryAction;
|
|
148
|
-
return typeof text === "string"
|
|
149
|
-
? text
|
|
150
|
-
: text[this.confirmedCountry] || text.default;
|
|
151
|
-
}
|
|
152
|
-
|
|
153
|
-
private get primaryActionVariant() {
|
|
154
|
-
if (this.currentSequenceStep === 1 && this.isJ2sFormInvalid) {
|
|
155
|
-
return "custom"; // override for disabled button styling
|
|
156
|
-
}
|
|
157
|
-
return this.primaryAction.variant;
|
|
158
|
-
}
|
|
159
|
-
|
|
160
|
-
private get primaryActionLinkTarget() {
|
|
161
|
-
return this.primaryAction.linkTarget || "_blank";
|
|
162
|
-
}
|
|
163
|
-
|
|
164
|
-
private get hasPrimaryAction() {
|
|
165
|
-
// new requirement: don't show primary action on final step if country isn't India
|
|
166
|
-
return this.currentSequenceStep !== 2 || this.confirmedCountry === "IN";
|
|
167
|
-
}
|
|
168
|
-
|
|
169
125
|
private get formIncomingUserInfo() {
|
|
170
126
|
if (!this.tbidUserInfo) {
|
|
171
127
|
return {} as DrmFormData;
|
|
@@ -232,27 +188,30 @@ export default class J2sCardSequence extends LightningElement {
|
|
|
232
188
|
}
|
|
233
189
|
|
|
234
190
|
renderedCallback() {
|
|
235
|
-
if (this.isLoading) {
|
|
236
|
-
|
|
237
|
-
|
|
238
|
-
|
|
239
|
-
|
|
240
|
-
|
|
241
|
-
this.updateStaticInnerHtml();
|
|
242
|
-
this._didRenderStaticInnerHtml = true;
|
|
191
|
+
if (!this.isLoading) {
|
|
192
|
+
(
|
|
193
|
+
this.template.querySelector(
|
|
194
|
+
"dx-step-sequence"
|
|
195
|
+
) as unknown as StepSequence
|
|
196
|
+
)?.remeasureSteps();
|
|
243
197
|
}
|
|
244
198
|
|
|
245
|
-
if (
|
|
246
|
-
|
|
247
|
-
|
|
248
|
-
|
|
249
|
-
|
|
199
|
+
if (
|
|
200
|
+
this.formSubmissionFailureState &&
|
|
201
|
+
this.stepsData[this.currentSequenceStep].formData
|
|
202
|
+
) {
|
|
203
|
+
const j2sCardStep = this.template.querySelectorAll(
|
|
204
|
+
"dw-j2s-card-sequence-step"
|
|
205
|
+
) as unknown as J2sCardSequenceStep[];
|
|
206
|
+
j2sCardStep[this.currentSequenceStep]?.notifyFormSubmitFailure(
|
|
207
|
+
this.formSubmissionFailureState
|
|
208
|
+
);
|
|
250
209
|
this.formSubmissionFailureState = null;
|
|
251
210
|
}
|
|
252
211
|
}
|
|
253
212
|
|
|
254
|
-
|
|
255
|
-
this.
|
|
213
|
+
handleCountryChange({ detail }: CustomEvent) {
|
|
214
|
+
this.selectedCountry = detail;
|
|
256
215
|
}
|
|
257
216
|
|
|
258
217
|
handleStepSequenceChange({ detail }: CustomEvent) {
|
|
@@ -275,39 +234,26 @@ export default class J2sCardSequence extends LightningElement {
|
|
|
275
234
|
}
|
|
276
235
|
}
|
|
277
236
|
|
|
278
|
-
handleGetStarted(
|
|
237
|
+
handleGetStarted() {
|
|
279
238
|
// If the user is not yet logged in, we need to prevent moving immediately to the next
|
|
280
239
|
// step, but set storage up so that they are on the second step when they return to the
|
|
281
240
|
// site in a logged-in state; then, we need to get them to log in.
|
|
282
241
|
if (!this.isLoggedIn) {
|
|
283
|
-
evt.preventDefault();
|
|
284
242
|
this.initialStepIndex = 1;
|
|
285
243
|
this._isTbidLoading = true;
|
|
286
244
|
(window as any).__startTbidLogin?.(); // call out to DSC tbid controller
|
|
245
|
+
} else {
|
|
246
|
+
this.jumpToStepIndex(1);
|
|
287
247
|
}
|
|
288
248
|
}
|
|
289
249
|
|
|
290
|
-
async handleFormSubmit(
|
|
291
|
-
if (!this.formHandler ||
|
|
250
|
+
async handleFormSubmit({ detail: formData }: CustomEvent<DrmFormData>) {
|
|
251
|
+
if (!this.formHandler || !this.isLoggedIn) {
|
|
292
252
|
return;
|
|
293
253
|
}
|
|
294
254
|
|
|
295
|
-
evt.preventDefault(); // don't proceed automatically to next step
|
|
296
255
|
this._isFormSubmitting = true;
|
|
297
256
|
|
|
298
|
-
const j2sFormEl = (this.template.querySelector(
|
|
299
|
-
"dw-j2s-form"
|
|
300
|
-
) as unknown) as J2sForm;
|
|
301
|
-
const formData = j2sFormEl.formDataForDrm;
|
|
302
|
-
|
|
303
|
-
// For some countries, explicit approvals will be present; for others, it is implicitly assumed
|
|
304
|
-
if (typeof formData.Opt_In__c !== "boolean") {
|
|
305
|
-
formData.Opt_In__c = true;
|
|
306
|
-
}
|
|
307
|
-
if (typeof formData.Privacy_Statement__c !== "boolean") {
|
|
308
|
-
formData.Privacy_Statement__c = true;
|
|
309
|
-
}
|
|
310
|
-
|
|
311
257
|
try {
|
|
312
258
|
const res = await fetch(this.formHandler, {
|
|
313
259
|
method: "POST",
|
|
@@ -326,7 +272,6 @@ export default class J2sCardSequence extends LightningElement {
|
|
|
326
272
|
const resData = await res.json();
|
|
327
273
|
const resOutput = resData.handlePostRequestOutput || resData;
|
|
328
274
|
if (resOutput?.status === "success") {
|
|
329
|
-
this.confirmedCountry = formData.MailingCountry as string;
|
|
330
275
|
this.jumpToStepIndex(2, false);
|
|
331
276
|
this.initialStepIndex = 0; // don't save final step in storage; rather, reset the starting step
|
|
332
277
|
} else {
|
|
@@ -347,31 +292,6 @@ export default class J2sCardSequence extends LightningElement {
|
|
|
347
292
|
this._isFormSubmitting = false;
|
|
348
293
|
}
|
|
349
294
|
|
|
350
|
-
primaryActionHandler(evt: Event) {
|
|
351
|
-
const target = evt.target as HTMLButtonElement;
|
|
352
|
-
|
|
353
|
-
if (!target || target.disabled) {
|
|
354
|
-
evt.preventDefault();
|
|
355
|
-
return;
|
|
356
|
-
}
|
|
357
|
-
|
|
358
|
-
track(target, "custEv_ctaButtonClick", {
|
|
359
|
-
click_text: target.textContent,
|
|
360
|
-
element_title: this.stepsData[this.currentSequenceStep].stepTitle,
|
|
361
|
-
click_url:
|
|
362
|
-
this.stepsData[this.currentSequenceStep].primaryAction.link ||
|
|
363
|
-
"",
|
|
364
|
-
element_type: "button",
|
|
365
|
-
content_category: "cta"
|
|
366
|
-
});
|
|
367
|
-
|
|
368
|
-
if (!this.currentSequenceStep) {
|
|
369
|
-
this.handleGetStarted(evt);
|
|
370
|
-
} else if (this.currentSequenceStep === 1) {
|
|
371
|
-
this.handleFormSubmit(evt);
|
|
372
|
-
}
|
|
373
|
-
}
|
|
374
|
-
|
|
375
295
|
private resetCustomButtonColors() {
|
|
376
296
|
let bgColor;
|
|
377
297
|
let textColor;
|
|
@@ -402,54 +322,11 @@ export default class J2sCardSequence extends LightningElement {
|
|
|
402
322
|
if (andStoreIndex) {
|
|
403
323
|
this.initialStepIndex = stepIndex; // update sessionStorage value
|
|
404
324
|
}
|
|
405
|
-
(
|
|
406
|
-
|
|
407
|
-
|
|
408
|
-
|
|
409
|
-
|
|
410
|
-
private updateStaticInnerHtml() {
|
|
411
|
-
const bodyMarkupContainers = this.template.querySelectorAll(
|
|
412
|
-
"span.body-markup"
|
|
413
|
-
);
|
|
414
|
-
const secondaryActionMarkupContainers = this.template.querySelectorAll(
|
|
415
|
-
"span.secondary-action-markup"
|
|
416
|
-
);
|
|
417
|
-
|
|
418
|
-
this.stepsData.forEach((step, stepIndex) => {
|
|
419
|
-
const { bodyHtml, secondaryActionHtml } = step;
|
|
420
|
-
const bodyMarkupContainer = bodyMarkupContainers[stepIndex];
|
|
421
|
-
const secondaryActionMarkupContainer =
|
|
422
|
-
secondaryActionMarkupContainers[stepIndex];
|
|
423
|
-
|
|
424
|
-
if (bodyMarkupContainer) {
|
|
425
|
-
let markup =
|
|
426
|
-
typeof bodyHtml === "string"
|
|
427
|
-
? bodyHtml
|
|
428
|
-
: bodyHtml?.[this.confirmedCountry] ||
|
|
429
|
-
bodyHtml?.default;
|
|
430
|
-
|
|
431
|
-
if (stepIndex === 2) {
|
|
432
|
-
// User's email is supposed to show on final step
|
|
433
|
-
markup = `${markup}${
|
|
434
|
-
!this.formIncomingUserInfo.Email
|
|
435
|
-
? ""
|
|
436
|
-
: `<span class="final-email-address">${this.formIncomingUserInfo.Email}</span>`
|
|
437
|
-
}`;
|
|
438
|
-
}
|
|
439
|
-
|
|
440
|
-
bodyMarkupContainer.innerHTML = markup || "";
|
|
441
|
-
}
|
|
442
|
-
|
|
443
|
-
if (secondaryActionMarkupContainer) {
|
|
444
|
-
const secondaryActionInnerHtml =
|
|
445
|
-
!secondaryActionHtml ||
|
|
446
|
-
// ugh, new special exception on step 2 to only show secondary action for IN
|
|
447
|
-
(stepIndex === 2 && this.confirmedCountry !== "IN")
|
|
448
|
-
? ""
|
|
449
|
-
: secondaryActionHtml;
|
|
450
|
-
secondaryActionMarkupContainer.innerHTML = secondaryActionInnerHtml;
|
|
451
|
-
}
|
|
452
|
-
});
|
|
325
|
+
(
|
|
326
|
+
this.template.querySelector(
|
|
327
|
+
"dx-step-sequence"
|
|
328
|
+
) as unknown as StepSequence
|
|
329
|
+
)?.jumpToStep(stepIndex);
|
|
453
330
|
}
|
|
454
331
|
|
|
455
332
|
private async getCountryList() {
|
|
@@ -463,8 +340,7 @@ export default class J2sCardSequence extends LightningElement {
|
|
|
463
340
|
if (!res.ok) {
|
|
464
341
|
throw new Error(errorMsg);
|
|
465
342
|
}
|
|
466
|
-
|
|
467
|
-
this.countries = JSON.stringify(data);
|
|
343
|
+
this.countries = await res.json();
|
|
468
344
|
} catch (error) {
|
|
469
345
|
console.error(error);
|
|
470
346
|
if (this.initialStepIndex > 0) {
|
|
@@ -484,6 +360,7 @@ export default class J2sCardSequence extends LightningElement {
|
|
|
484
360
|
const res = await fetch(`${this.tbidApiBaseUrl}/userinfo`);
|
|
485
361
|
if (res.ok) {
|
|
486
362
|
this.tbidUserInfo = await res.json();
|
|
363
|
+
this.selectedCountry = this.formIncomingUserInfo.MailingCountry;
|
|
487
364
|
}
|
|
488
365
|
} catch (ex) {
|
|
489
366
|
// noop; nothing to do here
|
|
@@ -0,0 +1,47 @@
|
|
|
1
|
+
@import "dxHelpers/reset";
|
|
2
|
+
@import "dxHelpers/text";
|
|
3
|
+
@import "dxHelpers/card";
|
|
4
|
+
|
|
5
|
+
/* Special styling for the final step's actions if they are shown */
|
|
6
|
+
dx-card-step.final-card-with-action::part(footer-container) {
|
|
7
|
+
background-color: var(--dx-g-indigo-vibrant-95);
|
|
8
|
+
border-radius: 8px;
|
|
9
|
+
margin: 0 30px 30px 30px;
|
|
10
|
+
}
|
|
11
|
+
|
|
12
|
+
[slot="secondary-action-section"] {
|
|
13
|
+
color: var(--dx-g-red-vibrant-50);
|
|
14
|
+
position: relative;
|
|
15
|
+
font-size: var(--dx-g-text-xs, 12px);
|
|
16
|
+
font-family: var(--dx-g-font-sans);
|
|
17
|
+
line-height: 18px;
|
|
18
|
+
text-align: left;
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
.body-container li {
|
|
22
|
+
line-height: var(--dx-g-text-2xl);
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
.body-container p:not(:last-child) {
|
|
26
|
+
padding-bottom: 20px;
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
.body-markup {
|
|
30
|
+
display: block;
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
.final-email-address {
|
|
34
|
+
display: block;
|
|
35
|
+
margin-top: 20px;
|
|
36
|
+
line-height: 24px;
|
|
37
|
+
color: var(--dx-g-blue-vibrant-50);
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
.referral-email-field {
|
|
41
|
+
--dx-c-input-width: 100%;
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
.spinner-container {
|
|
45
|
+
min-height: 200px;
|
|
46
|
+
position: relative;
|
|
47
|
+
}
|
|
@@ -0,0 +1,59 @@
|
|
|
1
|
+
<template>
|
|
2
|
+
<dx-card-step
|
|
3
|
+
class={stepClassName}
|
|
4
|
+
header-icon-symbol={stepDatum.headerData.iconSymbol}
|
|
5
|
+
header-icon-sprite={stepDatum.headerData.iconSprite}
|
|
6
|
+
header-icon-color={stepDatum.headerData.iconColor}
|
|
7
|
+
header-background-color={stepDatum.headerData.backgroundColor}
|
|
8
|
+
header-text-color={stepDatum.headerData.textColor}
|
|
9
|
+
show-step-number={stepDatum.showStepNumber}
|
|
10
|
+
step-count={stepTotalCount}
|
|
11
|
+
step-index={stepIndex}
|
|
12
|
+
step-title={stepDatum.stepTitle}
|
|
13
|
+
>
|
|
14
|
+
<div slot="card-body" class="body-container">
|
|
15
|
+
<template if:true={isLoading}>
|
|
16
|
+
<div class="spinner-container">
|
|
17
|
+
<dx-spinner size="large" variant="brand"></dx-spinner>
|
|
18
|
+
</div>
|
|
19
|
+
</template>
|
|
20
|
+
<template if:false={isLoading}>
|
|
21
|
+
<span lwc:dom="manual" class="body-markup"></span>
|
|
22
|
+
<template if:true={stepDatum.formData}>
|
|
23
|
+
<dw-j2s-form
|
|
24
|
+
id={stepDatum.formData.formId}
|
|
25
|
+
countries={countryOptions}
|
|
26
|
+
form-metadata={stepDatum.formData}
|
|
27
|
+
incoming-user-info={userInfo}
|
|
28
|
+
onformvaliditychange={handleFormValidityChange}
|
|
29
|
+
recaptcha-token={recaptchaToken}
|
|
30
|
+
>
|
|
31
|
+
<div slot="form-captcha-slot">
|
|
32
|
+
<slot name="captcha-slot"></slot>
|
|
33
|
+
</div>
|
|
34
|
+
</dw-j2s-form>
|
|
35
|
+
</template>
|
|
36
|
+
</template>
|
|
37
|
+
</div>
|
|
38
|
+
<div slot="secondary-action-section">
|
|
39
|
+
<span lwc:dom="manual" class="secondary-action-markup"></span>
|
|
40
|
+
</div>
|
|
41
|
+
<div slot="primary-action-section">
|
|
42
|
+
<dx-button
|
|
43
|
+
if:true={showPrimaryAction}
|
|
44
|
+
class="primary-action"
|
|
45
|
+
disabled={isJ2sFormInvalid}
|
|
46
|
+
href={primaryActionLink}
|
|
47
|
+
icon-sprite={stepDatum.primaryAction.iconSprite}
|
|
48
|
+
icon-symbol={stepDatum.primaryAction.iconSymbol}
|
|
49
|
+
loading={isLoading}
|
|
50
|
+
onclick={handlePrimaryAction}
|
|
51
|
+
size="large"
|
|
52
|
+
target={primaryActionLinkTarget}
|
|
53
|
+
variant={primaryActionVariant}
|
|
54
|
+
>
|
|
55
|
+
{primaryActionText}
|
|
56
|
+
</dx-button>
|
|
57
|
+
</div>
|
|
58
|
+
</dx-card-step>
|
|
59
|
+
</template>
|
|
@@ -0,0 +1,152 @@
|
|
|
1
|
+
import { api, LightningElement } from "lwc";
|
|
2
|
+
import { DrmFormData, StepDatum } from "dw/j2sCardSequence";
|
|
3
|
+
import { track } from "dxUtils/analytics";
|
|
4
|
+
import J2sForm from "dw/j2sForm";
|
|
5
|
+
|
|
6
|
+
export default class J2sCardSequenceStep extends LightningElement {
|
|
7
|
+
@api countryOptions: any[] = [];
|
|
8
|
+
@api isLoading = false;
|
|
9
|
+
@api recaptchaToken = "";
|
|
10
|
+
@api selectedCountry = "";
|
|
11
|
+
@api stepDatum!: StepDatum;
|
|
12
|
+
@api stepIndex = 0;
|
|
13
|
+
@api stepTotalCount = 0;
|
|
14
|
+
@api userInfo: any = {};
|
|
15
|
+
|
|
16
|
+
@api
|
|
17
|
+
public notifyFormSubmitFailure(formFailureData: Partial<DrmFormData>) {
|
|
18
|
+
(
|
|
19
|
+
this.template.querySelector("dw-j2s-form") as unknown as J2sForm
|
|
20
|
+
)?.notifySubmitFailure(formFailureData);
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
private _isJ2sFormInvalid = false;
|
|
24
|
+
|
|
25
|
+
private get stepClassName() {
|
|
26
|
+
return this.stepIndex === 2 && this.selectedCountry === "IN"
|
|
27
|
+
? "final-card-with-action"
|
|
28
|
+
: "";
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
private get isJ2sFormInvalid() {
|
|
32
|
+
return this.stepIndex === 1 && this._isJ2sFormInvalid;
|
|
33
|
+
}
|
|
34
|
+
private set isJ2sFormInvalid(value: boolean) {
|
|
35
|
+
this._isJ2sFormInvalid = value;
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
private get primaryActionLink() {
|
|
39
|
+
const { link } = this.stepDatum.primaryAction;
|
|
40
|
+
return typeof link === "string"
|
|
41
|
+
? link
|
|
42
|
+
: link?.[this.selectedCountry] || link?.default;
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
private get primaryActionText() {
|
|
46
|
+
const { text } = this.stepDatum.primaryAction;
|
|
47
|
+
return typeof text === "string"
|
|
48
|
+
? text
|
|
49
|
+
: text[this.selectedCountry] || text.default;
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
private get primaryActionVariant() {
|
|
53
|
+
if (this.stepIndex === 1 && this.isJ2sFormInvalid) {
|
|
54
|
+
return "custom"; // override for disabled button styling
|
|
55
|
+
}
|
|
56
|
+
return this.stepDatum.primaryAction.variant;
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
private get primaryActionLinkTarget() {
|
|
60
|
+
return this.stepDatum.primaryAction.linkTarget || "_blank";
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
private get showPrimaryAction() {
|
|
64
|
+
return this.stepIndex !== 2 || this.selectedCountry === "IN";
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
private get showSecondaryAction() {
|
|
68
|
+
return this.showPrimaryAction; // same requirement as above for now
|
|
69
|
+
}
|
|
70
|
+
|
|
71
|
+
renderedCallback() {
|
|
72
|
+
this.updateStaticInnerHtml();
|
|
73
|
+
}
|
|
74
|
+
|
|
75
|
+
handleFormValidityChange({ detail }: CustomEvent) {
|
|
76
|
+
this.isJ2sFormInvalid = !detail.isValid;
|
|
77
|
+
}
|
|
78
|
+
|
|
79
|
+
handlePrimaryAction(evt: Event) {
|
|
80
|
+
this.track(evt);
|
|
81
|
+
|
|
82
|
+
if (this.stepIndex === 0) {
|
|
83
|
+
this.dispatchEvent(new CustomEvent("getstarted"));
|
|
84
|
+
} else if (this.stepIndex === 1 && !this.isJ2sFormInvalid) {
|
|
85
|
+
const j2sFormEl = this.template.querySelector(
|
|
86
|
+
"dw-j2s-form"
|
|
87
|
+
) as unknown as J2sForm;
|
|
88
|
+
const formData = j2sFormEl.formDataForDrm;
|
|
89
|
+
|
|
90
|
+
// For some countries, explicit approvals will be present; for others, it is implicitly assumed
|
|
91
|
+
if (typeof formData.Opt_In__c !== "boolean") {
|
|
92
|
+
formData.Opt_In__c = true;
|
|
93
|
+
}
|
|
94
|
+
if (typeof formData.Privacy_Statement__c !== "boolean") {
|
|
95
|
+
formData.Privacy_Statement__c = true;
|
|
96
|
+
}
|
|
97
|
+
|
|
98
|
+
this.dispatchEvent(
|
|
99
|
+
new CustomEvent("formsubmit", {
|
|
100
|
+
detail: formData
|
|
101
|
+
})
|
|
102
|
+
);
|
|
103
|
+
}
|
|
104
|
+
}
|
|
105
|
+
|
|
106
|
+
private updateStaticInnerHtml() {
|
|
107
|
+
const { bodyHtml, secondaryActionHtml } = this.stepDatum;
|
|
108
|
+
const bodyMarkupContainer =
|
|
109
|
+
this.template.querySelector("span.body-markup");
|
|
110
|
+
const secondaryActionMarkupContainer = this.template.querySelector(
|
|
111
|
+
"span.secondary-action-markup"
|
|
112
|
+
);
|
|
113
|
+
|
|
114
|
+
if (bodyMarkupContainer) {
|
|
115
|
+
let markup =
|
|
116
|
+
typeof bodyHtml === "string"
|
|
117
|
+
? bodyHtml
|
|
118
|
+
: bodyHtml?.[this.selectedCountry] || bodyHtml?.default;
|
|
119
|
+
|
|
120
|
+
if (this.stepIndex === 2) {
|
|
121
|
+
// User's email is supposed to show on final step
|
|
122
|
+
markup = `${markup}${
|
|
123
|
+
!this.userInfo.Email
|
|
124
|
+
? ""
|
|
125
|
+
: `<span class="final-email-address">${this.userInfo.Email}</span>`
|
|
126
|
+
}`;
|
|
127
|
+
}
|
|
128
|
+
|
|
129
|
+
bodyMarkupContainer.innerHTML = markup || "";
|
|
130
|
+
}
|
|
131
|
+
|
|
132
|
+
if (secondaryActionMarkupContainer) {
|
|
133
|
+
// new special exception on step 2 to only show secondary action for IN
|
|
134
|
+
secondaryActionMarkupContainer.innerHTML =
|
|
135
|
+
secondaryActionHtml && this.showSecondaryAction
|
|
136
|
+
? secondaryActionHtml
|
|
137
|
+
: "";
|
|
138
|
+
}
|
|
139
|
+
}
|
|
140
|
+
|
|
141
|
+
private track(evt: Event) {
|
|
142
|
+
const target = evt.target as HTMLButtonElement;
|
|
143
|
+
|
|
144
|
+
track(target, "custEv_ctaButtonClick", {
|
|
145
|
+
click_text: target.textContent,
|
|
146
|
+
element_title: this.stepDatum.stepTitle,
|
|
147
|
+
click_url: this.stepDatum.primaryAction.link || "",
|
|
148
|
+
element_type: "button",
|
|
149
|
+
content_category: "cta"
|
|
150
|
+
});
|
|
151
|
+
}
|
|
152
|
+
}
|
|
@@ -203,10 +203,8 @@ export default class J2sForm extends LightningElementWithState<J2sFormState> {
|
|
|
203
203
|
handleFormFieldChange = (evt: CustomEvent) => {
|
|
204
204
|
// Event target information must be read prior to debouncing; the target is gone after the debounce.
|
|
205
205
|
const { target = {}, detail } = evt;
|
|
206
|
-
const {
|
|
207
|
-
|
|
208
|
-
required: isRequiredField
|
|
209
|
-
} = target as HTMLInputElement;
|
|
206
|
+
const { name: targetName, required: isRequiredField } =
|
|
207
|
+
target as HTMLInputElement;
|
|
210
208
|
const value =
|
|
211
209
|
typeof detail === "string"
|
|
212
210
|
? detail
|
|
@@ -279,6 +277,14 @@ export default class J2sForm extends LightningElementWithState<J2sFormState> {
|
|
|
279
277
|
showMarketingText: countryData.showMarketingText
|
|
280
278
|
});
|
|
281
279
|
|
|
280
|
+
this.dispatchEvent(
|
|
281
|
+
new CustomEvent("countrychange", {
|
|
282
|
+
bubbles: true,
|
|
283
|
+
composed: true,
|
|
284
|
+
detail: countryCode
|
|
285
|
+
})
|
|
286
|
+
);
|
|
287
|
+
|
|
282
288
|
// Because updating the country can update the required fields, we need to re-set form
|
|
283
289
|
// validity _after_ render
|
|
284
290
|
requestAnimationFrame(() =>
|
|
@@ -301,7 +307,7 @@ export default class J2sForm extends LightningElementWithState<J2sFormState> {
|
|
|
301
307
|
|
|
302
308
|
private checkValidity() {
|
|
303
309
|
return (
|
|
304
|
-
|
|
310
|
+
Boolean(this.recaptchaToken) &&
|
|
305
311
|
this.isParticipatingCountry(this.state.MailingCountry) &&
|
|
306
312
|
this.requiredFormFields.every(
|
|
307
313
|
(requiredFormField) =>
|