@capillarytech/creatives-library 9.0.56-alpha.7 → 9.0.56-alpha.8
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 +1 -1
- package/v2Components/CapActionButton/index.js +73 -60
- package/v2Components/CapActionButton/index.scss +44 -28
- package/v2Components/CapActionButton/messages.js +7 -3
- package/v2Components/CapActionButton/tests/index.test.js +17 -1
- package/v2Components/CapWhatsappCTA/messages.js +4 -0
- package/v2Components/CapWhatsappCarouselButton/index.js +42 -33
- package/v2Components/CapWhatsappCarouselButton/index.scss +44 -2
- package/v2Containers/CommunicationFlow/CommunicationFlowCard.js +9 -1
- package/v2Containers/CommunicationFlow/Tests/CommunicationFlowCard.test.js +58 -0
- package/v2Containers/CommunicationFlow/steps/ChannelSelectionStep/ChannelSelectionStep.js +3 -0
- package/v2Containers/CommunicationFlow/steps/DeliverySettingsStep/DeliverySettingsSection.js +19 -4
- package/v2Containers/CommunicationFlow/steps/DeliverySettingsStep/SenderDetails.js +8 -4
- package/v2Containers/CommunicationFlow/steps/DeliverySettingsStep/Tests/DeliverySettingsSection.test.js +11 -0
- package/v2Containers/CommunicationFlow/steps/DeliverySettingsStep/Tests/SenderDetails.test.js +26 -0
- package/v2Containers/CreativesContainer/SlideBoxContent.js +15 -0
- package/v2Containers/CreativesContainer/SlideBoxFooter.js +6 -2
- package/v2Containers/CreativesContainer/index.js +27 -0
- package/v2Containers/CreativesContainer/tests/SlideBoxFooter.test.js +29 -0
- package/v2Containers/CreativesContainer/tests/__snapshots__/index.test.js.snap +13 -0
- package/v2Containers/MobilePush/Create/index.js +18 -1
- package/v2Containers/MobilePush/Create/test/contentValidity.test.js +96 -0
- package/v2Containers/MobilePush/Edit/index.js +18 -1
- package/v2Containers/MobilePush/Edit/test/contentValidity.test.js +116 -0
- package/v2Containers/MobilePush/commonMethods.js +49 -1
- package/v2Containers/MobilePushNew/index.js +29 -4
- package/v2Containers/MobilePushNew/tests/index.test.js +119 -0
- package/v2Containers/MobilePushNew/tests/utils.test.js +82 -0
- package/v2Containers/MobilePushNew/utils.js +34 -1
- package/v2Containers/MobilepushWrapper/index.js +3 -1
- package/v2Containers/Rcs/index.js +34 -0
- package/v2Containers/Rcs/index.scss +15 -0
- package/v2Containers/Rcs/tests/index.test.js +67 -0
- package/v2Containers/Sms/Create/index.js +3 -1
- package/v2Containers/Sms/Edit/index.js +25 -0
- package/v2Containers/Sms/Edit/tests/index.test.js +85 -0
- package/v2Containers/Viber/index.js +24 -1
- package/v2Containers/Viber/tests/index.test.js +103 -0
- package/v2Containers/WebPush/Create/index.js +24 -0
- package/v2Containers/WebPush/Create/tests/contentValidity.test.js +294 -0
- package/v2Containers/Whatsapp/index.js +19 -1
- package/v2Containers/Whatsapp/tests/index.test.js +115 -0
- package/v2Containers/Zalo/index.js +28 -1
- package/v2Containers/Zalo/tests/index.test.js +99 -0
package/package.json
CHANGED
|
@@ -101,10 +101,12 @@ export const CapActionButton = (props) => {
|
|
|
101
101
|
const onButtonTextChange = ({target}) => {
|
|
102
102
|
const { value, id } = target;
|
|
103
103
|
let errorMessage = '';
|
|
104
|
-
if (value.
|
|
104
|
+
if (!value.trim()) {
|
|
105
|
+
errorMessage = formatMessage(messages.ctaButtonTextEmptyMessage);
|
|
106
|
+
} else if (!isValidText(value)) {
|
|
107
|
+
errorMessage = formatMessage(messages.ctaButtonTextErrorMessage);
|
|
108
|
+
} else if (value.length > BTN_MAX_LENGTH) {
|
|
105
109
|
errorMessage = formatMessage(messages.ctaButtonTextLengthError, { maxLength: BTN_MAX_LENGTH });
|
|
106
|
-
} if (!isValidText(value)) {
|
|
107
|
-
errorMessage = formatMessage(messages.ctaButtonErrorMessage);
|
|
108
110
|
}
|
|
109
111
|
setButtonError(errorMessage);
|
|
110
112
|
updateDisplayAndPostback(value, id);
|
|
@@ -446,12 +448,11 @@ export const CapActionButton = (props) => {
|
|
|
446
448
|
gutter={9}
|
|
447
449
|
>
|
|
448
450
|
<CapColumn
|
|
449
|
-
|
|
450
|
-
className={`${ctaIsPhone ? 'whatsapp-saved-cta-phone-icon' : ''}`}
|
|
451
|
+
className={`rcs-saved-cta-cell ${ctaIsPhone ? 'whatsapp-saved-cta-phone-icon' : ''}`}
|
|
451
452
|
>
|
|
452
453
|
<CapIcon size="s" type={ctaIsPhone ? 'call' : (ctaIsReply ? 'small-link' : 'open-in-new')} />
|
|
453
454
|
</CapColumn>
|
|
454
|
-
<CapColumn
|
|
455
|
+
<CapColumn className="rcs-saved-cta-cell rcs-saved-cta-text-cell">
|
|
455
456
|
<CapLabel
|
|
456
457
|
type="label2"
|
|
457
458
|
className="rcs-saved-cta-button-text"
|
|
@@ -459,64 +460,76 @@ export const CapActionButton = (props) => {
|
|
|
459
460
|
{text}
|
|
460
461
|
</CapLabel>
|
|
461
462
|
</CapColumn>
|
|
462
|
-
<CapColumn
|
|
463
|
-
|
|
464
|
-
|
|
465
|
-
|
|
466
|
-
|
|
467
|
-
|
|
468
|
-
|
|
469
|
-
|
|
470
|
-
|
|
471
|
-
|
|
472
|
-
|
|
473
|
-
|
|
474
|
-
|
|
475
|
-
|
|
476
|
-
|
|
477
|
-
|
|
478
|
-
|
|
479
|
-
|
|
480
|
-
|
|
481
|
-
|
|
482
|
-
|
|
483
|
-
|
|
484
|
-
|
|
485
|
-
|
|
486
|
-
|
|
487
|
-
|
|
488
|
-
|
|
463
|
+
<CapColumn className="rcs-saved-cta-cell rcs-saved-cta-type-cell">
|
|
464
|
+
{!ctaIsPhone && !ctaIsReply && (
|
|
465
|
+
<CapLabel className="url-type" type="label2">
|
|
466
|
+
{(cta.urlType || RCS_CTA_URL_TYPE.STATIC) === RCS_CTA_URL_TYPE.DYNAMIC
|
|
467
|
+
? formatMessage(messages.ctaWebsiteTypeDynamic)
|
|
468
|
+
: formatMessage(messages.ctaWebsiteTypeStatic)}
|
|
469
|
+
</CapLabel>
|
|
470
|
+
)}
|
|
471
|
+
</CapColumn>
|
|
472
|
+
<CapColumn className="rcs-saved-cta-cell rcs-saved-cta-url-cell">
|
|
473
|
+
{ctaIsPhone && (
|
|
474
|
+
<CapLabel className="phone">+{phoneNumber}</CapLabel>
|
|
475
|
+
)}
|
|
476
|
+
{!ctaIsPhone && !ctaIsReply && (
|
|
477
|
+
<CapTooltip
|
|
478
|
+
title={url}
|
|
479
|
+
placement="top"
|
|
480
|
+
wrapperClassName="rcs-cta-url-tooltip-wrapper"
|
|
481
|
+
triggerClassName="rcs-cta-url-tooltip-trigger"
|
|
482
|
+
>
|
|
483
|
+
<CapLabel className="url">{url}</CapLabel>
|
|
484
|
+
</CapTooltip>
|
|
485
|
+
)}
|
|
486
|
+
</CapColumn>
|
|
487
|
+
<CapColumn className="rcs-saved-cta-cell rcs-saved-cta-actions-cell">
|
|
488
|
+
{isDynamicUrlSubtype && (url || '').includes(DYNAMIC_URL_SUFFIX) && (
|
|
489
|
+
<TagList
|
|
490
|
+
className="rcs-cta-taglist"
|
|
491
|
+
label={formatMessage(messages.ctaTagListLabel)}
|
|
492
|
+
onTagSelect={(data) => onTagSelect(data, index, url)}
|
|
493
|
+
location={location}
|
|
494
|
+
tags={tags}
|
|
495
|
+
injectedTags={injectedTags}
|
|
496
|
+
selectedOfferDetails={selectedOfferDetails}
|
|
497
|
+
onContextChange={onContextChange}
|
|
498
|
+
/>
|
|
499
|
+
)}
|
|
500
|
+
{isDynamicUrlSubtype && !(url || '').includes(DYNAMIC_URL_SUFFIX) && (
|
|
501
|
+
<CapTooltip title={formatMessage(messages.ctaTagListRevert)} placement="top">
|
|
502
|
+
<CapIcon
|
|
503
|
+
size="s"
|
|
504
|
+
type="return"
|
|
505
|
+
className="rcs-cta-tag-revert"
|
|
506
|
+
onClick={() => revertTagSelect(index, url)}
|
|
489
507
|
/>
|
|
490
|
-
|
|
491
|
-
|
|
492
|
-
|
|
493
|
-
|
|
494
|
-
|
|
495
|
-
|
|
496
|
-
|
|
497
|
-
|
|
498
|
-
|
|
499
|
-
|
|
500
|
-
|
|
501
|
-
|
|
502
|
-
|
|
508
|
+
</CapTooltip>
|
|
509
|
+
)}
|
|
510
|
+
{(isFullMode && !isEditFlow) && (
|
|
511
|
+
<CapRow
|
|
512
|
+
className="rcs-saved-cta-action-icons"
|
|
513
|
+
type="flex"
|
|
514
|
+
align="middle"
|
|
515
|
+
noWrap
|
|
516
|
+
>
|
|
517
|
+
<CapIcon
|
|
518
|
+
size="s"
|
|
519
|
+
type="edit"
|
|
520
|
+
className="rcs-saved-cta-edit-icon"
|
|
521
|
+
onClick={() => editCta(index)}
|
|
522
|
+
/>
|
|
523
|
+
{!(isHostIcs && index === 0) && !hideDeleteForSuggestionIndex(index) && !cannotDeleteSavedMandatory(index) && (
|
|
503
524
|
<CapIcon
|
|
504
525
|
size="s"
|
|
505
|
-
type="
|
|
506
|
-
className="rcs-saved-cta-
|
|
507
|
-
onClick={() =>
|
|
526
|
+
type="delete"
|
|
527
|
+
className="rcs-saved-cta-delete-icon"
|
|
528
|
+
onClick={() => deleteButtonHandler(index)}
|
|
508
529
|
/>
|
|
509
|
-
|
|
510
|
-
|
|
511
|
-
|
|
512
|
-
type="delete"
|
|
513
|
-
className="rcs-saved-cta-delete-icon"
|
|
514
|
-
onClick={() => deleteButtonHandler(index)}
|
|
515
|
-
/>
|
|
516
|
-
)}
|
|
517
|
-
</div>
|
|
518
|
-
)}
|
|
519
|
-
</div>
|
|
530
|
+
)}
|
|
531
|
+
</CapRow>
|
|
532
|
+
)}
|
|
520
533
|
</CapColumn>
|
|
521
534
|
</CapRow>
|
|
522
535
|
);
|
|
@@ -25,37 +25,51 @@
|
|
|
25
25
|
margin-bottom: $CAP_SPACE_12;
|
|
26
26
|
flex-wrap: nowrap;
|
|
27
27
|
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
// fixed span, the gutter/margin between columns had nowhere to come from
|
|
32
|
-
// and pushed this column's content past the card's right border.
|
|
33
|
-
.rcs-saved-cta-value-column {
|
|
28
|
+
.rcs-saved-cta-cell {
|
|
29
|
+
display: flex;
|
|
30
|
+
align-items: center;
|
|
34
31
|
min-width: 0;
|
|
32
|
+
|
|
33
|
+
// Cell children are flex items too — without this their own min-content
|
|
34
|
+
// (the full text/URL) makes the cell unshrinkable and pushes the row.
|
|
35
|
+
> * {
|
|
36
|
+
min-width: 0;
|
|
37
|
+
}
|
|
35
38
|
}
|
|
36
39
|
|
|
37
|
-
//
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
40
|
+
// Fixed basis for the 20-char button text cap.
|
|
41
|
+
.rcs-saved-cta-text-cell {
|
|
42
|
+
flex: 0 1 10rem;
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
// Fixed, not auto: "Static" is narrower than "Dynamic", which left the URL
|
|
46
|
+
// starting at a different x per row.
|
|
47
|
+
.rcs-saved-cta-type-cell {
|
|
48
|
+
flex: 0 1 4rem;
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
.rcs-saved-cta-url-cell {
|
|
52
|
+
flex: 1 1 0;
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
.rcs-saved-cta-actions-cell {
|
|
56
|
+
flex: 0 0 auto;
|
|
44
57
|
justify-content: flex-end;
|
|
45
58
|
gap: $CAP_SPACE_08;
|
|
46
|
-
|
|
47
|
-
min-width: 0;
|
|
59
|
+
}
|
|
48
60
|
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
61
|
+
// CapTooltip nests `.url` two levels down, so these — not `.url` — are the
|
|
62
|
+
// boxes that must be allowed to shrink for the ellipsis to apply.
|
|
63
|
+
.rcs-cta-url-tooltip-wrapper {
|
|
64
|
+
flex: 1 1 0;
|
|
65
|
+
min-width: 0;
|
|
66
|
+
}
|
|
52
67
|
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
}
|
|
68
|
+
.rcs-cta-url-tooltip-trigger {
|
|
69
|
+
min-width: 0;
|
|
56
70
|
}
|
|
57
71
|
|
|
58
|
-
.url {
|
|
72
|
+
.url, .rcs-saved-cta-button-text, .url-type {
|
|
59
73
|
white-space: nowrap;
|
|
60
74
|
overflow: hidden;
|
|
61
75
|
text-overflow: ellipsis;
|
|
@@ -69,10 +83,6 @@
|
|
|
69
83
|
word-break: break-word;
|
|
70
84
|
}
|
|
71
85
|
|
|
72
|
-
.saved-button-text {
|
|
73
|
-
font-weight: 500;
|
|
74
|
-
}
|
|
75
|
-
|
|
76
86
|
.rcs-saved-cta-action-icons {
|
|
77
87
|
display: flex;
|
|
78
88
|
align-items: center;
|
|
@@ -85,8 +95,6 @@
|
|
|
85
95
|
cursor: pointer;
|
|
86
96
|
}
|
|
87
97
|
|
|
88
|
-
// Dynamic-URL tag controls: keep them from stretching the flex row's
|
|
89
|
-
// height/width — same treatment as the edit/delete icons above.
|
|
90
98
|
.rcs-cta-tag-revert {
|
|
91
99
|
display: flex;
|
|
92
100
|
align-items: center;
|
|
@@ -95,7 +103,15 @@
|
|
|
95
103
|
}
|
|
96
104
|
|
|
97
105
|
.rcs-cta-taglist {
|
|
106
|
+
display: flex;
|
|
107
|
+
align-items: center;
|
|
98
108
|
flex-shrink: 0;
|
|
109
|
+
|
|
110
|
+
// CapTagList floats this trigger right, taking it out of flow, which
|
|
111
|
+
// let it paint over the edit icon instead of occupying real width.
|
|
112
|
+
.tooltip-add-label-container {
|
|
113
|
+
float: none;
|
|
114
|
+
}
|
|
99
115
|
}
|
|
100
116
|
}
|
|
101
117
|
|
|
@@ -83,9 +83,13 @@ export default defineMessages({
|
|
|
83
83
|
id: `${prefix}.comingSoonTooltip`,
|
|
84
84
|
defaultMessage: 'Right now only one Call to action button is enabled, in future you would be able to add upto 3 buttons.',
|
|
85
85
|
},
|
|
86
|
-
|
|
87
|
-
id: `${prefix}.
|
|
88
|
-
defaultMessage: 'Button text cannot be empty',
|
|
86
|
+
ctaButtonTextEmptyMessage: {
|
|
87
|
+
id: `${prefix}.ctaButtonTextEmptyMessage`,
|
|
88
|
+
defaultMessage: 'Button text cannot be empty or contain only whitespace',
|
|
89
|
+
},
|
|
90
|
+
ctaButtonTextErrorMessage: {
|
|
91
|
+
id: `${prefix}.ctaButtonTextErrorMessage`,
|
|
92
|
+
defaultMessage: 'Newlines, Emojis, or Special characters are not allowed',
|
|
89
93
|
},
|
|
90
94
|
ctaButtonTextLengthError: {
|
|
91
95
|
id: `${prefix}.ctaButtonTextLengthError`,
|
|
@@ -521,7 +521,23 @@ describe('CapActionButton', () => {
|
|
|
521
521
|
initializeComponent([initial]);
|
|
522
522
|
const buttontextInput = screen.getByPlaceholderText('Enter button text');
|
|
523
523
|
fireEvent.change(buttontextInput, { target: { value: '&*^', id: 0 } });
|
|
524
|
-
expect(screen.getByText(/
|
|
524
|
+
expect(screen.getByText(/special characters are not allowed/i)).toBeInTheDocument();
|
|
525
|
+
});
|
|
526
|
+
|
|
527
|
+
it('should show empty error for whitespace-only button text (onButtonTextChange)', () => {
|
|
528
|
+
const initial = {
|
|
529
|
+
index: 0,
|
|
530
|
+
type: RCS_BUTTON_TYPES.QUICK_REPLY,
|
|
531
|
+
text: 'Shop',
|
|
532
|
+
phoneNumber: '',
|
|
533
|
+
url: '',
|
|
534
|
+
postback: 'Shop',
|
|
535
|
+
isSaved: false,
|
|
536
|
+
};
|
|
537
|
+
initializeComponent([initial]);
|
|
538
|
+
const buttontextInput = screen.getByPlaceholderText('Enter button text');
|
|
539
|
+
fireEvent.change(buttontextInput, { target: { value: ' ', id: 0 } });
|
|
540
|
+
expect(screen.getByText(/cannot be empty or contain only whitespace/i)).toBeInTheDocument();
|
|
525
541
|
});
|
|
526
542
|
|
|
527
543
|
it('should show error for invalid url (onUrlChange)', () => {
|
|
@@ -57,6 +57,10 @@ export default defineMessages({
|
|
|
57
57
|
id: `${prefix}.ctaButtonErrorMessage`,
|
|
58
58
|
defaultMessage: "Newlines, Emojis, or Special characters are not allowed",
|
|
59
59
|
},
|
|
60
|
+
ctaButtonTextEmptyMessage: {
|
|
61
|
+
id: `${prefix}.ctaButtonTextEmptyMessage`,
|
|
62
|
+
defaultMessage: 'Button text cannot be empty or contain only whitespace',
|
|
63
|
+
},
|
|
60
64
|
addButton: {
|
|
61
65
|
id: `${prefix}.addButton`,
|
|
62
66
|
defaultMessage: 'Add button',
|
|
@@ -126,7 +126,9 @@ export const CapWhatsappCarouselButton = (props) => {
|
|
|
126
126
|
|
|
127
127
|
const onButtonTextChange = (value, buttonIndex) => {
|
|
128
128
|
let errorMessage = '';
|
|
129
|
-
if (!
|
|
129
|
+
if (!value.trim()) {
|
|
130
|
+
errorMessage = formatMessage(capWhatsappCTAMsg.ctaButtonTextEmptyMessage);
|
|
131
|
+
} else if (!isValidWhatsappCtaText(value)) {
|
|
130
132
|
errorMessage = formatMessage(capWhatsappCTAMsg.ctaButtonErrorMessage);
|
|
131
133
|
}
|
|
132
134
|
onValueChange(buttonIndex, [{fieldName: 'text', value}, {fieldName: 'textError', value: errorMessage}]);
|
|
@@ -333,12 +335,11 @@ export const CapWhatsappCarouselButton = (props) => {
|
|
|
333
335
|
noWrap
|
|
334
336
|
>
|
|
335
337
|
<CapColumn
|
|
336
|
-
|
|
337
|
-
className={`${isPhoneNumberType ? 'whatsapp-saved-cta-phone-icon' : ''}`}
|
|
338
|
+
className={`whatsapp-saved-cta-cell ${isPhoneNumberType ? 'whatsapp-saved-cta-phone-icon' : ''}`}
|
|
338
339
|
>
|
|
339
340
|
<CapIcon size="s" type={isPhoneNumberType ? 'call' : isURLtype ? 'launch' : 'six-dots'} />
|
|
340
341
|
</CapColumn>
|
|
341
|
-
<CapColumn
|
|
342
|
+
<CapColumn className="whatsapp-saved-cta-cell whatsapp-saved-cta-text-cell">
|
|
342
343
|
<CapLabel
|
|
343
344
|
type="label2"
|
|
344
345
|
className="whatsapp-saved-cta-button-text"
|
|
@@ -346,39 +347,47 @@ export const CapWhatsappCarouselButton = (props) => {
|
|
|
346
347
|
{button?.text}
|
|
347
348
|
</CapLabel>
|
|
348
349
|
</CapColumn>
|
|
349
|
-
|
|
350
|
-
|
|
350
|
+
<CapColumn className="whatsapp-saved-cta-cell whatsapp-saved-cta-type-cell">
|
|
351
|
+
{isURLtype && (
|
|
352
|
+
<CapLabel className="url-type" type="label2">
|
|
353
|
+
{button?.urlType === STATIC_URL
|
|
354
|
+
? formatMessage(capWhatsappCTAMsg.ctaWebsiteTypeStatic)
|
|
355
|
+
: formatMessage(capWhatsappCTAMsg.ctaWebsiteTypeDynamic)}
|
|
356
|
+
</CapLabel>
|
|
357
|
+
)}
|
|
358
|
+
</CapColumn>
|
|
359
|
+
<CapColumn className="whatsapp-saved-cta-cell whatsapp-saved-cta-url-cell whatsapp-url-preview-wrapper">
|
|
360
|
+
{isPhoneNumberType && (
|
|
351
361
|
<CapLabel className="phone">
|
|
352
362
|
{button?.phone_number}
|
|
353
363
|
</CapLabel>
|
|
354
|
-
|
|
355
|
-
|
|
356
|
-
|
|
357
|
-
|
|
358
|
-
|
|
359
|
-
|
|
360
|
-
|
|
361
|
-
|
|
362
|
-
|
|
363
|
-
|
|
364
|
-
|
|
365
|
-
|
|
366
|
-
|
|
367
|
-
|
|
368
|
-
|
|
369
|
-
|
|
370
|
-
|
|
364
|
+
)}
|
|
365
|
+
{isURLtype && (
|
|
366
|
+
<CapTooltip
|
|
367
|
+
title={button?.url}
|
|
368
|
+
placement="top"
|
|
369
|
+
wrapperClassName="whatsapp-cta-url-tooltip-wrapper"
|
|
370
|
+
triggerClassName="whatsapp-cta-url-tooltip-trigger"
|
|
371
|
+
>
|
|
372
|
+
<CapLabel className="url">{button?.url}</CapLabel>
|
|
373
|
+
</CapTooltip>
|
|
374
|
+
)}
|
|
375
|
+
</CapColumn>
|
|
376
|
+
<CapColumn className="whatsapp-saved-cta-cell whatsapp-saved-cta-actions-cell">
|
|
377
|
+
{!isEditFlow && (
|
|
378
|
+
<CapRow
|
|
379
|
+
className="whatsapp-saved-cta-action-icons"
|
|
380
|
+
type="flex"
|
|
381
|
+
align="middle"
|
|
382
|
+
noWrap
|
|
383
|
+
>
|
|
384
|
+
<CapIcon size="s" type="edit" onClick={() => handleEditButton(index)}/>
|
|
385
|
+
{parseInt(carouselIndex, 10) === 0 && (
|
|
386
|
+
<CapIcon size="s" type="delete" onClick={() => handleDeleteButton(index)} disabled={buttonData?.length === 1}/>
|
|
387
|
+
)}
|
|
371
388
|
</CapRow>
|
|
372
|
-
|
|
373
|
-
|
|
374
|
-
{!isEditFlow && (
|
|
375
|
-
<CapRow type='flex' align='middle' justify="end" gap={12} fillSpace>
|
|
376
|
-
<CapIcon size="s" type="edit" onClick={() => handleEditButton(index)}/>
|
|
377
|
-
{parseInt(carouselIndex, 10) === 0 && (
|
|
378
|
-
<CapIcon size="s" type="delete" onClick={() => handleDeleteButton(index)} disabled={buttonData?.length === 1}/>
|
|
379
|
-
)}
|
|
380
|
-
</CapRow>
|
|
381
|
-
)}
|
|
389
|
+
)}
|
|
390
|
+
</CapColumn>
|
|
382
391
|
{isEditFlow && button?.urlType === DYNAMIC_URL && button?.url.includes('{{1}}') && (
|
|
383
392
|
<CapColumn>
|
|
384
393
|
<TagList
|
|
@@ -37,7 +37,49 @@
|
|
|
37
37
|
height: auto;
|
|
38
38
|
}
|
|
39
39
|
|
|
40
|
-
.whatsapp-
|
|
41
|
-
|
|
40
|
+
.whatsapp-saved-cta-cell {
|
|
41
|
+
display: flex;
|
|
42
|
+
align-items: center;
|
|
43
|
+
min-width: 0;
|
|
44
|
+
|
|
45
|
+
> * {
|
|
46
|
+
min-width: 0;
|
|
47
|
+
}
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
.whatsapp-saved-cta-text-cell {
|
|
51
|
+
flex: 0 1 10rem;
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
.whatsapp-saved-cta-type-cell {
|
|
55
|
+
flex: 0 1 5.5rem;
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
.whatsapp-saved-cta-url-cell {
|
|
59
|
+
flex: 1 1 0;
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
.whatsapp-saved-cta-actions-cell {
|
|
63
|
+
flex: 0 0 4rem;
|
|
64
|
+
justify-content: flex-end;
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
.whatsapp-saved-cta-action-icons {
|
|
68
|
+
display: flex;
|
|
69
|
+
align-items: center;
|
|
70
|
+
flex-shrink: 0;
|
|
71
|
+
gap: $CAP_SPACE_12;
|
|
72
|
+
}
|
|
73
|
+
|
|
74
|
+
// CapTooltip nests `.url` two levels down, so these — not `.url` — are the
|
|
75
|
+
// boxes that must be allowed to shrink for the ellipsis to apply.
|
|
76
|
+
.whatsapp-cta-url-tooltip-wrapper {
|
|
77
|
+
flex: 1 1 0;
|
|
78
|
+
min-width: 0;
|
|
79
|
+
}
|
|
80
|
+
|
|
81
|
+
.whatsapp-cta-url-tooltip-trigger {
|
|
82
|
+
width: 100%;
|
|
83
|
+
min-width: 0;
|
|
42
84
|
}
|
|
43
85
|
}
|
|
@@ -6,7 +6,7 @@
|
|
|
6
6
|
* - Configured state: shows a two-column CapCard with pen icon, channel preview (left), dynamic controls (right)
|
|
7
7
|
*/
|
|
8
8
|
|
|
9
|
-
import React, { useState, useCallback } from 'react';
|
|
9
|
+
import React, { useState, useCallback, useEffect } from 'react';
|
|
10
10
|
import PropTypes from 'prop-types';
|
|
11
11
|
import { injectIntl } from 'react-intl';
|
|
12
12
|
import { CAP_G09 } from '@capillarytech/cap-ui-library/styled/variables';
|
|
@@ -82,6 +82,14 @@ const CommunicationFlowCard = ({
|
|
|
82
82
|
const [showSlideBox, setShowSlideBox] = useState(false);
|
|
83
83
|
const [savedData, setSavedData] = useState(initialData || null);
|
|
84
84
|
|
|
85
|
+
// On a hard reload of an edit page, initialData is available but savedData is not yet set.
|
|
86
|
+
// This effect ensures that savedData is initialized from initialData in that case.
|
|
87
|
+
useEffect(() => {
|
|
88
|
+
if (initialData && !savedData) {
|
|
89
|
+
setSavedData(initialData);
|
|
90
|
+
}
|
|
91
|
+
}, [initialData]);
|
|
92
|
+
|
|
85
93
|
const handleSave = useCallback((data) => {
|
|
86
94
|
setSavedData(data);
|
|
87
95
|
setShowSlideBox(false);
|
|
@@ -652,4 +652,62 @@ describe('CommunicationFlowCard', () => {
|
|
|
652
652
|
expect(screen.getByText('Message:')).toBeInTheDocument();
|
|
653
653
|
});
|
|
654
654
|
});
|
|
655
|
+
|
|
656
|
+
describe('async initialData (edit page hard reload)', () => {
|
|
657
|
+
// On a hard reload of an edit page, the consumer's own by-id fetch hasn't
|
|
658
|
+
// resolved at first mount, so initialData starts as null and arrives a
|
|
659
|
+
// render or two later. savedData must pick it up then, not just at mount.
|
|
660
|
+
it('shows the summary card once initialData arrives after mount, instead of staying stuck on the empty "Add creatives" state', () => {
|
|
661
|
+
const { rerender } = render(
|
|
662
|
+
<IntlProvider locale="en" messages={{}} defaultLocale="en">
|
|
663
|
+
<CommunicationFlowCard
|
|
664
|
+
config={baseConfig}
|
|
665
|
+
initialData={null}
|
|
666
|
+
onSave={jest.fn()}
|
|
667
|
+
onCancel={jest.fn()}
|
|
668
|
+
onChange={jest.fn()}
|
|
669
|
+
cap={{}}
|
|
670
|
+
/>
|
|
671
|
+
</IntlProvider>,
|
|
672
|
+
);
|
|
673
|
+
expect(screen.getByText('Add creatives')).toBeInTheDocument();
|
|
674
|
+
|
|
675
|
+
rerender(
|
|
676
|
+
<IntlProvider locale="en" messages={{}} defaultLocale="en">
|
|
677
|
+
<CommunicationFlowCard
|
|
678
|
+
config={baseConfig}
|
|
679
|
+
initialData={makeSavedData()}
|
|
680
|
+
onSave={jest.fn()}
|
|
681
|
+
onCancel={jest.fn()}
|
|
682
|
+
onChange={jest.fn()}
|
|
683
|
+
cap={{}}
|
|
684
|
+
/>
|
|
685
|
+
</IntlProvider>,
|
|
686
|
+
);
|
|
687
|
+
expect(screen.getByText('Message:')).toBeInTheDocument();
|
|
688
|
+
expect(screen.queryByText('Add creatives')).not.toBeInTheDocument();
|
|
689
|
+
});
|
|
690
|
+
|
|
691
|
+
it('does not clobber content the user already saved locally when a later render passes a different initialData', () => {
|
|
692
|
+
const { rerender } = renderCard({ initialData: null });
|
|
693
|
+
fireEvent.click(screen.getByText('Add creatives'));
|
|
694
|
+
fireEvent.click(screen.getByTestId('flow-save'));
|
|
695
|
+
expect(screen.getByText('Message:')).toBeInTheDocument();
|
|
696
|
+
|
|
697
|
+
rerender(
|
|
698
|
+
<IntlProvider locale="en" messages={{}} defaultLocale="en">
|
|
699
|
+
<CommunicationFlowCard
|
|
700
|
+
config={baseConfig}
|
|
701
|
+
initialData={makeSavedData({ contentItems: [{ channel: 'EMAIL', templateData: {} }] })}
|
|
702
|
+
onSave={jest.fn()}
|
|
703
|
+
onCancel={jest.fn()}
|
|
704
|
+
onChange={jest.fn()}
|
|
705
|
+
cap={{}}
|
|
706
|
+
/>
|
|
707
|
+
</IntlProvider>,
|
|
708
|
+
);
|
|
709
|
+
// Locally-saved SMS content must survive; the later initialData prop must not overwrite it.
|
|
710
|
+
expect(screen.getByText('SMS')).toBeInTheDocument();
|
|
711
|
+
});
|
|
712
|
+
});
|
|
655
713
|
});
|
|
@@ -251,6 +251,7 @@ const ChannelSelectionStep = ({
|
|
|
251
251
|
};
|
|
252
252
|
|
|
253
253
|
const handleChannelsVisibleChange = (visible) => {
|
|
254
|
+
if (visible && renderChannelDropdownOverlay() === null) return;
|
|
254
255
|
setShowChannelsMenu(visible);
|
|
255
256
|
};
|
|
256
257
|
|
|
@@ -438,6 +439,7 @@ const ChannelSelectionStep = ({
|
|
|
438
439
|
overlay={renderChannelDropdownOverlay() || <CapMenu />}
|
|
439
440
|
onVisibleChange={handleChannelsVisibleChange}
|
|
440
441
|
visible={showChannelsMenu}
|
|
442
|
+
trigger={['click']}
|
|
441
443
|
>
|
|
442
444
|
<CapButton
|
|
443
445
|
isAddBtn
|
|
@@ -482,6 +484,7 @@ const ChannelSelectionStep = ({
|
|
|
482
484
|
deliverySetting={value?.deliverySetting}
|
|
483
485
|
onDeliverySettingChange={(deliverySetting) => onChange({ deliverySetting })}
|
|
484
486
|
onDomainPropertiesLoaded={setDomainPropertiesData}
|
|
487
|
+
orgUnitId={config?.context?.ouId}
|
|
485
488
|
intl={intl}
|
|
486
489
|
/>
|
|
487
490
|
)}
|