@capillarytech/creatives-library 8.0.250 → 8.0.252

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.
Files changed (276) hide show
  1. package/assets/Android.png +0 -0
  2. package/assets/iOS.png +0 -0
  3. package/constants/unified.js +2 -2
  4. package/initialReducer.js +2 -0
  5. package/package.json +1 -1
  6. package/services/api.js +10 -5
  7. package/services/tests/api.test.js +34 -0
  8. package/translations/en.json +3 -4
  9. package/utils/common.js +5 -6
  10. package/utils/commonUtils.js +28 -5
  11. package/utils/tests/commonUtil.test.js +224 -0
  12. package/utils/tests/transformerUtils.test.js +0 -297
  13. package/utils/transformTemplateConfig.js +0 -10
  14. package/utils/transformerUtils.js +0 -40
  15. package/v2Components/CapDeviceContent/index.js +61 -56
  16. package/v2Components/CapImageUpload/constants.js +0 -2
  17. package/v2Components/CapImageUpload/index.js +16 -65
  18. package/v2Components/CapImageUpload/index.scss +1 -4
  19. package/v2Components/CapImageUpload/messages.js +1 -5
  20. package/v2Components/CapTagList/index.js +6 -1
  21. package/v2Components/CapTagListWithInput/index.js +5 -1
  22. package/v2Components/CapTagListWithInput/messages.js +1 -1
  23. package/v2Components/CapWhatsappCTA/tests/index.test.js +5 -0
  24. package/v2Components/ErrorInfoNote/index.js +455 -72
  25. package/v2Components/ErrorInfoNote/messages.js +36 -6
  26. package/v2Components/ErrorInfoNote/style.scss +280 -4
  27. package/v2Components/FormBuilder/tests/index.test.js +13 -4
  28. package/v2Components/HtmlEditor/HTMLEditor.js +547 -94
  29. package/v2Components/HtmlEditor/__tests__/HTMLEditor.apiErrors.test.js +874 -0
  30. package/v2Components/HtmlEditor/__tests__/HTMLEditor.test.js +1358 -133
  31. package/v2Components/HtmlEditor/__tests__/index.lazy.test.js +27 -16
  32. package/v2Components/HtmlEditor/_htmlEditor.scss +108 -45
  33. package/v2Components/HtmlEditor/_index.lazy.scss +1 -1
  34. package/v2Components/HtmlEditor/components/CodeEditorPane/_codeEditorPane.scss +22 -101
  35. package/v2Components/HtmlEditor/components/CodeEditorPane/index.js +146 -140
  36. package/v2Components/HtmlEditor/components/DeviceToggle/_deviceToggle.scss +2 -1
  37. package/v2Components/HtmlEditor/components/DeviceToggle/index.js +3 -3
  38. package/v2Components/HtmlEditor/components/EditorToolbar/_editorToolbar.scss +9 -0
  39. package/v2Components/HtmlEditor/components/EditorToolbar/index.js +1 -1
  40. package/v2Components/HtmlEditor/components/FullscreenModal/_fullscreenModal.scss +22 -0
  41. package/v2Components/HtmlEditor/components/InAppPreviewPane/DeviceFrame.js +4 -7
  42. package/v2Components/HtmlEditor/components/InAppPreviewPane/__tests__/DeviceFrame.test.js +35 -45
  43. package/v2Components/HtmlEditor/components/InAppPreviewPane/_inAppPreviewPane.scss +1 -3
  44. package/v2Components/HtmlEditor/components/InAppPreviewPane/constants.js +33 -33
  45. package/v2Components/HtmlEditor/components/InAppPreviewPane/index.js +7 -6
  46. package/v2Components/HtmlEditor/components/PreviewPane/_previewPane.scss +3 -6
  47. package/v2Components/HtmlEditor/components/PreviewPane/index.js +24 -34
  48. package/v2Components/HtmlEditor/components/SplitContainer/_splitContainer.scss +1 -1
  49. package/v2Components/HtmlEditor/components/ValidationErrorDisplay/index.js +49 -31
  50. package/v2Components/HtmlEditor/components/ValidationPanel/_validationPanel.scss +50 -34
  51. package/v2Components/HtmlEditor/components/ValidationPanel/constants.js +6 -0
  52. package/v2Components/HtmlEditor/components/ValidationPanel/index.js +70 -41
  53. package/v2Components/HtmlEditor/components/ValidationTabs/_validationTabs.scss +254 -0
  54. package/v2Components/HtmlEditor/components/ValidationTabs/index.js +364 -0
  55. package/v2Components/HtmlEditor/components/ValidationTabs/messages.js +51 -0
  56. package/v2Components/HtmlEditor/constants.js +42 -20
  57. package/v2Components/HtmlEditor/hooks/__tests__/useInAppContent.test.js +373 -16
  58. package/v2Components/HtmlEditor/hooks/__tests__/useValidation.apiErrors.test.js +795 -0
  59. package/v2Components/HtmlEditor/hooks/useEditorContent.js +5 -2
  60. package/v2Components/HtmlEditor/hooks/useInAppContent.js +88 -146
  61. package/v2Components/HtmlEditor/hooks/useValidation.js +189 -53
  62. package/v2Components/HtmlEditor/index.js +1 -1
  63. package/v2Components/HtmlEditor/messages.js +95 -85
  64. package/v2Components/HtmlEditor/utils/__tests__/htmlValidator.enhanced.test.js +94 -45
  65. package/v2Components/HtmlEditor/utils/__tests__/validationAdapter.test.js +134 -0
  66. package/v2Components/HtmlEditor/utils/contentSanitizer.js +40 -41
  67. package/v2Components/HtmlEditor/utils/htmlValidator.js +71 -72
  68. package/v2Components/HtmlEditor/utils/liquidTemplateSupport.js +134 -102
  69. package/v2Components/HtmlEditor/utils/properSyntaxHighlighting.js +23 -25
  70. package/v2Components/HtmlEditor/utils/validationAdapter.js +66 -41
  71. package/v2Components/HtmlEditor/utils/validationConstants.js +40 -0
  72. package/v2Components/MobilePushPreviewV2/index.js +32 -7
  73. package/v2Components/TemplatePreview/_templatePreview.scss +55 -24
  74. package/v2Components/TemplatePreview/index.js +47 -32
  75. package/v2Components/TemplatePreview/messages.js +4 -0
  76. package/v2Components/TestAndPreviewSlidebox/_testAndPreviewSlidebox.scss +1 -0
  77. package/v2Containers/App/constants.js +0 -5
  78. package/v2Containers/BeeEditor/index.js +172 -90
  79. package/v2Containers/BeePopupEditor/_beePopupEditor.scss +14 -0
  80. package/v2Containers/BeePopupEditor/constants.js +10 -0
  81. package/v2Containers/BeePopupEditor/index.js +194 -0
  82. package/v2Containers/BeePopupEditor/tests/index.test.js +627 -0
  83. package/v2Containers/Cap/tests/__snapshots__/index.test.js.snap +3 -4
  84. package/v2Containers/CreativesContainer/SlideBoxContent.js +129 -107
  85. package/v2Containers/CreativesContainer/SlideBoxFooter.js +163 -13
  86. package/v2Containers/CreativesContainer/SlideBoxHeader.js +2 -2
  87. package/v2Containers/CreativesContainer/constants.js +1 -3
  88. package/v2Containers/CreativesContainer/index.js +239 -214
  89. package/v2Containers/CreativesContainer/messages.js +8 -4
  90. package/v2Containers/CreativesContainer/tests/SlideBoxContent.test.js +0 -210
  91. package/v2Containers/CreativesContainer/tests/SlideBoxFooter.test.js +11 -2
  92. package/v2Containers/CreativesContainer/tests/__snapshots__/SlideBoxContent.test.js.snap +38 -354
  93. package/v2Containers/CreativesContainer/tests/__snapshots__/index.test.js.snap +106 -0
  94. package/v2Containers/Email/actions.js +7 -0
  95. package/v2Containers/Email/constants.js +5 -1
  96. package/v2Containers/Email/index.js +241 -32
  97. package/v2Containers/Email/messages.js +32 -0
  98. package/v2Containers/Email/reducer.js +12 -1
  99. package/v2Containers/Email/sagas.js +61 -7
  100. package/v2Containers/Email/tests/__snapshots__/reducer.test.js.snap +2 -0
  101. package/v2Containers/Email/tests/reducer.test.js +46 -0
  102. package/v2Containers/Email/tests/sagas.test.js +320 -29
  103. package/v2Containers/EmailWrapper/components/EmailHTMLEditor.js +1285 -0
  104. package/v2Containers/EmailWrapper/components/EmailWrapperView.js +207 -19
  105. package/v2Containers/EmailWrapper/components/HTMLEditorTesting.js +40 -74
  106. package/v2Containers/EmailWrapper/components/__tests__/EmailHTMLEditor.test.js +1870 -0
  107. package/v2Containers/EmailWrapper/components/__tests__/EmailWrapperView.test.js +520 -0
  108. package/v2Containers/EmailWrapper/components/__tests__/HTMLEditorTesting.test.js +2 -67
  109. package/v2Containers/EmailWrapper/constants.js +2 -0
  110. package/v2Containers/EmailWrapper/hooks/useEmailWrapper.js +629 -77
  111. package/v2Containers/EmailWrapper/index.js +103 -23
  112. package/v2Containers/EmailWrapper/messages.js +61 -1
  113. package/v2Containers/EmailWrapper/tests/useEmailWrapper.edgeCases.test.js +643 -0
  114. package/v2Containers/EmailWrapper/tests/useEmailWrapper.test.js +594 -77
  115. package/v2Containers/InApp/__tests__/InAppHTMLEditor.test.js +376 -0
  116. package/v2Containers/InApp/__tests__/sagas.test.js +363 -0
  117. package/v2Containers/InApp/actions.js +7 -0
  118. package/v2Containers/InApp/constants.js +20 -4
  119. package/v2Containers/InApp/index.js +802 -359
  120. package/v2Containers/InApp/index.scss +4 -3
  121. package/v2Containers/InApp/messages.js +7 -3
  122. package/v2Containers/InApp/reducer.js +21 -3
  123. package/v2Containers/InApp/sagas.js +29 -9
  124. package/v2Containers/InApp/selectors.js +25 -5
  125. package/v2Containers/InApp/tests/index.test.js +154 -50
  126. package/v2Containers/InApp/tests/reducer.test.js +34 -0
  127. package/v2Containers/InApp/tests/sagas.test.js +61 -9
  128. package/v2Containers/InApp/tests/selectors.test.js +612 -0
  129. package/v2Containers/InAppWrapper/components/InAppWrapperView.js +151 -0
  130. package/v2Containers/InAppWrapper/components/__tests__/InAppWrapperView.test.js +267 -0
  131. package/v2Containers/InAppWrapper/components/inAppWrapperView.scss +23 -0
  132. package/v2Containers/InAppWrapper/constants.js +16 -0
  133. package/v2Containers/InAppWrapper/hooks/__tests__/useInAppWrapper.test.js +473 -0
  134. package/v2Containers/InAppWrapper/hooks/useInAppWrapper.js +198 -0
  135. package/v2Containers/InAppWrapper/index.js +148 -0
  136. package/v2Containers/InAppWrapper/messages.js +49 -0
  137. package/v2Containers/InappAdvance/index.js +1099 -0
  138. package/v2Containers/InappAdvance/index.scss +10 -0
  139. package/v2Containers/InappAdvance/tests/index.test.js +448 -0
  140. package/v2Containers/Line/Container/ImageCarousel/tests/__snapshots__/content.test.js.snap +12 -12
  141. package/v2Containers/Line/Container/ImageCarousel/tests/__snapshots__/index.test.js.snap +8 -8
  142. package/v2Containers/Line/Container/Wrapper/tests/__snapshots__/index.test.js.snap +77 -100
  143. package/v2Containers/Line/Container/tests/__snapshots__/index.test.js.snap +63 -72
  144. package/v2Containers/Rcs/tests/__snapshots__/index.test.js.snap +186 -232
  145. package/v2Containers/SmsTrai/Create/tests/__snapshots__/index.test.js.snap +12 -16
  146. package/v2Containers/SmsTrai/Edit/tests/__snapshots__/index.test.js.snap +40 -48
  147. package/v2Containers/TagList/index.js +62 -19
  148. package/v2Containers/Templates/ChannelTypeIllustration.js +1 -13
  149. package/v2Containers/Templates/_templates.scss +56 -202
  150. package/v2Containers/Templates/actions.js +1 -2
  151. package/v2Containers/Templates/constants.js +0 -1
  152. package/v2Containers/Templates/index.js +123 -278
  153. package/v2Containers/Templates/messages.js +4 -24
  154. package/v2Containers/Templates/reducer.js +0 -4
  155. package/v2Containers/Templates/tests/index.test.js +0 -10
  156. package/v2Containers/TemplatesV2/index.js +7 -15
  157. package/v2Containers/TemplatesV2/messages.js +0 -4
  158. package/v2Containers/Whatsapp/tests/__snapshots__/index.test.js.snap +520 -648
  159. package/utils/imageUrlUpload.js +0 -141
  160. package/v2Components/CapImageUrlUpload/constants.js +0 -26
  161. package/v2Components/CapImageUrlUpload/index.js +0 -365
  162. package/v2Components/CapImageUrlUpload/index.scss +0 -35
  163. package/v2Components/CapImageUrlUpload/messages.js +0 -47
  164. package/v2Components/HtmlEditor/components/ValidationErrorDisplay/__tests__/index.test.js +0 -152
  165. package/v2Containers/EmailWrapper/tests/EmailWrapperView.test.js +0 -214
  166. package/v2Containers/WebPush/Create/components/BrandIconSection.js +0 -108
  167. package/v2Containers/WebPush/Create/components/ButtonForm.js +0 -172
  168. package/v2Containers/WebPush/Create/components/ButtonItem.js +0 -101
  169. package/v2Containers/WebPush/Create/components/ButtonList.js +0 -107
  170. package/v2Containers/WebPush/Create/components/ButtonsLinksSection.js +0 -160
  171. package/v2Containers/WebPush/Create/components/ButtonsLinksSection.test.js +0 -476
  172. package/v2Containers/WebPush/Create/components/FormActions.js +0 -54
  173. package/v2Containers/WebPush/Create/components/FormActions.test.js +0 -163
  174. package/v2Containers/WebPush/Create/components/MediaSection.js +0 -143
  175. package/v2Containers/WebPush/Create/components/MediaSection.test.js +0 -341
  176. package/v2Containers/WebPush/Create/components/MessageSection.js +0 -103
  177. package/v2Containers/WebPush/Create/components/MessageSection.test.js +0 -268
  178. package/v2Containers/WebPush/Create/components/NotificationTitleSection.js +0 -87
  179. package/v2Containers/WebPush/Create/components/NotificationTitleSection.test.js +0 -210
  180. package/v2Containers/WebPush/Create/components/TemplateNameSection.js +0 -54
  181. package/v2Containers/WebPush/Create/components/TemplateNameSection.test.js +0 -143
  182. package/v2Containers/WebPush/Create/components/__snapshots__/ButtonsLinksSection.test.js.snap +0 -82
  183. package/v2Containers/WebPush/Create/components/__snapshots__/FormActions.test.js.snap +0 -16
  184. package/v2Containers/WebPush/Create/components/__snapshots__/MediaSection.test.js.snap +0 -41
  185. package/v2Containers/WebPush/Create/components/__snapshots__/MessageSection.test.js.snap +0 -54
  186. package/v2Containers/WebPush/Create/components/__snapshots__/NotificationTitleSection.test.js.snap +0 -37
  187. package/v2Containers/WebPush/Create/components/__snapshots__/TemplateNameSection.test.js.snap +0 -21
  188. package/v2Containers/WebPush/Create/components/_buttons.scss +0 -246
  189. package/v2Containers/WebPush/Create/components/tests/ButtonForm.test.js +0 -554
  190. package/v2Containers/WebPush/Create/components/tests/ButtonItem.test.js +0 -607
  191. package/v2Containers/WebPush/Create/components/tests/ButtonList.test.js +0 -515
  192. package/v2Containers/WebPush/Create/components/tests/__snapshots__/ButtonForm.test.js.snap +0 -666
  193. package/v2Containers/WebPush/Create/components/tests/__snapshots__/ButtonItem.test.js.snap +0 -74
  194. package/v2Containers/WebPush/Create/components/tests/__snapshots__/ButtonList.test.js.snap +0 -46
  195. package/v2Containers/WebPush/Create/hooks/useButtonManagement.js +0 -150
  196. package/v2Containers/WebPush/Create/hooks/useButtonManagement.test.js +0 -406
  197. package/v2Containers/WebPush/Create/hooks/useCharacterCount.js +0 -30
  198. package/v2Containers/WebPush/Create/hooks/useCharacterCount.test.js +0 -151
  199. package/v2Containers/WebPush/Create/hooks/useImageUpload.js +0 -104
  200. package/v2Containers/WebPush/Create/hooks/useImageUpload.test.js +0 -538
  201. package/v2Containers/WebPush/Create/hooks/useTagManagement.js +0 -122
  202. package/v2Containers/WebPush/Create/hooks/useTagManagement.test.js +0 -633
  203. package/v2Containers/WebPush/Create/index.js +0 -1148
  204. package/v2Containers/WebPush/Create/index.scss +0 -134
  205. package/v2Containers/WebPush/Create/messages.js +0 -203
  206. package/v2Containers/WebPush/Create/preview/DevicePreviewContent.js +0 -228
  207. package/v2Containers/WebPush/Create/preview/NotificationContainer.js +0 -294
  208. package/v2Containers/WebPush/Create/preview/PreviewContent.js +0 -90
  209. package/v2Containers/WebPush/Create/preview/PreviewControls.js +0 -305
  210. package/v2Containers/WebPush/Create/preview/PreviewDisclaimer.js +0 -23
  211. package/v2Containers/WebPush/Create/preview/WebPushPreview.js +0 -155
  212. package/v2Containers/WebPush/Create/preview/assets/Light.svg +0 -53
  213. package/v2Containers/WebPush/Create/preview/assets/Top.svg +0 -5
  214. package/v2Containers/WebPush/Create/preview/assets/android-arrow-down.svg +0 -9
  215. package/v2Containers/WebPush/Create/preview/assets/android-arrow-up.svg +0 -9
  216. package/v2Containers/WebPush/Create/preview/assets/chrome-icon.png +0 -0
  217. package/v2Containers/WebPush/Create/preview/assets/edge-icon.png +0 -0
  218. package/v2Containers/WebPush/Create/preview/assets/firefox-icon.svg +0 -106
  219. package/v2Containers/WebPush/Create/preview/assets/iOS.svg +0 -26
  220. package/v2Containers/WebPush/Create/preview/assets/macos-arrow-down-icon.svg +0 -9
  221. package/v2Containers/WebPush/Create/preview/assets/macos-triple-dot-icon.svg +0 -9
  222. package/v2Containers/WebPush/Create/preview/assets/opera-icon.svg +0 -18
  223. package/v2Containers/WebPush/Create/preview/assets/safari-icon.svg +0 -29
  224. package/v2Containers/WebPush/Create/preview/assets/windows-close-icon.svg +0 -9
  225. package/v2Containers/WebPush/Create/preview/assets/windows-triple-dot-icon.svg +0 -9
  226. package/v2Containers/WebPush/Create/preview/components/AndroidMobileChromeHeader.js +0 -47
  227. package/v2Containers/WebPush/Create/preview/components/AndroidMobileExpanded.js +0 -141
  228. package/v2Containers/WebPush/Create/preview/components/IOSHeader.js +0 -45
  229. package/v2Containers/WebPush/Create/preview/components/NotificationExpandedContent.js +0 -68
  230. package/v2Containers/WebPush/Create/preview/components/NotificationHeader.js +0 -61
  231. package/v2Containers/WebPush/Create/preview/components/WindowsChromeExpanded.js +0 -99
  232. package/v2Containers/WebPush/Create/preview/components/tests/AndroidMobileExpanded.test.js +0 -733
  233. package/v2Containers/WebPush/Create/preview/components/tests/WindowsChromeExpanded.test.js +0 -571
  234. package/v2Containers/WebPush/Create/preview/components/tests/__snapshots__/AndroidMobileExpanded.test.js.snap +0 -81
  235. package/v2Containers/WebPush/Create/preview/components/tests/__snapshots__/WindowsChromeExpanded.test.js.snap +0 -81
  236. package/v2Containers/WebPush/Create/preview/config/notificationMappings.js +0 -50
  237. package/v2Containers/WebPush/Create/preview/constants.js +0 -637
  238. package/v2Containers/WebPush/Create/preview/notification-container.scss +0 -79
  239. package/v2Containers/WebPush/Create/preview/preview.scss +0 -351
  240. package/v2Containers/WebPush/Create/preview/styles/_android-mobile-chrome.scss +0 -370
  241. package/v2Containers/WebPush/Create/preview/styles/_android-mobile-edge.scss +0 -12
  242. package/v2Containers/WebPush/Create/preview/styles/_android-mobile-firefox.scss +0 -12
  243. package/v2Containers/WebPush/Create/preview/styles/_android-mobile-opera.scss +0 -12
  244. package/v2Containers/WebPush/Create/preview/styles/_android-tablet-chrome.scss +0 -47
  245. package/v2Containers/WebPush/Create/preview/styles/_android-tablet-edge.scss +0 -11
  246. package/v2Containers/WebPush/Create/preview/styles/_android-tablet-firefox.scss +0 -11
  247. package/v2Containers/WebPush/Create/preview/styles/_android-tablet-opera.scss +0 -11
  248. package/v2Containers/WebPush/Create/preview/styles/_base.scss +0 -207
  249. package/v2Containers/WebPush/Create/preview/styles/_ios.scss +0 -153
  250. package/v2Containers/WebPush/Create/preview/styles/_ipados.scss +0 -107
  251. package/v2Containers/WebPush/Create/preview/styles/_macos-chrome.scss +0 -101
  252. package/v2Containers/WebPush/Create/preview/styles/_windows-chrome.scss +0 -229
  253. package/v2Containers/WebPush/Create/preview/tests/DevicePreviewContent.test.js +0 -909
  254. package/v2Containers/WebPush/Create/preview/tests/NotificationContainer.test.js +0 -1081
  255. package/v2Containers/WebPush/Create/preview/tests/PreviewControls.test.js +0 -723
  256. package/v2Containers/WebPush/Create/preview/tests/WebPushPreview.test.js +0 -1327
  257. package/v2Containers/WebPush/Create/preview/tests/__snapshots__/DevicePreviewContent.test.js.snap +0 -131
  258. package/v2Containers/WebPush/Create/preview/tests/__snapshots__/NotificationContainer.test.js.snap +0 -112
  259. package/v2Containers/WebPush/Create/preview/tests/__snapshots__/PreviewControls.test.js.snap +0 -144
  260. package/v2Containers/WebPush/Create/preview/tests/__snapshots__/WebPushPreview.test.js.snap +0 -129
  261. package/v2Containers/WebPush/Create/utils/payloadBuilder.js +0 -96
  262. package/v2Containers/WebPush/Create/utils/payloadBuilder.test.js +0 -396
  263. package/v2Containers/WebPush/Create/utils/previewUtils.js +0 -89
  264. package/v2Containers/WebPush/Create/utils/urlValidation.js +0 -115
  265. package/v2Containers/WebPush/Create/utils/urlValidation.test.js +0 -449
  266. package/v2Containers/WebPush/Create/utils/validation.js +0 -75
  267. package/v2Containers/WebPush/Create/utils/validation.test.js +0 -283
  268. package/v2Containers/WebPush/actions.js +0 -60
  269. package/v2Containers/WebPush/constants.js +0 -132
  270. package/v2Containers/WebPush/index.js +0 -2
  271. package/v2Containers/WebPush/reducer.js +0 -104
  272. package/v2Containers/WebPush/sagas.js +0 -119
  273. package/v2Containers/WebPush/selectors.js +0 -65
  274. package/v2Containers/WebPush/tests/reducer.test.js +0 -863
  275. package/v2Containers/WebPush/tests/sagas.test.js +0 -566
  276. package/v2Containers/WebPush/tests/selectors.test.js +0 -960
@@ -62,6 +62,7 @@ export class Email extends React.Component { // eslint-disable-line react/prefer
62
62
  isEdit: false,
63
63
  schema: {},
64
64
  loading: false,
65
+ isFormValid: true,
65
66
  injectedTags: {},
66
67
  checkValidation: false,
67
68
  saveEdmDataMode: 'save',
@@ -207,13 +208,31 @@ export class Email extends React.Component { // eslint-disable-line react/prefer
207
208
  const isBEESupport = (this.props.location.query.isBEESupport !== "false") || false;
208
209
  const isBEEAppEnable = this.checkBeeEditorAllowedForLibrary();
209
210
  if (!_.isEmpty(this.props.Templates.BEETemplate)) {
210
- if (this.props.Templates.BEETemplate.versions.base.is_drag_drop && isBEEAppEnable ) {
211
+ const isDragDrop = this.props.Templates.BEETemplate.versions?.base?.is_drag_drop;
212
+
213
+ if (isDragDrop && isBEEAppEnable ) {
211
214
  this.setState({isDragDrop: true});
212
215
  }
213
216
  if (this.props.params.id) {
214
- this.props.actions.getCmsSetting(BEE_PLUGIN, _.get(this.props.Templates.BEETemplate, 'versions.base.drag_drop_id', this.props.Templates.BEETemplate?._id), 'open', undefined, isBEESupport, isBEEAppEnable);
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);
215
226
  } else if (this.props.location.query.module !== "library" || (this.props.location.query.module === "library" && !this.props.templateData)) {
216
- this.props.actions.getCmsSetting(BEE_PLUGIN, _.get(this.props.Templates.BEETemplate, 'versions.base.drag_drop_id', this.props.Templates.BEETemplate?._id), 'create', undefined, isBEESupport, isBEEAppEnable);
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);
217
236
  }
218
237
  }
219
238
  this.setState({ content: (this.props.Templates.selectedEmailLayout ? this.props.Templates.selectedEmailLayout : ''), formData});
@@ -236,11 +255,52 @@ export class Email extends React.Component { // eslint-disable-line react/prefer
236
255
  if (this.props.location.query.type === 'embedded') {
237
256
  this.showNext();
238
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
+ }
239
289
  }
240
290
 
241
291
 
242
- checkBeeEditorAllowedForLibrary = () => {
243
- const { isFullMode = false, editor } = this.props || {};
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
244
304
  if ((editor === "BEE" && !isFullMode) || isFullMode) {
245
305
  return true;
246
306
  }
@@ -341,9 +401,61 @@ export class Email extends React.Component { // eslint-disable-line react/prefer
341
401
  // this.props.globalActions.fetchSchemaForEntity(query);
342
402
  // }
343
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
+
344
450
  if (this.state.isEdit && !this.state.editDataSet && !_.isEmpty(nextProps.Email.templateDetails) && !_.isEmpty(this.state.schema)) {
345
451
  this.setState({editDataSet: true}, () => {
346
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
+ }
347
459
  });
348
460
  }
349
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']`))) {
@@ -382,7 +494,7 @@ export class Email extends React.Component { // eslint-disable-line react/prefer
382
494
  const formData = _.cloneDeep(this.state.formData);
383
495
 
384
496
  const schema = _.cloneDeep(this.state.schema);
385
- const langIndex = formData[this.state.currentTab - 1].selectedLanguages.indexOf(langId);
497
+ const langIndex = formData[this.state.currentTab - 1]?.selectedLanguages?.indexOf(langId);
386
498
 
387
499
  const temp = (schema.containers || {})[this.state.currentTab - 1];
388
500
 
@@ -390,32 +502,91 @@ export class Email extends React.Component { // eslint-disable-line react/prefer
390
502
  if (nextProps.Email.CmsSettings.isDragDrop && this.checkBeeEditorAllowedForLibrary()) {
391
503
  const beeJson = `BEEeditor${currentTab > 1 ? currentTab : ''}json`;
392
504
  const beeToken = `BEEeditor${currentTab > 1 ? currentTab : ''}token`;
393
- let beeJsonValue = _.get(nextProps, 'Templates.BEETemplate.versions.base.json-content', '');
505
+ let beeJsonValue = '';
394
506
  const selectedId = _.get(this.props, 'Email.templateDetails._id', '') || _.get(this.props, 'Templates.BEETemplate.versions.base.drag_drop_id', '');
395
- if (this.state.isEdit) {
396
- if (this.props.location.query.module === "library") {
397
- beeJsonValue = _.get(this.state, `formData[${currentTab - 1}][${langId}].json-content`, '');
398
- } else {
399
- beeJsonValue = _.get(nextProps, `Email.templateDetails.versions.base[${langId}].json-content`, '');
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
+ }
543
+ }
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);
400
553
  }
401
554
  }
555
+
556
+ // Preserve existing formData values, especially template-subject
557
+ const existingFormData = formData[`${currentTab - 1}`][langId] || {};
402
558
  formData[`${currentTab - 1}`][langId] = {
403
- ...formData[`${currentTab - 1}`][langId],
559
+ ...existingFormData,
404
560
  is_drag_drop: true,
405
- [beeJson]: beeJsonValue,
561
+ [beeJson]: finalBeeJsonValue,
406
562
  [beeToken]: nextProps.Email.CmsSettings.tokenData,
407
563
  id: selectedId,
564
+ // Also store json-content for reference
565
+ 'json-content': finalBeeJsonValue,
408
566
  };
409
- _.forEach(temp.panes, (pane, index) => {
410
- const tempPane = pane;
411
- //
412
- if (parseInt(index, 10) === parseInt(langIndex, 10)) {
413
- //
414
- tempPane.sections[0].inputFields[0].cols[1].colStyle = {display: ""};
415
- 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;
416
573
  }
417
- });
418
- this.setState({schema, isSchemaChanged: true, loadingStatus: this.state.loadingStatus + 1});
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});
419
590
  } else {
420
591
  _.forEach(temp.panes, (pane, index) => {
421
592
  const tempPane = pane;
@@ -712,8 +883,18 @@ export class Email extends React.Component { // eslint-disable-line react/prefer
712
883
  const msgString = JSON.stringify(msg);
713
884
  const langId = formData[this.state.currentTab - 1].activeTab;
714
885
  const langIndex = formData[this.state.currentTab - 1].selectedLanguages.indexOf(langId);
715
- const win = document.getElementById(`edmeditor${(langIndex + 1) > 1 ? (langIndex + 1) : ''}`).contentWindow;
716
- win.postMessage(msgString, '*');
886
+ const elementToSelect = document.getElementById(`edmeditor${(langIndex + 1) > 1 ? (langIndex + 1) : ''}`);
887
+ if (elementToSelect) {
888
+ try {
889
+ const win = elementToSelect.contentWindow;
890
+ if (win) {
891
+ win.postMessage(msgString, '*');
892
+ }
893
+ } catch (error) {
894
+ // Handle cross-origin frame access errors
895
+ console.warn('Failed to access iframe contentWindow (cross-origin restriction):', error);
896
+ }
897
+ }
717
898
  } else if (data === "unsubscribe" && this.state.editorInstanse) {
718
899
  const anchor = `<a href='{{${data}}}'>${data}</a>`;
719
900
  this.state.editorInstanse.insertHtml(`${anchor}`);
@@ -888,12 +1069,19 @@ export class Email extends React.Component { // eslint-disable-line react/prefer
888
1069
  return '';
889
1070
  }
890
1071
 
891
- setFormValidity = () => {}
1072
+ setFormValidity = (isFormValid) => {
1073
+ this.setState({isFormValid});
1074
+ }
892
1075
 
893
1076
  setEditData(editData) {
894
1077
  const isBEESupport = (this.props.location.query.isBEESupport !== "false") || false;
895
1078
  const formData = _.cloneDeep(this.state.formData);
896
1079
 
1080
+ // Set template name from editData if available
1081
+ if (editData.name) {
1082
+ formData['template-name'] = editData.name;
1083
+ }
1084
+
897
1085
  const schema = (this.props.location.query.type === 'embedded') ? this.removeStandAlone(this.state.schema) : _.cloneDeep(this.state.schema);
898
1086
  const containers = _.cloneDeep(schema.containers.slice());
899
1087
  let tabKey = "";
@@ -902,7 +1090,8 @@ export class Email extends React.Component { // eslint-disable-line react/prefer
902
1090
  const type = this.props.location.query.type;
903
1091
 
904
1092
  formData['template-name'] = editData.name;
905
- formData['template-subject'] = _.get(editData, 'versions.base.subject');
1093
+ const subject = _.get(editData, 'versions.base.subject', '');
1094
+ formData['template-subject'] = subject;
906
1095
  formData.base = editData.versions.base;
907
1096
 
908
1097
  _.forEach(editData.versions.history, (data1, index) => {
@@ -983,8 +1172,13 @@ export class Email extends React.Component { // eslint-disable-line react/prefer
983
1172
 
984
1173
 
985
1174
  this.setState({ formData, schema, tabKey, currentTab, tabCount: editData.versions.history.length, loadingStatus: this.state.loadingStatus + 1 }, () => {
986
- if (this.props.isFullMode) {
987
- this.props.showTemplateName({formData, onFormDataChange: this.onFormDataChange});
1175
+ if (this.props.isFullMode && this.props.showTemplateName) {
1176
+ // Ensure template name is set before showing it
1177
+ const updatedFormData = _.cloneDeep(formData);
1178
+ if (editData.name && !updatedFormData['template-name']) {
1179
+ updatedFormData['template-name'] = editData.name;
1180
+ }
1181
+ this.props.showTemplateName({formData: updatedFormData, onFormDataChange: this.onFormDataChange});
988
1182
  }
989
1183
  const isBEEAppEnable = this.checkBeeEditorAllowedForLibrary();
990
1184
  _.forEach((editData.versions.base.selectedLanguages), (language) => {
@@ -1115,6 +1309,7 @@ export class Email extends React.Component { // eslint-disable-line react/prefer
1115
1309
  isEdit: false,
1116
1310
  schema: {},
1117
1311
  loading: false,
1312
+ isFormValid: true,
1118
1313
  injectedTags: {},
1119
1314
  checkValidation: false,
1120
1315
  tabKey: '',
@@ -2456,14 +2651,14 @@ export class Email extends React.Component { // eslint-disable-line react/prefer
2456
2651
  }
2457
2652
 
2458
2653
  saveFormData = (passedData) => {
2654
+ //saveFormData gets called only when validation result is true
2459
2655
  if (this.state.gettingFormData && !this.props.isFullMode) {
2460
2656
  const response = {
2461
2657
  action: "getFormData",
2462
2658
  postAction: this.state.getFormDataValue || 'next',
2463
2659
  id: _.get(this.props, 'Email.templateDetails._id', ''),
2464
2660
  value: this.transformFormData(passedData),
2465
- //saveFormData gets called only when validation result is true
2466
- validity: true,
2661
+ validity: this.state.isFormValid,
2467
2662
  type: 'EMAIL',
2468
2663
  };
2469
2664
 
@@ -2659,6 +2854,7 @@ export class Email extends React.Component { // eslint-disable-line react/prefer
2659
2854
  getTemplateDetailsInProgress,
2660
2855
  assetUploading,
2661
2856
  createTemplateInProgress,
2857
+ fetchingCmsSettings,
2662
2858
  } = this.props.Email;
2663
2859
  let isLoading =
2664
2860
  isLoadingMetaEntities ||
@@ -2667,7 +2863,7 @@ export class Email extends React.Component { // eslint-disable-line react/prefer
2667
2863
  ) || (
2668
2864
  assetUploading !== undefined && assetUploading
2669
2865
  ) || (
2670
- Email && (fetchingCmsData || getTemplateDetailsInProgress)
2866
+ Email && (fetchingCmsData || getTemplateDetailsInProgress || fetchingCmsSettings)
2671
2867
  );
2672
2868
 
2673
2869
  if (!isLoading) {
@@ -2989,6 +3185,19 @@ function mapDispatchToProps(dispatch) {
2989
3185
  const withReducer = injectReducer({ key: 'email', reducer: v2EmailReducer });
2990
3186
  const withEmailSaga = injectSaga({ key: 'email', saga: v2EmailSagas });
2991
3187
 
3188
+ // Base Email component without saga registration (for use from EmailWrapper)
3189
+ // EmailWrapper already registers the saga, so we don't need to register it here
3190
+ export const EmailWithoutSaga = withCreatives({
3191
+ WrappedComponent: Email,
3192
+ mapStateToProps,
3193
+ mapDispatchToProps,
3194
+ userAuth: true,
3195
+ sagas: [], // No saga - EmailWrapper registers it
3196
+ reducers: [withReducer],
3197
+ });
3198
+
3199
+ // Email component with saga registration (for direct use from SlideBoxContent in Edit mode)
3200
+ // When Email is used directly (not as child of EmailWrapper), it needs to register the saga
2992
3201
  export default withCreatives({
2993
3202
  WrappedComponent: Email,
2994
3203
  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 (!result.success || result.status.code === 500) {
13
- errorMsg = result.message;
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({ type: types.CREATE_TEMPLATE_SUCCESS, data: result.response, statusCode: result.status ? result.status.code : '', errorMsg });
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
- let { id, channel, callback } = payload;
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({ type: types.DUPLICATE_TEMPLATE_SUCCESS, data: result?.response, statusCode: result?.status?.code, errorMsg });
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({cmsType, projectId, cmsMode, langId, isEdmSupport, isBEEAppEnable}) {
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
  `;