@capillarytech/creatives-library 8.0.271 → 8.0.272

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 (149) 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/tests/commonUtil.test.js +224 -0
  14. package/utils/transformTemplateConfig.js +0 -10
  15. package/v2Components/CapDeviceContent/index.js +61 -56
  16. package/v2Components/CapTagList/index.js +6 -1
  17. package/v2Components/CapTagListWithInput/index.js +5 -1
  18. package/v2Components/CapTagListWithInput/messages.js +1 -1
  19. package/v2Components/CapWhatsappCTA/tests/index.test.js +5 -0
  20. package/v2Components/ErrorInfoNote/constants.js +1 -0
  21. package/v2Components/ErrorInfoNote/index.js +402 -72
  22. package/v2Components/ErrorInfoNote/messages.js +32 -6
  23. package/v2Components/ErrorInfoNote/style.scss +278 -6
  24. package/v2Components/FormBuilder/tests/index.test.js +13 -4
  25. package/v2Components/HtmlEditor/HTMLEditor.js +418 -99
  26. package/v2Components/HtmlEditor/__tests__/HTMLEditor.apiErrors.test.js +870 -0
  27. package/v2Components/HtmlEditor/__tests__/HTMLEditor.test.js +1882 -133
  28. package/v2Components/HtmlEditor/__tests__/index.lazy.test.js +27 -16
  29. package/v2Components/HtmlEditor/_htmlEditor.scss +108 -45
  30. package/v2Components/HtmlEditor/_index.lazy.scss +0 -1
  31. package/v2Components/HtmlEditor/components/CodeEditorPane/_codeEditorPane.scss +23 -102
  32. package/v2Components/HtmlEditor/components/CodeEditorPane/index.js +148 -140
  33. package/v2Components/HtmlEditor/components/DeviceToggle/_deviceToggle.scss +2 -1
  34. package/v2Components/HtmlEditor/components/DeviceToggle/index.js +3 -3
  35. package/v2Components/HtmlEditor/components/EditorToolbar/_editorToolbar.scss +9 -1
  36. package/v2Components/HtmlEditor/components/EditorToolbar/index.js +31 -6
  37. package/v2Components/HtmlEditor/components/FullscreenModal/_fullscreenModal.scss +22 -0
  38. package/v2Components/HtmlEditor/components/InAppPreviewPane/DeviceFrame.js +4 -7
  39. package/v2Components/HtmlEditor/components/InAppPreviewPane/__tests__/DeviceFrame.test.js +35 -45
  40. package/v2Components/HtmlEditor/components/InAppPreviewPane/_inAppPreviewPane.scss +1 -3
  41. package/v2Components/HtmlEditor/components/InAppPreviewPane/constants.js +33 -33
  42. package/v2Components/HtmlEditor/components/InAppPreviewPane/index.js +7 -6
  43. package/v2Components/HtmlEditor/components/PreviewPane/_previewPane.scss +7 -10
  44. package/v2Components/HtmlEditor/components/PreviewPane/index.js +22 -43
  45. package/v2Components/HtmlEditor/components/SplitContainer/_splitContainer.scss +1 -1
  46. package/v2Components/HtmlEditor/components/ValidationErrorDisplay/_validationErrorDisplay.scss +18 -0
  47. package/v2Components/HtmlEditor/components/ValidationErrorDisplay/index.js +36 -31
  48. package/v2Components/HtmlEditor/components/ValidationPanel/_validationPanel.scss +46 -34
  49. package/v2Components/HtmlEditor/components/ValidationPanel/constants.js +6 -0
  50. package/v2Components/HtmlEditor/components/ValidationPanel/index.js +52 -46
  51. package/v2Components/HtmlEditor/components/ValidationTabs/_validationTabs.scss +277 -0
  52. package/v2Components/HtmlEditor/components/ValidationTabs/index.js +295 -0
  53. package/v2Components/HtmlEditor/components/ValidationTabs/messages.js +51 -0
  54. package/v2Components/HtmlEditor/constants.js +45 -20
  55. package/v2Components/HtmlEditor/hooks/__tests__/useInAppContent.test.js +373 -16
  56. package/v2Components/HtmlEditor/hooks/__tests__/useValidation.test.js +351 -16
  57. package/v2Components/HtmlEditor/hooks/useEditorContent.js +5 -2
  58. package/v2Components/HtmlEditor/hooks/useInAppContent.js +88 -146
  59. package/v2Components/HtmlEditor/hooks/useValidation.js +213 -56
  60. package/v2Components/HtmlEditor/index.js +1 -1
  61. package/v2Components/HtmlEditor/messages.js +102 -94
  62. package/v2Components/HtmlEditor/utils/__tests__/htmlValidator.enhanced.test.js +214 -45
  63. package/v2Components/HtmlEditor/utils/__tests__/validationAdapter.test.js +134 -0
  64. package/v2Components/HtmlEditor/utils/contentSanitizer.js +40 -41
  65. package/v2Components/HtmlEditor/utils/htmlValidator.js +71 -72
  66. package/v2Components/HtmlEditor/utils/liquidTemplateSupport.js +158 -124
  67. package/v2Components/HtmlEditor/utils/properSyntaxHighlighting.js +23 -25
  68. package/v2Components/HtmlEditor/utils/validationAdapter.js +66 -41
  69. package/v2Components/HtmlEditor/utils/validationConstants.js +38 -0
  70. package/v2Components/MobilePushPreviewV2/constants.js +6 -0
  71. package/v2Components/MobilePushPreviewV2/index.js +33 -7
  72. package/v2Components/TemplatePreview/_templatePreview.scss +55 -24
  73. package/v2Components/TemplatePreview/index.js +47 -32
  74. package/v2Components/TemplatePreview/messages.js +4 -0
  75. package/v2Components/TestAndPreviewSlidebox/_testAndPreviewSlidebox.scss +1 -0
  76. package/v2Containers/BeeEditor/index.js +172 -90
  77. package/v2Containers/BeePopupEditor/_beePopupEditor.scss +14 -0
  78. package/v2Containers/BeePopupEditor/constants.js +10 -0
  79. package/v2Containers/BeePopupEditor/index.js +194 -0
  80. package/v2Containers/BeePopupEditor/tests/index.test.js +627 -0
  81. package/v2Containers/CreativesContainer/SlideBoxContent.js +127 -51
  82. package/v2Containers/CreativesContainer/SlideBoxFooter.js +156 -13
  83. package/v2Containers/CreativesContainer/SlideBoxHeader.js +2 -1
  84. package/v2Containers/CreativesContainer/constants.js +1 -0
  85. package/v2Containers/CreativesContainer/index.js +251 -47
  86. package/v2Containers/CreativesContainer/messages.js +8 -0
  87. package/v2Containers/CreativesContainer/tests/SlideBoxFooter.test.js +11 -2
  88. package/v2Containers/CreativesContainer/tests/__snapshots__/SlideBoxContent.test.js.snap +38 -50
  89. package/v2Containers/CreativesContainer/tests/__snapshots__/index.test.js.snap +103 -0
  90. package/v2Containers/Email/actions.js +7 -0
  91. package/v2Containers/Email/constants.js +5 -1
  92. package/v2Containers/Email/index.js +234 -29
  93. package/v2Containers/Email/messages.js +32 -0
  94. package/v2Containers/Email/reducer.js +12 -1
  95. package/v2Containers/Email/sagas.js +61 -7
  96. package/v2Containers/Email/tests/__snapshots__/reducer.test.js.snap +2 -0
  97. package/v2Containers/Email/tests/reducer.test.js +46 -0
  98. package/v2Containers/Email/tests/sagas.test.js +320 -29
  99. package/v2Containers/EmailWrapper/components/EmailHTMLEditor.js +1246 -0
  100. package/v2Containers/EmailWrapper/components/EmailWrapperView.js +212 -21
  101. package/v2Containers/EmailWrapper/components/HTMLEditorTesting.js +40 -74
  102. package/v2Containers/EmailWrapper/components/__tests__/EmailHTMLEditor.test.js +2472 -0
  103. package/v2Containers/EmailWrapper/components/__tests__/EmailWrapperView.test.js +520 -0
  104. package/v2Containers/EmailWrapper/components/__tests__/HTMLEditorTesting.test.js +2 -67
  105. package/v2Containers/EmailWrapper/constants.js +2 -0
  106. package/v2Containers/EmailWrapper/hooks/useEmailWrapper.js +627 -79
  107. package/v2Containers/EmailWrapper/index.js +103 -23
  108. package/v2Containers/EmailWrapper/messages.js +65 -1
  109. package/v2Containers/EmailWrapper/tests/useEmailWrapper.edgeCases.test.js +955 -0
  110. package/v2Containers/EmailWrapper/tests/useEmailWrapper.test.js +596 -82
  111. package/v2Containers/InApp/__tests__/InAppHTMLEditor.test.js +376 -0
  112. package/v2Containers/InApp/__tests__/sagas.test.js +363 -0
  113. package/v2Containers/InApp/actions.js +7 -0
  114. package/v2Containers/InApp/constants.js +20 -4
  115. package/v2Containers/InApp/index.js +802 -360
  116. package/v2Containers/InApp/index.scss +4 -3
  117. package/v2Containers/InApp/messages.js +7 -3
  118. package/v2Containers/InApp/reducer.js +21 -3
  119. package/v2Containers/InApp/sagas.js +29 -9
  120. package/v2Containers/InApp/selectors.js +25 -5
  121. package/v2Containers/InApp/tests/index.test.js +154 -50
  122. package/v2Containers/InApp/tests/reducer.test.js +34 -0
  123. package/v2Containers/InApp/tests/sagas.test.js +61 -9
  124. package/v2Containers/InApp/tests/selectors.test.js +612 -0
  125. package/v2Containers/InAppWrapper/components/InAppWrapperView.js +151 -0
  126. package/v2Containers/InAppWrapper/components/__tests__/InAppWrapperView.test.js +267 -0
  127. package/v2Containers/InAppWrapper/components/inAppWrapperView.scss +23 -0
  128. package/v2Containers/InAppWrapper/constants.js +16 -0
  129. package/v2Containers/InAppWrapper/hooks/__tests__/useInAppWrapper.test.js +473 -0
  130. package/v2Containers/InAppWrapper/hooks/useInAppWrapper.js +198 -0
  131. package/v2Containers/InAppWrapper/index.js +148 -0
  132. package/v2Containers/InAppWrapper/messages.js +49 -0
  133. package/v2Containers/InappAdvance/index.js +1099 -0
  134. package/v2Containers/InappAdvance/index.scss +10 -0
  135. package/v2Containers/InappAdvance/tests/index.test.js +448 -0
  136. package/v2Containers/Line/Container/ImageCarousel/tests/__snapshots__/content.test.js.snap +3 -0
  137. package/v2Containers/Line/Container/ImageCarousel/tests/__snapshots__/index.test.js.snap +2 -0
  138. package/v2Containers/Line/Container/Wrapper/tests/__snapshots__/index.test.js.snap +2 -0
  139. package/v2Containers/Line/Container/tests/__snapshots__/index.test.js.snap +9 -0
  140. package/v2Containers/Rcs/tests/__snapshots__/index.test.js.snap +12 -0
  141. package/v2Containers/SmsTrai/Edit/tests/__snapshots__/index.test.js.snap +4 -0
  142. package/v2Containers/TagList/index.js +62 -19
  143. package/v2Containers/Templates/_templates.scss +60 -1
  144. package/v2Containers/Templates/index.js +89 -4
  145. package/v2Containers/Templates/messages.js +4 -0
  146. package/v2Containers/TemplatesV2/TemplatesV2.style.js +4 -2
  147. package/v2Containers/Whatsapp/tests/__snapshots__/index.test.js.snap +34 -0
  148. package/v2Components/HtmlEditor/components/ValidationErrorDisplay/__tests__/index.test.js +0 -152
  149. package/v2Containers/EmailWrapper/tests/EmailWrapperView.test.js +0 -214
@@ -10,6 +10,7 @@ import SmsWrapper from '../SmsWrapper';
10
10
  import Email from '../Email';
11
11
  import EmailWrapper from '../EmailWrapper';
12
12
  import MobilepushWrapper from '../MobilepushWrapper';
13
+ import InAppWrapper from '../InAppWrapper';
13
14
  import EmailPreviewV2 from '../../v2Components/EmailPreviewV2';
14
15
  import MobilePushPreview from '../../v2Components/MobilePushPreviewV2';
15
16
  import WechatWrapper from '../WeChat/Wrapper';
@@ -119,7 +120,11 @@ export function SlideBoxContent(props) {
119
120
  emailCreateMode,
120
121
  onMobilepushModeChange,
121
122
  mobilePushCreateMode,
123
+ onInAppEditorTypeChange,
124
+ inAppEditorType,
122
125
  templateStep,
126
+ inAppCreateMode,
127
+ onInAppModeChange,
123
128
  onEnterTemplateName,
124
129
  onRemoveTemplateName,
125
130
  onCreateNextStep,
@@ -169,6 +174,7 @@ export function SlideBoxContent(props) {
169
174
  handleTestAndPreview,
170
175
  handleCloseTestAndPreview,
171
176
  isTestAndPreviewMode,
177
+ onHtmlEditorValidationStateChange,
172
178
  } = props;
173
179
  const type = (messageDetails.type || '').toLowerCase(); // type is context in get tags values : outbound | dvs | referral | loyalty | coupons
174
180
  const query = { type: !isFullMode && 'embedded', module: isFullMode ? 'default' : 'library', isEditFromCampaigns: (templateData || {}).isEditFromCampaigns};
@@ -668,44 +674,95 @@ export function SlideBoxContent(props) {
668
674
  handleTestAndPreview={handleTestAndPreview}
669
675
  handleCloseTestAndPreview={handleCloseTestAndPreview}
670
676
  isTestAndPreviewMode={isTestAndPreviewMode}
677
+ location={location}
678
+ onHtmlEditorValidationStateChange={onHtmlEditorValidationStateChange}
671
679
  />
672
680
  )}
673
681
  {(isEditEmailWithId || isEmailEditWithContent) && (
674
- <Email
675
- key="cretives-container-email-edit"
676
- setIsLoadingContent={setIsLoadingContent}
677
- location={{
678
- pathname: `/email/edit`,
679
- query: { type: 'embedded', module: 'library'},
680
- }}
681
- route={{ name: 'email' }}
682
- isGetFormData={isGetFormData}
683
- getFormdata={getFormData}
684
- params={{ id: templateData._id }}
685
- templateData={templateData}
686
- getFormSubscriptionData={getFormData}
687
- getDefaultTags={type}
688
- isFullMode={isFullMode}
689
- editor={editor}
690
- cap={cap}
691
- showTemplateName={showTemplateName}
692
- onValidationFail={onValidationFail}
693
- forwardedTags={forwardedTags}
694
- selectedOfferDetails={selectedOfferDetails}
695
- onPreviewContentClicked={onPreviewContentClicked}
696
- onTestContentClicked={onTestContentClicked}
697
- moduleType={moduleType}
698
- showLiquidErrorInFooter={showLiquidErrorInFooter}
699
- eventContextTags={eventContextTags}
700
- isLoyaltyModule={isLoyaltyModule}
701
- showTestAndPreviewSlidebox={showTestAndPreviewSlidebox}
702
- handleTestAndPreview={handleTestAndPreview}
703
- handleCloseTestAndPreview={handleCloseTestAndPreview}
704
- isTestAndPreviewMode={(() => {
705
- return isTestAndPreviewMode;
706
- })()}
707
- />
708
- )}
682
+ (() => {
683
+ const supportCKEditor = commonUtil.hasSupportCKEditor();
684
+ // When supportCKEditor is true: Always use Email component (legacy flow)
685
+ if (supportCKEditor || templateData?.is_drag_drop) {
686
+ return (
687
+ <Email
688
+ key="cretives-container-email-edit"
689
+ setIsLoadingContent={setIsLoadingContent}
690
+ location={{
691
+ pathname: `/email/edit`,
692
+ query: { type: 'embedded', module: 'library'},
693
+ }}
694
+ route={{ name: 'email' }}
695
+ isGetFormData={isGetFormData}
696
+ getFormdata={getFormData}
697
+ params={{ id: templateData._id }}
698
+ templateData={templateData}
699
+ getFormSubscriptionData={getFormData}
700
+ getDefaultTags={type}
701
+ isFullMode={isFullMode}
702
+ editor={editor}
703
+ cap={cap}
704
+ showTemplateName={showTemplateName}
705
+ onValidationFail={onValidationFail}
706
+ forwardedTags={forwardedTags}
707
+ selectedOfferDetails={selectedOfferDetails}
708
+ onPreviewContentClicked={onPreviewContentClicked}
709
+ onTestContentClicked={onTestContentClicked}
710
+ moduleType={moduleType}
711
+ showLiquidErrorInFooter={showLiquidErrorInFooter}
712
+ eventContextTags={eventContextTags}
713
+ isLoyaltyModule={isLoyaltyModule}
714
+ showTestAndPreviewSlidebox={showTestAndPreviewSlidebox}
715
+ handleTestAndPreview={handleTestAndPreview}
716
+ handleCloseTestAndPreview={handleCloseTestAndPreview}
717
+ isTestAndPreviewMode={isTestAndPreviewMode}
718
+ onHtmlEditorValidationStateChange={onHtmlEditorValidationStateChange}
719
+ />
720
+ );
721
+ }
722
+ // HTML template: Use EmailWrapper component (which uses EmailWithoutSaga)
723
+ return (
724
+ <EmailWrapper
725
+ key="cretives-container-email-edit-wrapper"
726
+ setIsLoadingContent={setIsLoadingContent}
727
+ onEmailModeChange={onEmailModeChange}
728
+ emailCreateMode="editor"
729
+ isGetFormData={isGetFormData}
730
+ getFormdata={getFormData}
731
+ templateData={templateData}
732
+ type={type}
733
+ step="createTemplateContent"
734
+ showNextStep={onCreateNextStep}
735
+ isFullMode={isFullMode}
736
+ editor={editor}
737
+ cap={cap}
738
+ onResetStep={onResetStep}
739
+ showTemplateName={showTemplateName}
740
+ onEnterTemplateName={onEnterTemplateName}
741
+ onRemoveTemplateName={onRemoveTemplateName}
742
+ onValidationFail={onValidationFail}
743
+ forwardedTags={forwardedTags}
744
+ selectedOfferDetails={selectedOfferDetails}
745
+ onPreviewContentClicked={onPreviewContentClicked}
746
+ onTestContentClicked={onTestContentClicked}
747
+ getCmsTemplatesInProgress={getCmsTemplatesInProgress}
748
+ moduleType={moduleType}
749
+ showLiquidErrorInFooter={showLiquidErrorInFooter}
750
+ eventContextTags={eventContextTags}
751
+ isLoyaltyModule={isLoyaltyModule}
752
+ showTestAndPreviewSlidebox={showTestAndPreviewSlidebox}
753
+ handleTestAndPreview={handleTestAndPreview}
754
+ handleCloseTestAndPreview={handleCloseTestAndPreview}
755
+ isTestAndPreviewMode={isTestAndPreviewMode}
756
+ onHtmlEditorValidationStateChange={onHtmlEditorValidationStateChange}
757
+ location={{
758
+ pathname: `/email/edit/${templateData._id}`,
759
+ query: { type: 'embedded', module: 'library', id: templateData._id },
760
+ }}
761
+ params={{ id: templateData._id }}
762
+ />
763
+ );
764
+ })()
765
+ )}
709
766
  {isEditMPush && (
710
767
  (isFullMode && !commonUtil.hasNewMobilePushFeatureEnabled()) ||
711
768
  (!isFullMode && isLoyaltyModule) ||
@@ -999,22 +1056,39 @@ export function SlideBoxContent(props) {
999
1056
  />
1000
1057
  )}
1001
1058
 
1002
- {isCreateInApp && (<InApp
1003
- isFullMode={isFullMode}
1004
- onCreateComplete={onCreateComplete}
1005
- handleClose={handleClose}
1006
- location={{
1007
- pathname: `/inapp/create`,
1008
- query,
1009
- search: '',
1010
- }}
1011
- getFormData={getFormData}
1012
- isGetFormData={isGetFormData}
1013
- templateData={templateData}
1014
- getDefaultTags={type}
1015
- eventContextTags={eventContextTags}
1016
- showLiquidErrorInFooter={showLiquidErrorInFooter}
1017
- showTestAndPreviewSlidebox={showTestAndPreviewSlidebox}
1059
+ {isCreateInApp && (
1060
+ <InAppWrapper
1061
+ key="creatives-inapp-wrapper"
1062
+ date={new Date().getMilliseconds()}
1063
+ setIsLoadingContent={setIsLoadingContent}
1064
+ onInAppEditorTypeChange={onInAppEditorTypeChange}
1065
+ inAppEditorType={inAppEditorType}
1066
+ isGetFormData={isGetFormData}
1067
+ getFormdata={getFormData}
1068
+ templateData={templateData}
1069
+ type={type}
1070
+ step={templateStep}
1071
+ showNextStep={onCreateNextStep}
1072
+ isFullMode={isFullMode}
1073
+ cap={cap}
1074
+ onResetStep={onResetStep}
1075
+ showTemplateName={showTemplateName}
1076
+ onEnterTemplateName={onEnterTemplateName}
1077
+ onRemoveTemplateName={onRemoveTemplateName}
1078
+ onValidationFail={onValidationFail}
1079
+ forwardedTags={forwardedTags}
1080
+ selectedOfferDetails={selectedOfferDetails}
1081
+ onPreviewContentClicked={onPreviewContentClicked}
1082
+ onTestContentClicked={onTestContentClicked}
1083
+ moduleType={moduleType}
1084
+ showLiquidErrorInFooter={showLiquidErrorInFooter}
1085
+ eventContextTags={eventContextTags}
1086
+ onCreateComplete={onCreateComplete}
1087
+ handleClose={handleClose}
1088
+ getDefaultTags={type}
1089
+ onInAppModeChange={onInAppModeChange}
1090
+ inAppCreateMode={inAppCreateMode}
1091
+ showTestAndPreviewSlidebox={showTestAndPreviewSlidebox}
1018
1092
  handleTestAndPreview={handleTestAndPreview}
1019
1093
  handleCloseTestAndPreview={handleCloseTestAndPreview}
1020
1094
  isTestAndPreviewMode={isTestAndPreviewMode}
@@ -1105,6 +1179,8 @@ SlideBoxContent.propTypes = {
1105
1179
  onSelectTemplate: PropTypes.func,
1106
1180
  onPreviewTemplate: PropTypes.func,
1107
1181
  templateData: PropTypes.object,
1182
+ onInAppEditorTypeChange: PropTypes.func,
1183
+ inAppEditorType: PropTypes.object,
1108
1184
  location: PropTypes.object,
1109
1185
  isGetFormData: PropTypes.bool,
1110
1186
  getFormData: PropTypes.func,
@@ -7,12 +7,15 @@ import PropTypes from 'prop-types';
7
7
  import messages from './messages';
8
8
  import ErrorInfoNote from '../../v2Components/ErrorInfoNote';
9
9
  import { PREVIEW } from './constants';
10
+ import { EMAIL_CREATE_MODES } from '../EmailWrapper/constants';
10
11
 
11
- function getFullModeSaveBtn(slidBoxContent) {
12
- return slidBoxContent === "editTemplate" ?
13
- <FormattedMessage {...messages.creativesTemplatesUpdate}/>
14
- :
15
- <FormattedMessage {...messages.creativesTemplatesSaveFullMode}/>;
12
+ function getFullModeSaveBtn(slidBoxContent, isCreatingTemplate) {
13
+ if (isCreatingTemplate) {
14
+ return <FormattedMessage {...messages.creativesTemplatesDone} />;
15
+ }
16
+ return slidBoxContent === "editTemplate"
17
+ ? <FormattedMessage {...messages.creativesTemplatesUpdate} />
18
+ : <FormattedMessage {...messages.creativesTemplatesSaveFullMode} />;
16
19
  }
17
20
  function SlideBoxFooter(props) {
18
21
  const {
@@ -24,18 +27,112 @@ function SlideBoxFooter(props) {
24
27
  fetchingCmsData,
25
28
  isTemplateNameEmpty,
26
29
  errorMessages,
27
- isLiquidValidationError,
30
+ // eslint-disable-next-line no-unused-vars
31
+ isLiquidValidationError, // Legacy prop, kept for PropTypes compatibility
28
32
  currentTab,
29
33
  onTestAndPreview,
30
34
  // isEmptyContent,
31
35
  showTestAndPreviewButton,
32
36
  shouldShowDoneFooter,
33
37
  shouldShowContinueFooter,
38
+ isContinueButtonDisabled,
39
+ continueButtonLabel,
40
+ htmlEditorValidationState,
41
+ isCreatingTemplate,
42
+ currentChannel,
43
+ emailCreateMode,
44
+ selectedEmailCreateMode,
34
45
  } = props;
35
46
 
47
+ // Calculate if buttons should be disabled
48
+ // Only apply validation state checks for EMAIL channel in HTML Editor mode (not BEE/DragDrop)
49
+ // For other channels, BEE editor, or when htmlEditorValidationState is not provided, don't disable based on validation
50
+ const isEmailChannel = currentChannel?.toUpperCase() === 'EMAIL';
51
+ const isEditMode = slidBoxContent === 'editTemplate';
52
+
53
+ // Use selectedEmailCreateMode for accurate mode detection in create mode (emailCreateMode is mapped for backwards compatibility)
54
+ // In edit mode: htmlEditorValidationState is initialized as {} but only updated by HTML Editor
55
+ // If it's still in initial state (validationComplete === false, issueCounts.total === 0), it's BEE editor
56
+ // Upload mode also uses HTML Editor, so include it in HTML Editor mode check
57
+ const isUploadMode = emailCreateMode === EMAIL_CREATE_MODES.UPLOAD;
58
+ const isHTMLEditorModeInCreate = selectedEmailCreateMode === EMAIL_CREATE_MODES.HTML_EDITOR || isUploadMode;
59
+ // In edit mode: Check if htmlEditorValidationState has been updated by HTML Editor
60
+ // HTML Editor will call updateHtmlEditorValidationState, setting validationComplete to true at some point
61
+ // If validationComplete is false and issueCounts.total === 0, it's likely still in initial state (BEE editor)
62
+ const isHtmlEditorValidationStateActive = htmlEditorValidationState && (
63
+ htmlEditorValidationState.validationComplete === true
64
+ || (htmlEditorValidationState.issueCounts && htmlEditorValidationState.issueCounts.total > 0)
65
+ || htmlEditorValidationState.hasErrors === true
66
+ );
67
+ const isHTMLEditorModeInEdit = isEditMode && isHtmlEditorValidationStateActive;
68
+ const isHTMLEditorMode = isHTMLEditorModeInCreate || isHTMLEditorModeInEdit;
69
+
70
+ // BEE editor detection: drag_drop mode OR (editor mode AND not HTML Editor)
71
+ // In edit mode: if htmlEditorValidationState is in initial state (not updated by HTML Editor), it's BEE editor
72
+ const isBEEEditor = selectedEmailCreateMode === EMAIL_CREATE_MODES.DRAG_DROP
73
+ || (emailCreateMode === EMAIL_CREATE_MODES.EDITOR && !isHTMLEditorMode)
74
+ || (isEditMode && !isHtmlEditorValidationStateActive);
75
+ // Only check validation for HTML Editor mode, not for BEE/DragDrop editor
76
+ const shouldCheckValidation = isEmailChannel && htmlEditorValidationState && isHTMLEditorMode && !isBEEEditor;
77
+ const isContentEmpty = shouldCheckValidation ? (htmlEditorValidationState?.isContentEmpty ?? true) : false;
78
+ // Check if validation has completed
79
+ const validationComplete = shouldCheckValidation ? (htmlEditorValidationState?.validationComplete ?? false) : true;
80
+ // Only Rule Group #1 (Input & Sanitization) blocks; hasErrors is set by HTMLEditor from hasBlockingErrors.
81
+ // hasErrors should always be set (defaults to false), so we only check for explicit true value.
82
+ // Warnings (label issues, HTML/CSS compatibility) do NOT block buttons.
83
+ const hasValidationErrors = shouldCheckValidation && htmlEditorValidationState?.hasErrors === true;
84
+ const errorsAcknowledged = shouldCheckValidation ? (htmlEditorValidationState?.errorsAcknowledged ?? false) : true;
85
+
86
+ // IMPORTANT: In both modes, if validation finds errors, buttons must stay disabled until user acknowledges by clicking redirection icon
87
+ let shouldDisableButtons = false;
88
+ if (shouldCheckValidation) {
89
+ if (isEditMode) {
90
+ // Edit mode: Disable if validation has completed AND found errors AND errors not acknowledged
91
+ shouldDisableButtons = validationComplete && hasValidationErrors && !errorsAcknowledged;
92
+ } else {
93
+ // Create mode:
94
+ // 1. Disable until validation completes
95
+ // 2. Disable if content is empty
96
+ // 3. Disable if validation finds errors AND errors not acknowledged (user must click redirection icon)
97
+ shouldDisableButtons = !validationComplete || isContentEmpty || (hasValidationErrors && !errorsAcknowledged);
98
+ }
99
+ }
100
+
101
+ // Show ErrorInfoNote for API validation errors (from validateLiquidTemplateContent)
102
+ // For HTML Editor: API validation errors are shown in ValidationErrorDisplay (inside CodeEditorPane), not here
103
+ const hasStandardErrors = errorMessages && errorMessages.STANDARD_ERROR_MSG && errorMessages.STANDARD_ERROR_MSG.length > 0;
104
+ const hasLiquidErrors = errorMessages && errorMessages.LIQUID_ERROR_MSG && errorMessages.LIQUID_ERROR_MSG.length > 0;
105
+
106
+ // Check if htmlEditorValidationState has actual validation errors
107
+ // If htmlEditorValidationState exists but has no errors (total === 0), and we have STANDARD/LIQUID errors,
108
+ // then those errors are from BEE editor (FormBuilder validation), not HTML Editor
109
+ const htmlEditorHasErrors = htmlEditorValidationState && htmlEditorValidationState.issueCounts && htmlEditorValidationState.issueCounts.total > 0;
110
+
111
+ // BEE editor errors: We have STANDARD/LIQUID errors AND either:
112
+ // 1. No htmlEditorValidationState exists, OR
113
+ // 2. htmlEditorValidationState exists but has no actual errors (meaning errors are from FormBuilder/BEE editor)
114
+ // IMPORTANT: Only check for BEE editor errors when NOT in HTML Editor mode (upload or html_editor)
115
+ // Upload mode uses HTML Editor, so BEE editor errors don't apply
116
+ // IMPORTANT: BEE editor doesn't have real-time content updates,
117
+ // so we should NOT disable buttons based on validation errors
118
+ // In edit mode: Check if htmlEditorValidationState is in initial state (not updated by HTML Editor)
119
+ // In edit mode with BEE editor, htmlEditorValidationState will remain in initial state
120
+ // In create mode, check selectedEmailCreateMode or emailCreateMode
121
+ const isBEEEditorModeInEdit = isEditMode && !isHtmlEditorValidationStateActive;
122
+ const isBEEEditorModeInCreate = !isHTMLEditorMode && !isEditMode;
123
+ const isBEEEditorMode = isBEEEditorModeInEdit || isBEEEditorModeInCreate;
124
+ const hasBEEEditorErrors = isEmailChannel && isBEEEditorMode && (hasStandardErrors || hasLiquidErrors) && (!htmlEditorValidationState || !htmlEditorHasErrors);
125
+
126
+ const shouldShowErrorInfoNote = hasBEEEditorErrors;
36
127
  return (
37
- <div className='template-footer-width'>
38
- {isLiquidValidationError && (<ErrorInfoNote errorMessages={errorMessages} currentTab={currentTab?.toUpperCase()} />)}
128
+ <div className="template-footer-width">
129
+ {shouldShowErrorInfoNote && (
130
+ <ErrorInfoNote
131
+ errorMessages={errorMessages}
132
+ currentTab={currentTab?.toUpperCase()}
133
+ useLegacyDisplay // Use simple list display for BEE Editor (not tabbed interface)
134
+ />
135
+ )}
39
136
  <div>
40
137
  {shouldShowDoneFooter() && (
41
138
  <div>
@@ -47,10 +144,10 @@ function SlideBoxFooter(props) {
47
144
  <CapRow>
48
145
  <CapButton
49
146
  onClick={onSave}
50
- disabled={isTemplateNameEmpty || fetchingCmsData || false}
147
+ disabled={isTemplateNameEmpty || fetchingCmsData || shouldDisableButtons}
51
148
  >
52
149
  {isFullMode ? (
53
- getFullModeSaveBtn(slidBoxContent)
150
+ getFullModeSaveBtn(slidBoxContent, isCreatingTemplate)
54
151
  ) : (
55
152
  <FormattedMessage {...messages.creativesTemplatesSave} />
56
153
  )}
@@ -59,7 +156,7 @@ function SlideBoxFooter(props) {
59
156
  <CapButton
60
157
  type="secondary"
61
158
  onClick={onTestAndPreview}
62
- // disabled={isEmptyContent || false}
159
+ disabled={shouldDisableButtons}
63
160
  style={{ marginLeft: '8px' }}
64
161
  >
65
162
  <FormattedMessage {...messages.testAndPreview} />
@@ -70,8 +167,11 @@ function SlideBoxFooter(props) {
70
167
  </div>
71
168
  )}
72
169
  {shouldShowContinueFooter() && (
73
- <CapButton onClick={onCreateNextStep}>
74
- <FormattedMessage {...messages.continue} />
170
+ <CapButton
171
+ onClick={onCreateNextStep}
172
+ disabled={isContinueButtonDisabled || false}
173
+ >
174
+ <FormattedMessage {...(continueButtonLabel || messages.continue)} />
75
175
  </CapButton>
76
176
  )}
77
177
  {slidBoxContent === PREVIEW && (
@@ -99,5 +199,48 @@ SlideBoxFooter.propTypes = {
99
199
  onTestAndPreview: PropTypes.func,
100
200
  isEmptyContent: PropTypes.bool,
101
201
  showTestAndPreviewButton: PropTypes.bool,
202
+ isContinueButtonDisabled: PropTypes.bool,
203
+ continueButtonLabel: PropTypes.object,
204
+ htmlEditorValidationState: PropTypes.shape({
205
+ isContentEmpty: PropTypes.bool,
206
+ issueCounts: PropTypes.shape({
207
+ html: PropTypes.number,
208
+ label: PropTypes.number,
209
+ liquid: PropTypes.number,
210
+ total: PropTypes.number,
211
+ }),
212
+ validationComplete: PropTypes.bool,
213
+ /** Only Rule Group #1 (Input & Sanitization) blocks; warnings do not block */
214
+ hasErrors: PropTypes.bool,
215
+ }),
216
+ isCreatingTemplate: PropTypes.bool,
217
+ currentChannel: PropTypes.string,
218
+ emailCreateMode: PropTypes.string,
219
+ selectedEmailCreateMode: PropTypes.string,
220
+ };
221
+
222
+ SlideBoxFooter.defaultProps = {
223
+ slidBoxContent: '',
224
+ onSave: () => {},
225
+ onEditTemplate: () => {},
226
+ onCreateNextStep: () => {},
227
+ shouldShowContinueFooter: () => {},
228
+ shouldShowDoneFooter: () => {},
229
+ isFullMode: false,
230
+ fetchingCmsData: false,
231
+ isTemplateNameEmpty: false,
232
+ errorMessages: [],
233
+ isLiquidValidationError: false,
234
+ currentTab: '',
235
+ onTestAndPreview: () => {},
236
+ isEmptyContent: false,
237
+ showTestAndPreviewButton: false,
238
+ isContinueButtonDisabled: false,
239
+ continueButtonLabel: {},
240
+ htmlEditorValidationState: {},
241
+ isCreatingTemplate: false,
242
+ currentChannel: '',
243
+ emailCreateMode: '',
244
+ selectedEmailCreateMode: '',
102
245
  };
103
246
  export default SlideBoxFooter;
@@ -45,6 +45,7 @@ export function SlideBoxHeader(props) {
45
45
  const isZaloEdit = channel.toLowerCase() === ZALO && slidBoxContent === 'editTemplate';
46
46
  const zaloOverview = isZaloEdit && isFullMode;
47
47
  const whatsappOverview = isWhatsappEdit && isFullMode;
48
+ const shouldShowInAppEditHeader = isInAppEdit && !isFullMode;
48
49
  const headerMessage = whatsappOverview ? messages.whatsappOverview : zaloOverview ? messages.zaloOverview : messages.editMessageContent;
49
50
  const {
50
51
  whatsappTemplateName,
@@ -110,7 +111,7 @@ export function SlideBoxHeader(props) {
110
111
  }
111
112
  />
112
113
  )}
113
- {!showTemplateNameHeader && slidBoxContent === 'editTemplate' && (
114
+ {!showTemplateNameHeader && slidBoxContent === 'editTemplate' && (shouldShowInAppEditHeader || !isInAppCreate) && (
114
115
  <CapHeader
115
116
  className="support-video-elements"
116
117
  title={<FormattedMessage {...headerMessage} values={{ channel: getChannelLabel(channel) }} />}
@@ -26,6 +26,7 @@ export const WEBPUSH_BRAND_ICON = "WEBPUSH_BRAND_ICON";
26
26
  export const PREVIEW = "preview";
27
27
  export const EDIT_TEMPLATE = "editTemplate";
28
28
  export const JOURNEY = "journey";
29
+ export const HTML = "HTML";
29
30
 
30
31
  export const LOYALTY_SUPPORTED_ACTION = "SEND_COMMUNICATION_ACTION";
31
32