@capillarytech/creatives-library 8.0.253 → 8.0.254
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/assets/Android.png +0 -0
- package/assets/iOS.png +0 -0
- package/constants/unified.js +1 -2
- package/initialReducer.js +0 -2
- package/package.json +1 -1
- package/services/api.js +0 -10
- package/services/tests/api.test.js +0 -34
- package/utils/common.js +0 -5
- package/utils/commonUtils.js +5 -28
- package/utils/tests/commonUtil.test.js +0 -224
- package/utils/transformTemplateConfig.js +10 -0
- package/v2Components/CapDeviceContent/index.js +56 -61
- package/v2Components/CapTagList/index.js +1 -6
- package/v2Components/CapTagListWithInput/index.js +1 -5
- package/v2Components/CapTagListWithInput/messages.js +1 -1
- package/v2Components/CapWhatsappCTA/tests/index.test.js +0 -5
- package/v2Components/ErrorInfoNote/index.js +72 -457
- package/v2Components/ErrorInfoNote/messages.js +6 -36
- package/v2Components/ErrorInfoNote/style.scss +6 -282
- package/v2Components/FormBuilder/tests/index.test.js +4 -13
- package/v2Components/HtmlEditor/HTMLEditor.js +94 -547
- package/v2Components/HtmlEditor/__tests__/HTMLEditor.test.js +133 -1358
- package/v2Components/HtmlEditor/__tests__/index.lazy.test.js +16 -27
- package/v2Components/HtmlEditor/_htmlEditor.scss +45 -108
- package/v2Components/HtmlEditor/_index.lazy.scss +1 -0
- package/v2Components/HtmlEditor/components/CodeEditorPane/_codeEditorPane.scss +101 -22
- package/v2Components/HtmlEditor/components/CodeEditorPane/index.js +140 -146
- package/v2Components/HtmlEditor/components/DeviceToggle/_deviceToggle.scss +1 -2
- package/v2Components/HtmlEditor/components/DeviceToggle/index.js +3 -3
- package/v2Components/HtmlEditor/components/EditorToolbar/_editorToolbar.scss +0 -9
- package/v2Components/HtmlEditor/components/EditorToolbar/index.js +1 -1
- package/v2Components/HtmlEditor/components/FullscreenModal/_fullscreenModal.scss +0 -22
- package/v2Components/HtmlEditor/components/InAppPreviewPane/DeviceFrame.js +7 -4
- package/v2Components/HtmlEditor/components/InAppPreviewPane/__tests__/DeviceFrame.test.js +45 -35
- package/v2Components/HtmlEditor/components/InAppPreviewPane/_inAppPreviewPane.scss +3 -1
- package/v2Components/HtmlEditor/components/InAppPreviewPane/constants.js +33 -33
- package/v2Components/HtmlEditor/components/InAppPreviewPane/index.js +6 -7
- package/v2Components/HtmlEditor/components/PreviewPane/_previewPane.scss +6 -3
- package/v2Components/HtmlEditor/components/PreviewPane/index.js +34 -24
- package/v2Components/HtmlEditor/components/SplitContainer/_splitContainer.scss +1 -1
- package/v2Components/HtmlEditor/components/ValidationErrorDisplay/__tests__/index.test.js +152 -0
- package/v2Components/HtmlEditor/components/ValidationErrorDisplay/index.js +31 -49
- package/v2Components/HtmlEditor/components/ValidationPanel/_validationPanel.scss +34 -50
- package/v2Components/HtmlEditor/components/ValidationPanel/index.js +41 -70
- package/v2Components/HtmlEditor/constants.js +20 -42
- package/v2Components/HtmlEditor/hooks/__tests__/useInAppContent.test.js +16 -373
- package/v2Components/HtmlEditor/hooks/useEditorContent.js +2 -5
- package/v2Components/HtmlEditor/hooks/useInAppContent.js +146 -88
- package/v2Components/HtmlEditor/hooks/useValidation.js +53 -189
- package/v2Components/HtmlEditor/index.js +1 -1
- package/v2Components/HtmlEditor/messages.js +85 -95
- package/v2Components/HtmlEditor/utils/__tests__/htmlValidator.enhanced.test.js +45 -94
- package/v2Components/HtmlEditor/utils/__tests__/validationAdapter.test.js +0 -134
- package/v2Components/HtmlEditor/utils/contentSanitizer.js +41 -40
- package/v2Components/HtmlEditor/utils/htmlValidator.js +72 -71
- package/v2Components/HtmlEditor/utils/liquidTemplateSupport.js +102 -134
- package/v2Components/HtmlEditor/utils/properSyntaxHighlighting.js +25 -23
- package/v2Components/HtmlEditor/utils/validationAdapter.js +41 -66
- package/v2Components/MobilePushPreviewV2/index.js +7 -32
- package/v2Components/TemplatePreview/_templatePreview.scss +24 -55
- package/v2Components/TemplatePreview/index.js +32 -47
- package/v2Components/TemplatePreview/messages.js +0 -4
- package/v2Components/TestAndPreviewSlidebox/_testAndPreviewSlidebox.scss +0 -1
- package/v2Containers/BeeEditor/index.js +90 -172
- package/v2Containers/CreativesContainer/SlideBoxContent.js +51 -128
- package/v2Containers/CreativesContainer/SlideBoxFooter.js +13 -163
- package/v2Containers/CreativesContainer/SlideBoxHeader.js +1 -2
- package/v2Containers/CreativesContainer/constants.js +0 -1
- package/v2Containers/CreativesContainer/index.js +46 -239
- package/v2Containers/CreativesContainer/messages.js +0 -8
- package/v2Containers/CreativesContainer/tests/SlideBoxFooter.test.js +2 -11
- package/v2Containers/CreativesContainer/tests/__snapshots__/SlideBoxContent.test.js.snap +50 -38
- package/v2Containers/CreativesContainer/tests/__snapshots__/index.test.js.snap +0 -106
- package/v2Containers/Email/actions.js +0 -7
- package/v2Containers/Email/constants.js +1 -5
- package/v2Containers/Email/index.js +32 -241
- package/v2Containers/Email/messages.js +0 -32
- package/v2Containers/Email/reducer.js +1 -12
- package/v2Containers/Email/sagas.js +7 -61
- package/v2Containers/Email/tests/__snapshots__/reducer.test.js.snap +0 -2
- package/v2Containers/Email/tests/reducer.test.js +0 -46
- package/v2Containers/Email/tests/sagas.test.js +29 -320
- package/v2Containers/EmailWrapper/components/EmailWrapperView.js +19 -207
- package/v2Containers/EmailWrapper/components/HTMLEditorTesting.js +74 -40
- package/v2Containers/EmailWrapper/components/__tests__/HTMLEditorTesting.test.js +67 -2
- package/v2Containers/EmailWrapper/constants.js +0 -2
- package/v2Containers/EmailWrapper/hooks/useEmailWrapper.js +77 -629
- package/v2Containers/EmailWrapper/index.js +23 -103
- package/v2Containers/EmailWrapper/messages.js +1 -61
- package/v2Containers/EmailWrapper/tests/EmailWrapperView.test.js +214 -0
- package/v2Containers/EmailWrapper/tests/useEmailWrapper.test.js +77 -594
- package/v2Containers/InApp/actions.js +0 -7
- package/v2Containers/InApp/constants.js +4 -20
- package/v2Containers/InApp/index.js +359 -802
- package/v2Containers/InApp/index.scss +3 -4
- package/v2Containers/InApp/messages.js +3 -7
- package/v2Containers/InApp/reducer.js +3 -21
- package/v2Containers/InApp/sagas.js +9 -29
- package/v2Containers/InApp/selectors.js +5 -25
- package/v2Containers/InApp/tests/index.test.js +50 -154
- package/v2Containers/InApp/tests/reducer.test.js +0 -34
- package/v2Containers/InApp/tests/sagas.test.js +9 -61
- package/v2Containers/Line/Container/ImageCarousel/tests/__snapshots__/content.test.js.snap +0 -3
- package/v2Containers/Line/Container/ImageCarousel/tests/__snapshots__/index.test.js.snap +0 -2
- package/v2Containers/Line/Container/Wrapper/tests/__snapshots__/index.test.js.snap +0 -2
- package/v2Containers/Line/Container/tests/__snapshots__/index.test.js.snap +0 -9
- package/v2Containers/Rcs/tests/__snapshots__/index.test.js.snap +0 -12
- package/v2Containers/SmsTrai/Edit/tests/__snapshots__/index.test.js.snap +0 -4
- package/v2Containers/TagList/index.js +19 -62
- package/v2Containers/Templates/_templates.scss +1 -60
- package/v2Containers/Templates/index.js +4 -89
- package/v2Containers/Templates/messages.js +0 -4
- package/v2Containers/Whatsapp/tests/__snapshots__/index.test.js.snap +0 -34
- package/v2Components/ErrorInfoNote/constants.js +0 -1
- package/v2Components/HtmlEditor/__tests__/HTMLEditor.apiErrors.test.js +0 -874
- package/v2Components/HtmlEditor/components/ValidationPanel/constants.js +0 -6
- package/v2Components/HtmlEditor/components/ValidationTabs/_validationTabs.scss +0 -254
- package/v2Components/HtmlEditor/components/ValidationTabs/index.js +0 -364
- package/v2Components/HtmlEditor/components/ValidationTabs/messages.js +0 -51
- package/v2Components/HtmlEditor/hooks/__tests__/useValidation.apiErrors.test.js +0 -795
- package/v2Components/HtmlEditor/utils/validationConstants.js +0 -40
- package/v2Containers/BeePopupEditor/_beePopupEditor.scss +0 -14
- package/v2Containers/BeePopupEditor/constants.js +0 -10
- package/v2Containers/BeePopupEditor/index.js +0 -194
- package/v2Containers/BeePopupEditor/tests/index.test.js +0 -627
- package/v2Containers/EmailWrapper/components/EmailHTMLEditor.js +0 -1285
- package/v2Containers/EmailWrapper/components/__tests__/EmailHTMLEditor.test.js +0 -1870
- package/v2Containers/EmailWrapper/components/__tests__/EmailWrapperView.test.js +0 -520
- package/v2Containers/EmailWrapper/tests/useEmailWrapper.edgeCases.test.js +0 -643
- package/v2Containers/InApp/__tests__/InAppHTMLEditor.test.js +0 -376
- package/v2Containers/InApp/__tests__/sagas.test.js +0 -363
- package/v2Containers/InApp/tests/selectors.test.js +0 -612
- package/v2Containers/InAppWrapper/components/InAppWrapperView.js +0 -151
- package/v2Containers/InAppWrapper/components/__tests__/InAppWrapperView.test.js +0 -267
- package/v2Containers/InAppWrapper/components/inAppWrapperView.scss +0 -23
- package/v2Containers/InAppWrapper/constants.js +0 -16
- package/v2Containers/InAppWrapper/hooks/__tests__/useInAppWrapper.test.js +0 -473
- package/v2Containers/InAppWrapper/hooks/useInAppWrapper.js +0 -198
- package/v2Containers/InAppWrapper/index.js +0 -148
- package/v2Containers/InAppWrapper/messages.js +0 -49
- package/v2Containers/InappAdvance/index.js +0 -1099
- package/v2Containers/InappAdvance/index.scss +0 -10
- package/v2Containers/InappAdvance/tests/index.test.js +0 -448
package/assets/Android.png
CHANGED
|
Binary file
|
package/assets/iOS.png
CHANGED
|
Binary file
|
package/constants/unified.js
CHANGED
|
@@ -45,7 +45,6 @@ export const GIFT_CARDS = 'GIFT_CARDS';
|
|
|
45
45
|
export const PROMO_ENGINE = 'PROMO_ENGINE';
|
|
46
46
|
export const LIQUID_SUPPORT = 'ENABLE_LIQUID_SUPPORT';
|
|
47
47
|
export const ENABLE_NEW_MPUSH = 'ENABLE_NEW_MPUSH';
|
|
48
|
-
export const SUPPORT_CK_EDITOR = 'SUPPORT_CK_EDITOR';
|
|
49
48
|
export const CUSTOM_TAG = 'CustomTagMessage';
|
|
50
49
|
export const CUSTOMER_EXTENDED_FIELD = 'Customer extended fields';
|
|
51
50
|
export const EXTENDED_TAG = 'ExtendedTagMessage';
|
|
@@ -169,7 +168,7 @@ export const JAPANESE_HIDE_DATE_TAGS = [
|
|
|
169
168
|
"dd.mm.yy",
|
|
170
169
|
"dd Mon",
|
|
171
170
|
"dd/m/yyyy",
|
|
172
|
-
];
|
|
171
|
+
];
|
|
173
172
|
|
|
174
173
|
export const LIQUID_SUPPORTED_CHANNELS = [EMAIL, SMS, MOBILE_PUSH, INAPP];
|
|
175
174
|
|
package/initialReducer.js
CHANGED
|
@@ -15,7 +15,6 @@ import galleryReducer from './v2Containers/Assets/Gallery/reducer';
|
|
|
15
15
|
import CapCollapsibleLeftNavigationReducer from '@capillarytech/cap-ui-library/CapCollapsibleLeftNavigation/reducer';
|
|
16
16
|
import { AIRA_REDUCER_DOMAIN, askAiraReducer } from '@capillarytech/cap-ui-library/CapAskAira';
|
|
17
17
|
import previewAndTestReducer from './v2Components/TestAndPreviewSlidebox/reducer';
|
|
18
|
-
import inAppReducer from './v2Containers/InApp/reducer';
|
|
19
18
|
|
|
20
19
|
export const initialReducer = {
|
|
21
20
|
language: languageProviderReducer,
|
|
@@ -34,5 +33,4 @@ export const initialReducer = {
|
|
|
34
33
|
gallery: galleryReducer,
|
|
35
34
|
navigationConfig: CapCollapsibleLeftNavigationReducer,
|
|
36
35
|
previewAndTest: previewAndTestReducer,
|
|
37
|
-
inApp: inAppReducer,
|
|
38
36
|
};
|
package/package.json
CHANGED
package/services/api.js
CHANGED
|
@@ -465,11 +465,6 @@ export const getCmsTemplateSettingsV2 = (cmsType, projectId, cmsMode, langId, is
|
|
|
465
465
|
return API.get(url);
|
|
466
466
|
};
|
|
467
467
|
|
|
468
|
-
export const getCmsAccounts = (cmsType) => {
|
|
469
|
-
const url = `${API_ENDPOINT}/cms/accounts?type=${cmsType}`;
|
|
470
|
-
return API.get(url);
|
|
471
|
-
};
|
|
472
|
-
|
|
473
468
|
export const getCmsTemplateData = (cmsType, projectId, langId) => {
|
|
474
469
|
const url = `${API_ENDPOINT}/cms/getContent?type=${cmsType}&projectId=${projectId}&langId=${langId}`;
|
|
475
470
|
return API.get(url);
|
|
@@ -725,9 +720,4 @@ export const getAssetStatus = (type, assetId) => {
|
|
|
725
720
|
return request(url, getAPICallObject('GET'));
|
|
726
721
|
};
|
|
727
722
|
|
|
728
|
-
export const getBeePopupBuilderToken = () => {
|
|
729
|
-
const url = `${API_ENDPOINT}/common/getInappTokenData`;
|
|
730
|
-
return request(url, getAPICallObject('GET'));
|
|
731
|
-
};
|
|
732
|
-
|
|
733
723
|
export {request, getAPICallObject};
|
|
@@ -26,8 +26,6 @@ import {
|
|
|
26
26
|
updateMetaConfig,
|
|
27
27
|
getMediaDetails,
|
|
28
28
|
getAssetStatus,
|
|
29
|
-
getBeePopupBuilderToken,
|
|
30
|
-
getCmsAccounts,
|
|
31
29
|
} from '../api';
|
|
32
30
|
import { mockData } from './mockData';
|
|
33
31
|
import getSchema from '../getSchema';
|
|
@@ -975,35 +973,3 @@ describe('getAssetStatus', () => {
|
|
|
975
973
|
expect(callArgs[0]).toContain('/assets/video/asset-456/status');
|
|
976
974
|
});
|
|
977
975
|
});
|
|
978
|
-
|
|
979
|
-
describe('getBeePopupBuilderToken', () => {
|
|
980
|
-
it('should return correct response', async () => {
|
|
981
|
-
global.fetch.mockReturnValue(Promise.resolve({
|
|
982
|
-
status: 200,
|
|
983
|
-
json: () => Promise.resolve({
|
|
984
|
-
status: 200,
|
|
985
|
-
response: 'test',
|
|
986
|
-
}),
|
|
987
|
-
}));
|
|
988
|
-
const result = await getBeePopupBuilderToken();
|
|
989
|
-
expect(result).toEqual({
|
|
990
|
-
status: 200,
|
|
991
|
-
response: 'test',
|
|
992
|
-
});
|
|
993
|
-
});
|
|
994
|
-
});
|
|
995
|
-
|
|
996
|
-
describe('getCmsAccounts', () => {
|
|
997
|
-
it('should return a promise (line 473-476)', () => {
|
|
998
|
-
// Similar to other API tests, just verify it returns a Promise
|
|
999
|
-
const result = getCmsAccounts('bee');
|
|
1000
|
-
expect(result).toBeInstanceOf(Promise);
|
|
1001
|
-
});
|
|
1002
|
-
|
|
1003
|
-
it('should be callable with cmsType parameter', () => {
|
|
1004
|
-
// Verify function exists and can be called
|
|
1005
|
-
expect(typeof getCmsAccounts).toBe('function');
|
|
1006
|
-
const result = getCmsAccounts('bee');
|
|
1007
|
-
expect(result).toBeInstanceOf(Promise);
|
|
1008
|
-
});
|
|
1009
|
-
});
|
package/utils/common.js
CHANGED
|
@@ -22,7 +22,6 @@ import {
|
|
|
22
22
|
BADGES_ISSUE,
|
|
23
23
|
ENABLE_WECHAT,
|
|
24
24
|
LIQUID_SUPPORT,
|
|
25
|
-
SUPPORT_CK_EDITOR,
|
|
26
25
|
ENABLE_NEW_MPUSH
|
|
27
26
|
} from '../constants/unified';
|
|
28
27
|
import { apiMessageFormatHandler } from './commonUtils';
|
|
@@ -96,10 +95,6 @@ export const hasLiquidSupportFeature = Auth.hasFeatureAccess.bind(
|
|
|
96
95
|
LIQUID_SUPPORT,
|
|
97
96
|
);
|
|
98
97
|
|
|
99
|
-
export const hasSupportCKEditor = Auth.hasFeatureAccess.bind(
|
|
100
|
-
null,
|
|
101
|
-
SUPPORT_CK_EDITOR,
|
|
102
|
-
);
|
|
103
98
|
|
|
104
99
|
export const hasGiftVoucherFeature = Auth.hasFeatureAccess.bind(
|
|
105
100
|
null,
|
package/utils/commonUtils.js
CHANGED
|
@@ -173,30 +173,20 @@ export const validateLiquidTemplateContent = async (
|
|
|
173
173
|
// Handle API errors or empty content
|
|
174
174
|
if (result?.errors?.length > 0 || !validString || isError) {
|
|
175
175
|
let standardErrors = [];
|
|
176
|
-
let liquidErrors = [];
|
|
177
|
-
|
|
178
|
-
// Empty content errors are NOT from liquid endpoints, so they go to standardErrors
|
|
179
176
|
if (!validString) {
|
|
180
177
|
standardErrors = [emptyBodyError];
|
|
181
178
|
}
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
// Only errors from these endpoints should appear in Liquid Issues tab
|
|
186
|
-
if (result && Array.isArray(result?.errors) && result.errors.length > 0) {
|
|
187
|
-
// Errors from extractTags or liquidValidation endpoints
|
|
188
|
-
liquidErrors = result.errors.map((error) => {
|
|
179
|
+
let liquidErrors;
|
|
180
|
+
if (result && Array.isArray(result?.errors)) {
|
|
181
|
+
liquidErrors = result?.errors?.map((error) => {
|
|
189
182
|
const message = typeof error?.message === "string"
|
|
190
183
|
? error.message
|
|
191
184
|
: somethingWrongMsg;
|
|
192
185
|
return message;
|
|
193
186
|
});
|
|
194
|
-
} else
|
|
195
|
-
// If isError is true, it means the API call to extractTags/liquidValidation failed
|
|
196
|
-
// This is also a liquid endpoint error, so categorize as liquidErrors
|
|
187
|
+
} else {
|
|
197
188
|
liquidErrors = [somethingWrongMsg];
|
|
198
189
|
}
|
|
199
|
-
|
|
200
190
|
onError({
|
|
201
191
|
standardErrors,
|
|
202
192
|
liquidErrors,
|
|
@@ -408,20 +398,7 @@ export const validateMobilePushContent = async (formData, options) => {
|
|
|
408
398
|
// Helper function to extract content for a platform
|
|
409
399
|
export const extractContent = (platformData) => {
|
|
410
400
|
if (!platformData) return '';
|
|
411
|
-
const { title, message, ctas
|
|
412
|
-
|
|
413
|
-
// For BEE editor, extract content from beeHtml
|
|
414
|
-
if (isBEEeditor && beeHtml) {
|
|
415
|
-
// beeHtml can be an object with value property or a string
|
|
416
|
-
const beeHtmlContent = typeof beeHtml === 'string' ? beeHtml : (beeHtml?.value || '');
|
|
417
|
-
return [
|
|
418
|
-
title,
|
|
419
|
-
beeHtmlContent,
|
|
420
|
-
...((ctas?.map((cta) => cta?.text || cta?.actionLink)) || []),
|
|
421
|
-
].filter(Boolean).join(' ');
|
|
422
|
-
}
|
|
423
|
-
|
|
424
|
-
// For regular content
|
|
401
|
+
const { title, message, ctas } = platformData;
|
|
425
402
|
return [
|
|
426
403
|
title,
|
|
427
404
|
message,
|
|
@@ -1376,228 +1376,4 @@ describe("validateCarouselCards", () => {
|
|
|
1376
1376
|
expect(result.isValid).toBe(true);
|
|
1377
1377
|
});
|
|
1378
1378
|
});
|
|
1379
|
-
|
|
1380
|
-
describe('extractContent BEE Editor Logic (L404-L412)', () => {
|
|
1381
|
-
it('extracts content from beeHtml as string', () => {
|
|
1382
|
-
const platformData = {
|
|
1383
|
-
title: 'Test Title',
|
|
1384
|
-
isBEEeditor: true,
|
|
1385
|
-
beeHtml: '<p>BEE HTML Content</p>',
|
|
1386
|
-
ctas: [
|
|
1387
|
-
{ text: 'Click Here', actionLink: 'https://example.com' },
|
|
1388
|
-
],
|
|
1389
|
-
};
|
|
1390
|
-
|
|
1391
|
-
const result = extractContent(platformData);
|
|
1392
|
-
|
|
1393
|
-
expect(result).toContain(platformData.title);
|
|
1394
|
-
expect(result).toContain(platformData.beeHtml);
|
|
1395
|
-
expect(result).toContain(platformData.ctas[0].text);
|
|
1396
|
-
});
|
|
1397
|
-
|
|
1398
|
-
it('extracts content from beeHtml as object with value property', () => {
|
|
1399
|
-
const platformData = {
|
|
1400
|
-
title: 'Test Title',
|
|
1401
|
-
isBEEeditor: true,
|
|
1402
|
-
beeHtml: { value: '<p>BEE HTML from Object</p>' },
|
|
1403
|
-
ctas: [
|
|
1404
|
-
{ text: 'Button Text' },
|
|
1405
|
-
],
|
|
1406
|
-
};
|
|
1407
|
-
|
|
1408
|
-
const result = extractContent(platformData);
|
|
1409
|
-
|
|
1410
|
-
expect(result).toContain(platformData.title);
|
|
1411
|
-
expect(result).toContain(platformData.beeHtml.value);
|
|
1412
|
-
expect(result).toContain(platformData.ctas[0].text);
|
|
1413
|
-
});
|
|
1414
|
-
|
|
1415
|
-
it('handles beeHtml as object without value property', () => {
|
|
1416
|
-
const platformData = {
|
|
1417
|
-
title: 'Test Title',
|
|
1418
|
-
isBEEeditor: true,
|
|
1419
|
-
beeHtml: { someOtherProperty: 'data' },
|
|
1420
|
-
ctas: [],
|
|
1421
|
-
};
|
|
1422
|
-
|
|
1423
|
-
const result = extractContent(platformData);
|
|
1424
|
-
|
|
1425
|
-
// Should extract title and empty beeHtml (since value is undefined)
|
|
1426
|
-
expect(result).toContain('Test Title');
|
|
1427
|
-
expect(result).not.toContain('someOtherProperty');
|
|
1428
|
-
});
|
|
1429
|
-
|
|
1430
|
-
it('extracts ctas with text property', () => {
|
|
1431
|
-
const platformData = {
|
|
1432
|
-
title: 'Title',
|
|
1433
|
-
isBEEeditor: true,
|
|
1434
|
-
beeHtml: '<p>Content</p>',
|
|
1435
|
-
ctas: [
|
|
1436
|
-
{ text: 'CTA Text 1' },
|
|
1437
|
-
{ text: 'CTA Text 2' },
|
|
1438
|
-
],
|
|
1439
|
-
};
|
|
1440
|
-
|
|
1441
|
-
const result = extractContent(platformData);
|
|
1442
|
-
|
|
1443
|
-
expect(result).toContain('CTA Text 1');
|
|
1444
|
-
expect(result).toContain('CTA Text 2');
|
|
1445
|
-
});
|
|
1446
|
-
|
|
1447
|
-
it('extracts ctas with actionLink when text is missing', () => {
|
|
1448
|
-
const platformData = {
|
|
1449
|
-
title: 'Title',
|
|
1450
|
-
isBEEeditor: true,
|
|
1451
|
-
beeHtml: '<p>Content</p>',
|
|
1452
|
-
ctas: [
|
|
1453
|
-
{ actionLink: 'https://link1.com' },
|
|
1454
|
-
{ actionLink: 'https://link2.com' },
|
|
1455
|
-
],
|
|
1456
|
-
};
|
|
1457
|
-
|
|
1458
|
-
const result = extractContent(platformData);
|
|
1459
|
-
|
|
1460
|
-
expect(result).toContain('https://link1.com');
|
|
1461
|
-
expect(result).toContain('https://link2.com');
|
|
1462
|
-
});
|
|
1463
|
-
|
|
1464
|
-
it('filters out falsy values with filter(Boolean)', () => {
|
|
1465
|
-
const platformData = {
|
|
1466
|
-
title: '',
|
|
1467
|
-
isBEEeditor: true,
|
|
1468
|
-
beeHtml: null,
|
|
1469
|
-
ctas: [
|
|
1470
|
-
{ text: null, actionLink: null },
|
|
1471
|
-
{ text: 'Valid Text' },
|
|
1472
|
-
],
|
|
1473
|
-
};
|
|
1474
|
-
|
|
1475
|
-
const result = extractContent(platformData);
|
|
1476
|
-
|
|
1477
|
-
// Should only contain 'Valid Text' after filtering
|
|
1478
|
-
expect(result).toBe('Valid Text');
|
|
1479
|
-
});
|
|
1480
|
-
|
|
1481
|
-
it('handles empty ctas array', () => {
|
|
1482
|
-
const platformData = {
|
|
1483
|
-
title: 'Title Only',
|
|
1484
|
-
isBEEeditor: true,
|
|
1485
|
-
beeHtml: '<p>BEE Content</p>',
|
|
1486
|
-
ctas: [],
|
|
1487
|
-
};
|
|
1488
|
-
|
|
1489
|
-
const result = extractContent(platformData);
|
|
1490
|
-
|
|
1491
|
-
expect(result).toContain('Title Only');
|
|
1492
|
-
expect(result).toContain('<p>BEE Content</p>');
|
|
1493
|
-
});
|
|
1494
|
-
|
|
1495
|
-
it('handles undefined ctas', () => {
|
|
1496
|
-
const platformData = {
|
|
1497
|
-
title: 'Title',
|
|
1498
|
-
isBEEeditor: true,
|
|
1499
|
-
beeHtml: '<p>Content</p>',
|
|
1500
|
-
ctas: undefined,
|
|
1501
|
-
};
|
|
1502
|
-
|
|
1503
|
-
const result = extractContent(platformData);
|
|
1504
|
-
|
|
1505
|
-
expect(result).toContain('Title');
|
|
1506
|
-
expect(result).toContain('<p>Content</p>');
|
|
1507
|
-
});
|
|
1508
|
-
|
|
1509
|
-
it('joins all content with spaces', () => {
|
|
1510
|
-
const platformData = {
|
|
1511
|
-
title: 'Title',
|
|
1512
|
-
isBEEeditor: true,
|
|
1513
|
-
beeHtml: 'HTML',
|
|
1514
|
-
ctas: [
|
|
1515
|
-
{ text: 'CTA1' },
|
|
1516
|
-
{ text: 'CTA2' },
|
|
1517
|
-
],
|
|
1518
|
-
};
|
|
1519
|
-
|
|
1520
|
-
const result = extractContent(platformData);
|
|
1521
|
-
|
|
1522
|
-
expect(result).toBe('Title HTML CTA1 CTA2');
|
|
1523
|
-
});
|
|
1524
|
-
|
|
1525
|
-
it('falls back to regular content when not BEE editor', () => {
|
|
1526
|
-
const platformData = {
|
|
1527
|
-
title: 'Title',
|
|
1528
|
-
message: 'Message',
|
|
1529
|
-
isBEEeditor: false,
|
|
1530
|
-
beeHtml: '<p>Should be ignored</p>',
|
|
1531
|
-
ctas: [
|
|
1532
|
-
{ text: 'CTA' },
|
|
1533
|
-
],
|
|
1534
|
-
};
|
|
1535
|
-
|
|
1536
|
-
const result = extractContent(platformData);
|
|
1537
|
-
|
|
1538
|
-
expect(result).toContain('Title');
|
|
1539
|
-
expect(result).toContain('Message');
|
|
1540
|
-
expect(result).toContain('CTA');
|
|
1541
|
-
expect(result).not.toContain('<p>Should be ignored</p>');
|
|
1542
|
-
});
|
|
1543
|
-
|
|
1544
|
-
it('handles null beeHtml', () => {
|
|
1545
|
-
const platformData = {
|
|
1546
|
-
title: 'Title',
|
|
1547
|
-
isBEEeditor: true,
|
|
1548
|
-
beeHtml: null,
|
|
1549
|
-
ctas: [{ text: 'CTA' }],
|
|
1550
|
-
};
|
|
1551
|
-
|
|
1552
|
-
const result = extractContent(platformData);
|
|
1553
|
-
|
|
1554
|
-
expect(result).toContain('Title');
|
|
1555
|
-
expect(result).toContain('CTA');
|
|
1556
|
-
});
|
|
1557
|
-
|
|
1558
|
-
it('handles undefined beeHtml', () => {
|
|
1559
|
-
const platformData = {
|
|
1560
|
-
title: 'Title',
|
|
1561
|
-
isBEEeditor: true,
|
|
1562
|
-
beeHtml: undefined,
|
|
1563
|
-
ctas: [],
|
|
1564
|
-
};
|
|
1565
|
-
|
|
1566
|
-
const result = extractContent(platformData);
|
|
1567
|
-
|
|
1568
|
-
expect(result).toBe('Title');
|
|
1569
|
-
});
|
|
1570
|
-
|
|
1571
|
-
it('handles complex ctas with both text and actionLink', () => {
|
|
1572
|
-
const platformData = {
|
|
1573
|
-
title: 'Title',
|
|
1574
|
-
isBEEeditor: true,
|
|
1575
|
-
beeHtml: 'Content',
|
|
1576
|
-
ctas: [
|
|
1577
|
-
{ text: 'CTA Text', actionLink: 'https://example.com' },
|
|
1578
|
-
],
|
|
1579
|
-
};
|
|
1580
|
-
|
|
1581
|
-
const result = extractContent(platformData);
|
|
1582
|
-
|
|
1583
|
-
// Should prefer text over actionLink
|
|
1584
|
-
expect(result).toContain('CTA Text');
|
|
1585
|
-
expect(result).toContain('Title');
|
|
1586
|
-
expect(result).toContain('Content');
|
|
1587
|
-
});
|
|
1588
|
-
|
|
1589
|
-
it('handles empty string beeHtml', () => {
|
|
1590
|
-
const platformData = {
|
|
1591
|
-
title: 'Title',
|
|
1592
|
-
isBEEeditor: true,
|
|
1593
|
-
beeHtml: '',
|
|
1594
|
-
ctas: [{ text: 'CTA' }],
|
|
1595
|
-
};
|
|
1596
|
-
|
|
1597
|
-
const result = extractContent(platformData);
|
|
1598
|
-
|
|
1599
|
-
expect(result).toBe('Title CTA');
|
|
1600
|
-
});
|
|
1601
|
-
});
|
|
1602
1379
|
});
|
|
1603
|
-
|
|
@@ -101,6 +101,7 @@ export async function transformTemplateConfigWithMediaDetails(templateConfig, ch
|
|
|
101
101
|
const contentType = detectMediaContentType(templateConfig);
|
|
102
102
|
|
|
103
103
|
if (contentType === MEDIA_CONTENT_TYPE.NONE) {
|
|
104
|
+
console.log('No media content detected, returning original config');
|
|
104
105
|
return templateConfig;
|
|
105
106
|
}
|
|
106
107
|
|
|
@@ -108,19 +109,24 @@ export async function transformTemplateConfigWithMediaDetails(templateConfig, ch
|
|
|
108
109
|
let transformDirection;
|
|
109
110
|
if (forceDirection) {
|
|
110
111
|
transformDirection = forceDirection;
|
|
112
|
+
console.log(`Forced transformation direction: ${transformDirection}`);
|
|
111
113
|
} else {
|
|
112
114
|
// Auto-detect based on content
|
|
113
115
|
if (contentType === MEDIA_CONTENT_TYPE.URLS) {
|
|
114
116
|
transformDirection = TRANSFORM_DIRECTION.FORWARD; // URLs → tags
|
|
117
|
+
console.log('Detected URLs, applying forward transformation (URLs → tags)');
|
|
115
118
|
} else if (contentType === MEDIA_CONTENT_TYPE.TAGS) {
|
|
116
119
|
transformDirection = TRANSFORM_DIRECTION.REVERSE; // tags → URLs
|
|
120
|
+
console.log('Detected media_content tags, applying reverse transformation (tags → URLs)');
|
|
117
121
|
} else if (contentType === MEDIA_CONTENT_TYPE.MIXED) {
|
|
118
122
|
transformDirection = TRANSFORM_DIRECTION.SMART; // Handle mixed content intelligently
|
|
123
|
+
console.log('Detected mixed content, applying smart transformation');
|
|
119
124
|
}
|
|
120
125
|
}
|
|
121
126
|
|
|
122
127
|
const newConfig = cloneDeep(templateConfig);
|
|
123
128
|
try {
|
|
129
|
+
console.log(`Fetching media details for ${transformDirection} transformation, ID: ${mediaDetailsId}`);
|
|
124
130
|
|
|
125
131
|
// Fetch media details mapping from API
|
|
126
132
|
const response = await getMediaDetails({ id: mediaDetailsId })
|
|
@@ -139,6 +145,7 @@ export async function transformTemplateConfigWithMediaDetails(templateConfig, ch
|
|
|
139
145
|
idToUrlMapping[mediaId] = url;
|
|
140
146
|
});
|
|
141
147
|
|
|
148
|
+
console.log(`Processing ${Object.keys(urlToIdMapping).length} media mappings`);
|
|
142
149
|
|
|
143
150
|
// Apply transformations based on direction
|
|
144
151
|
newConfig?.cards?.forEach(card => {
|
|
@@ -150,6 +157,7 @@ export async function transformTemplateConfigWithMediaDetails(templateConfig, ch
|
|
|
150
157
|
// Forward transformation: URL → tag
|
|
151
158
|
const mediaDetailId = urlToIdMapping[currentUrl];
|
|
152
159
|
if (mediaDetailId) {
|
|
160
|
+
console.log(`Forward: ${currentUrl} → {{media_content(${mediaDetailId})}}`);
|
|
153
161
|
card.media.url = `{{media_content(${mediaDetailId})}}`;
|
|
154
162
|
} else {
|
|
155
163
|
console.warn(`No media detail ID found for URL: ${currentUrl}`);
|
|
@@ -161,6 +169,7 @@ export async function transformTemplateConfigWithMediaDetails(templateConfig, ch
|
|
|
161
169
|
if (mediaId) {
|
|
162
170
|
const actualUrl = idToUrlMapping[mediaId];
|
|
163
171
|
if (actualUrl) {
|
|
172
|
+
console.log(`Reverse: {{media_content(${mediaId})}} → ${actualUrl}`);
|
|
164
173
|
card.media.url = actualUrl;
|
|
165
174
|
} else {
|
|
166
175
|
console.warn(`No URL found for media ID: ${mediaId}`);
|
|
@@ -176,6 +185,7 @@ export async function transformTemplateConfigWithMediaDetails(templateConfig, ch
|
|
|
176
185
|
console.error('Failed to fetch media details for transformation:', error);
|
|
177
186
|
|
|
178
187
|
// Fallback: try to extract/convert what we can without API
|
|
188
|
+
console.log('Falling back to URL extraction method');
|
|
179
189
|
newConfig.cards.forEach(card => {
|
|
180
190
|
if (card.media && card.media.url) {
|
|
181
191
|
if (transformDirection === TRANSFORM_DIRECTION.FORWARD) {
|
|
@@ -69,7 +69,7 @@ const CapDeviceContent = (props) => {
|
|
|
69
69
|
templateDescErrorHandler,
|
|
70
70
|
templateTitleError,
|
|
71
71
|
setTemplateTitleError,
|
|
72
|
-
isAiContentBotDisabled
|
|
72
|
+
isAiContentBotDisabled
|
|
73
73
|
} = props || {};
|
|
74
74
|
const { TextArea } = CapInput;
|
|
75
75
|
const { formatMessage } = intl;
|
|
@@ -167,22 +167,21 @@ const CapDeviceContent = (props) => {
|
|
|
167
167
|
return (
|
|
168
168
|
<>
|
|
169
169
|
<CapRow className="creatives-device-content">
|
|
170
|
-
|
|
170
|
+
<CapLink
|
|
171
171
|
title={isAndroid
|
|
172
|
-
|
|
173
|
-
|
|
172
|
+
? formatMessage(messages.copyContentFromIOS)
|
|
173
|
+
: formatMessage(messages.copyCotentFromAndroid)}
|
|
174
174
|
className="inapp-copy-content"
|
|
175
175
|
onClick={onCopyTitleAndContent}
|
|
176
|
-
|
|
176
|
+
/>
|
|
177
177
|
<CapRow className="creatives-inapp-title">
|
|
178
178
|
<CapColumn
|
|
179
|
-
|
|
179
|
+
className="inapp-content-main"
|
|
180
180
|
>
|
|
181
181
|
<CapHeading type="h5" className="inapp-title">
|
|
182
182
|
{formatMessage(messages.title)}
|
|
183
183
|
</CapHeading>
|
|
184
|
-
{getTagList(0)}
|
|
185
|
-
{/* here 0 signifies the tags for template title */}
|
|
184
|
+
{getTagList(0)} {/* here 0 signifies the tags for template title */}
|
|
186
185
|
</CapColumn>
|
|
187
186
|
<CapInput
|
|
188
187
|
id="inapp-title-name-input"
|
|
@@ -214,7 +213,7 @@ const CapDeviceContent = (props) => {
|
|
|
214
213
|
</CapRow>
|
|
215
214
|
<CapRow className={`creatives-inapp-message ${!isMediaTypeImage && "message-bottom-margin"}`}>
|
|
216
215
|
<CapColumn
|
|
217
|
-
|
|
216
|
+
className="inapp-message-header"
|
|
218
217
|
>
|
|
219
218
|
<CapHeading type="h5" className="inapp-message-header-style">
|
|
220
219
|
{formatMessage(messages.message)}
|
|
@@ -223,37 +222,37 @@ const CapDeviceContent = (props) => {
|
|
|
223
222
|
{/* here 1 signifies the tags for template message */}
|
|
224
223
|
</CapColumn>
|
|
225
224
|
<div className="inapp-create-template-message-input-wrapper">
|
|
226
|
-
|
|
227
|
-
|
|
228
|
-
|
|
229
|
-
|
|
230
|
-
|
|
231
|
-
|
|
232
|
-
|
|
233
|
-
|
|
234
|
-
|
|
235
|
-
|
|
236
|
-
|
|
237
|
-
|
|
238
|
-
|
|
239
|
-
|
|
225
|
+
<TextArea
|
|
226
|
+
id="inapp-create-template-message-input"
|
|
227
|
+
className="inapp-create-template-message-input"
|
|
228
|
+
placeholder={formatMessage(messages.textAreaInputPlaceholder)}
|
|
229
|
+
onChange={onTemplateMessageChange}
|
|
230
|
+
value={templateMessage || ""}
|
|
231
|
+
autosize={{ minRows: 5, maxRows: 5 }}
|
|
232
|
+
errorMessage={
|
|
233
|
+
templateMessageError && (
|
|
234
|
+
<CapError className="inapp-template-message-error">
|
|
235
|
+
{templateMessageError}
|
|
236
|
+
</CapError>
|
|
237
|
+
)
|
|
238
|
+
}
|
|
239
|
+
/>
|
|
240
|
+
{!isAiContentBotDisabled && (
|
|
241
|
+
<CapAskAira.ContentGenerationBot
|
|
242
|
+
text={templateMessage || ""}
|
|
243
|
+
setText={(text) => {
|
|
244
|
+
onTemplateMessageChange({ target: { value: text } });
|
|
245
|
+
}}
|
|
246
|
+
iconPlacement="float-br"
|
|
247
|
+
iconSize="1.6rem"
|
|
248
|
+
rootStyle={{
|
|
249
|
+
bottom: "0.2rem",
|
|
250
|
+
right: "0.2rem",
|
|
251
|
+
left: "auto",
|
|
252
|
+
position: "absolute",
|
|
253
|
+
}}
|
|
240
254
|
/>
|
|
241
|
-
|
|
242
|
-
<CapAskAira.ContentGenerationBot
|
|
243
|
-
text={templateMessage || ""}
|
|
244
|
-
setText={(text) => {
|
|
245
|
-
onTemplateMessageChange({ target: { value: text } });
|
|
246
|
-
}}
|
|
247
|
-
iconPlacement="float-br"
|
|
248
|
-
iconSize="1.6rem"
|
|
249
|
-
rootStyle={{
|
|
250
|
-
bottom: "0.2rem",
|
|
251
|
-
right: "0.2rem",
|
|
252
|
-
left: "auto",
|
|
253
|
-
position: "absolute",
|
|
254
|
-
}}
|
|
255
|
-
/>
|
|
256
|
-
)}
|
|
255
|
+
)}
|
|
257
256
|
</div>
|
|
258
257
|
{isMediaTypeImage && (
|
|
259
258
|
<>
|
|
@@ -280,16 +279,14 @@ const CapDeviceContent = (props) => {
|
|
|
280
279
|
</CapRow>
|
|
281
280
|
</CapRow>
|
|
282
281
|
<CapRow className="inapp-action-link">
|
|
283
|
-
<CapCheckbox onChange={onActionLinkCheckBoxChange} checked={addActionLink}
|
|
282
|
+
<CapCheckbox onChange={onActionLinkCheckBoxChange} checked={addActionLink}/>
|
|
284
283
|
<CapRow className="inapp-render-heading">
|
|
285
284
|
<CapHeader
|
|
286
|
-
title={
|
|
287
|
-
<
|
|
288
|
-
|
|
289
|
-
|
|
290
|
-
|
|
291
|
-
</CapRow>
|
|
292
|
-
)}
|
|
285
|
+
title={<CapRow type="flex">
|
|
286
|
+
<CapHeading type="h4">
|
|
287
|
+
{formatMessage(messages.addActionLink)}
|
|
288
|
+
</CapHeading>
|
|
289
|
+
</CapRow>}
|
|
293
290
|
description={<CapLabel type="label3">{formatMessage(messages.addActionLinkDesc)}</CapLabel>}
|
|
294
291
|
/>
|
|
295
292
|
{addActionLink && (
|
|
@@ -313,21 +310,19 @@ const CapDeviceContent = (props) => {
|
|
|
313
310
|
<CapRow className="inapp-cta-button">
|
|
314
311
|
<CapHeader
|
|
315
312
|
className="inapp-render-heading-cta-button"
|
|
316
|
-
title={
|
|
317
|
-
<
|
|
318
|
-
|
|
319
|
-
|
|
320
|
-
|
|
321
|
-
|
|
322
|
-
|
|
323
|
-
|
|
324
|
-
|
|
325
|
-
|
|
326
|
-
|
|
327
|
-
</CapRow>
|
|
328
|
-
)}
|
|
313
|
+
title={<CapRow type="flex">
|
|
314
|
+
<CapHeading type="h4">
|
|
315
|
+
{formatMessage(messages.btnLabel)}
|
|
316
|
+
</CapHeading>
|
|
317
|
+
<CapHeading
|
|
318
|
+
type="h6"
|
|
319
|
+
className="inapp-optional-label"
|
|
320
|
+
>
|
|
321
|
+
{formatMessage(messages.optional)}
|
|
322
|
+
</CapHeading>
|
|
323
|
+
</CapRow>}
|
|
329
324
|
description={<CapLabel type="label3">{formatMessage(messages.btnDesc)}</CapLabel>}
|
|
330
|
-
|
|
325
|
+
/>
|
|
331
326
|
<CapRadioGroup
|
|
332
327
|
options={BUTTON_RADIO_OPTIONS}
|
|
333
328
|
value={buttonType}
|
|
@@ -227,10 +227,6 @@ class CapTagList extends React.Component { // eslint-disable-line react/prefer-s
|
|
|
227
227
|
|
|
228
228
|
togglePopoverVisibility = (visible) => {
|
|
229
229
|
this.setState({visible});
|
|
230
|
-
// Call onVisibleChange callback if provided (for triggering API calls when popover opens)
|
|
231
|
-
if (this.props.onVisibleChange) {
|
|
232
|
-
this.props.onVisibleChange(visible);
|
|
233
|
-
}
|
|
234
230
|
};
|
|
235
231
|
|
|
236
232
|
renderDynamicTagFlow = () => {
|
|
@@ -472,7 +468,7 @@ class CapTagList extends React.Component { // eslint-disable-line react/prefer-s
|
|
|
472
468
|
onVisibleChange={this.togglePopoverVisibility}
|
|
473
469
|
content={contentSection}
|
|
474
470
|
trigger="click"
|
|
475
|
-
placement={
|
|
471
|
+
placement={channel === EMAIL.toUpperCase() ? "leftTop" : "rightTop"}
|
|
476
472
|
>
|
|
477
473
|
<CapTooltip
|
|
478
474
|
title={
|
|
@@ -539,7 +535,6 @@ CapTagList.propTypes = {
|
|
|
539
535
|
channel: PropTypes.string,
|
|
540
536
|
disabled: PropTypes.bool,
|
|
541
537
|
fetchingSchemaError: PropTypes.bool,
|
|
542
|
-
popoverPlacement: PropTypes.string,
|
|
543
538
|
};
|
|
544
539
|
|
|
545
540
|
CapTagList.defaultValue = {
|