@capillarytech/creatives-library 8.0.247 → 8.0.249

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 CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@capillarytech/creatives-library",
3
3
  "author": "meharaj",
4
- "version": "8.0.247",
4
+ "version": "8.0.249",
5
5
  "description": "Capillary creatives ui",
6
6
  "main": "./index.js",
7
7
  "module": "./index.es.js",
@@ -15,6 +15,7 @@ import {
15
15
  RCS,
16
16
  LINE,
17
17
  VIBER,
18
+ WEBPUSH,
18
19
  } from "../../v2Containers/CreativesContainer/constants";
19
20
 
20
21
  describe("transformerUtils", () => {
@@ -1182,6 +1183,302 @@ describe("transformerUtils", () => {
1182
1183
  });
1183
1184
  });
1184
1185
 
1186
+ describe("WebPush payload transformation", () => {
1187
+ it("should transform WebPush data correctly with minimal data", () => {
1188
+ const mockData = {
1189
+ channel: WEBPUSH,
1190
+ messageSubject: "test webpush notification"
1191
+ };
1192
+
1193
+ const result = transformChannelPayload(mockData);
1194
+
1195
+ expect(result.centralCommsPayload).toBeDefined();
1196
+ expect(result.centralCommsPayload.channel).toEqual(WEBPUSH);
1197
+ expect(result.centralCommsPayload.webpushMessageContent.messageSubject).toEqual(
1198
+ "test webpush notification"
1199
+ );
1200
+ expect(result.centralCommsPayload.clientName).toEqual("VENENO");
1201
+ });
1202
+
1203
+ it("should transform WebPush data with all options", () => {
1204
+ const mockData = {
1205
+ channel: WEBPUSH,
1206
+ messageSubject: "test webpush notification",
1207
+ messageContent: {
1208
+ content: {
1209
+ accountId: 12345,
1210
+ content: {
1211
+ title: "WebPush Title",
1212
+ message: "WebPush Message",
1213
+ iconImageUrl: "https://example.com/icon.png",
1214
+ cta: {
1215
+ actionLink: "https://example.com/action",
1216
+ actionText: "Click Here"
1217
+ },
1218
+ expandableDetails: {
1219
+ style: "BIG_TEXT",
1220
+ message: "Expanded Message"
1221
+ }
1222
+ },
1223
+ offers: [
1224
+ { id: "offer-1", title: "Offer 1" },
1225
+ { id: "offer-2", title: "Offer 2" }
1226
+ ]
1227
+ }
1228
+ }
1229
+ };
1230
+
1231
+ const options = {
1232
+ loyaltyMetaData: {
1233
+ actionId: "action-123",
1234
+ ouId: 456,
1235
+ clientName: "TestClient",
1236
+ module: "TestModule",
1237
+ transformedMessageDetails: {
1238
+ webpushDeliverySettings: {
1239
+ sendDate: "2023-01-01",
1240
+ priority: "HIGH"
1241
+ }
1242
+ }
1243
+ }
1244
+ };
1245
+
1246
+ const result = transformChannelPayload(mockData, options);
1247
+
1248
+ // Check base payload
1249
+ expect(result.centralCommsPayload.sourceEntityId).toEqual("action-123");
1250
+ expect(result.centralCommsPayload.ouId).toEqual(456);
1251
+ expect(result.centralCommsPayload.clientName).toEqual("TestClient");
1252
+ expect(result.centralCommsPayload.module).toEqual("TestModule");
1253
+
1254
+ // Check WebPush-specific content
1255
+ expect(result.centralCommsPayload.webpushMessageContent.channel).toEqual(WEBPUSH);
1256
+ expect(result.centralCommsPayload.webpushMessageContent.accountId).toEqual(12345);
1257
+ expect(result.centralCommsPayload.webpushMessageContent.messageSubject).toEqual(
1258
+ "test webpush notification"
1259
+ );
1260
+ expect(result.centralCommsPayload.webpushMessageContent.content.title).toEqual(
1261
+ "WebPush Title"
1262
+ );
1263
+ expect(result.centralCommsPayload.webpushMessageContent.content.message).toEqual(
1264
+ "WebPush Message"
1265
+ );
1266
+ expect(result.centralCommsPayload.webpushMessageContent.content.iconImageUrl).toEqual(
1267
+ "https://example.com/icon.png"
1268
+ );
1269
+ expect(result.centralCommsPayload.webpushMessageContent.content.cta).toEqual({
1270
+ actionLink: "https://example.com/action",
1271
+ actionText: "Click Here"
1272
+ });
1273
+ expect(result.centralCommsPayload.webpushMessageContent.content.expandableDetails).toEqual({
1274
+ style: "BIG_TEXT",
1275
+ message: "Expanded Message"
1276
+ });
1277
+ expect(result.centralCommsPayload.webpushMessageContent.offers).toEqual([
1278
+ { id: "offer-1", title: "Offer 1" },
1279
+ { id: "offer-2", title: "Offer 2" }
1280
+ ]);
1281
+
1282
+ // Check delivery settings
1283
+ expect(result.centralCommsPayload.webpushDeliverySettings).toEqual({
1284
+ sendDate: "2023-01-01",
1285
+ priority: "HIGH"
1286
+ });
1287
+ });
1288
+
1289
+ it("should handle missing messageContent structure", () => {
1290
+ const mockData = {
1291
+ channel: WEBPUSH,
1292
+ messageSubject: "test webpush notification"
1293
+ };
1294
+
1295
+ const result = transformChannelPayload(mockData);
1296
+
1297
+ expect(result.centralCommsPayload.webpushMessageContent.accountId).toEqual(0);
1298
+ expect(result.centralCommsPayload.webpushMessageContent.content.title).toEqual("");
1299
+ expect(result.centralCommsPayload.webpushMessageContent.content.message).toEqual("");
1300
+ expect(result.centralCommsPayload.webpushMessageContent.offers).toEqual([]);
1301
+ });
1302
+
1303
+ it("should handle missing content properties", () => {
1304
+ const mockData = {
1305
+ channel: WEBPUSH,
1306
+ messageSubject: "test webpush notification",
1307
+ messageContent: {
1308
+ content: {
1309
+ accountId: 12345,
1310
+ content: {}
1311
+ }
1312
+ }
1313
+ };
1314
+
1315
+ const result = transformChannelPayload(mockData);
1316
+
1317
+ expect(result.centralCommsPayload.webpushMessageContent.accountId).toEqual(12345);
1318
+ expect(result.centralCommsPayload.webpushMessageContent.content.title).toEqual("");
1319
+ expect(result.centralCommsPayload.webpushMessageContent.content.message).toEqual("");
1320
+ expect(result.centralCommsPayload.webpushMessageContent.content.iconImageUrl).toBeUndefined();
1321
+ expect(result.centralCommsPayload.webpushMessageContent.content.cta).toBeUndefined();
1322
+ expect(result.centralCommsPayload.webpushMessageContent.content.expandableDetails).toBeUndefined();
1323
+ });
1324
+
1325
+ it("should conditionally include iconImageUrl only when present", () => {
1326
+ const mockDataWithoutIcon = {
1327
+ channel: WEBPUSH,
1328
+ messageSubject: "test",
1329
+ messageContent: {
1330
+ content: {
1331
+ content: {
1332
+ title: "Title",
1333
+ message: "Message"
1334
+ }
1335
+ }
1336
+ }
1337
+ };
1338
+
1339
+ const resultWithoutIcon = transformChannelPayload(mockDataWithoutIcon);
1340
+ expect(resultWithoutIcon.centralCommsPayload.webpushMessageContent.content.iconImageUrl).toBeUndefined();
1341
+
1342
+ const mockDataWithIcon = {
1343
+ channel: WEBPUSH,
1344
+ messageSubject: "test",
1345
+ messageContent: {
1346
+ content: {
1347
+ content: {
1348
+ title: "Title",
1349
+ message: "Message",
1350
+ iconImageUrl: "https://example.com/icon.png"
1351
+ }
1352
+ }
1353
+ }
1354
+ };
1355
+
1356
+ const resultWithIcon = transformChannelPayload(mockDataWithIcon);
1357
+ expect(resultWithIcon.centralCommsPayload.webpushMessageContent.content.iconImageUrl).toEqual(
1358
+ "https://example.com/icon.png"
1359
+ );
1360
+ });
1361
+
1362
+ it("should conditionally include cta only when present", () => {
1363
+ const mockDataWithoutCta = {
1364
+ channel: WEBPUSH,
1365
+ messageSubject: "test",
1366
+ messageContent: {
1367
+ content: {
1368
+ content: {
1369
+ title: "Title",
1370
+ message: "Message"
1371
+ }
1372
+ }
1373
+ }
1374
+ };
1375
+
1376
+ const resultWithoutCta = transformChannelPayload(mockDataWithoutCta);
1377
+ expect(resultWithoutCta.centralCommsPayload.webpushMessageContent.content.cta).toBeUndefined();
1378
+
1379
+ const mockDataWithCta = {
1380
+ channel: WEBPUSH,
1381
+ messageSubject: "test",
1382
+ messageContent: {
1383
+ content: {
1384
+ content: {
1385
+ title: "Title",
1386
+ message: "Message",
1387
+ cta: {
1388
+ actionLink: "https://example.com",
1389
+ actionText: "Click"
1390
+ }
1391
+ }
1392
+ }
1393
+ }
1394
+ };
1395
+
1396
+ const resultWithCta = transformChannelPayload(mockDataWithCta);
1397
+ expect(resultWithCta.centralCommsPayload.webpushMessageContent.content.cta).toEqual({
1398
+ actionLink: "https://example.com",
1399
+ actionText: "Click"
1400
+ });
1401
+ });
1402
+
1403
+ it("should conditionally include expandableDetails only when present", () => {
1404
+ const mockDataWithoutExpandable = {
1405
+ channel: WEBPUSH,
1406
+ messageSubject: "test",
1407
+ messageContent: {
1408
+ content: {
1409
+ content: {
1410
+ title: "Title",
1411
+ message: "Message"
1412
+ }
1413
+ }
1414
+ }
1415
+ };
1416
+
1417
+ const resultWithoutExpandable = transformChannelPayload(mockDataWithoutExpandable);
1418
+ expect(resultWithoutExpandable.centralCommsPayload.webpushMessageContent.content.expandableDetails).toBeUndefined();
1419
+
1420
+ const mockDataWithExpandable = {
1421
+ channel: WEBPUSH,
1422
+ messageSubject: "test",
1423
+ messageContent: {
1424
+ content: {
1425
+ content: {
1426
+ title: "Title",
1427
+ message: "Message",
1428
+ expandableDetails: {
1429
+ style: "BIG_TEXT",
1430
+ message: "Expanded"
1431
+ }
1432
+ }
1433
+ }
1434
+ }
1435
+ };
1436
+
1437
+ const resultWithExpandable = transformChannelPayload(mockDataWithExpandable);
1438
+ expect(resultWithExpandable.centralCommsPayload.webpushMessageContent.content.expandableDetails).toEqual({
1439
+ style: "BIG_TEXT",
1440
+ message: "Expanded"
1441
+ });
1442
+ });
1443
+
1444
+ it("should handle undefined webpushDeliverySettings", () => {
1445
+ const mockData = {
1446
+ channel: WEBPUSH,
1447
+ messageSubject: "test webpush notification"
1448
+ };
1449
+
1450
+ const options = {
1451
+ loyaltyMetaData: {
1452
+ transformedMessageDetails: {}
1453
+ }
1454
+ };
1455
+
1456
+ const result = transformChannelPayload(mockData, options);
1457
+
1458
+ expect(result.centralCommsPayload.webpushDeliverySettings).toEqual({});
1459
+ });
1460
+
1461
+ it("should handle empty offers array", () => {
1462
+ const mockData = {
1463
+ channel: WEBPUSH,
1464
+ messageSubject: "test",
1465
+ messageContent: {
1466
+ content: {
1467
+ content: {
1468
+ title: "Title",
1469
+ message: "Message"
1470
+ },
1471
+ offers: []
1472
+ }
1473
+ }
1474
+ };
1475
+
1476
+ const result = transformChannelPayload(mockData);
1477
+
1478
+ expect(result.centralCommsPayload.webpushMessageContent.offers).toEqual([]);
1479
+ });
1480
+ });
1481
+
1185
1482
  describe("getTemplateDiffState", () => {
1186
1483
  it("should return false for unsupported channel", () => {
1187
1484
  const result = getTemplateDiffState("UNSUPPORTED_CHANNEL", {}, {});
@@ -10,6 +10,7 @@ import {
10
10
  RCS,
11
11
  LINE,
12
12
  VIBER,
13
+ WEBPUSH,
13
14
  EMF,
14
15
  VENENO,
15
16
  TEXT,
@@ -63,6 +64,8 @@ export const transformChannelPayload = (data, options = {}) => {
63
64
  return transformLinePayload(data, options);
64
65
  case VIBER:
65
66
  return transformViberPayload(data, options);
67
+ case WEBPUSH:
68
+ return transformWebpushPayload(data, options);
66
69
  default:
67
70
  return data; // Return unchanged for unsupported channels
68
71
  }
@@ -317,6 +320,43 @@ const transformViberPayload = (viberData, options = {}) => {
317
320
  return payload;
318
321
  };
319
322
 
323
+ /**
324
+ * Transforms WebPush data to the required payload format
325
+ * @param {Object} webpushData - Current WebPush data
326
+ * @param {Object} options - Additional options (ouId, sourceEntityId, etc.)
327
+ * @returns {Object} - Transformed WebPush payload
328
+ */
329
+ const transformWebpushPayload = (webpushData, options = {}) => {
330
+ const { loyaltyMetaData = {} } = options;
331
+ const { transformedMessageDetails = {} } = loyaltyMetaData;
332
+ const { webpushDeliverySettings = {} } = transformedMessageDetails || {};
333
+
334
+ // Get base payload structure
335
+ const payload = createBasePayload(WEBPUSH, loyaltyMetaData);
336
+
337
+ // Extract webpush content from messageContent.content.content structure
338
+ const webpushContent = webpushData?.messageContent?.content?.content || {};
339
+ const accountId = webpushData?.messageContent?.content?.accountId || 0;
340
+
341
+ // Add WebPush-specific properties
342
+ payload.centralCommsPayload.webpushMessageContent = {
343
+ channel: WEBPUSH,
344
+ accountId,
345
+ content: {
346
+ title: webpushContent?.title || '',
347
+ message: webpushContent?.message || '',
348
+ ...(webpushContent?.iconImageUrl && { iconImageUrl: webpushContent.iconImageUrl }),
349
+ ...(webpushContent?.cta && { cta: webpushContent.cta }),
350
+ ...(webpushContent?.expandableDetails && { expandableDetails: webpushContent.expandableDetails }),
351
+ },
352
+ messageSubject: webpushData?.messageSubject || "",
353
+ offers: webpushData?.messageContent?.content?.offers || [],
354
+ };
355
+ payload.centralCommsPayload.webpushDeliverySettings = webpushDeliverySettings;
356
+
357
+ return payload;
358
+ };
359
+
320
360
  // Checks if the template has changed
321
361
  export const getTemplateDiffState = (channel, oldData, newData) => {
322
362
  switch (channel.toUpperCase()) {
@@ -1919,14 +1919,14 @@
1919
1919
  background-color: $CAP_WHITE;
1920
1920
 
1921
1921
  .mpush-video-preview {
1922
- max-width: '100%';
1923
- max-height: '120px';
1922
+ max-width: 100%;
1923
+ max-height: 7.5rem;
1924
1924
  margin-left: $CAP_SPACE_24;
1925
1925
  }
1926
1926
 
1927
1927
  .mpush-gif-preview {
1928
- max-width: '100%';
1929
- max-height: '120px';
1928
+ max-width: 100%;
1929
+ max-height: 7.5rem;
1930
1930
  }
1931
1931
 
1932
1932
  img {
@@ -216,7 +216,6 @@
216
216
 
217
217
  .json-key {
218
218
  color: #3D7790;
219
- ;
220
219
  font-weight: 500;
221
220
  }
222
221
 
@@ -1051,6 +1051,8 @@ export function SlideBoxContent(props) {
1051
1051
  isFullMode={isFullMode}
1052
1052
  handleClose={handleClose}
1053
1053
  onCreateComplete={onCreateComplete}
1054
+ getFormData={getFormData}
1055
+ isGetFormData={isGetFormData}
1054
1056
  templateData={isEditWebPush ? templateData : undefined}
1055
1057
  creativesMode={creativesMode}
1056
1058
  params={isEditWebPush && templateData ? { id: templateData._id } : undefined}
@@ -50,3 +50,4 @@ export const BIG_TEXT = "BIG_TEXT";
50
50
  export const GENERIC = "GENERIC";
51
51
  export const LIQUID_ERROR_MSG = "LIQUID_ERROR_MSG";
52
52
  export const STANDARD_ERROR_MSG = "STANDARD_ERROR_MSG";
53
+ export const COMMON_CHANNELS = ['sms', 'email', 'wechat', 'mobilepush', 'webpush', 'line', 'viber', 'facebook', 'call_task', 'ftp', 'assets'];
@@ -42,6 +42,7 @@ import { makeSelectFetchingCmsData } from '../Email/selectors';
42
42
  import {
43
43
  IMAGE as LINE_IMAGE, IMAGE_MAP, IMAGE_CAROUSEL, VIDEO as LINE_VIDEO, TEMPLATE, STICKER,
44
44
  } from '../Line/Container/constants';
45
+ import {EXTERNAL_URL, SITE_URL, WEBPUSH_MEDIA_TYPES} from '../WebPush/constants';
45
46
  import { IMAGE, VIDEO } from '../Facebook/Advertisement/constant';
46
47
  import {RCS_STATUSES} from '../Rcs/constants';
47
48
  import { CREATIVE } from '../Facebook/constants';
@@ -708,6 +709,73 @@ export class Creatives extends React.Component {
708
709
  };
709
710
  break;
710
711
  }
712
+ case constants.WEBPUSH: {
713
+ // Convert from campaign format (messageContent.content.content) to creatives format
714
+ const webpushContent = get(templateData, 'content', {});
715
+ const accountId = get(templateData, 'accountId');
716
+ const {
717
+ title,
718
+ message,
719
+ iconImageUrl: brandIcon = "",
720
+ cta,
721
+ expandableDetails
722
+ } = webpushContent || {};
723
+
724
+ // Map cta to onClickAction
725
+ let onClickAction = null;
726
+ if (cta) {
727
+ if (cta?.type === EXTERNAL_URL) {
728
+ onClickAction = {
729
+ type: URL,
730
+ url: cta?.actionLink || '',
731
+ };
732
+ } else {
733
+ onClickAction = {
734
+ type: cta?.type || SITE_URL,
735
+ };
736
+ }
737
+ }
738
+
739
+ // Map expandableDetails.ctas to ctas array
740
+ let ctas = [];
741
+ if (expandableDetails?.ctas && expandableDetails?.ctas?.length > 0) {
742
+ ctas = expandableDetails?.ctas?.map((ctaItem) => ({
743
+ actionText: ctaItem?.title || ctaItem?.actionText || '',
744
+ type: URL,
745
+ actionLink: ctaItem?.actionLink || '',
746
+ }));
747
+ }
748
+
749
+ // Map expandableDetails.media to image if present
750
+ let image = null;
751
+ if (expandableDetails?.media && expandableDetails?.media?.length > 0) {
752
+ const firstMedia = expandableDetails?.media[0];
753
+ if (firstMedia?.type === WEBPUSH_MEDIA_TYPES.IMAGE && firstMedia?.url) {
754
+ image = firstMedia?.url;
755
+ }
756
+ }
757
+
758
+ creativesTemplateData = {
759
+ type: channel,
760
+ name: templateData?.messageSubject,
761
+ versions: {
762
+ base: {
763
+ content: {
764
+ webpush: {
765
+ title: title || '',
766
+ message: message || '',
767
+ ...(brandIcon && { brandIcon }),
768
+ ...(onClickAction && { onClickAction }),
769
+ ...(ctas.length > 0 && { ctas }),
770
+ ...(image && { image, mediaType: IMAGE }),
771
+ },
772
+ },
773
+ },
774
+ },
775
+ definition: { accountId },
776
+ };
777
+ break;
778
+ }
711
779
  default:
712
780
  break;
713
781
  }
@@ -1122,6 +1190,105 @@ export class Creatives extends React.Component {
1122
1190
  }
1123
1191
  }
1124
1192
  break;
1193
+ case constants.WEBPUSH: {
1194
+ if (template.value) {
1195
+ const channelTemplate = template.value;
1196
+ const accountId = get(channelTemplate, 'definition.accountId');
1197
+ const webpushContent = get(channelTemplate, 'versions.base.content.webpush', {});
1198
+ const {
1199
+ title,
1200
+ message,
1201
+ brandIcon,
1202
+ iconImageUrl: templateImageUrl ,
1203
+ onClickAction,
1204
+ ctas: templateCtas,
1205
+ cta: templateCta,
1206
+ expandableDetails: templateExpandableDetails,
1207
+ image
1208
+ } = webpushContent || {};
1209
+
1210
+ const iconImageUrl = brandIcon || templateImageUrl || '';
1211
+
1212
+ // Map onClickAction to cta
1213
+ let cta = null;
1214
+ if (onClickAction) {
1215
+ if (onClickAction?.type === URL) {
1216
+ cta = {
1217
+ type: EXTERNAL_URL,
1218
+ actionLink: onClickAction?.url || '',
1219
+ };
1220
+ } else {
1221
+ cta = {
1222
+ type: onClickAction?.type || SITE_URL,
1223
+ actionLink: onClickAction?.url || '',
1224
+ };
1225
+ }
1226
+ } else if (templateCta) {
1227
+ // Fallback to cta if onClickAction is not present
1228
+ cta = {
1229
+ type: templateCta?.type || EXTERNAL_URL,
1230
+ actionLink: templateCta?.actionLink || '',
1231
+ };
1232
+ }
1233
+
1234
+ // Map ctas array to expandableDetails.ctas
1235
+ let expandableDetails = null;
1236
+ const hasCtas = templateCtas && templateCtas.length > 0;
1237
+ const hasImage = image;
1238
+
1239
+ if (hasCtas || hasImage) {
1240
+ expandableDetails = {
1241
+ media: [],
1242
+ ctas: [],
1243
+ };
1244
+
1245
+ // Map image to expandableDetails.media
1246
+ if (hasImage) {
1247
+ expandableDetails.media = [{
1248
+ url: image,
1249
+ type: IMAGE,
1250
+ }];
1251
+ }
1252
+
1253
+ // Map ctas array to expandableDetails.ctas
1254
+ if (hasCtas) {
1255
+ expandableDetails.ctas = templateCtas.map((ctaItem) => ({
1256
+ type: ctaItem?.type === URL ? EXTERNAL_URL : ctaItem?.type,
1257
+ action: ctaItem?.action || '',
1258
+ title: ctaItem?.actionText || ctaItem?.title || '',
1259
+ actionLink: ctaItem?.actionLink || '',
1260
+ }));
1261
+ }
1262
+ } else if (templateExpandableDetails) {
1263
+ // If expandableDetails already exists, use it
1264
+ expandableDetails = {
1265
+ media: templateExpandableDetails?.media || [],
1266
+ ctas: templateExpandableDetails?.ctas || [],
1267
+ };
1268
+ }
1269
+
1270
+ // Convert from creatives format to campaign format
1271
+ templateData = {
1272
+ channel,
1273
+ messageContent: {
1274
+ content: {
1275
+ channel: constants.WEBPUSH,
1276
+ accountId,
1277
+ content: {
1278
+ title: title || '',
1279
+ message: message || '',
1280
+ ...(iconImageUrl && { iconImageUrl }),
1281
+ ...(cta && { cta }),
1282
+ ...(expandableDetails && { expandableDetails }),
1283
+ },
1284
+ messageSubject: channelTemplate?.name ? channelTemplate.name : 'messageSubject',
1285
+ offers: [],
1286
+ },
1287
+ },
1288
+ };
1289
+ }
1290
+ break;
1291
+ }
1125
1292
  default:
1126
1293
  break;
1127
1294
  }
@@ -1173,6 +1340,7 @@ export class Creatives extends React.Component {
1173
1340
  case constants.SMS:
1174
1341
  case constants.WECHAT:
1175
1342
  case constants.VIBER:
1343
+ case constants.WEBPUSH:
1176
1344
  break;
1177
1345
  case constants.EMAIL:
1178
1346
  gtmDetails = {