@capillarytech/creatives-library 8.0.125 → 8.0.127-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/config/app.js +6 -0
- package/containers/App/constants.js +1 -0
- package/index.html +3 -1
- package/initialReducer.js +2 -0
- package/package.json +1 -1
- package/services/api.js +94 -1
- package/services/tests/api.test.js +191 -0
- package/tests/integration/TemplateCreation/TemplateCreation.integration.test.js +8 -3
- package/tests/integration/TemplateCreation/api-response.js +5 -0
- package/tests/integration/TemplateCreation/msw-handler.js +42 -63
- package/utils/common.js +7 -0
- package/utils/commonUtils.js +2 -6
- package/utils/createPayload.js +272 -0
- package/utils/tests/createPayload.test.js +761 -0
- package/v2Components/CapImageUpload/index.js +59 -46
- package/v2Components/CapInAppCTA/index.js +1 -0
- package/v2Components/CapMpushCTA/constants.js +25 -0
- package/v2Components/CapMpushCTA/index.js +332 -0
- package/v2Components/CapMpushCTA/index.scss +95 -0
- package/v2Components/CapMpushCTA/messages.js +89 -0
- package/v2Components/CapTagList/index.js +177 -120
- package/v2Components/CapVideoUpload/constants.js +3 -0
- package/v2Components/CapVideoUpload/index.js +167 -110
- package/v2Components/CapVideoUpload/messages.js +16 -0
- package/v2Components/Carousel/index.js +15 -13
- package/v2Components/CustomerSearchSection/_customerSearch.scss +309 -0
- package/v2Components/CustomerSearchSection/constants.js +5 -0
- package/v2Components/CustomerSearchSection/index.js +367 -0
- package/v2Components/CustomerSearchSection/messages.js +20 -0
- package/v2Components/CustomerSearchSection/tests/utils.test.js +334 -0
- package/v2Components/CustomerSearchSection/utils.js +49 -0
- package/v2Components/ErrorInfoNote/style.scss +1 -0
- package/v2Components/MobilePushPreviewV2/index.js +37 -5
- package/v2Components/TemplatePreview/_templatePreview.scss +114 -72
- package/v2Components/TemplatePreview/assets/images/Android _ With date and time.svg +29 -0
- package/v2Components/TemplatePreview/assets/images/android.svg +9 -0
- package/v2Components/TemplatePreview/assets/images/iOS _ With date and time.svg +26 -0
- package/v2Components/TemplatePreview/assets/images/ios.svg +9 -0
- package/v2Components/TemplatePreview/index.js +178 -50
- package/v2Components/TemplatePreview/messages.js +4 -0
- package/v2Components/TestAndPreviewSlidebox/CustomValuesEditor.js +169 -0
- package/v2Components/TestAndPreviewSlidebox/LeftPanelContent.js +95 -0
- package/v2Components/TestAndPreviewSlidebox/PreviewSection.js +69 -0
- package/v2Components/TestAndPreviewSlidebox/SendTestMessage.js +68 -0
- package/v2Components/TestAndPreviewSlidebox/_testAndPreviewSlidebox.scss +543 -0
- package/v2Components/TestAndPreviewSlidebox/actions.js +67 -0
- package/v2Components/TestAndPreviewSlidebox/constants.js +67 -0
- package/v2Components/TestAndPreviewSlidebox/index.js +592 -0
- package/v2Components/TestAndPreviewSlidebox/messages.js +147 -0
- package/v2Components/TestAndPreviewSlidebox/reducer.js +233 -0
- package/v2Components/TestAndPreviewSlidebox/sagas.js +258 -0
- package/v2Components/TestAndPreviewSlidebox/selectors.js +142 -0
- package/v2Components/TestAndPreviewSlidebox/tests/CustomValuesEditor.test.js +425 -0
- package/v2Components/TestAndPreviewSlidebox/tests/LeftPanelContent.test.js +400 -0
- package/v2Components/TestAndPreviewSlidebox/tests/SendTestMessage.test.js +448 -0
- package/v2Components/TestAndPreviewSlidebox/tests/actions.test.js +80 -0
- package/v2Components/TestAndPreviewSlidebox/tests/reducer.test.js +367 -0
- package/v2Components/TestAndPreviewSlidebox/tests/saga.rtl.test.js +192 -0
- package/v2Components/TestAndPreviewSlidebox/tests/saga.test.js +652 -0
- package/v2Components/TestAndPreviewSlidebox/tests/selector.test.js +182 -0
- package/v2Containers/CreativesContainer/SlideBoxContent.js +22 -10
- package/v2Containers/CreativesContainer/SlideBoxFooter.js +23 -2
- package/v2Containers/CreativesContainer/index.js +216 -136
- package/v2Containers/CreativesContainer/messages.js +4 -0
- package/v2Containers/CreativesContainer/tests/__snapshots__/index.test.js.snap +21 -0
- package/v2Containers/Email/index.js +27 -2
- package/v2Containers/EmailWrapper/hooks/useEmailWrapper.js +10 -0
- package/v2Containers/EmailWrapper/index.js +6 -0
- package/v2Containers/InApp/constants.js +1 -0
- package/v2Containers/InApp/index.js +13 -13
- package/v2Containers/Line/Container/ImageCarousel/tests/__snapshots__/content.test.js.snap +3 -0
- package/v2Containers/Line/Container/ImageCarousel/tests/__snapshots__/index.test.js.snap +2 -0
- package/v2Containers/Line/Container/Wrapper/tests/__snapshots__/index.test.js.snap +2 -0
- package/v2Containers/Line/Container/tests/__snapshots__/index.test.js.snap +9 -0
- package/v2Containers/MobilePush/Create/index.js +1 -0
- package/v2Containers/MobilePush/commonMethods.js +7 -14
- package/v2Containers/MobilePushNew/actions.js +116 -0
- package/v2Containers/MobilePushNew/components/CtaButtons.js +170 -0
- package/v2Containers/MobilePushNew/components/MediaUploaders.js +754 -0
- package/v2Containers/MobilePushNew/components/PlatformContentFields.js +279 -0
- package/v2Containers/MobilePushNew/components/index.js +5 -0
- package/v2Containers/MobilePushNew/components/tests/CtaButtons.test.js +779 -0
- package/v2Containers/MobilePushNew/components/tests/MediaUploaders.test.js +2114 -0
- package/v2Containers/MobilePushNew/components/tests/PlatformContentFields.test.js +343 -0
- package/v2Containers/MobilePushNew/constants.js +115 -0
- package/v2Containers/MobilePushNew/hooks/tests/usePlatformSync.test.js +1299 -0
- package/v2Containers/MobilePushNew/hooks/tests/useUpload.test.js +1223 -0
- package/v2Containers/MobilePushNew/hooks/usePlatformSync.js +246 -0
- package/v2Containers/MobilePushNew/hooks/useUpload.js +726 -0
- package/v2Containers/MobilePushNew/index.js +2280 -0
- package/v2Containers/MobilePushNew/index.scss +308 -0
- package/v2Containers/MobilePushNew/messages.js +226 -0
- package/v2Containers/MobilePushNew/reducer.js +160 -0
- package/v2Containers/MobilePushNew/sagas.js +198 -0
- package/v2Containers/MobilePushNew/selectors.js +55 -0
- package/v2Containers/MobilePushNew/tests/reducer.test.js +741 -0
- package/v2Containers/MobilePushNew/tests/sagas.test.js +863 -0
- package/v2Containers/MobilePushNew/tests/selectors.test.js +425 -0
- package/v2Containers/MobilePushNew/tests/utils.test.js +322 -0
- package/v2Containers/MobilePushNew/utils.js +33 -0
- package/v2Containers/Rcs/tests/__snapshots__/index.test.js.snap +23 -5
- package/v2Containers/SmsTrai/Edit/tests/__snapshots__/index.test.js.snap +4 -0
- package/v2Containers/TagList/index.js +56 -10
- package/v2Containers/Templates/_templates.scss +101 -1
- package/v2Containers/Templates/index.js +147 -35
- package/v2Containers/Templates/messages.js +8 -0
- package/v2Containers/Templates/sagas.js +2 -0
- package/v2Containers/Whatsapp/constants.js +1 -0
- package/v2Containers/Whatsapp/tests/__snapshots__/index.test.js.snap +35 -0
- package/v2Containers/Email/tests/index.test.js +0 -35
|
@@ -0,0 +1,272 @@
|
|
|
1
|
+
// Utility to create the Mobile Push payload for rich media, with validation
|
|
2
|
+
import { DEEP_LINK } from "../v2Components/CapInAppCTA/constants";
|
|
3
|
+
import { EXTERNAL_URL } from "../v2Components/CapMpushCTA/constants";
|
|
4
|
+
import {
|
|
5
|
+
IMAGE, VIDEO, GIF, CAROUSEL, TEXT, BIG_TEXT, BIG_PICTURE, MOBILE_PUSH_CHANNEL,
|
|
6
|
+
EXTERNAL_LINK,
|
|
7
|
+
ANDROID,
|
|
8
|
+
IOS,
|
|
9
|
+
MANUAL_CAROUSEL,
|
|
10
|
+
AUTO_CAROUSEL,
|
|
11
|
+
FILMSTRIP_CAROUSEL,
|
|
12
|
+
} from "../v2Containers/MobilePushNew/constants";
|
|
13
|
+
import { NONE } from "../v2Containers/Whatsapp/constants";
|
|
14
|
+
/**
|
|
15
|
+
* Constructs the payload for Mobile Push, supporting both legacy and rich media as per backend contract.
|
|
16
|
+
* - Trims and validates templateName
|
|
17
|
+
* - Handles legacy and rich media (VIDEO, GIF, CAROUSEL, etc.)
|
|
18
|
+
* - Builds androidContent and iosContent with correct structure
|
|
19
|
+
* @param {Object} params - All required params
|
|
20
|
+
* @param {string} params.templateName
|
|
21
|
+
* @param {Object} params.androidContent
|
|
22
|
+
* @param {Object} params.iosContent
|
|
23
|
+
* @param {Object} params.accountData
|
|
24
|
+
* @param {Object} [params.options] - Optional extra options (ouId, actionId, etc.)
|
|
25
|
+
* @returns {Object} - Payload ready for backend
|
|
26
|
+
*/
|
|
27
|
+
function createPayload({
|
|
28
|
+
templateName, androidContent, iosContent, imageSrc = {}, mpushVideoSrcAndPreview = {}, accountData, options = {}, sameContent = false,
|
|
29
|
+
} = {}) {
|
|
30
|
+
// Platform support checks must be at the top
|
|
31
|
+
const isAndroidSupported = accountData?.configs?.android === '1';
|
|
32
|
+
const isIosSupported = accountData?.configs?.ios === '1';
|
|
33
|
+
// Validate and trim template name
|
|
34
|
+
const trimmedTemplateName = (templateName || "").trim();
|
|
35
|
+
if (!trimmedTemplateName) {
|
|
36
|
+
throw new Error("Template name is empty or contains only white spaces");
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
// Validate androidContent and iosContent
|
|
40
|
+
if (androidContent && (!androidContent?.title || !androidContent?.message)) {
|
|
41
|
+
throw new Error("Android content must have title and message");
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
if (iosContent && (!iosContent?.title || !iosContent?.message)) {
|
|
45
|
+
throw new Error("iOS content must have title and message");
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
// Validate accountData
|
|
49
|
+
if (!accountData) {
|
|
50
|
+
throw new Error("Account data is required. Please select a MobilePush account.");
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
const accountId = accountData?.accountId || accountData?.id;
|
|
54
|
+
const licenseCode = accountData?.licenseCode || accountData?.sourceAccountIdentifier;
|
|
55
|
+
const sourceType = accountData?.sourceType || accountData?.sourceTypeName;
|
|
56
|
+
|
|
57
|
+
// Ensure imageSrc has the required properties
|
|
58
|
+
const safeImageSrc = {
|
|
59
|
+
androidImageSrc: imageSrc?.androidImageSrc || "",
|
|
60
|
+
iosImageSrc: imageSrc?.iosImageSrc || "",
|
|
61
|
+
};
|
|
62
|
+
|
|
63
|
+
// Helper to build expandableDetails for legacy and rich media
|
|
64
|
+
function buildExpandableDetails(content, contentImageSrc, platform = ANDROID) {
|
|
65
|
+
const style = content?.expandableDetails?.style || content?.mediaType || BIG_TEXT;
|
|
66
|
+
const expandableDetails = { style };
|
|
67
|
+
|
|
68
|
+
if (style === IMAGE || style === BIG_PICTURE) {
|
|
69
|
+
expandableDetails.style = BIG_PICTURE;
|
|
70
|
+
expandableDetails.message = content?.message;
|
|
71
|
+
expandableDetails.image = contentImageSrc || "";
|
|
72
|
+
} else if (style === VIDEO) {
|
|
73
|
+
expandableDetails.message = content?.message;
|
|
74
|
+
// Always build media array for VIDEO
|
|
75
|
+
let url = '';
|
|
76
|
+
let text = '';
|
|
77
|
+
let videoPreviewUrl = '';
|
|
78
|
+
if (mpushVideoSrcAndPreview?.mpushVideoSrc) {
|
|
79
|
+
url = mpushVideoSrcAndPreview?.mpushVideoSrc;
|
|
80
|
+
videoPreviewUrl = mpushVideoSrcAndPreview?.mpushVideoPreviewImg || '';
|
|
81
|
+
} else if (content?.mediaList && content?.mediaList[0]) {
|
|
82
|
+
const { url: mediaUrl = '', text: mediaText = '' } = content?.mediaList[0];
|
|
83
|
+
url = mediaUrl;
|
|
84
|
+
text = mediaText;
|
|
85
|
+
}
|
|
86
|
+
expandableDetails.media = [
|
|
87
|
+
{
|
|
88
|
+
url,
|
|
89
|
+
text,
|
|
90
|
+
type: VIDEO,
|
|
91
|
+
videoPreviewUrl,
|
|
92
|
+
},
|
|
93
|
+
];
|
|
94
|
+
} else if (style === GIF) {
|
|
95
|
+
expandableDetails.message = content?.message;
|
|
96
|
+
// Handle GIF: preserve original type from mediaList if available, otherwise convert to VIDEO
|
|
97
|
+
let url = '';
|
|
98
|
+
let text = '';
|
|
99
|
+
let mediaType = VIDEO; // Default to VIDEO for backend compatibility
|
|
100
|
+
|
|
101
|
+
if (content?.mediaList && content?.mediaList[0]) {
|
|
102
|
+
// If mediaList exists, use it and preserve the original type
|
|
103
|
+
const { url: mediaUrl = '', text: mediaText = '', type: originalType = VIDEO } = content?.mediaList[0];
|
|
104
|
+
url = mediaUrl;
|
|
105
|
+
text = mediaText;
|
|
106
|
+
mediaType = originalType; // Preserve original type from mediaList
|
|
107
|
+
} else if (mpushVideoSrcAndPreview?.mpushVideoSrc) {
|
|
108
|
+
// If no mediaList but mpushVideoSrc exists, convert to VIDEO
|
|
109
|
+
url = mpushVideoSrcAndPreview?.mpushVideoSrc;
|
|
110
|
+
mediaType = VIDEO;
|
|
111
|
+
}
|
|
112
|
+
|
|
113
|
+
expandableDetails.media = [
|
|
114
|
+
{
|
|
115
|
+
url,
|
|
116
|
+
text,
|
|
117
|
+
type: mediaType,
|
|
118
|
+
},
|
|
119
|
+
];
|
|
120
|
+
} else if (style === BIG_TEXT || style === TEXT || style === NONE) {
|
|
121
|
+
expandableDetails.style = BIG_TEXT;
|
|
122
|
+
expandableDetails.message = content?.message;
|
|
123
|
+
} else if ((style === CAROUSEL || style === MANUAL_CAROUSEL || style === AUTO_CAROUSEL || style === FILMSTRIP_CAROUSEL)) {
|
|
124
|
+
// Handle carousel data
|
|
125
|
+
expandableDetails.style = 'MANUAL_CAROUSEL';
|
|
126
|
+
expandableDetails.message = content?.message;
|
|
127
|
+
|
|
128
|
+
// Add carousel data if it exists
|
|
129
|
+
if (content?.carouselData && Array.isArray(content?.carouselData) && content?.carouselData.length > 0) {
|
|
130
|
+
expandableDetails.carouselData = content?.carouselData.map((card) => ({
|
|
131
|
+
mediaType: card.mediaType || 'image',
|
|
132
|
+
imageUrl: card.imageUrl || '',
|
|
133
|
+
videoSrc: card.videoSrc || '',
|
|
134
|
+
buttons: card.buttons || [],
|
|
135
|
+
}));
|
|
136
|
+
}
|
|
137
|
+
|
|
138
|
+
// Handle mediaList for carousel (used in tests and some scenarios)
|
|
139
|
+
if (content?.mediaList && Array.isArray(content?.mediaList) && content?.mediaList.length > 0) {
|
|
140
|
+
expandableDetails.media = content?.mediaList.map((m) => ({
|
|
141
|
+
url: m.url,
|
|
142
|
+
text: m.text || "",
|
|
143
|
+
type: m.type,
|
|
144
|
+
}));
|
|
145
|
+
}
|
|
146
|
+
} else if ([GIF].includes(style) && content?.mediaList) {
|
|
147
|
+
expandableDetails.media = (content?.mediaList || []).map((m) => ({
|
|
148
|
+
url: m.url,
|
|
149
|
+
text: m.text || "",
|
|
150
|
+
type: m.type,
|
|
151
|
+
}));
|
|
152
|
+
}
|
|
153
|
+
|
|
154
|
+
// iOS always needs ctas array
|
|
155
|
+
if (platform === IOS) {
|
|
156
|
+
expandableDetails.ctas = content?.expandableDetails?.ctas || [];
|
|
157
|
+
}
|
|
158
|
+
|
|
159
|
+
// Add any additional expandableDetails fields
|
|
160
|
+
if (content?.expandableDetails) {
|
|
161
|
+
Object.entries(content?.expandableDetails).forEach(([k, v]) => {
|
|
162
|
+
if (!(k in expandableDetails)) expandableDetails[k] = v;
|
|
163
|
+
});
|
|
164
|
+
}
|
|
165
|
+
return expandableDetails;
|
|
166
|
+
}
|
|
167
|
+
|
|
168
|
+
// Helper to build custom fields array (legacy)
|
|
169
|
+
function buildCustomFields(content) {
|
|
170
|
+
// If content.custom is already an array, return as is
|
|
171
|
+
if (Array.isArray(content?.custom)) return content?.custom;
|
|
172
|
+
// If it's an object, map to array
|
|
173
|
+
if (content?.custom && typeof content?.custom === 'object') {
|
|
174
|
+
return Object.entries(content?.custom).map(([key, value]) => ({ key, value }));
|
|
175
|
+
}
|
|
176
|
+
return [];
|
|
177
|
+
}
|
|
178
|
+
|
|
179
|
+
// Compose androidContent for legacy payload
|
|
180
|
+
let androidLegacy;
|
|
181
|
+
if (isAndroidSupported && isValidContent(androidContent)) {
|
|
182
|
+
androidLegacy = {
|
|
183
|
+
luid: "{{luid}}",
|
|
184
|
+
cuid: "{{cuid}}",
|
|
185
|
+
communicationId: "{{communicationId}}",
|
|
186
|
+
title: androidContent.title,
|
|
187
|
+
message: androidContent.message,
|
|
188
|
+
expandableDetails: buildExpandableDetails(androidContent, safeImageSrc.androidImageSrc),
|
|
189
|
+
custom: buildCustomFields(androidContent),
|
|
190
|
+
type: androidContent.mediaType,
|
|
191
|
+
deviceType: 'ANDROID',
|
|
192
|
+
};
|
|
193
|
+
if (androidContent?.actionOnClick && (androidContent?.deepLinkValue || androidContent?.externalLinkValue)) {
|
|
194
|
+
const actionLink = androidContent?.linkType === EXTERNAL_LINK ? androidContent?.externalLinkValue : androidContent?.deepLinkValue;
|
|
195
|
+
androidLegacy.cta = {
|
|
196
|
+
type: androidContent.linkType === EXTERNAL_LINK ? EXTERNAL_URL : DEEP_LINK,
|
|
197
|
+
actionLink,
|
|
198
|
+
};
|
|
199
|
+
}
|
|
200
|
+
}
|
|
201
|
+
|
|
202
|
+
// Compose iosContent for legacy payload
|
|
203
|
+
let iosLegacy;
|
|
204
|
+
if (isIosSupported && isValidContent(iosContent)) {
|
|
205
|
+
iosLegacy = {
|
|
206
|
+
luid: "{{luid}}",
|
|
207
|
+
cuid: "{{cuid}}",
|
|
208
|
+
communicationId: "{{communicationId}}",
|
|
209
|
+
title: iosContent.title,
|
|
210
|
+
message: iosContent.message,
|
|
211
|
+
expandableDetails: buildExpandableDetails(iosContent, safeImageSrc.iosImageSrc, 'IOS'),
|
|
212
|
+
custom: buildCustomFields(iosContent),
|
|
213
|
+
type: iosContent.mediaType,
|
|
214
|
+
deviceType: 'IOS',
|
|
215
|
+
};
|
|
216
|
+
if (iosContent?.actionOnClick && (iosContent?.deepLinkValue || iosContent?.externalLinkValue)) {
|
|
217
|
+
const actionLink = iosContent?.linkType === EXTERNAL_LINK ? iosContent?.externalLinkValue : iosContent?.deepLinkValue;
|
|
218
|
+
iosLegacy.cta = {
|
|
219
|
+
type: iosContent?.linkType === EXTERNAL_LINK ? EXTERNAL_URL : DEEP_LINK,
|
|
220
|
+
actionLink,
|
|
221
|
+
};
|
|
222
|
+
}
|
|
223
|
+
}
|
|
224
|
+
|
|
225
|
+
// Helper to check if content is non-empty and valid
|
|
226
|
+
function isValidContent(content) {
|
|
227
|
+
return content && typeof content === 'object' && content.title && content.message;
|
|
228
|
+
}
|
|
229
|
+
|
|
230
|
+
// Determine platform support from accountData
|
|
231
|
+
// const isAndroidSupported = accountData?.configs?.android === '1';
|
|
232
|
+
// const isIosSupported = accountData?.configs?.ios === '1';
|
|
233
|
+
|
|
234
|
+
if (isAndroidSupported && (!androidContent || !androidContent?.title || !androidContent?.message)) {
|
|
235
|
+
console.error('Android content missing or invalid:', androidContent);
|
|
236
|
+
throw new Error("Android content must have title and message");
|
|
237
|
+
}
|
|
238
|
+
if (isIosSupported && (!iosContent || !iosContent?.title || !iosContent?.message)) {
|
|
239
|
+
console.error('iOS content missing or invalid:', iosContent);
|
|
240
|
+
throw new Error("iOS content must have title and message");
|
|
241
|
+
}
|
|
242
|
+
|
|
243
|
+
// Compose the full payload in legacy format
|
|
244
|
+
const versionsBase = {};
|
|
245
|
+
if (androidLegacy) versionsBase.ANDROID = androidLegacy;
|
|
246
|
+
if (iosLegacy) versionsBase.IOS = iosLegacy;
|
|
247
|
+
|
|
248
|
+
// Fallback template name to platform title if not provided
|
|
249
|
+
let finalTemplateName = trimmedTemplateName;
|
|
250
|
+
if (!finalTemplateName) {
|
|
251
|
+
finalTemplateName = (androidContent && androidContent.title) || (iosContent && iosContent.title) || '';
|
|
252
|
+
}
|
|
253
|
+
|
|
254
|
+
const payload = {
|
|
255
|
+
versions: {
|
|
256
|
+
base: versionsBase,
|
|
257
|
+
},
|
|
258
|
+
type: MOBILE_PUSH_CHANNEL,
|
|
259
|
+
name: finalTemplateName,
|
|
260
|
+
definition: {
|
|
261
|
+
accountId,
|
|
262
|
+
licenseCode,
|
|
263
|
+
mode: options?.mode || TEXT.toLowerCase(),
|
|
264
|
+
sourceType,
|
|
265
|
+
sameContent,
|
|
266
|
+
},
|
|
267
|
+
};
|
|
268
|
+
|
|
269
|
+
return payload;
|
|
270
|
+
}
|
|
271
|
+
|
|
272
|
+
export { createPayload };
|