@capillarytech/creatives-library 8.0.248 → 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 +1 -1
- package/utils/tests/transformerUtils.test.js +297 -0
- package/utils/transformerUtils.js +40 -0
- package/v2Containers/CreativesContainer/SlideBoxContent.js +2 -0
- package/v2Containers/CreativesContainer/constants.js +1 -0
- package/v2Containers/CreativesContainer/index.js +168 -0
- package/v2Containers/TemplatesV2/index.js +8 -7
- package/v2Containers/WebPush/Create/components/ButtonsLinksSection.test.js +4 -4
- package/v2Containers/WebPush/Create/components/__snapshots__/ButtonsLinksSection.test.js.snap +2 -2
- package/v2Containers/WebPush/Create/index.js +104 -12
- package/v2Containers/WebPush/Create/preview/WebPushPreview.js +6 -1
- package/v2Containers/WebPush/Create/preview/tests/WebPushPreview.test.js +384 -0
- package/v2Containers/WebPush/Create/utils/payloadBuilder.js +4 -2
- package/v2Containers/WebPush/Create/utils/payloadBuilder.test.js +13 -7
- package/v2Containers/WebPush/constants.js +6 -2
- package/v2Containers/WebPush/tests/selectors.test.js +117 -0
package/package.json
CHANGED
|
@@ -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()) {
|
|
@@ -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 = {
|
|
@@ -34,7 +34,7 @@ import { CREATIVES_UI_VIEW, LOYALTY, WHATSAPP, RCS, LINE, EMAIL, ASSETS, JP_LOCA
|
|
|
34
34
|
import AccessForbidden from '../../v2Components/AccessForbidden';
|
|
35
35
|
import { getObjFromQueryParams } from '../../utils/v2common';
|
|
36
36
|
import { makeSelectAuthenticated, selectCurrentOrgDetails } from "../../v2Containers/Cap/selectors";
|
|
37
|
-
import { LOYALTY_SUPPORTED_ACTION } from "../CreativesContainer/constants";
|
|
37
|
+
import { LOYALTY_SUPPORTED_ACTION, COMMON_CHANNELS } from "../CreativesContainer/constants";
|
|
38
38
|
|
|
39
39
|
const {CapCustomCardList} = CapCustomCard;
|
|
40
40
|
|
|
@@ -66,7 +66,7 @@ export class TemplatesV2 extends React.Component { // eslint-disable-line react/
|
|
|
66
66
|
//'wechat': {content: this.getTemplatesComponent('wechat'), tab: 'Wechat', key: 'wechat'},
|
|
67
67
|
mPush: {content: <></>, tab: intl.formatMessage(messages.pushNotification), key: 'mobilepush'},
|
|
68
68
|
...(commonUtil.hasWebPushFeatureEnabled() ? {
|
|
69
|
-
|
|
69
|
+
webpush: {
|
|
70
70
|
content: <div></div>,
|
|
71
71
|
tab: intl.formatMessage(messages.webPush),
|
|
72
72
|
key: WEBPUSH,
|
|
@@ -95,7 +95,7 @@ export class TemplatesV2 extends React.Component { // eslint-disable-line react/
|
|
|
95
95
|
return obj;
|
|
96
96
|
}, []);
|
|
97
97
|
|
|
98
|
-
|
|
98
|
+
if (isFullMode ) {
|
|
99
99
|
filteredPanes.push({content: <div></div>, tab: intl.formatMessage(messages.gallery), key: 'assets'});
|
|
100
100
|
} else {
|
|
101
101
|
if (!channelsToHide.includes('callTask')) {
|
|
@@ -105,18 +105,19 @@ export class TemplatesV2 extends React.Component { // eslint-disable-line react/
|
|
|
105
105
|
filteredPanes.push({content: <></>, tab: intl.formatMessage(messages.FTP), key: 'ftp'});
|
|
106
106
|
defaultChannel = 'FTP';
|
|
107
107
|
}
|
|
108
|
-
const commonChannels = ['sms', 'email', 'wechat', 'mobilepush', 'line', 'viber', 'facebook', 'call_task', 'ftp', 'assets'];
|
|
109
108
|
|
|
109
|
+
// Create a local copy of COMMON_CHANNELS to avoid mutating the imported array
|
|
110
|
+
const channels = [...COMMON_CHANNELS];
|
|
110
111
|
const { actionName = ''} = loyaltyMetaData;
|
|
111
112
|
if (isLoyaltyModule && actionName === LOYALTY_SUPPORTED_ACTION) {
|
|
112
|
-
|
|
113
|
+
channels.push(WHATSAPP, ZALO);
|
|
113
114
|
}
|
|
114
115
|
|
|
115
|
-
// we only show channels which other than
|
|
116
|
+
// we only show channels which other than COMMON_CHANNELS
|
|
116
117
|
// if it is coming in enableNewChannels array
|
|
117
118
|
filteredPanes = filteredPanes.filter((item) => {
|
|
118
119
|
const channel = item.key;
|
|
119
|
-
if (!
|
|
120
|
+
if (!channels.includes(channel)) {
|
|
120
121
|
return enableNewChannels.includes(channel.toUpperCase());
|
|
121
122
|
}
|
|
122
123
|
return true;
|
|
@@ -98,9 +98,9 @@ describe('ButtonsLinksSection', () => {
|
|
|
98
98
|
});
|
|
99
99
|
|
|
100
100
|
const defaultProps = {
|
|
101
|
-
onClickBehaviour: ON_CLICK_BEHAVIOUR_OPTIONS.
|
|
101
|
+
onClickBehaviour: ON_CLICK_BEHAVIOUR_OPTIONS.SITE_URL,
|
|
102
102
|
onClickBehaviourOptions: [
|
|
103
|
-
{ value: ON_CLICK_BEHAVIOUR_OPTIONS.
|
|
103
|
+
{ value: ON_CLICK_BEHAVIOUR_OPTIONS.SITE_URL, label: 'Open Site' },
|
|
104
104
|
{ value: ON_CLICK_BEHAVIOUR_OPTIONS.REDIRECT_TO_URL, label: 'Redirect to URL' },
|
|
105
105
|
],
|
|
106
106
|
onClickBehaviourChange: mockOnClickBehaviourChange,
|
|
@@ -151,7 +151,7 @@ describe('ButtonsLinksSection', () => {
|
|
|
151
151
|
const radioGroup = wrapper.find(CapRadioGroup);
|
|
152
152
|
expect(radioGroup.exists()).toBe(true);
|
|
153
153
|
expect(radioGroup.prop('options')).toEqual(defaultProps.onClickBehaviourOptions);
|
|
154
|
-
expect(radioGroup.prop('value')).toBe(ON_CLICK_BEHAVIOUR_OPTIONS.
|
|
154
|
+
expect(radioGroup.prop('value')).toBe(ON_CLICK_BEHAVIOUR_OPTIONS.SITE_URL);
|
|
155
155
|
});
|
|
156
156
|
});
|
|
157
157
|
|
|
@@ -175,7 +175,7 @@ describe('ButtonsLinksSection', () => {
|
|
|
175
175
|
expect(input.exists()).toBe(true);
|
|
176
176
|
});
|
|
177
177
|
|
|
178
|
-
it('should not render redirect URL input when
|
|
178
|
+
it('should not render redirect URL input when SITE_URL is selected', () => {
|
|
179
179
|
const wrapper = mountWithIntl(<ButtonsLinksSection {...defaultProps} />);
|
|
180
180
|
const input = wrapper.find(CapInput).find('#webpush-redirect-url-input');
|
|
181
181
|
expect(input.exists()).toBe(false);
|
package/v2Containers/WebPush/Create/components/__snapshots__/ButtonsLinksSection.test.js.snap
CHANGED
|
@@ -32,7 +32,7 @@ exports[`ButtonsLinksSection Rendering should render correctly with default prop
|
|
|
32
32
|
Array [
|
|
33
33
|
Object {
|
|
34
34
|
"label": "Open Site",
|
|
35
|
-
"value": "
|
|
35
|
+
"value": "SITE_URL",
|
|
36
36
|
},
|
|
37
37
|
Object {
|
|
38
38
|
"label": "Redirect to URL",
|
|
@@ -40,7 +40,7 @@ exports[`ButtonsLinksSection Rendering should render correctly with default prop
|
|
|
40
40
|
},
|
|
41
41
|
]
|
|
42
42
|
}
|
|
43
|
-
value="
|
|
43
|
+
value="SITE_URL"
|
|
44
44
|
/>
|
|
45
45
|
</CapRow>
|
|
46
46
|
<CapRow
|