@capillarytech/creatives-library 8.0.249 → 8.0.250-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/assets/Android.png +0 -0
- package/assets/iOS.png +0 -0
- package/constants/unified.js +2 -1
- package/initialReducer.js +2 -0
- package/package.json +1 -1
- package/services/api.js +10 -0
- package/services/tests/api.test.js +18 -0
- package/utils/common.js +5 -0
- package/utils/commonUtils.js +28 -5
- package/utils/tests/commonUtil.test.js +224 -0
- package/utils/transformTemplateConfig.js +0 -10
- package/v2Components/CapDeviceContent/index.js +61 -56
- package/v2Components/CapTagList/index.js +6 -1
- package/v2Components/CapTagListWithInput/index.js +5 -1
- package/v2Components/CapTagListWithInput/messages.js +1 -1
- package/v2Components/CapWhatsappCTA/tests/index.test.js +5 -0
- package/v2Components/ErrorInfoNote/index.js +452 -72
- package/v2Components/ErrorInfoNote/messages.js +22 -0
- package/v2Components/ErrorInfoNote/style.scss +280 -4
- package/v2Components/FormBuilder/tests/index.test.js +13 -4
- package/v2Components/HtmlEditor/HTMLEditor.js +640 -94
- package/v2Components/HtmlEditor/__tests__/HTMLEditor.apiErrors.test.js +874 -0
- package/v2Components/HtmlEditor/__tests__/HTMLEditor.test.js +1167 -133
- package/v2Components/HtmlEditor/__tests__/index.lazy.test.js +27 -16
- package/v2Components/HtmlEditor/_htmlEditor.scss +108 -45
- package/v2Components/HtmlEditor/_index.lazy.scss +1 -1
- package/v2Components/HtmlEditor/components/CodeEditorPane/_codeEditorPane.scss +13 -101
- package/v2Components/HtmlEditor/components/CodeEditorPane/index.js +148 -139
- package/v2Components/HtmlEditor/components/DeviceToggle/_deviceToggle.scss +2 -1
- package/v2Components/HtmlEditor/components/DeviceToggle/index.js +3 -3
- package/v2Components/HtmlEditor/components/EditorToolbar/_editorToolbar.scss +9 -0
- package/v2Components/HtmlEditor/components/EditorToolbar/index.js +1 -1
- package/v2Components/HtmlEditor/components/FullscreenModal/_fullscreenModal.scss +22 -0
- package/v2Components/HtmlEditor/components/InAppPreviewPane/DeviceFrame.js +4 -7
- package/v2Components/HtmlEditor/components/InAppPreviewPane/__tests__/DeviceFrame.test.js +35 -45
- package/v2Components/HtmlEditor/components/InAppPreviewPane/_inAppPreviewPane.scss +1 -3
- package/v2Components/HtmlEditor/components/InAppPreviewPane/constants.js +33 -33
- package/v2Components/HtmlEditor/components/InAppPreviewPane/index.js +7 -6
- package/v2Components/HtmlEditor/components/PreviewPane/_previewPane.scss +3 -6
- package/v2Components/HtmlEditor/components/PreviewPane/index.js +11 -13
- package/v2Components/HtmlEditor/components/SplitContainer/_splitContainer.scss +1 -1
- package/v2Components/HtmlEditor/components/ValidationErrorDisplay/index.js +49 -31
- package/v2Components/HtmlEditor/components/ValidationPanel/index.js +68 -39
- package/v2Components/HtmlEditor/components/ValidationTabs/_validationTabs.scss +254 -0
- package/v2Components/HtmlEditor/components/ValidationTabs/index.js +391 -0
- package/v2Components/HtmlEditor/components/ValidationTabs/messages.js +51 -0
- package/v2Components/HtmlEditor/constants.js +42 -20
- package/v2Components/HtmlEditor/hooks/__tests__/useInAppContent.test.js +373 -16
- package/v2Components/HtmlEditor/hooks/__tests__/useValidation.apiErrors.test.js +795 -0
- package/v2Components/HtmlEditor/hooks/useEditorContent.js +5 -2
- package/v2Components/HtmlEditor/hooks/useInAppContent.js +88 -146
- package/v2Components/HtmlEditor/hooks/useValidation.js +189 -53
- package/v2Components/HtmlEditor/index.js +1 -1
- package/v2Components/HtmlEditor/messages.js +95 -85
- package/v2Components/HtmlEditor/utils/__tests__/htmlValidator.enhanced.test.js +94 -45
- package/v2Components/HtmlEditor/utils/contentSanitizer.js +40 -41
- package/v2Components/HtmlEditor/utils/htmlValidator.js +71 -72
- package/v2Components/HtmlEditor/utils/liquidTemplateSupport.js +134 -102
- package/v2Components/HtmlEditor/utils/properSyntaxHighlighting.js +23 -25
- package/v2Components/HtmlEditor/utils/validationAdapter.js +66 -41
- package/v2Components/MobilePushPreviewV2/index.js +32 -7
- package/v2Components/TemplatePreview/_templatePreview.scss +44 -24
- package/v2Components/TemplatePreview/index.js +47 -32
- package/v2Components/TemplatePreview/messages.js +4 -0
- package/v2Components/TestAndPreviewSlidebox/_testAndPreviewSlidebox.scss +1 -0
- package/v2Containers/BeeEditor/index.js +172 -90
- package/v2Containers/BeePopupEditor/constants.js +10 -0
- package/v2Containers/BeePopupEditor/index.js +193 -0
- package/v2Containers/BeePopupEditor/tests/index.test.js +627 -0
- package/v2Containers/CreativesContainer/SlideBoxContent.js +127 -51
- package/v2Containers/CreativesContainer/SlideBoxFooter.js +163 -13
- package/v2Containers/CreativesContainer/SlideBoxHeader.js +2 -1
- package/v2Containers/CreativesContainer/constants.js +1 -0
- package/v2Containers/CreativesContainer/index.js +239 -46
- package/v2Containers/CreativesContainer/messages.js +8 -0
- package/v2Containers/CreativesContainer/tests/SlideBoxFooter.test.js +11 -2
- package/v2Containers/CreativesContainer/tests/__snapshots__/SlideBoxContent.test.js.snap +38 -50
- package/v2Containers/CreativesContainer/tests/__snapshots__/index.test.js.snap +106 -0
- package/v2Containers/Email/actions.js +7 -0
- package/v2Containers/Email/constants.js +5 -1
- package/v2Containers/Email/index.js +222 -27
- package/v2Containers/Email/messages.js +32 -0
- package/v2Containers/Email/reducer.js +12 -1
- package/v2Containers/Email/sagas.js +61 -7
- package/v2Containers/Email/tests/__snapshots__/reducer.test.js.snap +2 -0
- package/v2Containers/Email/tests/sagas.test.js +320 -29
- package/v2Containers/EmailWrapper/components/EmailHTMLEditor.js +1321 -0
- package/v2Containers/EmailWrapper/components/EmailWrapperView.js +210 -15
- package/v2Containers/EmailWrapper/components/HTMLEditorTesting.js +40 -74
- package/v2Containers/EmailWrapper/components/__tests__/EmailHTMLEditor.test.js +1749 -0
- package/v2Containers/EmailWrapper/components/__tests__/EmailWrapperView.test.js +520 -0
- package/v2Containers/EmailWrapper/components/__tests__/HTMLEditorTesting.test.js +2 -67
- package/v2Containers/EmailWrapper/constants.js +2 -0
- package/v2Containers/EmailWrapper/hooks/useEmailWrapper.js +629 -77
- package/v2Containers/EmailWrapper/index.js +103 -23
- package/v2Containers/EmailWrapper/messages.js +61 -1
- package/v2Containers/EmailWrapper/tests/useEmailWrapper.edgeCases.test.js +643 -0
- package/v2Containers/EmailWrapper/tests/useEmailWrapper.test.js +594 -77
- package/v2Containers/InApp/__tests__/InAppHTMLEditor.test.js +376 -0
- package/v2Containers/InApp/__tests__/sagas.test.js +363 -0
- package/v2Containers/InApp/actions.js +7 -0
- package/v2Containers/InApp/constants.js +20 -4
- package/v2Containers/InApp/index.js +802 -359
- package/v2Containers/InApp/index.scss +4 -3
- package/v2Containers/InApp/messages.js +7 -3
- package/v2Containers/InApp/reducer.js +21 -3
- package/v2Containers/InApp/sagas.js +29 -9
- package/v2Containers/InApp/selectors.js +25 -5
- package/v2Containers/InApp/tests/index.test.js +154 -50
- package/v2Containers/InApp/tests/reducer.test.js +34 -0
- package/v2Containers/InApp/tests/sagas.test.js +61 -9
- package/v2Containers/InApp/tests/selectors.test.js +612 -0
- package/v2Containers/InAppWrapper/components/InAppWrapperView.js +162 -0
- package/v2Containers/InAppWrapper/components/__tests__/InAppWrapperView.test.js +267 -0
- package/v2Containers/InAppWrapper/components/inAppWrapperView.scss +9 -0
- package/v2Containers/InAppWrapper/constants.js +16 -0
- package/v2Containers/InAppWrapper/hooks/__tests__/useInAppWrapper.test.js +473 -0
- package/v2Containers/InAppWrapper/hooks/useInAppWrapper.js +198 -0
- package/v2Containers/InAppWrapper/index.js +148 -0
- package/v2Containers/InAppWrapper/messages.js +49 -0
- package/v2Containers/InappAdvance/index.js +1099 -0
- package/v2Containers/InappAdvance/index.scss +10 -0
- package/v2Containers/InappAdvance/tests/index.test.js +448 -0
- 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/Rcs/tests/__snapshots__/index.test.js.snap +12 -0
- package/v2Containers/SmsTrai/Edit/tests/__snapshots__/index.test.js.snap +4 -0
- package/v2Containers/TagList/index.js +62 -19
- package/v2Containers/Templates/_templates.scss +60 -1
- package/v2Containers/Templates/index.js +89 -4
- package/v2Containers/Templates/messages.js +4 -0
- package/v2Containers/Whatsapp/tests/__snapshots__/index.test.js.snap +34 -0
- package/v2Components/HtmlEditor/components/ValidationErrorDisplay/__tests__/index.test.js +0 -152
- package/v2Containers/EmailWrapper/tests/EmailWrapperView.test.js +0 -214
|
@@ -208,13 +208,31 @@ export class Email extends React.Component { // eslint-disable-line react/prefer
|
|
|
208
208
|
const isBEESupport = (this.props.location.query.isBEESupport !== "false") || false;
|
|
209
209
|
const isBEEAppEnable = this.checkBeeEditorAllowedForLibrary();
|
|
210
210
|
if (!_.isEmpty(this.props.Templates.BEETemplate)) {
|
|
211
|
-
|
|
211
|
+
const isDragDrop = this.props.Templates.BEETemplate.versions?.base?.is_drag_drop;
|
|
212
|
+
|
|
213
|
+
if (isDragDrop && isBEEAppEnable ) {
|
|
212
214
|
this.setState({isDragDrop: true});
|
|
213
215
|
}
|
|
214
216
|
if (this.props.params.id) {
|
|
215
|
-
|
|
217
|
+
// Extract drag_drop_id - check multiple possible paths
|
|
218
|
+
const activeTab = this.props.Templates.BEETemplate.versions?.base?.activeTab || 'en';
|
|
219
|
+
const activeTabData = this.props.Templates.BEETemplate.versions?.base?.[activeTab] || {};
|
|
220
|
+
const dragDropId = activeTabData.drag_drop_id
|
|
221
|
+
|| activeTabData.id
|
|
222
|
+
|| _.get(this.props.Templates.BEETemplate, 'versions.base.drag_drop_id')
|
|
223
|
+
|| _.get(this.props.Templates.BEETemplate, 'versions.base.id')
|
|
224
|
+
|| this.props.Templates.BEETemplate?._id;
|
|
225
|
+
this.props.actions.getCmsSetting(BEE_PLUGIN, dragDropId, 'open', undefined, isBEESupport, isBEEAppEnable);
|
|
216
226
|
} else if (this.props.location.query.module !== "library" || (this.props.location.query.module === "library" && !this.props.templateData)) {
|
|
217
|
-
|
|
227
|
+
// Extract drag_drop_id - check multiple possible paths
|
|
228
|
+
const activeTab = this.props.Templates.BEETemplate.versions?.base?.activeTab || 'en';
|
|
229
|
+
const activeTabData = this.props.Templates.BEETemplate.versions?.base?.[activeTab] || {};
|
|
230
|
+
const dragDropId = activeTabData.drag_drop_id
|
|
231
|
+
|| activeTabData.id
|
|
232
|
+
|| _.get(this.props.Templates.BEETemplate, 'versions.base.drag_drop_id')
|
|
233
|
+
|| _.get(this.props.Templates.BEETemplate, 'versions.base.id')
|
|
234
|
+
|| this.props.Templates.BEETemplate?._id;
|
|
235
|
+
this.props.actions.getCmsSetting(BEE_PLUGIN, dragDropId, 'create', undefined, isBEESupport, isBEEAppEnable);
|
|
218
236
|
}
|
|
219
237
|
}
|
|
220
238
|
this.setState({ content: (this.props.Templates.selectedEmailLayout ? this.props.Templates.selectedEmailLayout : ''), formData});
|
|
@@ -237,11 +255,52 @@ export class Email extends React.Component { // eslint-disable-line react/prefer
|
|
|
237
255
|
if (this.props.location.query.type === 'embedded') {
|
|
238
256
|
this.showNext();
|
|
239
257
|
}
|
|
258
|
+
|
|
259
|
+
// Check if BEETemplate was set after componentWillMount but before componentDidMount
|
|
260
|
+
// This can happen if BEETemplate is set asynchronously
|
|
261
|
+
if (!_.isEmpty(this.props.Templates.BEETemplate) && !this.state.isDragDrop) {
|
|
262
|
+
const isBEESupport = (this.props.location.query.isBEESupport !== "false") || false;
|
|
263
|
+
const isBEEAppEnable = this.checkBeeEditorAllowedForLibrary();
|
|
264
|
+
const beeTemplate = this.props.Templates.BEETemplate;
|
|
265
|
+
const activeTab = beeTemplate.versions?.base?.activeTab || 'en';
|
|
266
|
+
const activeTabData = beeTemplate.versions?.base?.[activeTab] || {};
|
|
267
|
+
const isDragDrop = activeTabData.is_drag_drop
|
|
268
|
+
|| beeTemplate.versions?.base?.is_drag_drop
|
|
269
|
+
|| beeTemplate.base?.is_drag_drop
|
|
270
|
+
|| beeTemplate.is_drag_drop;
|
|
271
|
+
|
|
272
|
+
if (isDragDrop && isBEEAppEnable) {
|
|
273
|
+
this.setState({isDragDrop: true});
|
|
274
|
+
|
|
275
|
+
const dragDropId = activeTabData.drag_drop_id
|
|
276
|
+
|| activeTabData.id
|
|
277
|
+
|| _.get(beeTemplate, 'versions.base.drag_drop_id')
|
|
278
|
+
|| _.get(beeTemplate, 'versions.base.id')
|
|
279
|
+
|| beeTemplate._id;
|
|
280
|
+
|
|
281
|
+
if (this.props.params.id) {
|
|
282
|
+
const activeTabForLang = beeTemplate.versions?.base?.activeTab || 'en';
|
|
283
|
+
this.props.actions.getCmsSetting(BEE_PLUGIN, dragDropId, 'open', activeTabForLang, isBEESupport, isBEEAppEnable);
|
|
284
|
+
} else {
|
|
285
|
+
this.props.actions.getCmsSetting(BEE_PLUGIN, dragDropId, 'create', undefined, isBEESupport, isBEEAppEnable);
|
|
286
|
+
}
|
|
287
|
+
}
|
|
288
|
+
}
|
|
240
289
|
}
|
|
241
290
|
|
|
242
291
|
|
|
243
|
-
checkBeeEditorAllowedForLibrary = () => {
|
|
244
|
-
|
|
292
|
+
checkBeeEditorAllowedForLibrary = (props = null) => {
|
|
293
|
+
// Allow passing props for use in componentWillReceiveProps (to use nextProps)
|
|
294
|
+
const componentProps = props || this.props;
|
|
295
|
+
const { isFullMode = false, editor, Email } = componentProps || {};
|
|
296
|
+
// IMPORTANT: For isBEEAppEnable API parameter, use API response if available
|
|
297
|
+
// This ensures consistent behavior across full mode and library mode
|
|
298
|
+
// The API response (Email.isBeeEnabled) represents the actual org setting
|
|
299
|
+
if (Email?.isBeeEnabled !== undefined && Email?.isBeeEnabled !== null) {
|
|
300
|
+
return Email.isBeeEnabled;
|
|
301
|
+
}
|
|
302
|
+
// Fallback to mode-based logic for UI purposes (editor selection, etc.)
|
|
303
|
+
// But for API calls, this should ideally use the API response
|
|
245
304
|
if ((editor === "BEE" && !isFullMode) || isFullMode) {
|
|
246
305
|
return true;
|
|
247
306
|
}
|
|
@@ -342,9 +401,61 @@ export class Email extends React.Component { // eslint-disable-line react/prefer
|
|
|
342
401
|
// this.props.globalActions.fetchSchemaForEntity(query);
|
|
343
402
|
// }
|
|
344
403
|
|
|
404
|
+
// Check if BEETemplate was just set (for new flow when template details load)
|
|
405
|
+
// This handles the case where BEETemplate is set after componentWillMount
|
|
406
|
+
const wasBEETemplateEmpty = _.isEmpty(this.props.Templates.BEETemplate);
|
|
407
|
+
const isBEETemplateNowSet = !_.isEmpty(nextProps.Templates.BEETemplate);
|
|
408
|
+
const isBEEAppEnable = this.checkBeeEditorAllowedForLibrary(nextProps);
|
|
409
|
+
const isBEESupport = (nextProps.location.query.isBEESupport !== "false") || false;
|
|
410
|
+
|
|
411
|
+
if (wasBEETemplateEmpty && isBEETemplateNowSet && isBEEAppEnable) {
|
|
412
|
+
const beeTemplate = nextProps.Templates.BEETemplate;
|
|
413
|
+
const isDragDrop = beeTemplate.versions?.base?.is_drag_drop
|
|
414
|
+
|| beeTemplate.versions?.base?.[beeTemplate.versions?.base?.activeTab || 'en']?.is_drag_drop
|
|
415
|
+
|| beeTemplate.base?.is_drag_drop
|
|
416
|
+
|| beeTemplate.is_drag_drop;
|
|
417
|
+
|
|
418
|
+
// Check if we're in edit mode - check multiple sources for id
|
|
419
|
+
const hasParamsId = nextProps.params?.id
|
|
420
|
+
|| nextProps.location?.query?.id
|
|
421
|
+
|| nextProps.location?.params?.id
|
|
422
|
+
|| (nextProps.location?.pathname && nextProps.location.pathname.includes('/edit/'));
|
|
423
|
+
|
|
424
|
+
if (isDragDrop) {
|
|
425
|
+
this.setState({isDragDrop: true});
|
|
426
|
+
|
|
427
|
+
// Extract drag_drop_id - check multiple possible paths
|
|
428
|
+
// Priority: versions.base[activeTab].drag_drop_id > versions.base[activeTab].id > versions.base.drag_drop_id > _id
|
|
429
|
+
const activeTab = beeTemplate.versions?.base?.activeTab || 'en';
|
|
430
|
+
const activeTabData = beeTemplate.versions?.base?.[activeTab] || {};
|
|
431
|
+
let dragDropId = activeTabData.drag_drop_id
|
|
432
|
+
|| activeTabData.id
|
|
433
|
+
|| beeTemplate.versions?.base?.drag_drop_id
|
|
434
|
+
|| beeTemplate.versions?.base?.id
|
|
435
|
+
|| beeTemplate.base?.drag_drop_id
|
|
436
|
+
|| beeTemplate.base?.id
|
|
437
|
+
|| beeTemplate._id;
|
|
438
|
+
|
|
439
|
+
// Call getCmsSetting for BEE template - use 'open' mode if in edit mode
|
|
440
|
+
// Extract langId from active tab
|
|
441
|
+
const activeTabForLang = beeTemplate.versions?.base?.activeTab || 'en';
|
|
442
|
+
if (hasParamsId) {
|
|
443
|
+
this.props.actions.getCmsSetting(BEE_PLUGIN, dragDropId, 'open', activeTabForLang, isBEESupport, isBEEAppEnable);
|
|
444
|
+
} else if (nextProps.location.query.module !== "library" || (nextProps.location.query.module === "library" && !nextProps.templateData)) {
|
|
445
|
+
this.props.actions.getCmsSetting(BEE_PLUGIN, dragDropId, 'create', undefined, isBEESupport, isBEEAppEnable);
|
|
446
|
+
}
|
|
447
|
+
}
|
|
448
|
+
}
|
|
449
|
+
|
|
345
450
|
if (this.state.isEdit && !this.state.editDataSet && !_.isEmpty(nextProps.Email.templateDetails) && !_.isEmpty(this.state.schema)) {
|
|
346
451
|
this.setState({editDataSet: true}, () => {
|
|
347
452
|
this.setEditData(nextProps.Email.templateDetails);
|
|
453
|
+
// Update template name in parent if available
|
|
454
|
+
if (this.props.isFullMode && this.props.showTemplateName && nextProps.Email.templateDetails.name) {
|
|
455
|
+
const formData = this.state.formData;
|
|
456
|
+
formData['template-name'] = nextProps.Email.templateDetails.name;
|
|
457
|
+
this.props.showTemplateName({formData, onFormDataChange: this.onFormDataChange});
|
|
458
|
+
}
|
|
348
459
|
});
|
|
349
460
|
}
|
|
350
461
|
if (this.state.isEdit && nextProps.location.query.module === "library" && !_.isEmpty(nextProps.templateData) && !this.props.params.id && !nextProps.isGetFormData && _.isEmpty(_.get(this, `state.formData['template-subject']`))) {
|
|
@@ -383,7 +494,7 @@ export class Email extends React.Component { // eslint-disable-line react/prefer
|
|
|
383
494
|
const formData = _.cloneDeep(this.state.formData);
|
|
384
495
|
|
|
385
496
|
const schema = _.cloneDeep(this.state.schema);
|
|
386
|
-
const langIndex = formData[this.state.currentTab - 1]
|
|
497
|
+
const langIndex = formData[this.state.currentTab - 1]?.selectedLanguages?.indexOf(langId);
|
|
387
498
|
|
|
388
499
|
const temp = (schema.containers || {})[this.state.currentTab - 1];
|
|
389
500
|
|
|
@@ -391,32 +502,91 @@ export class Email extends React.Component { // eslint-disable-line react/prefer
|
|
|
391
502
|
if (nextProps.Email.CmsSettings.isDragDrop && this.checkBeeEditorAllowedForLibrary()) {
|
|
392
503
|
const beeJson = `BEEeditor${currentTab > 1 ? currentTab : ''}json`;
|
|
393
504
|
const beeToken = `BEEeditor${currentTab > 1 ? currentTab : ''}token`;
|
|
394
|
-
let beeJsonValue =
|
|
505
|
+
let beeJsonValue = '';
|
|
395
506
|
const selectedId = _.get(this.props, 'Email.templateDetails._id', '') || _.get(this.props, 'Templates.BEETemplate.versions.base.drag_drop_id', '');
|
|
396
|
-
|
|
397
|
-
|
|
398
|
-
|
|
399
|
-
|
|
400
|
-
|
|
507
|
+
|
|
508
|
+
// Get beeJsonValue from template data - check multiple sources
|
|
509
|
+
// First check if it's already in formData (from setEditData)
|
|
510
|
+
beeJsonValue = _.get(this.state, `formData[${currentTab - 1}][${langId}].json-content`, '');
|
|
511
|
+
|
|
512
|
+
// Also check formData.base
|
|
513
|
+
if (!beeJsonValue) {
|
|
514
|
+
beeJsonValue = _.get(this.state, `formData.base[${langId}].json-content`, '');
|
|
515
|
+
}
|
|
516
|
+
|
|
517
|
+
// Always check templateDetails and BEETemplate regardless of mode
|
|
518
|
+
if (!beeJsonValue) {
|
|
519
|
+
// Check Email.templateDetails first
|
|
520
|
+
const templateDetails = nextProps.Email.templateDetails;
|
|
521
|
+
if (templateDetails && templateDetails.versions && templateDetails.versions.base) {
|
|
522
|
+
const baseVersion = templateDetails.versions.base;
|
|
523
|
+
// Try language-specific path first (e.g., base.en.json-content)
|
|
524
|
+
if (baseVersion[langId] && baseVersion[langId]['json-content']) {
|
|
525
|
+
beeJsonValue = baseVersion[langId]['json-content'];
|
|
526
|
+
} else if (baseVersion['json-content']) {
|
|
527
|
+
// Fallback to base-level json-content
|
|
528
|
+
beeJsonValue = baseVersion['json-content'];
|
|
529
|
+
}
|
|
530
|
+
}
|
|
531
|
+
|
|
532
|
+
// If still not found, check BEETemplate
|
|
533
|
+
if (!beeJsonValue) {
|
|
534
|
+
const beeTemplate = nextProps.Templates.BEETemplate;
|
|
535
|
+
if (beeTemplate && beeTemplate.versions && beeTemplate.versions.base) {
|
|
536
|
+
const beeBase = beeTemplate.versions.base;
|
|
537
|
+
if (beeBase[langId] && beeBase[langId]['json-content']) {
|
|
538
|
+
beeJsonValue = beeBase[langId]['json-content'];
|
|
539
|
+
} else if (beeBase['json-content']) {
|
|
540
|
+
beeJsonValue = beeBase['json-content'];
|
|
541
|
+
}
|
|
542
|
+
}
|
|
401
543
|
}
|
|
402
544
|
}
|
|
545
|
+
// Ensure we have a valid beeJsonValue - if it's a string, try to parse it to verify it's valid JSON
|
|
546
|
+
let finalBeeJsonValue = beeJsonValue;
|
|
547
|
+
if (beeJsonValue && typeof beeJsonValue === 'string') {
|
|
548
|
+
try {
|
|
549
|
+
// Try to parse to verify it's valid JSON
|
|
550
|
+
JSON.parse(beeJsonValue);
|
|
551
|
+
} catch (e) {
|
|
552
|
+
console.warn('[Email] componentWillReceiveProps - beeJsonValue is not valid JSON, using as-is:', e);
|
|
553
|
+
}
|
|
554
|
+
}
|
|
555
|
+
|
|
556
|
+
// Preserve existing formData values, especially template-subject
|
|
557
|
+
const existingFormData = formData[`${currentTab - 1}`][langId] || {};
|
|
403
558
|
formData[`${currentTab - 1}`][langId] = {
|
|
404
|
-
...
|
|
559
|
+
...existingFormData,
|
|
405
560
|
is_drag_drop: true,
|
|
406
|
-
[beeJson]:
|
|
561
|
+
[beeJson]: finalBeeJsonValue,
|
|
407
562
|
[beeToken]: nextProps.Email.CmsSettings.tokenData,
|
|
408
563
|
id: selectedId,
|
|
564
|
+
// Also store json-content for reference
|
|
565
|
+
'json-content': finalBeeJsonValue,
|
|
409
566
|
};
|
|
410
|
-
|
|
411
|
-
|
|
412
|
-
|
|
413
|
-
|
|
414
|
-
|
|
415
|
-
|
|
416
|
-
tempPane.sections[0].inputFields[0].cols[0].colStyle = {display: "none"};
|
|
567
|
+
|
|
568
|
+
// Ensure template-subject is preserved at the top level
|
|
569
|
+
if (formData['template-subject'] === undefined || formData['template-subject'] === '') {
|
|
570
|
+
const subjectFromEditData = _.get(nextProps, 'Email.templateDetails.versions.base.subject', '');
|
|
571
|
+
if (subjectFromEditData) {
|
|
572
|
+
formData['template-subject'] = subjectFromEditData;
|
|
417
573
|
}
|
|
418
|
-
}
|
|
419
|
-
|
|
574
|
+
}
|
|
575
|
+
|
|
576
|
+
if (langIndex !== undefined && langIndex !== -1 && temp && temp.panes) {
|
|
577
|
+
_.forEach(temp.panes, (pane, index) => {
|
|
578
|
+
const tempPane = pane;
|
|
579
|
+
//
|
|
580
|
+
if (parseInt(index, 10) === parseInt(langIndex, 10)) {
|
|
581
|
+
//
|
|
582
|
+
if (tempPane.sections && tempPane.sections[0] && tempPane.sections[0].inputFields && tempPane.sections[0].inputFields[0] && tempPane.sections[0].inputFields[0].cols) {
|
|
583
|
+
tempPane.sections[0].inputFields[0].cols[1].colStyle = {display: ""};
|
|
584
|
+
tempPane.sections[0].inputFields[0].cols[0].colStyle = {display: "none"};
|
|
585
|
+
}
|
|
586
|
+
}
|
|
587
|
+
});
|
|
588
|
+
}
|
|
589
|
+
this.setState({schema, isSchemaChanged: true, loadingStatus: this.state.loadingStatus + 1, formData});
|
|
420
590
|
} else {
|
|
421
591
|
_.forEach(temp.panes, (pane, index) => {
|
|
422
592
|
const tempPane = pane;
|
|
@@ -897,6 +1067,11 @@ export class Email extends React.Component { // eslint-disable-line react/prefer
|
|
|
897
1067
|
const isBEESupport = (this.props.location.query.isBEESupport !== "false") || false;
|
|
898
1068
|
const formData = _.cloneDeep(this.state.formData);
|
|
899
1069
|
|
|
1070
|
+
// Set template name from editData if available
|
|
1071
|
+
if (editData.name) {
|
|
1072
|
+
formData['template-name'] = editData.name;
|
|
1073
|
+
}
|
|
1074
|
+
|
|
900
1075
|
const schema = (this.props.location.query.type === 'embedded') ? this.removeStandAlone(this.state.schema) : _.cloneDeep(this.state.schema);
|
|
901
1076
|
const containers = _.cloneDeep(schema.containers.slice());
|
|
902
1077
|
let tabKey = "";
|
|
@@ -905,7 +1080,8 @@ export class Email extends React.Component { // eslint-disable-line react/prefer
|
|
|
905
1080
|
const type = this.props.location.query.type;
|
|
906
1081
|
|
|
907
1082
|
formData['template-name'] = editData.name;
|
|
908
|
-
|
|
1083
|
+
const subject = _.get(editData, 'versions.base.subject', '');
|
|
1084
|
+
formData['template-subject'] = subject;
|
|
909
1085
|
formData.base = editData.versions.base;
|
|
910
1086
|
|
|
911
1087
|
_.forEach(editData.versions.history, (data1, index) => {
|
|
@@ -986,8 +1162,13 @@ export class Email extends React.Component { // eslint-disable-line react/prefer
|
|
|
986
1162
|
|
|
987
1163
|
|
|
988
1164
|
this.setState({ formData, schema, tabKey, currentTab, tabCount: editData.versions.history.length, loadingStatus: this.state.loadingStatus + 1 }, () => {
|
|
989
|
-
if (this.props.isFullMode) {
|
|
990
|
-
|
|
1165
|
+
if (this.props.isFullMode && this.props.showTemplateName) {
|
|
1166
|
+
// Ensure template name is set before showing it
|
|
1167
|
+
const updatedFormData = _.cloneDeep(formData);
|
|
1168
|
+
if (editData.name && !updatedFormData['template-name']) {
|
|
1169
|
+
updatedFormData['template-name'] = editData.name;
|
|
1170
|
+
}
|
|
1171
|
+
this.props.showTemplateName({formData: updatedFormData, onFormDataChange: this.onFormDataChange});
|
|
991
1172
|
}
|
|
992
1173
|
const isBEEAppEnable = this.checkBeeEditorAllowedForLibrary();
|
|
993
1174
|
_.forEach((editData.versions.base.selectedLanguages), (language) => {
|
|
@@ -2663,6 +2844,7 @@ export class Email extends React.Component { // eslint-disable-line react/prefer
|
|
|
2663
2844
|
getTemplateDetailsInProgress,
|
|
2664
2845
|
assetUploading,
|
|
2665
2846
|
createTemplateInProgress,
|
|
2847
|
+
fetchingCmsSettings,
|
|
2666
2848
|
} = this.props.Email;
|
|
2667
2849
|
let isLoading =
|
|
2668
2850
|
isLoadingMetaEntities ||
|
|
@@ -2671,7 +2853,7 @@ export class Email extends React.Component { // eslint-disable-line react/prefer
|
|
|
2671
2853
|
) || (
|
|
2672
2854
|
assetUploading !== undefined && assetUploading
|
|
2673
2855
|
) || (
|
|
2674
|
-
Email && (fetchingCmsData || getTemplateDetailsInProgress)
|
|
2856
|
+
Email && (fetchingCmsData || getTemplateDetailsInProgress || fetchingCmsSettings)
|
|
2675
2857
|
);
|
|
2676
2858
|
|
|
2677
2859
|
if (!isLoading) {
|
|
@@ -2993,6 +3175,19 @@ function mapDispatchToProps(dispatch) {
|
|
|
2993
3175
|
const withReducer = injectReducer({ key: 'email', reducer: v2EmailReducer });
|
|
2994
3176
|
const withEmailSaga = injectSaga({ key: 'email', saga: v2EmailSagas });
|
|
2995
3177
|
|
|
3178
|
+
// Base Email component without saga registration (for use from EmailWrapper)
|
|
3179
|
+
// EmailWrapper already registers the saga, so we don't need to register it here
|
|
3180
|
+
export const EmailWithoutSaga = withCreatives({
|
|
3181
|
+
WrappedComponent: Email,
|
|
3182
|
+
mapStateToProps,
|
|
3183
|
+
mapDispatchToProps,
|
|
3184
|
+
userAuth: true,
|
|
3185
|
+
sagas: [], // No saga - EmailWrapper registers it
|
|
3186
|
+
reducers: [withReducer],
|
|
3187
|
+
});
|
|
3188
|
+
|
|
3189
|
+
// Email component with saga registration (for direct use from SlideBoxContent in Edit mode)
|
|
3190
|
+
// When Email is used directly (not as child of EmailWrapper), it needs to register the saga
|
|
2996
3191
|
export default withCreatives({
|
|
2997
3192
|
WrappedComponent: Email,
|
|
2998
3193
|
mapStateToProps,
|
|
@@ -302,4 +302,36 @@ export default defineMessages({
|
|
|
302
302
|
id: 'creatives.containersV2.Email.base64ImageError',
|
|
303
303
|
defaultMessage: 'Base64 images are not allowed. Please upload your image to a gallery and use it, or add the image URL instead.',
|
|
304
304
|
},
|
|
305
|
+
"editorTypeTitle": {
|
|
306
|
+
id: 'creatives.containersV2.Email.editorTypeTitle',
|
|
307
|
+
defaultMessage: 'Editor type',
|
|
308
|
+
},
|
|
309
|
+
"htmlEditorTitle": {
|
|
310
|
+
id: 'creatives.containersV2.Email.htmlEditorTitle',
|
|
311
|
+
defaultMessage: 'HTML editor',
|
|
312
|
+
},
|
|
313
|
+
"htmlEditorDescription": {
|
|
314
|
+
id: 'creatives.containersV2.Email.htmlEditorDescription',
|
|
315
|
+
defaultMessage: 'Use a basic HTML editor to write and format your content. Suitable if you are familiar with HTML.',
|
|
316
|
+
},
|
|
317
|
+
"dragDropEditorTitle": {
|
|
318
|
+
id: 'creatives.containersV2.Email.dragDropEditorTitle',
|
|
319
|
+
defaultMessage: 'Drag & drop editor',
|
|
320
|
+
},
|
|
321
|
+
"dragDropEditorDescription": {
|
|
322
|
+
id: 'creatives.containersV2.Email.dragDropEditorDescription',
|
|
323
|
+
defaultMessage: 'Create your content visually by dragging blocks — no coding needed. Great for quick, easy designs.',
|
|
324
|
+
},
|
|
325
|
+
"uploadZipTitle": {
|
|
326
|
+
id: 'creatives.containersV2.Email.uploadZipTitle',
|
|
327
|
+
defaultMessage: 'Upload zip file',
|
|
328
|
+
},
|
|
329
|
+
"uploadZipDescription": {
|
|
330
|
+
id: 'creatives.containersV2.Email.uploadZipDescription',
|
|
331
|
+
defaultMessage: 'Upload a ZIP containing your custom HTML, images, and assets. Ideal if your content is already built.',
|
|
332
|
+
},
|
|
333
|
+
"nextButton": {
|
|
334
|
+
id: 'creatives.containersV2.Email.nextButton',
|
|
335
|
+
defaultMessage: 'Next',
|
|
336
|
+
},
|
|
305
337
|
});
|
|
@@ -11,6 +11,7 @@ import * as types from './constants';
|
|
|
11
11
|
const initialState = fromJS({
|
|
12
12
|
createTemplateInProgress: false,
|
|
13
13
|
createResponse: {},
|
|
14
|
+
isBeeEnabled: false,
|
|
14
15
|
});
|
|
15
16
|
|
|
16
17
|
function emailReducer(state = initialState, action) {
|
|
@@ -107,6 +108,15 @@ function emailReducer(state = initialState, action) {
|
|
|
107
108
|
return state
|
|
108
109
|
.set('fetchingCmsData', false)
|
|
109
110
|
.set('fetchingCmsDataFailed', true);
|
|
111
|
+
case types.GET_CMS_ACCOUNTS_REQUEST:
|
|
112
|
+
return state
|
|
113
|
+
.set('isBeeEnabled', false); // default to false
|
|
114
|
+
case types.GET_CMS_ACCOUNTS_SUCCESS:
|
|
115
|
+
return state
|
|
116
|
+
.set('isBeeEnabled', action.isBeeEnabled);
|
|
117
|
+
case types.GET_CMS_ACCOUNTS_FAILURE:
|
|
118
|
+
return state
|
|
119
|
+
.set('isBeeEnabled', false);
|
|
110
120
|
case types.CLEAR_EMAIL_CRUD_RESPONSE_REQUEST:
|
|
111
121
|
return state
|
|
112
122
|
.set('createResponse', fromJS({}));
|
|
@@ -139,7 +149,8 @@ function emailReducer(state = initialState, action) {
|
|
|
139
149
|
.set('CmsSettings', fromJS({}))
|
|
140
150
|
.set('fetchingCmsData', false)
|
|
141
151
|
.set('duplicateResponse', fromJS({}))
|
|
142
|
-
.set('cmsData', '')
|
|
152
|
+
.set('cmsData', '')
|
|
153
|
+
.set('isBeeEnabled', false);
|
|
143
154
|
case types.TRANSFORM_EMAIL_TEMPLATE_REQUEST:
|
|
144
155
|
return state.set("createTemplateInProgress", true);
|
|
145
156
|
default:
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import {
|
|
2
2
|
call, put, takeLatest, takeEvery, all,
|
|
3
3
|
} from 'redux-saga/effects';
|
|
4
|
+
import CapNotification from '@capillarytech/cap-ui-library/CapNotification';
|
|
4
5
|
import * as Api from '../../services/api';
|
|
5
6
|
import * as types from './constants';
|
|
6
7
|
import { transformEmailTemplates, storeS3FileSizeDetails } from '../../utils/cdnTransformation';
|
|
@@ -9,15 +10,47 @@ export function* createTemplate(template) {
|
|
|
9
10
|
let errorMsg;
|
|
10
11
|
try {
|
|
11
12
|
const result = yield call(Api.createEmailTemplate, template);
|
|
12
|
-
if (
|
|
13
|
-
|
|
13
|
+
// Check if the API call failed (non-2xx status codes or explicit failure)
|
|
14
|
+
const statusCode = result.status?.code || result.status;
|
|
15
|
+
const isError = !result.success || statusCode >= 400;
|
|
16
|
+
|
|
17
|
+
if (isError) {
|
|
18
|
+
// Extract error message from various possible locations in the response
|
|
19
|
+
errorMsg = result.message
|
|
20
|
+
|| result.errorMessage
|
|
21
|
+
|| result.error?.message
|
|
22
|
+
|| (result.response && result.response.message)
|
|
23
|
+
|| (result.status && result.status.message)
|
|
24
|
+
|| (result.data && result.data.message)
|
|
25
|
+
|| `API Error: ${statusCode || 'Unknown error'}`;
|
|
26
|
+
// Show error notification directly from saga
|
|
27
|
+
CapNotification.error({
|
|
28
|
+
key: 'createTemplateError',
|
|
29
|
+
message: errorMsg,
|
|
30
|
+
});
|
|
14
31
|
yield put({ type: types.CREATE_TEMPLATE_FAILURE, errorMsg });
|
|
32
|
+
// Call callback with error so component can handle it (if needed)
|
|
33
|
+
if (template.onCreateTemplateComplete) {
|
|
34
|
+
try {
|
|
35
|
+
// Call the callback directly (it's a regular function, not a generator)
|
|
36
|
+
template.onCreateTemplateComplete({ error: true, message: errorMsg, statusCode });
|
|
37
|
+
} catch (callbackError) {
|
|
38
|
+
console.error('[Email Saga] Error executing callback:', callbackError);
|
|
39
|
+
}
|
|
40
|
+
}
|
|
15
41
|
} else {
|
|
16
|
-
yield put({
|
|
42
|
+
yield put({
|
|
43
|
+
type: types.CREATE_TEMPLATE_SUCCESS, data: result.response, statusCode: result.status ? result.status.code : '', errorMsg,
|
|
44
|
+
});
|
|
17
45
|
yield template.onCreateTemplateComplete(result.response);
|
|
18
46
|
}
|
|
19
47
|
} catch (error) {
|
|
48
|
+
errorMsg = error.message || error.toString() || 'An unexpected error occurred';
|
|
20
49
|
yield put({ type: types.CREATE_TEMPLATE_FAILURE, error, errorMsg });
|
|
50
|
+
// Call callback with error so component can handle it
|
|
51
|
+
if (template.onCreateTemplateComplete) {
|
|
52
|
+
yield template.onCreateTemplateComplete({ error: true, message: errorMsg });
|
|
53
|
+
}
|
|
21
54
|
}
|
|
22
55
|
}
|
|
23
56
|
|
|
@@ -26,14 +59,14 @@ export function* transformEmailTemplate({template, callback}) {
|
|
|
26
59
|
const result = yield call(transformEmailTemplates, template);
|
|
27
60
|
yield callback(result);
|
|
28
61
|
} catch (error) {
|
|
29
|
-
yield callback(template);
|
|
62
|
+
yield callback(template);
|
|
30
63
|
}
|
|
31
64
|
}
|
|
32
65
|
|
|
33
66
|
export function* duplicateTemplate(payload) {
|
|
34
67
|
let errorMsg;
|
|
35
68
|
let result;
|
|
36
|
-
|
|
69
|
+
const { id, channel, callback } = payload;
|
|
37
70
|
try {
|
|
38
71
|
result = yield call(Api.duplicateTemplate, {id, channel} );
|
|
39
72
|
if (result.status.code === 500) {
|
|
@@ -42,7 +75,9 @@ export function* duplicateTemplate(payload) {
|
|
|
42
75
|
if (callback) {
|
|
43
76
|
callback(result?.response);
|
|
44
77
|
}
|
|
45
|
-
yield put({
|
|
78
|
+
yield put({
|
|
79
|
+
type: types.DUPLICATE_TEMPLATE_SUCCESS, data: result?.response, statusCode: result?.status?.code, errorMsg,
|
|
80
|
+
});
|
|
46
81
|
} catch (error) {
|
|
47
82
|
yield put({ type: types.DUPLICATE_TEMPLATE_FAILURE, error, errorMsg });
|
|
48
83
|
}
|
|
@@ -67,7 +102,9 @@ export function* getAllAssets(assetType, queryParams) {
|
|
|
67
102
|
}
|
|
68
103
|
}
|
|
69
104
|
|
|
70
|
-
export function* getCmsSetting({
|
|
105
|
+
export function* getCmsSetting({
|
|
106
|
+
cmsType, projectId, cmsMode, langId, isEdmSupport, isBEEAppEnable,
|
|
107
|
+
}) {
|
|
71
108
|
try {
|
|
72
109
|
const result = yield call(Api.getCmsTemplateSettingsV2, cmsType, projectId, cmsMode, langId, isEdmSupport, isBEEAppEnable);
|
|
73
110
|
|
|
@@ -87,6 +124,17 @@ export function* getCmsData({cmsType, projectId, langId}) {
|
|
|
87
124
|
}
|
|
88
125
|
}
|
|
89
126
|
|
|
127
|
+
export function* getCmsAccounts({cmsType}) {
|
|
128
|
+
try {
|
|
129
|
+
const result = yield call(Api.getCmsAccounts, cmsType);
|
|
130
|
+
const { cmsAccounts } = result.data?.response || {};
|
|
131
|
+
const isBeeEnabled = cmsAccounts?.type === cmsType;
|
|
132
|
+
yield put({ type: types.GET_CMS_ACCOUNTS_SUCCESS, isBeeEnabled });
|
|
133
|
+
} catch (error) {
|
|
134
|
+
yield put({ type: types.GET_CMS_ACCOUNTS_FAILURE, error });
|
|
135
|
+
}
|
|
136
|
+
}
|
|
137
|
+
|
|
90
138
|
export function* uploadAsset(file, assetType, fileParams) {
|
|
91
139
|
try {
|
|
92
140
|
const result = yield call(Api.uploadFile, file, assetType, fileParams);
|
|
@@ -123,6 +171,10 @@ function* watchGetCmsData() {
|
|
|
123
171
|
yield takeEvery(types.GET_CMS_EDITOR_DATA_REQUEST, getCmsData);
|
|
124
172
|
}
|
|
125
173
|
|
|
174
|
+
function* watchGetCmsAccounts() {
|
|
175
|
+
yield takeEvery(types.GET_CMS_ACCOUNTS_REQUEST, getCmsAccounts);
|
|
176
|
+
}
|
|
177
|
+
|
|
126
178
|
function* watchUploadAsset() {
|
|
127
179
|
yield takeLatest(types.UPLOAD_ASSET_REQUEST, uploadAsset);
|
|
128
180
|
}
|
|
@@ -139,6 +191,7 @@ export default [
|
|
|
139
191
|
watchGetAllAssets,
|
|
140
192
|
watchGetCmsSetting,
|
|
141
193
|
watchGetCmsData,
|
|
194
|
+
watchGetCmsAccounts,
|
|
142
195
|
watchUploadAsset,
|
|
143
196
|
watchDuplicateTemplate,
|
|
144
197
|
];
|
|
@@ -151,6 +204,7 @@ export function* v2EmailSagas() {
|
|
|
151
204
|
watchGetAllAssets(),
|
|
152
205
|
watchGetCmsSetting(),
|
|
153
206
|
watchGetCmsData(),
|
|
207
|
+
watchGetCmsAccounts(),
|
|
154
208
|
watchUploadAsset(),
|
|
155
209
|
]);
|
|
156
210
|
}
|
|
@@ -4,6 +4,7 @@ exports[` 1`] = `
|
|
|
4
4
|
Immutable.Map {
|
|
5
5
|
"createTemplateInProgress": false,
|
|
6
6
|
"createResponse": Immutable.Map {},
|
|
7
|
+
"isBeeEnabled": false,
|
|
7
8
|
}
|
|
8
9
|
`;
|
|
9
10
|
|
|
@@ -11,5 +12,6 @@ exports[` 2`] = `
|
|
|
11
12
|
Immutable.Map {
|
|
12
13
|
"createTemplateInProgress": true,
|
|
13
14
|
"createResponse": Immutable.Map {},
|
|
15
|
+
"isBeeEnabled": false,
|
|
14
16
|
}
|
|
15
17
|
`;
|