@capillarytech/creatives-library 8.0.271 → 8.0.273

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 (153) hide show
  1. package/assets/Android.png +0 -0
  2. package/assets/iOS.png +0 -0
  3. package/constants/unified.js +2 -1
  4. package/initialReducer.js +2 -0
  5. package/package.json +1 -1
  6. package/services/api.js +10 -0
  7. package/services/tests/api.test.js +34 -0
  8. package/tests/integration/TemplateCreation/TemplateCreation.integration.test.js +17 -35
  9. package/tests/integration/TemplateCreation/api-response.js +31 -1
  10. package/tests/integration/TemplateCreation/msw-handler.js +2 -0
  11. package/utils/common.js +5 -0
  12. package/utils/commonUtils.js +28 -5
  13. package/utils/imageUrlUpload.js +13 -14
  14. package/utils/tests/commonUtil.test.js +224 -0
  15. package/utils/tests/imageUrlUpload.test.js +298 -0
  16. package/utils/transformTemplateConfig.js +0 -10
  17. package/v2Components/CapDeviceContent/index.js +61 -56
  18. package/v2Components/CapTagList/index.js +6 -1
  19. package/v2Components/CapTagListWithInput/index.js +5 -1
  20. package/v2Components/CapTagListWithInput/messages.js +1 -1
  21. package/v2Components/CapWhatsappCTA/tests/index.test.js +5 -0
  22. package/v2Components/ErrorInfoNote/constants.js +1 -0
  23. package/v2Components/ErrorInfoNote/index.js +402 -72
  24. package/v2Components/ErrorInfoNote/messages.js +32 -6
  25. package/v2Components/ErrorInfoNote/style.scss +278 -6
  26. package/v2Components/FormBuilder/tests/index.test.js +13 -4
  27. package/v2Components/HtmlEditor/HTMLEditor.js +418 -99
  28. package/v2Components/HtmlEditor/__tests__/HTMLEditor.apiErrors.test.js +870 -0
  29. package/v2Components/HtmlEditor/__tests__/HTMLEditor.test.js +1882 -133
  30. package/v2Components/HtmlEditor/__tests__/index.lazy.test.js +27 -16
  31. package/v2Components/HtmlEditor/_htmlEditor.scss +108 -45
  32. package/v2Components/HtmlEditor/_index.lazy.scss +0 -1
  33. package/v2Components/HtmlEditor/components/CodeEditorPane/_codeEditorPane.scss +23 -102
  34. package/v2Components/HtmlEditor/components/CodeEditorPane/index.js +148 -140
  35. package/v2Components/HtmlEditor/components/DeviceToggle/_deviceToggle.scss +2 -1
  36. package/v2Components/HtmlEditor/components/DeviceToggle/index.js +3 -3
  37. package/v2Components/HtmlEditor/components/EditorToolbar/_editorToolbar.scss +9 -1
  38. package/v2Components/HtmlEditor/components/EditorToolbar/index.js +31 -6
  39. package/v2Components/HtmlEditor/components/FullscreenModal/_fullscreenModal.scss +22 -0
  40. package/v2Components/HtmlEditor/components/InAppPreviewPane/DeviceFrame.js +4 -7
  41. package/v2Components/HtmlEditor/components/InAppPreviewPane/__tests__/DeviceFrame.test.js +35 -45
  42. package/v2Components/HtmlEditor/components/InAppPreviewPane/_inAppPreviewPane.scss +1 -3
  43. package/v2Components/HtmlEditor/components/InAppPreviewPane/constants.js +33 -33
  44. package/v2Components/HtmlEditor/components/InAppPreviewPane/index.js +7 -6
  45. package/v2Components/HtmlEditor/components/PreviewPane/_previewPane.scss +7 -10
  46. package/v2Components/HtmlEditor/components/PreviewPane/index.js +22 -43
  47. package/v2Components/HtmlEditor/components/SplitContainer/_splitContainer.scss +1 -1
  48. package/v2Components/HtmlEditor/components/ValidationErrorDisplay/_validationErrorDisplay.scss +18 -0
  49. package/v2Components/HtmlEditor/components/ValidationErrorDisplay/index.js +36 -31
  50. package/v2Components/HtmlEditor/components/ValidationPanel/_validationPanel.scss +46 -34
  51. package/v2Components/HtmlEditor/components/ValidationPanel/constants.js +6 -0
  52. package/v2Components/HtmlEditor/components/ValidationPanel/index.js +52 -46
  53. package/v2Components/HtmlEditor/components/ValidationTabs/_validationTabs.scss +277 -0
  54. package/v2Components/HtmlEditor/components/ValidationTabs/index.js +295 -0
  55. package/v2Components/HtmlEditor/components/ValidationTabs/messages.js +51 -0
  56. package/v2Components/HtmlEditor/constants.js +45 -20
  57. package/v2Components/HtmlEditor/hooks/__tests__/useInAppContent.test.js +373 -16
  58. package/v2Components/HtmlEditor/hooks/__tests__/useValidation.test.js +351 -16
  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 +213 -56
  62. package/v2Components/HtmlEditor/index.js +1 -1
  63. package/v2Components/HtmlEditor/messages.js +102 -94
  64. package/v2Components/HtmlEditor/utils/__tests__/htmlValidator.enhanced.test.js +214 -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 +158 -124
  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 +38 -0
  72. package/v2Components/MobilePushPreviewV2/constants.js +6 -0
  73. package/v2Components/MobilePushPreviewV2/index.js +33 -7
  74. package/v2Components/TemplatePreview/_templatePreview.scss +55 -24
  75. package/v2Components/TemplatePreview/index.js +47 -32
  76. package/v2Components/TemplatePreview/messages.js +4 -0
  77. package/v2Components/TestAndPreviewSlidebox/_testAndPreviewSlidebox.scss +1 -0
  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/CreativesContainer/SlideBoxContent.js +127 -51
  84. package/v2Containers/CreativesContainer/SlideBoxFooter.js +156 -13
  85. package/v2Containers/CreativesContainer/SlideBoxHeader.js +2 -1
  86. package/v2Containers/CreativesContainer/constants.js +1 -0
  87. package/v2Containers/CreativesContainer/index.js +251 -47
  88. package/v2Containers/CreativesContainer/messages.js +8 -0
  89. package/v2Containers/CreativesContainer/tests/SlideBoxFooter.test.js +11 -2
  90. package/v2Containers/CreativesContainer/tests/__snapshots__/SlideBoxContent.test.js.snap +38 -50
  91. package/v2Containers/CreativesContainer/tests/__snapshots__/index.test.js.snap +103 -0
  92. package/v2Containers/Email/actions.js +7 -0
  93. package/v2Containers/Email/constants.js +5 -1
  94. package/v2Containers/Email/index.js +234 -29
  95. package/v2Containers/Email/messages.js +32 -0
  96. package/v2Containers/Email/reducer.js +12 -1
  97. package/v2Containers/Email/sagas.js +61 -7
  98. package/v2Containers/Email/tests/__snapshots__/reducer.test.js.snap +2 -0
  99. package/v2Containers/Email/tests/reducer.test.js +46 -0
  100. package/v2Containers/Email/tests/sagas.test.js +320 -29
  101. package/v2Containers/EmailWrapper/components/EmailHTMLEditor.js +1246 -0
  102. package/v2Containers/EmailWrapper/components/EmailWrapperView.js +212 -21
  103. package/v2Containers/EmailWrapper/components/HTMLEditorTesting.js +40 -74
  104. package/v2Containers/EmailWrapper/components/__tests__/EmailHTMLEditor.test.js +2614 -0
  105. package/v2Containers/EmailWrapper/components/__tests__/EmailWrapperView.test.js +520 -0
  106. package/v2Containers/EmailWrapper/components/__tests__/HTMLEditorTesting.test.js +2 -67
  107. package/v2Containers/EmailWrapper/constants.js +2 -0
  108. package/v2Containers/EmailWrapper/hooks/useEmailWrapper.js +627 -79
  109. package/v2Containers/EmailWrapper/index.js +103 -23
  110. package/v2Containers/EmailWrapper/messages.js +65 -1
  111. package/v2Containers/EmailWrapper/tests/useEmailWrapper.edgeCases.test.js +955 -0
  112. package/v2Containers/EmailWrapper/tests/useEmailWrapper.test.js +596 -82
  113. package/v2Containers/InApp/__tests__/InAppHTMLEditor.test.js +376 -0
  114. package/v2Containers/InApp/__tests__/sagas.test.js +363 -0
  115. package/v2Containers/InApp/actions.js +7 -0
  116. package/v2Containers/InApp/constants.js +20 -4
  117. package/v2Containers/InApp/index.js +802 -360
  118. package/v2Containers/InApp/index.scss +4 -3
  119. package/v2Containers/InApp/messages.js +7 -3
  120. package/v2Containers/InApp/reducer.js +21 -3
  121. package/v2Containers/InApp/sagas.js +29 -9
  122. package/v2Containers/InApp/selectors.js +25 -5
  123. package/v2Containers/InApp/tests/index.test.js +154 -50
  124. package/v2Containers/InApp/tests/reducer.test.js +34 -0
  125. package/v2Containers/InApp/tests/sagas.test.js +61 -9
  126. package/v2Containers/InApp/tests/selectors.test.js +612 -0
  127. package/v2Containers/InAppWrapper/components/InAppWrapperView.js +151 -0
  128. package/v2Containers/InAppWrapper/components/__tests__/InAppWrapperView.test.js +267 -0
  129. package/v2Containers/InAppWrapper/components/inAppWrapperView.scss +23 -0
  130. package/v2Containers/InAppWrapper/constants.js +16 -0
  131. package/v2Containers/InAppWrapper/hooks/__tests__/useInAppWrapper.test.js +473 -0
  132. package/v2Containers/InAppWrapper/hooks/useInAppWrapper.js +198 -0
  133. package/v2Containers/InAppWrapper/index.js +148 -0
  134. package/v2Containers/InAppWrapper/messages.js +49 -0
  135. package/v2Containers/InappAdvance/index.js +1099 -0
  136. package/v2Containers/InappAdvance/index.scss +10 -0
  137. package/v2Containers/InappAdvance/tests/index.test.js +448 -0
  138. package/v2Containers/Line/Container/ImageCarousel/tests/__snapshots__/content.test.js.snap +3 -0
  139. package/v2Containers/Line/Container/ImageCarousel/tests/__snapshots__/index.test.js.snap +2 -0
  140. package/v2Containers/Line/Container/Wrapper/tests/__snapshots__/index.test.js.snap +2 -0
  141. package/v2Containers/Line/Container/tests/__snapshots__/index.test.js.snap +9 -0
  142. package/v2Containers/MobilePush/Create/index.js +1 -1
  143. package/v2Containers/MobilePush/Edit/index.js +10 -6
  144. package/v2Containers/Rcs/tests/__snapshots__/index.test.js.snap +12 -0
  145. package/v2Containers/SmsTrai/Edit/tests/__snapshots__/index.test.js.snap +4 -0
  146. package/v2Containers/TagList/index.js +62 -19
  147. package/v2Containers/Templates/_templates.scss +60 -1
  148. package/v2Containers/Templates/index.js +89 -4
  149. package/v2Containers/Templates/messages.js +4 -0
  150. package/v2Containers/TemplatesV2/TemplatesV2.style.js +4 -2
  151. package/v2Containers/Whatsapp/tests/__snapshots__/index.test.js.snap +34 -0
  152. package/v2Components/HtmlEditor/components/ValidationErrorDisplay/__tests__/index.test.js +0 -152
  153. package/v2Containers/EmailWrapper/tests/EmailWrapperView.test.js +0 -214
@@ -1,6 +1,8 @@
1
1
  import React from 'react';
2
2
  import PropTypes from 'prop-types';
3
- import { CAP_SPACE_32, CAP_SPACE_56, CAP_SPACE_64 } from '@capillarytech/cap-ui-library/styled/variables';
3
+ import {
4
+ CAP_SPACE_16, CAP_SPACE_32, CAP_SPACE_56, CAP_SPACE_64,
5
+ } from '@capillarytech/cap-ui-library/styled/variables';
4
6
 
5
7
  import CapSlideBox from '@capillarytech/cap-ui-library/CapSlideBox';
6
8
  import CapHeader from '@capillarytech/cap-ui-library/CapHeader';
@@ -44,7 +46,7 @@ import {
44
46
  } from '../Line/Container/constants';
45
47
  import {EXTERNAL_URL, SITE_URL, WEBPUSH_MEDIA_TYPES} from '../WebPush/constants';
46
48
  import { IMAGE, VIDEO } from '../Facebook/Advertisement/constant';
47
- import {RCS_STATUSES} from '../Rcs/constants';
49
+ import { RCS_STATUSES } from '../Rcs/constants';
48
50
  import { CREATIVE } from '../Facebook/constants';
49
51
  import { LOYALTY } from '../App/constants';
50
52
  import {
@@ -65,19 +67,29 @@ import {
65
67
  // getTemplateDiffState
66
68
  } from "../../utils/transformerUtils";
67
69
  import { MANUAL_CAROUSEL } from '../MobilePushNew/constants';
70
+ import { BIG_HTML } from '../InApp/constants';
68
71
 
69
72
  const classPrefix = 'add-creatives-section';
70
73
  const CREATIVES_CONTAINER = 'creativesContainer';
71
74
 
72
75
  const SlideBoxWrapper = styled.div`
73
76
  .cap-slide-box-v2-container{
74
- .slidebox-header, .slidebox-content-container, .slidebox-footer{
77
+ .slidebox-header, .slidebox-content-container{
75
78
  margin-bottom: ${({ slideBoxWrapperMargin }) => `${slideBoxWrapperMargin}`};
76
79
  padding: 0 rem;
77
80
  &.has-footer{
78
81
  overflow-x: hidden;
79
82
  }
80
83
  }
84
+ .slidebox-footer{
85
+ /* Only apply margin-bottom to footer when ErrorInfoNote is shown in footer (BEE editor) */
86
+ /* For HTML Editor, errors are shown in ValidationErrorDisplay (inside content area), so no footer margin needed */
87
+ margin-bottom: ${({ shouldApplyFooterMargin }) => (shouldApplyFooterMargin ? `${CAP_SPACE_16}` : '0')};
88
+ padding: 0 rem;
89
+ &.has-footer{
90
+ overflow-x: hidden;
91
+ }
92
+ }
81
93
  }
82
94
  `;
83
95
  export class Creatives extends React.Component {
@@ -96,6 +108,7 @@ export class Creatives extends React.Component {
96
108
  currentChannel: this.props.channel || 'sms',
97
109
  weChatTemplateType: '',
98
110
  weChatMaptemplateStep: 0,
111
+ inAppEditorType: null,
99
112
  isLiquidValidationError: false,
100
113
  errorMessages: [],
101
114
  liquidErrorMessage: {
@@ -108,6 +121,15 @@ export class Creatives extends React.Component {
108
121
  isTestAndPreviewMode: false, // Add flag to track Test & Preview mode
109
122
  // Performance optimization: Local template name for immediate UI feedback
110
123
  localTemplateName: '',
124
+ // Track selected email create mode for new flow (HTML Editor vs Drag & Drop)
125
+ selectedEmailCreateMode: null,
126
+ // HTML Editor validation state (for email channel)
127
+ htmlEditorValidationState: {
128
+ isContentEmpty: true,
129
+ issueCounts: { errors: 0, warnings: 0, total: 0 },
130
+ validationComplete: false, // Flag to track if validation has completed
131
+ errorsAcknowledged: false, // Flag to track if user has acknowledged errors by clicking redirection icon
132
+ },
111
133
  };
112
134
  this.liquidFlow = Boolean(commonUtil.hasLiquidSupportFeature());
113
135
  this.creativesTemplateSteps = {
@@ -137,7 +159,7 @@ export class Creatives extends React.Component {
137
159
  if (!this.props?.isFullMode) {
138
160
  this.props?.templateActions.getCdnTransformationConfig();
139
161
  }
140
-
162
+
141
163
  // Store loyalty tag props if loyaltyTagFetchingDependencies is provided
142
164
  const { loyaltyTagFetchingDependencies } = this.props;
143
165
  if (loyaltyTagFetchingDependencies) {
@@ -163,9 +185,9 @@ export class Creatives extends React.Component {
163
185
  const isEmptyTemplateName = !value.trim();
164
186
 
165
187
  // 1. IMMEDIATE: Update local state for instant UI feedback
166
- this.setState({
188
+ this.setState({
167
189
  isTemplateNameEmpty: isEmptyTemplateName,
168
- localTemplateName: value
190
+ localTemplateName: value,
169
191
  });
170
192
 
171
193
  // 2. DEBOUNCED: Only debounce the expensive onFormDataChange call
@@ -244,8 +266,19 @@ export class Creatives extends React.Component {
244
266
  onCreateNextStep = () => {
245
267
  this.setState((prevState) => {
246
268
  let templateStep = prevState.templateStep + 1;
247
- const { emailCreateMode, currentChannel } = prevState;
248
- if ((currentChannel.toUpperCase() === constants.EMAIL && emailCreateMode === "upload") || [constants.MOBILE_PUSH, constants.WECHAT, constants.INAPP].includes(currentChannel.toUpperCase())) {
269
+ const { emailCreateMode, currentChannel, selectedEmailCreateMode } = prevState;
270
+
271
+ // Check if we should skip template selection for HTML Editor
272
+ const supportCKEditor = commonUtil.hasSupportCKEditor();
273
+ const shouldSkipTemplateSelection = !supportCKEditor
274
+ && selectedEmailCreateMode === 'html_editor'
275
+ && currentChannel.toUpperCase() === constants.EMAIL
276
+ && prevState.templateStep === 1; // Only skip if we're at modeSelection step
277
+
278
+ if (shouldSkipTemplateSelection) {
279
+ // Skip template selection (step 2), go directly to createTemplateContent (step 3)
280
+ templateStep = prevState.templateStep + 2;
281
+ } else if ((currentChannel.toUpperCase() === constants.EMAIL && emailCreateMode === "upload") || [constants.MOBILE_PUSH, constants.WECHAT, constants.INAPP].includes(currentChannel.toUpperCase())) {
249
282
  templateStep = prevState.templateStep + 2;
250
283
  }
251
284
  return {
@@ -254,14 +287,21 @@ export class Creatives extends React.Component {
254
287
  });
255
288
  }
256
289
 
257
- onEmailModeChange = (mode) => {
258
- this.setState({ emailCreateMode: mode });
290
+ onEmailModeChange = (mode, selectedMode = null) => {
291
+ this.setState({
292
+ emailCreateMode: mode,
293
+ selectedEmailCreateMode: selectedMode || mode, // Store the selected mode for new flow
294
+ });
259
295
  }
260
296
 
261
297
  onInAppModeChange = (mode) => {
262
298
  this.setState({ inAppCreateMode: mode });
263
299
  }
264
300
 
301
+ onInAppEditorTypeChange = (editorType) => {
302
+ this.setState({ inAppEditorType: editorType });
303
+ }
304
+
265
305
  onMobilepushModeChange = (mode) => {
266
306
  this.setState({ mobilePushCreateMode: mode });
267
307
  }
@@ -305,7 +345,7 @@ export class Creatives extends React.Component {
305
345
  }
306
346
  return buttonObj;
307
347
  });
308
- const {url, previewUrl} = media || {};
348
+ const { url, previewUrl } = media || {};
309
349
  return {
310
350
  bodyText: bodyTemplate,
311
351
  varMap: cardVarMapped,
@@ -434,14 +474,35 @@ export class Creatives extends React.Component {
434
474
  }
435
475
  case constants.INAPP: {
436
476
  const mode = get(templateData, 'androidContent.type') || get(templateData, 'iosContent.type') || '';
477
+
478
+ // Check if this is a BEE editor template (identified by special title 'bee free template')
479
+ const isAndroidBeeEditor = templateData?.androidContent?.type === constants.HTML
480
+ && templateData?.androidContent?.title?.toLowerCase() === 'bee free template';
481
+ const isIosBeeEditor = templateData?.iosContent?.type === constants.HTML
482
+ && templateData?.iosContent?.title?.toLowerCase() === 'bee free template';
483
+
437
484
  creativesTemplateData = {
438
485
  type: channel,
439
486
  name: templateData.messageSubject,
440
487
  versions: {
441
488
  base: {
442
489
  content: {
443
- ANDROID: templateData?.androidContent,
444
- IOS: templateData?.iosContent,
490
+ ANDROID: isAndroidBeeEditor ? {
491
+ type: templateData?.androidContent?.type,
492
+ bodyType: templateData?.androidContent?.bodyType,
493
+ deviceType: constants.ANDROID,
494
+ beeHtml: { value: templateData?.androidContent?.message },
495
+ beeJson: templateData?.androidContent?.expandableDetails?.message,
496
+ isBEEeditor: true,
497
+ } : templateData?.androidContent,
498
+ IOS: isIosBeeEditor ? {
499
+ type: templateData?.iosContent?.type,
500
+ bodyType: templateData?.iosContent?.bodyType,
501
+ deviceType: constants.IOS,
502
+ beeHtml: { value: templateData?.iosContent?.message },
503
+ beeJson: templateData?.iosContent?.expandableDetails?.message,
504
+ isBEEeditor: true,
505
+ } : templateData?.iosContent,
445
506
  },
446
507
  },
447
508
  },
@@ -676,7 +737,7 @@ export class Creatives extends React.Component {
676
737
  } = templateData || {};
677
738
  const cardContent = (rcsContent.cardContent && rcsContent.cardContent[0]) || {};
678
739
  const Status = RCS_STATUSES.approved || '';
679
-
740
+
680
741
  creativesTemplateData = {
681
742
  type: channel,
682
743
  edit: true,
@@ -828,7 +889,7 @@ export class Creatives extends React.Component {
828
889
  });
829
890
 
830
891
  getMobilePushCarouselData = (expandableDetails = []) => {
831
- const newExpandableDetails = {...expandableDetails};
892
+ const newExpandableDetails = { ...expandableDetails };
832
893
  newExpandableDetails.style = expandableDetails.style || MANUAL_CAROUSEL;
833
894
  newExpandableDetails.message = expandableDetails.message || '';
834
895
  newExpandableDetails.ctas = expandableDetails.ctas || [];
@@ -923,11 +984,24 @@ export class Creatives extends React.Component {
923
984
  androidContent.custom = custom;
924
985
  }
925
986
  if (channel === constants.MOBILE_PUSH && androidContent?.expandableDetails?.carouselData?.length) {
926
- androidContent.expandableDetails = this.getMobilePushCarouselData({...androidContent?.expandableDetails});
987
+ androidContent.expandableDetails = this.getMobilePushCarouselData({ ...androidContent?.expandableDetails });
988
+ }
989
+ if (androidContent?.isBEEeditor && androidContent?.beeHtml?.value) {
990
+ templateData.androidContent = {};
991
+ templateData.androidContent.type = constants.HTML;
992
+ templateData.androidContent.message = androidContent?.beeHtml?.value || '';
993
+ templateData.androidContent.title = 'bee free template';
994
+ templateData.androidContent.bodyType = androidContent?.bodyType;
995
+ templateData.androidContent.deviceType = constants.ANDROID;
996
+ templateData.androidContent.expandableDetails = {
997
+ style: BIG_HTML,
998
+ message: androidContent?.beeJson || '',
999
+ };
1000
+ } else if (!androidContent?.isBEEeditor) {
1001
+ templateData.androidContent = androidContent;
1002
+ templateData.androidContent.type = androidContent?.type || get(channelTemplate, 'definition.mode', '')?.toUpperCase() || constants.TEXT;
1003
+ templateData.androidContent.deviceType = constants.ANDROID;
927
1004
  }
928
- templateData.androidContent = androidContent;
929
- templateData.androidContent.type = androidContent?.type || get(channelTemplate, 'definition.mode', '')?.toUpperCase() || constants.TEXT;
930
- templateData.androidContent.deviceType = constants.ANDROID;
931
1005
  }
932
1006
  const iosContent = channel === constants.INAPP ? get(channelTemplate, 'versions.base.content.IOS') : get(channelTemplate, 'versions.base.IOS');
933
1007
  if (!isEmpty(iosContent)) {
@@ -945,11 +1019,24 @@ export class Creatives extends React.Component {
945
1019
  iosContent.custom = custom;
946
1020
  }
947
1021
  if (channel === constants.MOBILE_PUSH && iosContent?.expandableDetails?.carouselData?.length) {
948
- iosContent.expandableDetails = this.getMobilePushCarouselData({...iosContent?.expandableDetails});
1022
+ iosContent.expandableDetails = this.getMobilePushCarouselData({ ...iosContent?.expandableDetails });
1023
+ }
1024
+ if (iosContent?.isBEEeditor && iosContent?.beeHtml?.value) {
1025
+ templateData.iosContent = {};
1026
+ templateData.iosContent.type = constants.HTML;
1027
+ templateData.iosContent.message = iosContent?.beeHtml?.value || '';
1028
+ templateData.iosContent.title = 'bee free template';
1029
+ templateData.iosContent.bodyType = iosContent?.bodyType;
1030
+ templateData.iosContent.deviceType = constants.IOS;
1031
+ templateData.iosContent.expandableDetails = {
1032
+ style: BIG_HTML,
1033
+ message: iosContent?.beeJson || '',
1034
+ };
1035
+ } else if (!iosContent?.isBEEeditor) {
1036
+ templateData.iosContent = iosContent;
1037
+ templateData.iosContent.type = iosContent?.type || get(channelTemplate, 'definition.mode', '')?.toUpperCase() || 'TEXT';
1038
+ templateData.iosContent.deviceType = constants.IOS;
949
1039
  }
950
- templateData.iosContent = iosContent;
951
- templateData.iosContent.type = iosContent?.type || get(channelTemplate, 'definition.mode', '')?.toUpperCase() || 'TEXT';
952
- templateData.iosContent.deviceType = constants.IOS;
953
1040
  }
954
1041
  templateData.messageSubject = channelTemplate?.name ? channelTemplate?.name : "messageSubject";
955
1042
  }
@@ -1164,7 +1251,7 @@ export class Creatives extends React.Component {
1164
1251
  contentType = "",
1165
1252
  cardType = "",
1166
1253
  cardSettings = {},
1167
- } = get(versions, 'base.content.RCS.rcsContent',{});
1254
+ } = get(versions, 'base.content.RCS.rcsContent', {});
1168
1255
  const rcsContent = {
1169
1256
  contentType,
1170
1257
  cardType,
@@ -1402,7 +1489,7 @@ export class Creatives extends React.Component {
1402
1489
  processCentralCommsMetaId = (channel, creativesData) => {
1403
1490
  // Create the payload for the centralcommnsmetaId API call
1404
1491
  const { isLoyaltyModule = false, loyaltyMetaData = {} } = this.props;
1405
- const { actionName, setMetaData = () => {} } = loyaltyMetaData;
1492
+ const { actionName, setMetaData = () => { } } = loyaltyMetaData;
1406
1493
 
1407
1494
  // const isTemplateModified = getTemplateDiffState(
1408
1495
  // channel,
@@ -1452,6 +1539,9 @@ export class Creatives extends React.Component {
1452
1539
  if (prevState.currentChannel.toUpperCase() === constants.EMAIL) {
1453
1540
  newState = { ...newState, emailCreateMode: null };
1454
1541
  }
1542
+ if (prevState.currentChannel.toUpperCase() === constants.INAPP) {
1543
+ newState = { ...newState, inAppEditorType: null };
1544
+ }
1455
1545
  return newState;
1456
1546
  });
1457
1547
  }
@@ -1497,7 +1587,7 @@ export class Creatives extends React.Component {
1497
1587
  shouldShowFooter = () => {
1498
1588
  const { isFullMode } = this.props;
1499
1589
  const {
1500
- slidBoxContent, currentChannel, emailCreateMode, templateNameExists, templateStep, mobilePushCreateMode, weChatTemplateType, templateData,
1590
+ slidBoxContent, currentChannel, emailCreateMode, templateNameExists, templateStep, mobilePushCreateMode, weChatTemplateType, templateData, inAppCreateMode,
1501
1591
  } = this.state;
1502
1592
  const channel = currentChannel.toUpperCase();
1503
1593
  const currentStep = this.creativesTemplateSteps[templateStep];
@@ -1505,6 +1595,13 @@ export class Creatives extends React.Component {
1505
1595
  showFooter = isFullMode && slidBoxContent === "preview";
1506
1596
  const isMobilepush = channel === constants.MOBILE_PUSH;
1507
1597
 
1598
+ const supportCKEditor = commonUtil.hasSupportCKEditor();
1599
+ if (!supportCKEditor && channel === constants.EMAIL && currentStep === 'modeSelection' && slidBoxContent === 'createTemplate') {
1600
+ return true;
1601
+ }
1602
+ if (!supportCKEditor && channel === constants.EMAIL && currentStep === 'createTemplateContent' && slidBoxContent === 'createTemplate') {
1603
+ showFooter = true;
1604
+ }
1508
1605
 
1509
1606
  if (!isFullMode) {
1510
1607
  const isEmailCreate = slidBoxContent === 'createTemplate' && channel === constants.EMAIL && currentStep !== 'createTemplateContent';
@@ -1516,7 +1613,12 @@ export class Creatives extends React.Component {
1516
1613
  }
1517
1614
  } else if (channel === constants.EMAIL && isFullMode) {
1518
1615
  const isEmailCreate = slidBoxContent === 'createTemplate' && channel === constants.EMAIL && currentStep !== 'createTemplateContent';
1519
- showFooter = isEmailCreate && emailCreateMode && templateNameExists;
1616
+ // CK editor flow: show footer on mode selection when a card is selected so user sees Continue (disabled until name + card)
1617
+ if (supportCKEditor && slidBoxContent === 'createTemplate' && currentStep === 'modeSelection') {
1618
+ showFooter = !!emailCreateMode;
1619
+ } else {
1620
+ showFooter = isEmailCreate && emailCreateMode && templateNameExists;
1621
+ }
1520
1622
  }
1521
1623
  if (channel === constants.EMAIL && emailCreateMode === "upload") {
1522
1624
  showFooter = showFooter && !this.props.isUploading;
@@ -1540,6 +1642,7 @@ export class Creatives extends React.Component {
1540
1642
  showFooter = true;
1541
1643
  }
1542
1644
 
1645
+
1543
1646
  if (showFooter) {
1544
1647
  if (slidBoxContent === "createTemplate" && ((channel === constants.EMAIL && currentStep === 'createTemplateContent')
1545
1648
  || ([constants.SMS, constants.WECHAT].includes(channel) && currentStep === 'modeSelection'))) {
@@ -1562,7 +1665,7 @@ export class Creatives extends React.Component {
1562
1665
 
1563
1666
  shouldShowDoneFooter = () => {
1564
1667
  const {
1565
- slidBoxContent, templateStep, currentChannel, templateData,
1668
+ slidBoxContent, templateStep, currentChannel, templateData, inAppCreateMode,
1566
1669
  } = this.state;
1567
1670
  const { isFullMode } = this.props;
1568
1671
  const currentStep = this.creativesTemplateSteps[templateStep];
@@ -1570,10 +1673,17 @@ export class Creatives extends React.Component {
1570
1673
  const channelName = !isFullMode && templateData ? templateData.type : currentChannel;
1571
1674
  const channel = channelName?.toUpperCase();
1572
1675
 
1573
-
1676
+ // Check supportCKEditor flag for new HTML editor flow
1677
+ const supportCKEditor = commonUtil.hasSupportCKEditor();
1574
1678
  if (channel === constants.EMAIL || channel === constants.SMS) {
1575
1679
  const isEmailCreate = slidBoxContent === 'createTemplate' && channel === constants.EMAIL && currentStep !== 'createTemplateContent';
1576
- showDone = (slidBoxContent === 'editTemplate' || slidBoxContent === 'createTemplate') && !isEmailCreate;
1680
+
1681
+ // For new HTML editor flow (when supportCKEditor is false), show Done footer when in createTemplateContent step
1682
+ if (!supportCKEditor && channel === constants.EMAIL && slidBoxContent === 'createTemplate' && currentStep === 'createTemplateContent') {
1683
+ showDone = true;
1684
+ } else {
1685
+ showDone = (slidBoxContent === 'editTemplate' || slidBoxContent === 'createTemplate') && !isEmailCreate;
1686
+ }
1577
1687
  } else if ([constants.WECHAT, constants.MOBILE_PUSH].includes(channel)) {
1578
1688
  showDone = currentStep === "createTemplateContent" || slidBoxContent === "editTemplate";
1579
1689
 
@@ -1583,7 +1693,6 @@ export class Creatives extends React.Component {
1583
1693
  }
1584
1694
  }
1585
1695
 
1586
-
1587
1696
  return showDone;
1588
1697
  }
1589
1698
 
@@ -1603,18 +1712,18 @@ export class Creatives extends React.Component {
1603
1712
  templateNameComponentInput = ({ formData, onFormDataChange, name }) => {
1604
1713
  // Use local state for immediate UI feedback, fallback to prop value
1605
1714
  const displayValue = this.state.localTemplateName !== '' ? this.state.localTemplateName : name;
1606
-
1715
+
1607
1716
  return (
1608
1717
  <CapInput
1609
1718
  value={displayValue}
1610
1719
  suffix={<span />}
1611
- onBlur={() => {
1612
- this.setState({
1720
+ onBlur={() => {
1721
+ this.setState({
1613
1722
  isEditName: false,
1614
- localTemplateName: '' // Clear local state on blur
1615
- }, () => {
1616
- this.showTemplateName({ formData, onFormDataChange });
1617
- });
1723
+ localTemplateName: '', // Clear local state on blur
1724
+ }, () => {
1725
+ this.showTemplateName({ formData, onFormDataChange });
1726
+ });
1618
1727
  }}
1619
1728
  onChange={(ev) => {
1620
1729
  const { value } = ev.currentTarget;
@@ -1626,10 +1735,18 @@ export class Creatives extends React.Component {
1626
1735
  }
1627
1736
 
1628
1737
  showTemplateName = ({ formData, onFormDataChange }) => { //gets called from email/index after template data is fetched
1629
- const { slidBoxContent, currentChannel, isEditName } = this.state;
1738
+ const {
1739
+ slidBoxContent, currentChannel, isEditName, templateStep,
1740
+ } = this.state;
1630
1741
  const channel = currentChannel.toUpperCase();
1631
1742
  if ([constants.EMAIL, constants.MOBILE_PUSH, constants.INAPP].includes(channel) && (slidBoxContent === 'editTemplate' || slidBoxContent === 'createTemplate')) {
1632
1743
  const name = get(formData, 'template-name');
1744
+
1745
+ const isModeSelectionStep = templateStep === 'modeSelection' || this.creativesTemplateSteps[templateStep] === 'modeSelection';
1746
+ const isCreateMode = slidBoxContent === 'createTemplate';
1747
+ if (isCreateMode && isModeSelectionStep) {
1748
+ return;
1749
+ }
1633
1750
  if (channel === constants.EMAIL && !name && slidBoxContent === 'createTemplate') {
1634
1751
  this.setState({ isTemplateNameEmpty: true });
1635
1752
  }
@@ -1637,9 +1754,9 @@ export class Creatives extends React.Component {
1637
1754
  if (name && !isEditName) {
1638
1755
  this.setState({ showTemplateNameComponentEdit: false });
1639
1756
  } else if (isEditName) {
1640
- this.setState({
1757
+ this.setState({
1641
1758
  showTemplateNameComponentEdit: true,
1642
- localTemplateName: name || '' // Initialize local state with current value
1759
+ localTemplateName: name || '', // Initialize local state with current value
1643
1760
  });
1644
1761
  }
1645
1762
  }
@@ -1653,15 +1770,31 @@ export class Creatives extends React.Component {
1653
1770
  });
1654
1771
  }
1655
1772
 
1773
+ // Callback to update HTML Editor validation state (called from EmailWrapper)
1774
+ updateHtmlEditorValidationState = (validationState) => {
1775
+ this.setState({
1776
+ htmlEditorValidationState: validationState,
1777
+ });
1778
+ }
1779
+
1656
1780
  shouldShowContinueFooter = () => { // only for email for now, has to be modified according to channel
1657
1781
  const {
1658
- slidBoxContent, templateStep, currentChannel, emailCreateMode, mobilePushCreateMode, inAppCreateMode, weChatTemplateType,
1782
+ slidBoxContent, templateStep, currentChannel, emailCreateMode, mobilePushCreateMode, inAppEditorType, weChatTemplateType,
1659
1783
  } = this.state;
1660
1784
  let isShowContinueFooter = false;
1661
1785
  const currentStep = this.creativesTemplateSteps[templateStep];
1662
1786
  const channel = currentChannel.toUpperCase();
1787
+ // Check if supportCKEditor is false (new flow)
1788
+ const supportCKEditor = commonUtil.hasSupportCKEditor(); // Default to legacy flow
1663
1789
  if (channel === constants.EMAIL || channel === constants.SMS) {
1664
- if ((emailCreateMode === "upload" && !isEmpty(this.props.EmailLayout)) || emailCreateMode === "editor") {
1790
+ // New flow: Show Continue button when supportCKEditor is false and in modeSelection
1791
+ // Always show it (even if disabled) - visibility is separate from enabled state
1792
+ if (!supportCKEditor && currentStep === 'modeSelection' && slidBoxContent === 'createTemplate') {
1793
+ return true; // Return early to ensure visibility
1794
+ }
1795
+
1796
+ // Legacy flow: Original logic (only when supportCKEditor is true)
1797
+ if (supportCKEditor && ((emailCreateMode === "upload" && !isEmpty(this.props.EmailLayout)) || emailCreateMode === "editor")) {
1665
1798
  let isEmailCreate = slidBoxContent === 'createTemplate';
1666
1799
  isEmailCreate = currentChannel.toUpperCase() === constants.EMAIL && ((emailCreateMode === "upload" && currentStep !== 'createTemplateContent') || (emailCreateMode === "editor" && currentStep !== 'createTemplateContent' && currentStep !== "templateSelection"));
1667
1800
  isShowContinueFooter = isEmailCreate && emailCreateMode;
@@ -1670,8 +1803,6 @@ export class Creatives extends React.Component {
1670
1803
  isShowContinueFooter = !isEmpty(mobilePushCreateMode) && currentStep === "modeSelection";
1671
1804
  } else if (currentChannel.toUpperCase() === constants.WECHAT) {
1672
1805
  isShowContinueFooter = !isEmpty(weChatTemplateType) && currentStep === "modeSelection";
1673
- } else if (currentChannel.toUpperCase() === constants.INAPP) {
1674
- isShowContinueFooter = !isEmpty(inAppCreateMode) && currentChannel === "modeSelection";
1675
1806
  }
1676
1807
 
1677
1808
  return isShowContinueFooter;
@@ -1697,6 +1828,34 @@ export class Creatives extends React.Component {
1697
1828
  return true;
1698
1829
  }
1699
1830
 
1831
+ // Check if Continue button should be disabled (for new flow only)
1832
+ isContinueButtonDisabled = () => {
1833
+ const {
1834
+ currentChannel, emailCreateMode, templateNameExists, mobilePushCreateMode, templateStep,
1835
+ } = this.state;
1836
+ const { isFullMode, EmailLayout } = this.props;
1837
+ if (currentChannel.toUpperCase() === constants.EMAIL) {
1838
+ // Upload mode: enable when a file has been uploaded (EmailLayout set by ZIP or HTML upload)
1839
+ // Other modes: enable when an editor type is selected (html_editor, drag_drop, editor)
1840
+ const isUploadComplete = emailCreateMode === 'upload' && !isEmpty(EmailLayout);
1841
+ const isEditorSelected = !!emailCreateMode && emailCreateMode !== 'upload';
1842
+ const canContinue = isUploadComplete || isEditorSelected;
1843
+ // In full mode: require both template name AND (upload complete or editor selected)
1844
+ // In library mode: require only upload complete or editor selection
1845
+ // Same rules for both CK editor and non-CK flows
1846
+ if (isFullMode) {
1847
+ const isTemplateNameValid = templateNameExists;
1848
+ return !(isTemplateNameValid && canContinue);
1849
+ }
1850
+ return !canContinue;
1851
+ }
1852
+ if (currentChannel.toUpperCase() === constants.MOBILE_PUSH) {
1853
+ const currentStep = this.creativesTemplateSteps[templateStep];
1854
+ return !(!isEmpty(mobilePushCreateMode) && currentStep === 'modeSelection');
1855
+ }
1856
+ return false;
1857
+ }
1858
+
1700
1859
  render() {
1701
1860
  const {
1702
1861
  slidBoxContent,
@@ -1705,6 +1864,7 @@ export class Creatives extends React.Component {
1705
1864
  templateData,
1706
1865
  currentChannel,
1707
1866
  emailCreateMode,
1867
+ selectedEmailCreateMode,
1708
1868
  templateStep,
1709
1869
  isLoadingContent,
1710
1870
  mobilePushCreateMode,
@@ -1717,6 +1877,8 @@ export class Creatives extends React.Component {
1717
1877
  activeFormBuilderTab,
1718
1878
  showTestAndPreviewSlidebox,
1719
1879
  isTestAndPreviewMode,
1880
+ inAppEditorType,
1881
+ htmlEditorValidationState,
1720
1882
  } = this.state;
1721
1883
  const {
1722
1884
  isFullMode,
@@ -1739,9 +1901,37 @@ export class Creatives extends React.Component {
1739
1901
  isLoyaltyModule,
1740
1902
  loyaltyMetaData = {},
1741
1903
  } = this.props;
1904
+ // Compute Continue button label: "Continue" for EMAIL (when CK) and MOBILE_PUSH; "Next" for others
1905
+ const supportCKEditor = commonUtil.hasSupportCKEditor();
1906
+ const useContinueLabel = (currentChannel?.toUpperCase() === constants.EMAIL && supportCKEditor)
1907
+ || currentChannel?.toUpperCase() === constants.MOBILE_PUSH;
1908
+ const continueButtonLabel = useContinueLabel ? messages.continue : messages.next;
1909
+
1742
1910
  const mapTemplateCreate = slidBoxContent === "createTemplate"
1743
1911
  && weChatTemplateType === MAP_TEMPLATE
1744
1912
  && templateStep !== "modeSelection";
1913
+
1914
+ // Determine if we're in HTML Editor mode (where errors are shown in ValidationErrorDisplay, not ErrorInfoNote in footer)
1915
+ const isEmailChannel = currentChannel?.toUpperCase() === constants.EMAIL;
1916
+ const isEditMode = slidBoxContent === 'editTemplate';
1917
+ const isHTMLEditorModeInCreate = selectedEmailCreateMode === 'html_editor';
1918
+ const isHTMLEditorModeInEdit = isEditMode && htmlEditorValidationState != null;
1919
+ const isHTMLEditorMode = isEmailChannel && (isHTMLEditorModeInCreate || isHTMLEditorModeInEdit);
1920
+ const isBEEEditor = selectedEmailCreateMode === 'drag_drop'
1921
+ || (emailCreateMode === 'editor' && !isHTMLEditorMode);
1922
+
1923
+ // Check for BEE editor errors (same logic as SlideBoxFooter)
1924
+ const hasStandardErrors = liquidErrorMessage && liquidErrorMessage.STANDARD_ERROR_MSG && liquidErrorMessage.STANDARD_ERROR_MSG.length > 0;
1925
+ const hasLiquidErrors = liquidErrorMessage && liquidErrorMessage.LIQUID_ERROR_MSG && liquidErrorMessage.LIQUID_ERROR_MSG.length > 0;
1926
+ const htmlEditorHasErrors = htmlEditorValidationState && htmlEditorValidationState.issueCounts && htmlEditorValidationState.issueCounts.total > 0;
1927
+ const hasBEEEditorErrors = isEmailChannel && (hasStandardErrors || hasLiquidErrors) && (!htmlEditorValidationState || !htmlEditorHasErrors);
1928
+
1929
+ // Only apply margin to footer when ErrorInfoNote is shown in footer (BEE editor)
1930
+ // For HTML Editor, errors are shown in ValidationErrorDisplay (inside content area), so no footer margin needed
1931
+ // IMPORTANT: Never show ErrorInfoNote in footer when in HTML Editor mode, even if liquidErrorMessage exists
1932
+ const shouldShowErrorInfoNoteInFooter = isHTMLEditorMode ? false : hasBEEEditorErrors;
1933
+
1934
+ // Calculate margin for header/content (always apply if there are errors, regardless of editor type)
1745
1935
  const slideBoxWrapperMargin = (get(liquidErrorMessage, 'STANDARD_ERROR_MSG.length', 0) > 0 && get(liquidErrorMessage, 'LIQUID_ERROR_MSG.length', 0) > 0)
1746
1936
  ? CAP_SPACE_64
1747
1937
  : get(liquidErrorMessage, 'LIQUID_ERROR_MSG.length', 0) > 0
@@ -1751,7 +1941,11 @@ export class Creatives extends React.Component {
1751
1941
  : 0;
1752
1942
  /* TODO: Instead of passing down same props separately to each component down, write common function to these props and pass it accordingly */
1753
1943
  return (
1754
- <SlideBoxWrapper slideBoxWrapperMargin={slideBoxWrapperMargin} className={classnames(`${classPrefix} ${isFullMode ? 'creatives-full-mode' : 'creatives-library-mode'} ${mapTemplateCreate ? 'map-template-create' : ''}`)}>
1944
+ <SlideBoxWrapper
1945
+ slideBoxWrapperMargin={slideBoxWrapperMargin}
1946
+ shouldApplyFooterMargin={shouldShowErrorInfoNoteInFooter}
1947
+ className={classnames(`${classPrefix} ${isFullMode ? 'creatives-full-mode' : 'creatives-library-mode'} ${mapTemplateCreate ? 'map-template-create' : ''}`)}
1948
+ >
1755
1949
  <CapSlideBox
1756
1950
  header={
1757
1951
  this.shouldShowHeader() && (
@@ -1800,6 +1994,8 @@ export class Creatives extends React.Component {
1800
1994
  onChannelChange={this.onChannelChange}
1801
1995
  onEmailModeChange={this.onEmailModeChange}//used when create is clicked in email
1802
1996
  emailCreateMode={emailCreateMode}// upload zip || use editor are values
1997
+ onInAppEditorTypeChange={this.onInAppEditorTypeChange}//used when create is clicked in inapp
1998
+ inAppEditorType={inAppEditorType}// htmlEditor || dragDropEditor are values
1803
1999
  templateStep={this.creativesTemplateSteps[templateStep]}
1804
2000
  onCreateNextStep={this.onCreateNextStep}
1805
2001
  onEnterTemplateName={this.onEnterTemplateName}
@@ -1809,6 +2005,8 @@ export class Creatives extends React.Component {
1809
2005
  cap={cap}
1810
2006
  setIsLoadingContent={this.setIsLoadingContent}
1811
2007
  onMobilepushModeChange={this.onMobilepushModeChange}
2008
+ inAppCreateMode={this.state.inAppCreateMode}
2009
+ onInAppModeChange={this.onInAppModeChange}
1812
2010
  mobilePushCreateMode={mobilePushCreateMode}
1813
2011
  showTemplateName={this.showTemplateName}
1814
2012
  onValidationFail={this.onValidationFail}
@@ -1847,6 +2045,7 @@ export class Creatives extends React.Component {
1847
2045
  handleTestAndPreview={this.handleTestAndPreview}
1848
2046
  handleCloseTestAndPreview={this.handleCloseTestAndPreview}
1849
2047
  isTestAndPreviewMode={(() => this.state.isTestAndPreviewMode)()}
2048
+ onHtmlEditorValidationStateChange={this.updateHtmlEditorValidationState}
1850
2049
  />
1851
2050
  )}
1852
2051
  footer={this.shouldShowFooter() ? (
@@ -1861,6 +2060,7 @@ export class Creatives extends React.Component {
1861
2060
  currentChannel={currentChannel.toUpperCase()}
1862
2061
  templateStep={this.creativesTemplateSteps[templateStep]}
1863
2062
  emailCreateMode={emailCreateMode}
2063
+ selectedEmailCreateMode={selectedEmailCreateMode}
1864
2064
  shouldShowContinueFooter={this.shouldShowContinueFooter}
1865
2065
  shouldShowDoneFooter={this.shouldShowDoneFooter}
1866
2066
  fetchingCmsData={fetchingCmsData}
@@ -1869,18 +2069,22 @@ export class Creatives extends React.Component {
1869
2069
  errorMessages={liquidErrorMessage}
1870
2070
  currentTab={activeFormBuilderTab}
1871
2071
  onTestAndPreview={this.handleTestAndPreview}
2072
+ isContinueButtonDisabled={this.isContinueButtonDisabled()}
2073
+ continueButtonLabel={continueButtonLabel}
1872
2074
  showTestAndPreviewButton={(() => {
1873
2075
  const isEmailOrSmsOrWhatsappOrRcsOrInAppOrMobilePush = [constants.EMAIL, constants.SMS, constants.WHATSAPP, constants.RCS, constants.INAPP, constants.MOBILE_PUSH, constants.VIBER, constants.ZALO].includes(currentChannel.toUpperCase());
1874
2076
  const showButton = isEmailOrSmsOrWhatsappOrRcsOrInAppOrMobilePush && (slidBoxContent === 'editTemplate' || slidBoxContent === 'createTemplate');
1875
2077
  return showButton;
1876
2078
  })()}
2079
+ htmlEditorValidationState={htmlEditorValidationState}
2080
+ isCreatingTemplate={slidBoxContent === 'createTemplate' && currentChannel.toUpperCase() === constants.EMAIL}
1877
2081
  />
1878
2082
  ) : isLiquidValidationError && (
1879
2083
  <CapRow className="template-footer-width">
1880
2084
  {(() => {
1881
2085
  const errorsToShow = get(liquidErrorMessage, constants.LIQUID_ERROR_MSG, []);
1882
2086
  const standardErrorsToShow = get(liquidErrorMessage, constants.STANDARD_ERROR_MSG, []);
1883
- return <ErrorInfoNote currentTab={activeFormBuilderTab?.toUpperCase()} errorMessages={{LIQUID_ERROR_MSG: errorsToShow, STANDARD_ERROR_MSG: standardErrorsToShow}} />;
2087
+ return <ErrorInfoNote currentTab={activeFormBuilderTab?.toUpperCase()} errorMessages={{ LIQUID_ERROR_MSG: errorsToShow, STANDARD_ERROR_MSG: standardErrorsToShow }} />;
1884
2088
  })()}
1885
2089
  </CapRow>
1886
2090
  )}
@@ -282,6 +282,10 @@ export default defineMessages({
282
282
  id: `${scope}.creativesTemplatesUpdate`,
283
283
  defaultMessage: `Update`,
284
284
  },
285
+ "creativesTemplatesDone": {
286
+ id: `${scope}.creativesTemplatesDone`,
287
+ defaultMessage: `Done`,
288
+ },
285
289
  "creativesTemplatesDiscard": {
286
290
  id: `${scope}.creativesTemplatesDiscard`,
287
291
  defaultMessage: `Discard`,
@@ -370,4 +374,8 @@ export default defineMessages({
370
374
  id: `${scope}.testAndPreview`,
371
375
  defaultMessage: `Preview and Test`,
372
376
  },
377
+ "next": {
378
+ id: `${scope}.next`,
379
+ defaultMessage: `Next`,
380
+ },
373
381
  });