@capillarytech/creatives-library 8.0.357 → 8.0.359-alpha.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/index.html +0 -1
- package/package.json +1 -1
- package/utils/cdnTransformation.js +3 -75
- package/utils/tests/cdnTransformation.test.js +0 -127
- package/v2Components/CommonTestAndPreview/UnifiedPreview/PreviewHeader.js +0 -16
- package/v2Components/CommonTestAndPreview/UnifiedPreview/ViberPreviewContent.js +132 -14
- package/v2Components/CommonTestAndPreview/UnifiedPreview/_unifiedPreview.scss +163 -54
- package/v2Components/CommonTestAndPreview/UnifiedPreview/index.js +6 -52
- package/v2Components/CommonTestAndPreview/constants.js +0 -2
- package/v2Components/CommonTestAndPreview/index.js +231 -77
- package/v2Components/CommonTestAndPreview/tests/UnifiedPreview/PreviewHeader.test.js +0 -163
- package/v2Components/CommonTestAndPreview/tests/UnifiedPreview/ViberPreviewContent.test.js +364 -0
- package/v2Components/CommonTestAndPreview/tests/UnifiedPreview/index.test.js +0 -255
- package/v2Components/CommonTestAndPreview/tests/constants.test.js +1 -2
- package/v2Components/CommonTestAndPreview/tests/index.test.js +0 -194
- package/v2Components/FormBuilder/index.js +52 -162
- package/v2Components/TestAndPreviewSlidebox/index.js +2 -2
- package/v2Containers/App/constants.js +0 -3
- package/v2Containers/CreativesContainer/index.js +24 -60
- package/v2Containers/Templates/_templates.scss +77 -0
- package/v2Containers/Templates/index.js +92 -82
- package/v2Containers/Templates/sagas.js +1 -6
- package/v2Containers/Templates/tests/sagas.test.js +6 -23
- package/v2Containers/Viber/constants.js +19 -0
- package/v2Containers/Viber/index.js +714 -47
- package/v2Containers/Viber/index.scss +148 -0
- package/v2Containers/Viber/messages.js +116 -0
- package/v2Containers/Viber/tests/index.test.js +80 -0
- package/v2Containers/WebPush/Create/index.js +8 -91
- package/v2Containers/WebPush/Create/index.scss +0 -7
- package/v2Components/CommonTestAndPreview/UnifiedPreview/WebPushPreviewContent.js +0 -169
- package/v2Components/CommonTestAndPreview/tests/UnifiedPreview/WebPushPreviewContent.test.js +0 -522
- package/v2Containers/App/tests/constants.test.js +0 -61
- package/v2Containers/Templates/tests/webpush.test.js +0 -375
- package/v2Containers/WebPush/Create/tests/getTemplateContent.test.js +0 -348
- package/v2Containers/WebPush/Create/tests/testAndPreviewIntegration.test.js +0 -325
|
@@ -81,8 +81,7 @@ import {
|
|
|
81
81
|
IMAGE,
|
|
82
82
|
VIDEO,
|
|
83
83
|
URL,
|
|
84
|
-
CHANNELS_USING_ANDROID_PREVIEW_DEVICE
|
|
85
|
-
DAYS,
|
|
84
|
+
CHANNELS_USING_ANDROID_PREVIEW_DEVICE
|
|
86
85
|
} from './constants';
|
|
87
86
|
|
|
88
87
|
// Import utilities
|
|
@@ -189,6 +188,8 @@ const CommonTestAndPreview = (props) => {
|
|
|
189
188
|
const [previewDevice, setPreviewDevice] = useState(initialDevice);
|
|
190
189
|
// Track if a preview call has been made (to know when to use previewDataHtml vs raw content)
|
|
191
190
|
const [hasPreviewCallBeenMade, setHasPreviewCallBeenMade] = useState(false);
|
|
191
|
+
// Viber: tag values applied to preview only after explicit Update preview / Discard (not while typing)
|
|
192
|
+
const [viberPreviewTagValues, setViberPreviewTagValues] = useState(null);
|
|
192
193
|
const [previewDataHtml, setPreviewDataHtml] = useState(() => {
|
|
193
194
|
// Initialize preview data based on channel
|
|
194
195
|
if (channel === CHANNELS.EMAIL && formData) {
|
|
@@ -456,6 +457,144 @@ const CommonTestAndPreview = (props) => {
|
|
|
456
457
|
return resolvedText;
|
|
457
458
|
};
|
|
458
459
|
|
|
460
|
+
const getViberMergedFormData = useCallback((formDataOverride) => {
|
|
461
|
+
const formDataObj = formDataOverride && typeof formDataOverride === 'object'
|
|
462
|
+
? formDataOverride
|
|
463
|
+
: (formData && typeof formData === 'object' ? formData : {});
|
|
464
|
+
let contentObj = {};
|
|
465
|
+
if (content && typeof content === 'object') {
|
|
466
|
+
contentObj = content;
|
|
467
|
+
} else if (typeof content === 'string' && content.trim()) {
|
|
468
|
+
try {
|
|
469
|
+
contentObj = JSON.parse(content);
|
|
470
|
+
} catch (e) {
|
|
471
|
+
contentObj = {};
|
|
472
|
+
}
|
|
473
|
+
}
|
|
474
|
+
const previewCards = formDataObj.viberPreviewContent?.cards
|
|
475
|
+
?? formDataObj.cards
|
|
476
|
+
?? contentObj.viberPreviewContent?.cards
|
|
477
|
+
?? contentObj.cards;
|
|
478
|
+
const mergedPreview = {
|
|
479
|
+
...(contentObj.viberPreviewContent || {}),
|
|
480
|
+
...(formDataObj.viberPreviewContent || {}),
|
|
481
|
+
...(Array.isArray(previewCards) && previewCards.length ? { cards: previewCards } : {}),
|
|
482
|
+
};
|
|
483
|
+
return {
|
|
484
|
+
...contentObj,
|
|
485
|
+
...formDataObj,
|
|
486
|
+
...(Array.isArray(previewCards) && previewCards.length ? { cards: previewCards } : {}),
|
|
487
|
+
...(Object.keys(mergedPreview).length ? { viberPreviewContent: mergedPreview } : {}),
|
|
488
|
+
};
|
|
489
|
+
}, [formData, content]);
|
|
490
|
+
|
|
491
|
+
const getViberCarouselCardsFromFormData = (formDataObj) => {
|
|
492
|
+
const previewCards = formDataObj?.viberPreviewContent?.cards;
|
|
493
|
+
if (Array.isArray(previewCards) && previewCards.length) {
|
|
494
|
+
return previewCards;
|
|
495
|
+
}
|
|
496
|
+
const rootCards = formDataObj?.cards;
|
|
497
|
+
if (Array.isArray(rootCards) && rootCards.length) {
|
|
498
|
+
return rootCards;
|
|
499
|
+
}
|
|
500
|
+
return [];
|
|
501
|
+
};
|
|
502
|
+
|
|
503
|
+
const getViberTagExtractionContent = (formDataObj, contentStr = '') => {
|
|
504
|
+
const messageText = formDataObj?.messageContent
|
|
505
|
+
|| formDataObj?.viberPreviewContent?.messageContent
|
|
506
|
+
|| contentStr
|
|
507
|
+
|| '';
|
|
508
|
+
const cardFieldTexts = getViberCarouselCardsFromFormData(formDataObj).flatMap((card) => {
|
|
509
|
+
const fields = [card?.text || ''];
|
|
510
|
+
(card?.buttons || []).forEach((button) => {
|
|
511
|
+
fields.push(button?.title || '', button?.action || '');
|
|
512
|
+
});
|
|
513
|
+
return fields;
|
|
514
|
+
});
|
|
515
|
+
return [messageText, ...cardFieldTexts]
|
|
516
|
+
.filter((value) => typeof value === 'string' && value.trim())
|
|
517
|
+
.join(' ');
|
|
518
|
+
};
|
|
519
|
+
|
|
520
|
+
const resolveViberCarouselCards = (cards, tagValues) => {
|
|
521
|
+
if (!Array.isArray(cards) || !tagValues || !Object.keys(tagValues).length) {
|
|
522
|
+
return cards;
|
|
523
|
+
}
|
|
524
|
+
return cards.map((card) => ({
|
|
525
|
+
...card,
|
|
526
|
+
text: resolveTagsInText(card?.text || '', tagValues),
|
|
527
|
+
buttons: (card?.buttons || []).map((button) => ({
|
|
528
|
+
...button,
|
|
529
|
+
title: resolveTagsInText(button?.title || '', tagValues),
|
|
530
|
+
action: resolveTagsInText(button?.action || '', tagValues),
|
|
531
|
+
})),
|
|
532
|
+
}));
|
|
533
|
+
};
|
|
534
|
+
|
|
535
|
+
const applyViberCustomValuesToContent = (contentObj, tagValues) => {
|
|
536
|
+
if (!contentObj || typeof contentObj !== 'object' || !tagValues || !Object.keys(tagValues).length) {
|
|
537
|
+
return contentObj;
|
|
538
|
+
}
|
|
539
|
+
const result = { ...contentObj };
|
|
540
|
+
if (typeof result.messageContent === 'string') {
|
|
541
|
+
result.messageContent = resolveTagsInText(result.messageContent, tagValues);
|
|
542
|
+
}
|
|
543
|
+
if (Array.isArray(result.cards)) {
|
|
544
|
+
result.cards = resolveViberCarouselCards(result.cards, tagValues);
|
|
545
|
+
}
|
|
546
|
+
if (result.viberPreviewContent && typeof result.viberPreviewContent === 'object') {
|
|
547
|
+
const preview = result.viberPreviewContent;
|
|
548
|
+
result.viberPreviewContent = {
|
|
549
|
+
...preview,
|
|
550
|
+
messageContent: resolveTagsInText(preview.messageContent || '', tagValues),
|
|
551
|
+
cards: resolveViberCarouselCards(preview.cards, tagValues),
|
|
552
|
+
};
|
|
553
|
+
}
|
|
554
|
+
return result;
|
|
555
|
+
};
|
|
556
|
+
|
|
557
|
+
const mergeViberPreviewWithResolved = (base, resolved) => {
|
|
558
|
+
if (!resolved || typeof resolved !== 'object') {
|
|
559
|
+
return base && typeof base === 'object' ? base : {};
|
|
560
|
+
}
|
|
561
|
+
const baseObj = base && typeof base === 'object' ? base : {};
|
|
562
|
+
const basePreview = baseObj.viberPreviewContent || {};
|
|
563
|
+
const resolvedPreview = resolved.viberPreviewContent || {};
|
|
564
|
+
const baseCards = basePreview.cards || baseObj.cards || [];
|
|
565
|
+
const resolvedCards = resolvedPreview.cards || resolved.cards || [];
|
|
566
|
+
const mergedCards = baseCards.length
|
|
567
|
+
? baseCards.map((card, index) => {
|
|
568
|
+
const resolvedCard = resolvedCards[index];
|
|
569
|
+
if (!resolvedCard) {
|
|
570
|
+
return card;
|
|
571
|
+
}
|
|
572
|
+
return {
|
|
573
|
+
...card,
|
|
574
|
+
...(resolvedCard.text != null ? { text: resolvedCard.text } : {}),
|
|
575
|
+
...(resolvedCard.mediaUrl != null ? { mediaUrl: resolvedCard.mediaUrl } : {}),
|
|
576
|
+
buttons: (card.buttons || []).map((button, buttonIndex) => ({
|
|
577
|
+
...button,
|
|
578
|
+
...(resolvedCard.buttons?.[buttonIndex] || {}),
|
|
579
|
+
})),
|
|
580
|
+
};
|
|
581
|
+
})
|
|
582
|
+
: resolvedCards;
|
|
583
|
+
const resolvedMessage = resolved.messageContent ?? resolvedPreview.messageContent;
|
|
584
|
+
|
|
585
|
+
return {
|
|
586
|
+
...baseObj,
|
|
587
|
+
...resolved,
|
|
588
|
+
viberPreviewContent: {
|
|
589
|
+
...basePreview,
|
|
590
|
+
...resolvedPreview,
|
|
591
|
+
type: resolvedPreview.type || basePreview.type || baseObj.type,
|
|
592
|
+
cards: mergedCards.length ? mergedCards : (resolvedPreview.cards || basePreview.cards),
|
|
593
|
+
...(resolvedMessage != null ? { messageContent: resolvedMessage } : {}),
|
|
594
|
+
},
|
|
595
|
+
};
|
|
596
|
+
};
|
|
597
|
+
|
|
459
598
|
/**
|
|
460
599
|
* Common handler for saving test customers (both new and existing)
|
|
461
600
|
*/
|
|
@@ -611,12 +750,6 @@ const CommonTestAndPreview = (props) => {
|
|
|
611
750
|
messageBody: contentStr,
|
|
612
751
|
};
|
|
613
752
|
|
|
614
|
-
case CHANNELS.WEBPUSH:
|
|
615
|
-
return {
|
|
616
|
-
...basePayload,
|
|
617
|
-
messageBody: contentStr,
|
|
618
|
-
};
|
|
619
|
-
|
|
620
753
|
default:
|
|
621
754
|
return basePayload;
|
|
622
755
|
}
|
|
@@ -663,17 +796,13 @@ const CommonTestAndPreview = (props) => {
|
|
|
663
796
|
templateContent: formDataObj?.bodyText || contentStr,
|
|
664
797
|
};
|
|
665
798
|
|
|
666
|
-
case CHANNELS.VIBER:
|
|
667
|
-
|
|
668
|
-
templateSubject: formDataObj?.messageTitle || '',
|
|
669
|
-
templateContent: contentStr,
|
|
670
|
-
};
|
|
671
|
-
|
|
672
|
-
case CHANNELS.WEBPUSH:
|
|
799
|
+
case CHANNELS.VIBER: {
|
|
800
|
+
const viberFormData = getViberMergedFormData(formDataObj);
|
|
673
801
|
return {
|
|
674
|
-
templateSubject:
|
|
675
|
-
templateContent: contentStr,
|
|
802
|
+
templateSubject: viberFormData?.messageTitle || '',
|
|
803
|
+
templateContent: getViberTagExtractionContent(viberFormData, contentStr),
|
|
676
804
|
};
|
|
805
|
+
}
|
|
677
806
|
|
|
678
807
|
case CHANNELS.ZALO: {
|
|
679
808
|
// For Zalo, extract content from templateListParams array
|
|
@@ -1562,11 +1691,16 @@ const CommonTestAndPreview = (props) => {
|
|
|
1562
1691
|
// 1. formDataObj from getTemplateContent (contains both viberPreviewContent and payload fields)
|
|
1563
1692
|
// 2. formDataObj[0] (array format - legacy)
|
|
1564
1693
|
// 3. contentStr (direct string - legacy)
|
|
1694
|
+
// Merge content prop so listing / preview-only flows include carousel card tags
|
|
1695
|
+
const viberFormData = getViberMergedFormData(formDataObj);
|
|
1696
|
+
formDataObj = viberFormData;
|
|
1565
1697
|
|
|
1566
1698
|
let messageText = '';
|
|
1567
1699
|
let imageData = null;
|
|
1568
1700
|
let videoData = null;
|
|
1569
1701
|
let buttonData = null;
|
|
1702
|
+
let cardsData = [];
|
|
1703
|
+
let messageType = '';
|
|
1570
1704
|
let accountId = null;
|
|
1571
1705
|
let accountDetails = null;
|
|
1572
1706
|
let scenarioKey = '';
|
|
@@ -1581,6 +1715,8 @@ const CommonTestAndPreview = (props) => {
|
|
|
1581
1715
|
imageData = formDataObj.image || null;
|
|
1582
1716
|
videoData = formDataObj.video || null;
|
|
1583
1717
|
buttonData = formDataObj.button || null;
|
|
1718
|
+
cardsData = formDataObj.cards || [];
|
|
1719
|
+
messageType = formDataObj.type || '';
|
|
1584
1720
|
accountId = formDataObj.accountId || null;
|
|
1585
1721
|
accountDetails = formDataObj.accountDetails || null;
|
|
1586
1722
|
scenarioKey = formDataObj.scenarioKey || VIBER_API_SCENARIO_KEY;
|
|
@@ -1607,6 +1743,8 @@ const CommonTestAndPreview = (props) => {
|
|
|
1607
1743
|
url: formDataObj?.buttonURL || '',
|
|
1608
1744
|
};
|
|
1609
1745
|
}
|
|
1746
|
+
cardsData = viberPreview.cards || formDataObj?.cards || [];
|
|
1747
|
+
messageType = viberPreview.type || formDataObj?.type || '';
|
|
1610
1748
|
// Extract account info from parent formDataObj if available
|
|
1611
1749
|
accountId = formDataObj.accountId || null;
|
|
1612
1750
|
accountDetails = formDataObj.accountDetails || null;
|
|
@@ -1649,6 +1787,10 @@ const CommonTestAndPreview = (props) => {
|
|
|
1649
1787
|
text: messageText,
|
|
1650
1788
|
};
|
|
1651
1789
|
|
|
1790
|
+
if (messageType === CHANNELS.VIBER) {
|
|
1791
|
+
messageType = '';
|
|
1792
|
+
}
|
|
1793
|
+
|
|
1652
1794
|
// Add image if present
|
|
1653
1795
|
if (imageData && imageData.url) {
|
|
1654
1796
|
viberContent.image = {
|
|
@@ -1677,9 +1819,34 @@ const CommonTestAndPreview = (props) => {
|
|
|
1677
1819
|
}
|
|
1678
1820
|
}
|
|
1679
1821
|
|
|
1680
|
-
|
|
1681
|
-
|
|
1682
|
-
viberContent.
|
|
1822
|
+
if (messageType === MEDIA_TYPE_CAROUSEL || (Array.isArray(cardsData) && cardsData.length)) {
|
|
1823
|
+
viberContent.type = MEDIA_TYPE_CAROUSEL;
|
|
1824
|
+
viberContent.cards = (cardsData || []).map((card) => ({
|
|
1825
|
+
text: card?.text || '',
|
|
1826
|
+
mediaUrl: card?.mediaUrl || '',
|
|
1827
|
+
buttons: (card?.buttons || []).map((button) => ({
|
|
1828
|
+
title: button?.title || '',
|
|
1829
|
+
action: button?.action || '',
|
|
1830
|
+
})),
|
|
1831
|
+
}));
|
|
1832
|
+
delete viberContent.button;
|
|
1833
|
+
}
|
|
1834
|
+
|
|
1835
|
+
// Resolve tags in text/cards if custom values are provided
|
|
1836
|
+
if (customValuesObj && Object.keys(customValuesObj).length > 0) {
|
|
1837
|
+
if (viberContent.text) {
|
|
1838
|
+
viberContent.text = resolveTagsInText(viberContent.text, customValuesObj);
|
|
1839
|
+
}
|
|
1840
|
+
if (Array.isArray(viberContent.cards)) {
|
|
1841
|
+
viberContent.cards = resolveViberCarouselCards(viberContent.cards, customValuesObj);
|
|
1842
|
+
}
|
|
1843
|
+
if (viberContent.button) {
|
|
1844
|
+
viberContent.button = {
|
|
1845
|
+
...viberContent.button,
|
|
1846
|
+
text: resolveTagsInText(viberContent.button.text || '', customValuesObj),
|
|
1847
|
+
url: resolveTagsInText(viberContent.button.url || '', customValuesObj),
|
|
1848
|
+
};
|
|
1849
|
+
}
|
|
1683
1850
|
}
|
|
1684
1851
|
|
|
1685
1852
|
// Build messageBody JSON string
|
|
@@ -1814,42 +1981,6 @@ const CommonTestAndPreview = (props) => {
|
|
|
1814
1981
|
};
|
|
1815
1982
|
}
|
|
1816
1983
|
|
|
1817
|
-
case CHANNELS.WEBPUSH: {
|
|
1818
|
-
const webpushData = (typeof formDataObj === 'object' && formDataObj !== null)
|
|
1819
|
-
? formDataObj
|
|
1820
|
-
: {};
|
|
1821
|
-
const innerContent = webpushData?.content || {};
|
|
1822
|
-
|
|
1823
|
-
const resolvedTitle = resolveTagsInText(innerContent?.title || '', customValuesObj);
|
|
1824
|
-
const resolvedMessage = resolveTagsInText(innerContent?.message || '', customValuesObj);
|
|
1825
|
-
|
|
1826
|
-
return {
|
|
1827
|
-
...basePayload,
|
|
1828
|
-
webPushMessageContent: {
|
|
1829
|
-
channel: CHANNELS.WEBPUSH,
|
|
1830
|
-
accountId: webpushData?.accountId || null,
|
|
1831
|
-
content: {
|
|
1832
|
-
title: resolvedTitle,
|
|
1833
|
-
message: resolvedMessage,
|
|
1834
|
-
...(innerContent?.iconImageUrl && { iconImageUrl: innerContent.iconImageUrl }),
|
|
1835
|
-
...(innerContent?.cta && { cta: innerContent.cta }),
|
|
1836
|
-
...(innerContent?.expandableDetails && { expandableDetails: innerContent.expandableDetails }),
|
|
1837
|
-
},
|
|
1838
|
-
messageSubject: webpushData?.messageSubject || resolvedTitle || '',
|
|
1839
|
-
},
|
|
1840
|
-
webPushDeliverySettings: {
|
|
1841
|
-
channelSettings: {
|
|
1842
|
-
channel: CHANNELS.WEBPUSH,
|
|
1843
|
-
notificationTtl: {
|
|
1844
|
-
duration: 7,
|
|
1845
|
-
timeUnit: DAYS,
|
|
1846
|
-
},
|
|
1847
|
-
},
|
|
1848
|
-
additionalSettings: {},
|
|
1849
|
-
},
|
|
1850
|
-
};
|
|
1851
|
-
}
|
|
1852
|
-
|
|
1853
1984
|
default:
|
|
1854
1985
|
return basePayload;
|
|
1855
1986
|
}
|
|
@@ -1881,7 +2012,7 @@ const CommonTestAndPreview = (props) => {
|
|
|
1881
2012
|
contentObj = hasPreviewCallBeenMade && previewDataHtml?.resolvedBody
|
|
1882
2013
|
? previewDataHtml.resolvedBody
|
|
1883
2014
|
: getCurrentContent || '';
|
|
1884
|
-
} else if (
|
|
2015
|
+
} else if (channel === CHANNELS.WHATSAPP) {
|
|
1885
2016
|
// For WhatsApp, content is an object with templateMsg, media, CTA, etc.
|
|
1886
2017
|
// Content comes from WhatsApp component state, passed via content prop
|
|
1887
2018
|
let resolvedContent = null;
|
|
@@ -2059,33 +2190,39 @@ const CommonTestAndPreview = (props) => {
|
|
|
2059
2190
|
// Only use previewDataHtml if preview call was made
|
|
2060
2191
|
if (hasPreviewCallBeenMade && previewDataHtml?.resolvedBody) {
|
|
2061
2192
|
resolvedContent = previewDataHtml.resolvedBody;
|
|
2193
|
+
if (typeof resolvedContent === 'string') {
|
|
2194
|
+
try {
|
|
2195
|
+
resolvedContent = JSON.parse(resolvedContent);
|
|
2196
|
+
} catch (e) {
|
|
2197
|
+
resolvedContent = null;
|
|
2198
|
+
}
|
|
2199
|
+
}
|
|
2062
2200
|
}
|
|
2063
2201
|
|
|
2064
|
-
// Parse content if it's a string
|
|
2065
|
-
let parsedViberContent =
|
|
2066
|
-
if (typeof
|
|
2067
|
-
|
|
2068
|
-
parsedViberContent = JSON.parse(content);
|
|
2069
|
-
} catch (e) {
|
|
2070
|
-
parsedViberContent = {};
|
|
2071
|
-
}
|
|
2202
|
+
// Parse content if it's a string, then merge with formData for carousel + tags in all entry flows
|
|
2203
|
+
let parsedViberContent = getViberMergedFormData();
|
|
2204
|
+
if (!parsedViberContent || typeof parsedViberContent !== 'object') {
|
|
2205
|
+
parsedViberContent = {};
|
|
2072
2206
|
}
|
|
2073
|
-
//
|
|
2207
|
+
// Merge template preview state with API resolved body so carousel type/cards survive slim responses
|
|
2074
2208
|
if (resolvedContent && typeof resolvedContent === 'object') {
|
|
2075
|
-
|
|
2076
|
-
|
|
2077
|
-
if (
|
|
2078
|
-
contentObj.accountName =
|
|
2209
|
+
const base = parsedViberContent && typeof parsedViberContent === 'object' ? parsedViberContent : {};
|
|
2210
|
+
contentObj = mergeViberPreviewWithResolved(base, resolvedContent);
|
|
2211
|
+
if (base.accountName && !contentObj.accountName) {
|
|
2212
|
+
contentObj.accountName = base.accountName;
|
|
2079
2213
|
}
|
|
2080
|
-
if (
|
|
2081
|
-
contentObj.brandName =
|
|
2214
|
+
if (base.brandName && !contentObj.brandName) {
|
|
2215
|
+
contentObj.brandName = base.brandName;
|
|
2082
2216
|
}
|
|
2083
2217
|
} else {
|
|
2084
|
-
|
|
2085
|
-
|
|
2086
|
-
|
|
2087
|
-
|
|
2088
|
-
|
|
2218
|
+
contentObj = parsedViberContent && typeof parsedViberContent === 'object' ? parsedViberContent : {};
|
|
2219
|
+
}
|
|
2220
|
+
if (
|
|
2221
|
+
hasPreviewCallBeenMade
|
|
2222
|
+
&& viberPreviewTagValues
|
|
2223
|
+
&& Object.keys(viberPreviewTagValues).length > 0
|
|
2224
|
+
) {
|
|
2225
|
+
contentObj = applyViberCustomValuesToContent(contentObj, viberPreviewTagValues);
|
|
2089
2226
|
}
|
|
2090
2227
|
} else if (channel === CHANNELS.ZALO) {
|
|
2091
2228
|
// For Zalo, content is an object with templatePreviewUrl, templateStatus, etc.
|
|
@@ -2341,6 +2478,8 @@ const CommonTestAndPreview = (props) => {
|
|
|
2341
2478
|
setShowJSON(false);
|
|
2342
2479
|
setTagsExtracted(false);
|
|
2343
2480
|
setPreviewDevice(DESKTOP);
|
|
2481
|
+
setHasPreviewCallBeenMade(false);
|
|
2482
|
+
setViberPreviewTagValues(null);
|
|
2344
2483
|
setSelectedTestEntities([]);
|
|
2345
2484
|
actions.clearPrefilledValues();
|
|
2346
2485
|
} else {
|
|
@@ -2470,6 +2609,11 @@ const CommonTestAndPreview = (props) => {
|
|
|
2470
2609
|
|
|
2471
2610
|
setCustomValues(updatedValues);
|
|
2472
2611
|
|
|
2612
|
+
// Viber: do not auto-resolve tags in preview; user must click Update preview
|
|
2613
|
+
if (channel === CHANNELS.VIBER) {
|
|
2614
|
+
return;
|
|
2615
|
+
}
|
|
2616
|
+
|
|
2473
2617
|
// Update preview with prefilled values (this is a valid preview call trigger)
|
|
2474
2618
|
const payload = preparePreviewPayload(
|
|
2475
2619
|
channel,
|
|
@@ -2547,6 +2691,7 @@ const CommonTestAndPreview = (props) => {
|
|
|
2547
2691
|
setPreviewDevice(DESKTOP);
|
|
2548
2692
|
setPreviewDataHtml('');
|
|
2549
2693
|
setHasPreviewCallBeenMade(false); // Reset preview call flag
|
|
2694
|
+
setViberPreviewTagValues(null);
|
|
2550
2695
|
setSelectedTestEntities([]);
|
|
2551
2696
|
setBeeContent('');
|
|
2552
2697
|
previousBeeContentRef.current = '';
|
|
@@ -2588,6 +2733,7 @@ const CommonTestAndPreview = (props) => {
|
|
|
2588
2733
|
const handleClearSelection = () => {
|
|
2589
2734
|
setSelectedCustomer(null);
|
|
2590
2735
|
setHasPreviewCallBeenMade(false); // Reset flag when customer is cleared
|
|
2736
|
+
setViberPreviewTagValues(null);
|
|
2591
2737
|
|
|
2592
2738
|
// Clear all preview errors when customer is cleared
|
|
2593
2739
|
actions.clearPreviewErrors();
|
|
@@ -2647,6 +2793,9 @@ const CommonTestAndPreview = (props) => {
|
|
|
2647
2793
|
emptyValues,
|
|
2648
2794
|
selectedCustomer
|
|
2649
2795
|
);
|
|
2796
|
+
if (channel === CHANNELS.VIBER) {
|
|
2797
|
+
setViberPreviewTagValues({ ...emptyValues });
|
|
2798
|
+
}
|
|
2650
2799
|
actions.updatePreviewRequested(payload);
|
|
2651
2800
|
setHasPreviewCallBeenMade(true); // Mark that preview call was made
|
|
2652
2801
|
};
|
|
@@ -2664,6 +2813,9 @@ const CommonTestAndPreview = (props) => {
|
|
|
2664
2813
|
customValues,
|
|
2665
2814
|
selectedCustomer
|
|
2666
2815
|
);
|
|
2816
|
+
if (channel === CHANNELS.VIBER) {
|
|
2817
|
+
setViberPreviewTagValues({ ...customValues });
|
|
2818
|
+
}
|
|
2667
2819
|
await actions.updatePreviewRequested(payload);
|
|
2668
2820
|
setHasPreviewCallBeenMade(true); // Mark that preview call was made
|
|
2669
2821
|
} catch (error) {
|
|
@@ -2685,6 +2837,8 @@ const CommonTestAndPreview = (props) => {
|
|
|
2685
2837
|
const activeTab = currentTabData?.activeTab;
|
|
2686
2838
|
const templateContent = currentTabData?.[activeTab]?.['template-content'];
|
|
2687
2839
|
contentToExtract = templateContent || contentToExtract;
|
|
2840
|
+
} else if (channel === CHANNELS.VIBER) {
|
|
2841
|
+
contentToExtract = getViberTagExtractionContent(getViberMergedFormData(), contentToExtract);
|
|
2688
2842
|
}
|
|
2689
2843
|
|
|
2690
2844
|
// Check for personalization tags (excluding unsubscribe)
|
|
@@ -514,167 +514,4 @@ describe('PreviewHeader', () => {
|
|
|
514
514
|
consoleSpy.mockRestore();
|
|
515
515
|
});
|
|
516
516
|
});
|
|
517
|
-
|
|
518
|
-
describe('WEBPUSH channel - Fullscreen expander', () => {
|
|
519
|
-
it('should render expander icon for WEBPUSH channel', () => {
|
|
520
|
-
const setIsFullscreenOpen = jest.fn();
|
|
521
|
-
const props = {
|
|
522
|
-
...defaultProps,
|
|
523
|
-
channel: CHANNELS.WEBPUSH,
|
|
524
|
-
setIsFullscreenOpen,
|
|
525
|
-
};
|
|
526
|
-
|
|
527
|
-
const { container } = render(
|
|
528
|
-
<TestWrapper>
|
|
529
|
-
<PreviewHeader {...props} />
|
|
530
|
-
</TestWrapper>
|
|
531
|
-
);
|
|
532
|
-
|
|
533
|
-
// expander icon should be present for WEBPUSH
|
|
534
|
-
const expanderIcon = container.querySelector('[class*="expander"], [aria-label*="expander"], .anticon');
|
|
535
|
-
expect(expanderIcon).toBeTruthy();
|
|
536
|
-
});
|
|
537
|
-
|
|
538
|
-
it('should NOT render expander icon for non-WEBPUSH channels', () => {
|
|
539
|
-
const setIsFullscreenOpen = jest.fn();
|
|
540
|
-
const props = {
|
|
541
|
-
...defaultProps,
|
|
542
|
-
channel: CHANNELS.EMAIL,
|
|
543
|
-
setIsFullscreenOpen,
|
|
544
|
-
showDeviceToggle: false,
|
|
545
|
-
};
|
|
546
|
-
|
|
547
|
-
const { container } = render(
|
|
548
|
-
<TestWrapper>
|
|
549
|
-
<PreviewHeader {...props} />
|
|
550
|
-
</TestWrapper>
|
|
551
|
-
);
|
|
552
|
-
|
|
553
|
-
// No expander icon for EMAIL channel (only device toggle icons may appear)
|
|
554
|
-
const expanderIcon = container.querySelector('[class*="expander"]');
|
|
555
|
-
expect(expanderIcon).toBeNull();
|
|
556
|
-
});
|
|
557
|
-
|
|
558
|
-
it('should call setIsFullscreenOpen(true) when expander icon is clicked', () => {
|
|
559
|
-
const setIsFullscreenOpen = jest.fn();
|
|
560
|
-
const props = {
|
|
561
|
-
...defaultProps,
|
|
562
|
-
channel: CHANNELS.WEBPUSH,
|
|
563
|
-
setIsFullscreenOpen,
|
|
564
|
-
};
|
|
565
|
-
|
|
566
|
-
const { container } = render(
|
|
567
|
-
<TestWrapper>
|
|
568
|
-
<PreviewHeader {...props} />
|
|
569
|
-
</TestWrapper>
|
|
570
|
-
);
|
|
571
|
-
|
|
572
|
-
const expanderIcon = container.querySelector('[class*="expander"]') ||
|
|
573
|
-
container.querySelector('.anticon');
|
|
574
|
-
if (expanderIcon) {
|
|
575
|
-
fireEvent.click(expanderIcon);
|
|
576
|
-
expect(setIsFullscreenOpen).toHaveBeenCalledWith(true);
|
|
577
|
-
}
|
|
578
|
-
});
|
|
579
|
-
|
|
580
|
-
it('should render expander icon without ACTIVE class when device is MOBILE', () => {
|
|
581
|
-
const setIsFullscreenOpen = jest.fn();
|
|
582
|
-
const props = {
|
|
583
|
-
...defaultProps,
|
|
584
|
-
channel: CHANNELS.WEBPUSH,
|
|
585
|
-
device: MOBILE,
|
|
586
|
-
setIsFullscreenOpen,
|
|
587
|
-
};
|
|
588
|
-
|
|
589
|
-
const { container } = render(
|
|
590
|
-
<TestWrapper>
|
|
591
|
-
<PreviewHeader {...props} />
|
|
592
|
-
</TestWrapper>
|
|
593
|
-
);
|
|
594
|
-
|
|
595
|
-
// Expander icon no longer adds ACTIVE class based on device
|
|
596
|
-
const activeEl = container.querySelector('.active');
|
|
597
|
-
expect(activeEl).toBeNull();
|
|
598
|
-
// But the expander icon itself should still be present
|
|
599
|
-
const expanderIcon = container.querySelector('[class*="expander"]') ||
|
|
600
|
-
container.querySelector('.anticon');
|
|
601
|
-
expect(expanderIcon).toBeTruthy();
|
|
602
|
-
});
|
|
603
|
-
|
|
604
|
-
it('should render expander icon without ACTIVE class when device is DESKTOP', () => {
|
|
605
|
-
const setIsFullscreenOpen = jest.fn();
|
|
606
|
-
const props = {
|
|
607
|
-
...defaultProps,
|
|
608
|
-
channel: CHANNELS.WEBPUSH,
|
|
609
|
-
device: DESKTOP,
|
|
610
|
-
setIsFullscreenOpen,
|
|
611
|
-
};
|
|
612
|
-
|
|
613
|
-
const { container } = render(
|
|
614
|
-
<TestWrapper>
|
|
615
|
-
<PreviewHeader {...props} />
|
|
616
|
-
</TestWrapper>
|
|
617
|
-
);
|
|
618
|
-
|
|
619
|
-
// Expander icon does not have ACTIVE class for any device
|
|
620
|
-
const activeEl = container.querySelector('.active');
|
|
621
|
-
expect(activeEl).toBeNull();
|
|
622
|
-
});
|
|
623
|
-
|
|
624
|
-
it('should render expander icon alongside device content for WEBPUSH', () => {
|
|
625
|
-
// Note: suppression of showDeviceToggle for WEBPUSH is done in UnifiedPreview (parent),
|
|
626
|
-
// not in PreviewHeader itself. PreviewHeader only adds the expander icon for WEBPUSH.
|
|
627
|
-
const setIsFullscreenOpen = jest.fn();
|
|
628
|
-
const props = {
|
|
629
|
-
...defaultProps,
|
|
630
|
-
channel: CHANNELS.WEBPUSH,
|
|
631
|
-
setIsFullscreenOpen,
|
|
632
|
-
showDeviceToggle: false,
|
|
633
|
-
};
|
|
634
|
-
|
|
635
|
-
const { container } = render(
|
|
636
|
-
<TestWrapper>
|
|
637
|
-
<PreviewHeader {...props} />
|
|
638
|
-
</TestWrapper>
|
|
639
|
-
);
|
|
640
|
-
|
|
641
|
-
// expander icon should be present for WEBPUSH
|
|
642
|
-
const expanderIcon = container.querySelector('[class*="expander"]') ||
|
|
643
|
-
container.querySelector('.anticon');
|
|
644
|
-
expect(expanderIcon).toBeTruthy();
|
|
645
|
-
});
|
|
646
|
-
|
|
647
|
-
it('should accept isFullscreenOpen and setIsFullscreenOpen as props', () => {
|
|
648
|
-
const setIsFullscreenOpen = jest.fn();
|
|
649
|
-
const props = {
|
|
650
|
-
...defaultProps,
|
|
651
|
-
channel: CHANNELS.WEBPUSH,
|
|
652
|
-
isFullscreenOpen: false,
|
|
653
|
-
setIsFullscreenOpen,
|
|
654
|
-
};
|
|
655
|
-
|
|
656
|
-
expect(() =>
|
|
657
|
-
render(
|
|
658
|
-
<TestWrapper>
|
|
659
|
-
<PreviewHeader {...props} />
|
|
660
|
-
</TestWrapper>
|
|
661
|
-
)
|
|
662
|
-
).not.toThrow();
|
|
663
|
-
});
|
|
664
|
-
|
|
665
|
-
it('should use default setIsFullscreenOpen when not provided', () => {
|
|
666
|
-
const props = {
|
|
667
|
-
...defaultProps,
|
|
668
|
-
channel: CHANNELS.WEBPUSH,
|
|
669
|
-
};
|
|
670
|
-
|
|
671
|
-
expect(() =>
|
|
672
|
-
render(
|
|
673
|
-
<TestWrapper>
|
|
674
|
-
<PreviewHeader {...props} />
|
|
675
|
-
</TestWrapper>
|
|
676
|
-
)
|
|
677
|
-
).not.toThrow();
|
|
678
|
-
});
|
|
679
|
-
});
|
|
680
517
|
});
|