@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,16 +1,20 @@
1
- import { useState, useEffect, useMemo, useCallback } from 'react';
1
+ import React, {
2
+ useState, useEffect, useMemo, useCallback, useRef,
3
+ } from 'react';
2
4
  import isEmpty from 'lodash/isEmpty';
3
- import get from 'lodash/get';
4
5
  import find from 'lodash/find';
6
+ import get from 'lodash/get';
5
7
  import { GA } from '@capillarytech/cap-ui-utils';
6
8
  import CapNotification from '@capillarytech/cap-ui-library/CapNotification';
7
- import { CHANNEL_CREATE_TRACK_MAPPING } from '../../App/constants';
9
+ import CapIcon from '@capillarytech/cap-ui-library/CapIcon';
10
+ import { CHANNEL_CREATE_TRACK_MAPPING, BEE_PLUGIN } from '../../App/constants';
8
11
  import { gtmPush } from '../../../utils/gtmTrackers';
9
12
  import { EMAIL } from '../../CreativesContainer/constants';
10
13
  import messages from '../messages';
11
- import { STEPS } from '../constants';
12
- import { EMAIL_CREATE_MODES } from '../constants';
14
+ import { STEPS, EMAIL_CREATE_MODES } from '../constants';
13
15
  import { containsBase64Images } from '../../../utils/content';
16
+ import { hasSupportCKEditor } from '../../../utils/common';
17
+
14
18
 
15
19
  /**
16
20
  * Custom hook to handle EmailWrapper component business logic
@@ -56,27 +60,35 @@ const useEmailWrapper = ({
56
60
  handleTestAndPreview,
57
61
  handleCloseTestAndPreview,
58
62
  isTestAndPreviewMode,
63
+ // Props for BEE enabled check
64
+ location,
65
+ emailActions,
66
+ Email,
67
+ templateData,
68
+ params,
59
69
  }) => {
60
70
  // State management
61
71
  const [templateName, setTemplateName] = useState('');
62
72
  const [isTemplateNameEmpty, setIsTemplateNameEmpty] = useState(true);
63
73
  const [selectedCreateMode, setSelectedCreateMode] = useState('');
64
74
  const [modeContent, setModeContent] = useState({});
75
+ const [isBeeEditorEnabled, setIsBeeEditorEnabled] = useState(null); // null = not checked yet, true/false = checked
76
+ const beeStatusCheckRef = useRef(false); // Track if we've made the API call for current step
77
+ const defaultTemplatesFetchedRef = useRef(false);
78
+ const beeTemplateSetRef = useRef(false); // Track if we've set BEETemplate for current template
65
79
  const [routeParams] = useState({
66
80
  pathname: `/email/create`,
67
81
  query: { module: 'library', type: 'embedded' },
68
82
  });
69
83
 
70
84
  // Cleanup effect
71
- useEffect(() => {
72
- return () => {
73
- onResetStep();
74
- templatesActions.resetTemplateData();
75
- };
85
+ useEffect(() => () => {
86
+ onResetStep();
87
+ templatesActions.resetTemplateData();
76
88
  }, [onResetStep, templatesActions]);
77
89
 
78
90
  // Event handlers
79
- const onTemplateNameChange = useCallback(({target: {value}}) => {
91
+ const onTemplateNameChange = useCallback(({ target: { value } }) => {
80
92
  const isEmptyTemplateName = !value?.trim();
81
93
  setTemplateName(value);
82
94
  setIsTemplateNameEmpty(isEmptyTemplateName);
@@ -88,9 +100,234 @@ const useEmailWrapper = ({
88
100
  }
89
101
  }, [onEnterTemplateName, onRemoveTemplateName]);
90
102
 
103
+ // Check BEE enabled status from API response
104
+ // BEE is enabled if isDragDrop is true in the API response
105
+ // This should work for both full mode and library mode
106
+ const checkBeeEditorEnabled = useCallback(() => {
107
+ // IMPORTANT: Always use API response when available, regardless of mode
108
+ // This ensures consistent behavior across full mode and library mode
109
+ // The API response represents whether BEE is enabled for the organization
110
+ if (isBeeEditorEnabled !== null) {
111
+ return isBeeEditorEnabled;
112
+ }
113
+ // If we haven't checked yet, return false (disabled) until API responds
114
+ // Note: In full mode, BEE might still be allowed for UI purposes (editor selection),
115
+ // but for API calls (isBEEAppEnable), we should use the actual org setting
116
+ return false;
117
+ }, [isBeeEditorEnabled]);
118
+
119
+ // Helper function to convert numeric templateStep to string step
120
+ const getStepFromTemplateStep = useCallback((templateStepValue) => {
121
+ // templateStep is numeric: 1 = modeSelection, 2 = templateSelection, 3 = createTemplateContent
122
+ if (typeof templateStepValue === 'number') {
123
+ switch (templateStepValue) {
124
+ case 1:
125
+ return STEPS.MODE_SELECTION;
126
+ case 2:
127
+ return STEPS.TEMPLATE_SELECTION;
128
+ case 3:
129
+ return STEPS.CREATE_TEMPLATE_CONTENT;
130
+ default:
131
+ return STEPS.MODE_SELECTION;
132
+ }
133
+ }
134
+ // If it's already a string, return as-is
135
+ return templateStepValue || STEPS.MODE_SELECTION;
136
+ }, []);
137
+
138
+ // Convert step to string format if it's numeric
139
+ const currentStep = useMemo(() => getStepFromTemplateStep(step), [step, getStepFromTemplateStep]);
140
+
141
+ // Effect to check BEE enabled status via new API when entering MODE_SELECTION step or edit mode
142
+ useEffect(() => {
143
+ const supportCKEditor = hasSupportCKEditor();
144
+ // Only check BEE enabled status for new flow (when supportCKEditor is false)
145
+ // Reset the ref when step changes to MODE_SELECTION to allow API call
146
+ if (currentStep === STEPS.MODE_SELECTION) {
147
+ beeStatusCheckRef.current = false;
148
+ }
149
+
150
+ // Check if we're in edit mode (need to check BEE status for editor selection)
151
+ const hasParamsId = params?.id || location?.query?.id || location?.params?.id || location?.pathname?.includes('/edit/');
152
+ const isEditMode = hasParamsId;
153
+
154
+ // Only check BEE enabled status for new flow (when supportCKEditor is false)
155
+ // Call API in MODE_SELECTION step OR in edit mode (if not already called)
156
+ // Check all conditions
157
+ const shouldMakeCall = !supportCKEditor
158
+ && (currentStep === STEPS.MODE_SELECTION || isEditMode)
159
+ && !beeStatusCheckRef.current
160
+ && emailActions;
161
+
162
+ if (shouldMakeCall) {
163
+ // Mark that we've made the API call
164
+ beeStatusCheckRef.current = true;
165
+
166
+ // Make API call to check BEE enabled status using new endpoint
167
+ emailActions.getCmsAccounts('BEE_PLUGIN');
168
+ }
169
+ }, [currentStep, emailActions, params?.id, location?.query?.id, location?.params?.id, location?.pathname]);
170
+
171
+ // Effect to update isBeeEditorEnabled based on new API response
172
+ // This effect watches for isBeeEnabled from the new API response
173
+ useEffect(() => {
174
+ // Process API response regardless of step (needed for edit mode editor selection)
175
+ // Also check if we've made the API call (beeStatusCheckRef.current === true)
176
+ if (beeStatusCheckRef.current) {
177
+ // Use isBeeEnabled from the new API response
178
+ if (Email?.isBeeEnabled !== undefined && Email?.isBeeEnabled !== null) {
179
+ setIsBeeEditorEnabled(Email.isBeeEnabled);
180
+ }
181
+ }
182
+ // If API call fails, treat as disabled
183
+ if (Email?.fetchingCmsAccountsError && beeStatusCheckRef.current) {
184
+ setIsBeeEditorEnabled(false);
185
+ }
186
+ }, [Email?.isBeeEnabled, Email?.fetchingCmsAccountsError]);
187
+
188
+ // Effect to fetch template details when in edit mode
189
+ // This ensures template data is loaded so editor type can be determined correctly
190
+ useEffect(() => {
191
+ const supportCKEditor = hasSupportCKEditor();
192
+ if (supportCKEditor) {
193
+ // Legacy flow: Email component handles getTemplateDetails
194
+ return;
195
+ }
196
+
197
+ // New flow: Fetch template details if we're in edit mode and don't have template data yet
198
+ const hasParamsId = params?.id || location?.query?.id || location?.params?.id || location?.pathname?.includes('/edit/');
199
+ const hasTemplateDetails = Email?.templateDetails && !isEmpty(Email.templateDetails);
200
+ const hasTemplateDataProp = templateData && !isEmpty(templateData);
201
+ const isTemplateLoading = Email?.getTemplateDetailsInProgress;
202
+
203
+ // Only fetch if we have an ID, don't have template data yet, and not already loading
204
+ if (hasParamsId && !hasTemplateDetails && !hasTemplateDataProp && !isTemplateLoading && emailActions?.getTemplateDetails) {
205
+ const templateId = params?.id || location?.query?.id || location?.params?.id;
206
+ if (templateId) {
207
+ emailActions.getTemplateDetails(templateId, 'email');
208
+ }
209
+ }
210
+ }, [params?.id, location?.query?.id, location?.params?.id, location?.pathname, Email?.templateDetails, Email?.getTemplateDetailsInProgress, templateData, emailActions]);
211
+
212
+ // Effect to set BEETemplate when template details are loaded for BEE templates
213
+ // This ensures Email component can properly initialize BEE editor
214
+ useEffect(() => {
215
+ const supportCKEditor = hasSupportCKEditor();
216
+ if (supportCKEditor) {
217
+ // Legacy flow: Email component handles this
218
+ return;
219
+ }
220
+
221
+ // New flow: When template details are loaded and it's a BEE template, set it in Templates.BEETemplate
222
+ // This allows Email component to properly initialize and call getCmsSetting
223
+ const hasTemplateDetails = Email?.templateDetails && !isEmpty(Email.templateDetails);
224
+ // Note: We check Email?.BEETemplate as a proxy, but the actual BEETemplate is in Templates reducer
225
+ // The Email component will detect it via this.props.Templates.BEETemplate
226
+ const hasBEETemplate = Email?.BEETemplate && !isEmpty(Email.BEETemplate);
227
+
228
+ if (hasTemplateDetails && !hasBEETemplate && templatesActions?.setBEETemplate && !beeTemplateSetRef.current) {
229
+ // Check if it's a BEE template
230
+ const editTemplateData = Email.templateDetails;
231
+ const getIsDragDrop = (data) => {
232
+ if (!data) return false;
233
+ const baseDragDrop = get(data, 'versions.base.is_drag_drop', false);
234
+ if (baseDragDrop === true || baseDragDrop === 1) return true;
235
+ const activeTab = get(data, 'versions.base.activeTab', 'en');
236
+ const activeTabDragDrop = get(data, `versions.base.${activeTab}.is_drag_drop`, false);
237
+ if (activeTabDragDrop === true || activeTabDragDrop === 1) return true;
238
+ const baseLevelDragDrop = get(data, 'base.is_drag_drop', false);
239
+ if (baseLevelDragDrop === true || baseLevelDragDrop === 1) return true;
240
+ const rootDragDrop = get(data, 'is_drag_drop', false);
241
+ if (rootDragDrop === true || rootDragDrop === 1) return true;
242
+ return false;
243
+ };
244
+
245
+ const isDragDrop = getIsDragDrop(editTemplateData);
246
+
247
+ // If it's a BEE template, set it in Templates.BEETemplate
248
+ if (isDragDrop) {
249
+ beeTemplateSetRef.current = true;
250
+ templatesActions.setBEETemplate(editTemplateData);
251
+
252
+ // Also call getCmsSetting directly as a fallback if Email component doesn't detect it
253
+ // Extract drag_drop_id - check multiple possible paths
254
+ const activeTab = get(editTemplateData, 'versions.base.activeTab', 'en');
255
+ const activeTabData = get(editTemplateData, `versions.base.${activeTab}`, {});
256
+ const dragDropId = activeTabData.drag_drop_id
257
+ || activeTabData.id
258
+ || get(editTemplateData, 'versions.base.drag_drop_id')
259
+ || get(editTemplateData, 'versions.base.id')
260
+ || editTemplateData._id;
261
+
262
+ const isBEESupport = (location?.query?.isBEESupport !== "false") || false;
263
+ // IMPORTANT: isBEEAppEnable should be consistent across full mode and library mode
264
+ // It represents whether BEE is enabled for the organization, not the mode
265
+ // This ensures the same template behaves the same way in both modes
266
+ const isBEEAppEnable = checkBeeEditorEnabled();
267
+ // Check if we're in edit mode - check multiple sources for id
268
+ const hasParamsId = params?.id
269
+ || location?.query?.id
270
+ || location?.params?.id
271
+ || (location?.pathname && location.pathname.includes('/edit/'));
272
+ const cmsMode = hasParamsId ? 'open' : 'create';
273
+ // Extract langId from active tab
274
+ const activeTabForLang = get(editTemplateData, 'versions.base.activeTab', 'en');
275
+
276
+ // Call getCmsSetting if emailActions is available
277
+ // Note: This is a fallback - the Email component should also call it in componentWillReceiveProps
278
+ if (emailActions?.getCmsSetting) {
279
+ emailActions.getCmsSetting(BEE_PLUGIN, dragDropId, cmsMode, activeTabForLang, isBEESupport, isBEEAppEnable);
280
+ } else {
281
+ console.warn('[useEmailWrapper] emailActions.getCmsSetting not available');
282
+ }
283
+ }
284
+ }
285
+
286
+ // Reset ref when template changes (template details cleared)
287
+ if (!hasTemplateDetails && beeTemplateSetRef.current) {
288
+ beeTemplateSetRef.current = false;
289
+ }
290
+ }, [Email?.templateDetails, Email?.BEETemplate, Email?.getTemplateDetailsInProgress, Email?.fetchingCmsSettings, templatesActions, emailActions, params?.id, location?.query, checkBeeEditorEnabled, isFullMode]);
291
+
91
292
  const onChange = useCallback((e) => {
92
- onEmailModeChange(e.target.value);
93
- }, [onEmailModeChange]);
293
+ const { target: { value } } = e;
294
+ // Prevent selection if Drag & Drop is selected but BEE editor is not enabled
295
+ if (value === EMAIL_CREATE_MODES.DRAG_DROP && !checkBeeEditorEnabled()) {
296
+ return; // Ignore selection if BEE editor is disabled
297
+ }
298
+
299
+ // CRITICAL: When DRAG_DROP is selected, set selectedCreateMode to DRAG_DROP
300
+ // This ensures emailProps will have editor: 'BEE' and selectedEditorMode: null
301
+ if (value === EMAIL_CREATE_MODES.DRAG_DROP) {
302
+ setSelectedCreateMode(EMAIL_CREATE_MODES.DRAG_DROP);
303
+ } else {
304
+ setSelectedCreateMode(value);
305
+ }
306
+
307
+ const supportCKEditor = hasSupportCKEditor();
308
+
309
+ // Map new modes to existing modes for backwards compatibility
310
+ let mappedValue = value;
311
+
312
+ if (!supportCKEditor) {
313
+ // New flow: Handle HTML Editor, Drag & Drop, and Upload Zip
314
+ // Don't auto-navigate - wait for Next button click
315
+ if (value === EMAIL_CREATE_MODES.HTML_EDITOR) {
316
+ // HTML Editor: Map to EDITOR but skip template selection
317
+ mappedValue = EMAIL_CREATE_MODES.EDITOR;
318
+ setModeContent({ skipTemplateSelection: true });
319
+ } else if (value === EMAIL_CREATE_MODES.DRAG_DROP) {
320
+ // Drag & Drop: Map to EDITOR and show template selection
321
+ mappedValue = EMAIL_CREATE_MODES.EDITOR;
322
+ } else if (value === EMAIL_CREATE_MODES.UPLOAD) {
323
+ // Upload Zip: Keep as UPLOAD
324
+ mappedValue = EMAIL_CREATE_MODES.UPLOAD;
325
+ }
326
+ }
327
+ // Legacy (CK editor) flow: do not auto-navigate; user must enter template name and click Continue in footer
328
+
329
+ onEmailModeChange(mappedValue, value); // Pass both mapped value and original selected mode
330
+ }, [onEmailModeChange, checkBeeEditorEnabled]);
94
331
 
95
332
  const handleZipUploadError = useCallback(() => {
96
333
  const message = {
@@ -151,7 +388,7 @@ const useEmailWrapper = ({
151
388
  templatesActions.handleZipUpload(file.originFileObj, () => { // Handle upload success
152
389
  stopTimerGA();
153
390
  setModeContent({ file });
154
- showNextStep();
391
+ // Do not auto-advance; user must enter template name and click Continue in footer
155
392
  }, handleZipUploadError);
156
393
  } else if (fileExtension === 'html' || fileExtension === 'htm') {
157
394
  // Verify originFileObj exists
@@ -168,10 +405,10 @@ const useEmailWrapper = ({
168
405
  handleZipUploadError();
169
406
  return;
170
407
  }
171
-
408
+
172
409
  // Check for base64 images in HTML content
173
- containsBase64Images({content:text, CapNotification});
174
-
410
+ containsBase64Images({content: text, CapNotification});
411
+
175
412
  setModeContent({ file });
176
413
  templatesActions.handleHtmlUpload(text);
177
414
  };
@@ -188,14 +425,18 @@ const useEmailWrapper = ({
188
425
  CapNotification.error(message);
189
426
  }
190
427
  }
191
- }, [isUploading, formatMessage, templatesActions, stopTimerGA, handleZipUploadError, showNextStep]);
428
+ }, [isUploading, formatMessage, templatesActions, stopTimerGA, handleZipUploadError]);
192
429
 
193
430
  const handleEdmDefaultTemplateSelection = useCallback((id) => {
194
431
  const data = find(CmsTemplates, { _id: id });
195
432
  templatesActions.setEdmTemplate(data);
196
433
  templatesActions.setBEETemplate(data);
197
- setSelectedCreateMode(EMAIL_CREATE_MODES.EDITOR);
198
- }, [CmsTemplates, templatesActions]);
434
+ // Don't override selectedCreateMode - preserve DRAG_DROP or EDITOR mode
435
+ // Only set if not already set
436
+ if (!selectedCreateMode) {
437
+ setSelectedCreateMode(EMAIL_CREATE_MODES.EDITOR);
438
+ }
439
+ }, [CmsTemplates, templatesActions, selectedCreateMode]);
199
440
 
200
441
  const useFileUpload = useCallback(({ file }) => {
201
442
  setModeContent({});
@@ -209,41 +450,73 @@ const useEmailWrapper = ({
209
450
 
210
451
  // Main logic effect - MOVED AFTER function declarations
211
452
  useEffect(() => {
212
- // Skip if user has already made a selection
213
- if (selectedCreateMode) return;
453
+ const supportCKEditor = hasSupportCKEditor();
214
454
 
215
455
  // Handle different steps
216
- switch (step) {
456
+ switch (currentStep) {
217
457
  case STEPS.MODE_SELECTION:
218
458
  if (emailCreateMode === EMAIL_CREATE_MODES.UPLOAD && !EmailLayout) {
219
459
  // Commented out: document.getElementById('upload-email-template').click();
220
460
  }
221
461
  break;
222
462
 
223
- case STEPS.TEMPLATE_SELECTION:
224
- const needsTemplates = emailCreateMode === EMAIL_CREATE_MODES.EDITOR
225
- && !CmsTemplates
226
- && !getCmsTemplatesInProgress;
463
+ case STEPS.TEMPLATE_SELECTION: {
464
+ // Template selection is needed for:
465
+ // 1. Legacy EDITOR mode (when supportCKEditor is true)
466
+ // 2. New DRAG_DROP mode (when supportCKEditor is false)
467
+ // NOT needed for HTML_EDITOR (goes directly to editor)
227
468
 
228
- if (needsTemplates) {
469
+ let needsTemplates = false;
470
+ if (supportCKEditor) {
471
+ // Legacy flow: only for EDITOR mode
472
+ needsTemplates = emailCreateMode === EMAIL_CREATE_MODES.EDITOR
473
+ && !CmsTemplates
474
+ && !getCmsTemplatesInProgress;
475
+ } else {
476
+ // New flow: for DRAG_DROP only (not HTML_EDITOR)
477
+ needsTemplates = selectedCreateMode === EMAIL_CREATE_MODES.DRAG_DROP
478
+ && !CmsTemplates
479
+ && !getCmsTemplatesInProgress;
480
+ }
481
+
482
+ if (needsTemplates && !defaultTemplatesFetchedRef.current) {
229
483
  templatesActions.getDefaultBeeTemplates();
484
+ defaultTemplatesFetchedRef.current = true;
230
485
  }
231
486
  break;
487
+ }
232
488
 
233
- case STEPS.CREATE_TEMPLATE_CONTENT:
489
+ case STEPS.CREATE_TEMPLATE_CONTENT: {
234
490
  if (emailCreateMode === EMAIL_CREATE_MODES.UPLOAD && !isEmpty(EmailLayout)) {
235
491
  setSelectedCreateMode(EMAIL_CREATE_MODES.UPLOAD);
236
- } else if (emailCreateMode === EMAIL_CREATE_MODES.EDITOR && isEmpty(SelectedEdmDefaultTemplate)) {
237
- handleEdmDefaultTemplateSelection(modeContent.id);
492
+ } else if (emailCreateMode === EMAIL_CREATE_MODES.EDITOR
493
+ || emailCreateMode === EMAIL_CREATE_MODES.DRAG_DROP
494
+ || selectedCreateMode === EMAIL_CREATE_MODES.EDITOR
495
+ || selectedCreateMode === EMAIL_CREATE_MODES.DRAG_DROP) {
496
+ if (!supportCKEditor && selectedCreateMode === EMAIL_CREATE_MODES.HTML_EDITOR) {
497
+ // HTML Editor mode: Skip template selection, go directly to editor
498
+ setSelectedCreateMode(EMAIL_CREATE_MODES.HTML_EDITOR);
499
+ } else if (isEmpty(SelectedEdmDefaultTemplate) && modeContent.id) {
500
+ // Legacy EDITOR or DRAG_DROP: Need template selection
501
+ handleEdmDefaultTemplateSelection(modeContent.id);
502
+ } else if (!supportCKEditor && selectedCreateMode === EMAIL_CREATE_MODES.DRAG_DROP) {
503
+ // CRITICAL: Template already selected for DRAG_DROP - ensure selectedCreateMode is DRAG_DROP
504
+ // This ensures emailProps will have editor: 'BEE' and selectedEditorMode: null
505
+ setSelectedCreateMode(EMAIL_CREATE_MODES.DRAG_DROP);
506
+ } else {
507
+ // Template already selected for legacy EDITOR
508
+ setSelectedCreateMode(EMAIL_CREATE_MODES.EDITOR);
509
+ }
238
510
  }
239
511
  break;
512
+ }
240
513
 
241
514
  default:
242
515
  // No operation for other steps
243
516
  break;
244
517
  }
245
518
  }, [
246
- step,
519
+ currentStep,
247
520
  selectedCreateMode,
248
521
  emailCreateMode,
249
522
  EmailLayout,
@@ -252,58 +525,223 @@ const useEmailWrapper = ({
252
525
  modeContent.id,
253
526
  SelectedEdmDefaultTemplate,
254
527
  templatesActions,
255
- handleEdmDefaultTemplateSelection
528
+ handleEdmDefaultTemplateSelection,
256
529
  ]);
257
530
 
531
+ // CRITICAL: Reset selectedCreateMode when templateData is cleared (new template creation)
532
+ // This ensures that when user creates a new template after editing, selectedCreateMode is reset
533
+ useEffect(() => {
534
+ // If templateData is cleared/null and we're not in edit mode, reset selectedCreateMode
535
+ const hasParamsId = params?.id
536
+ || location?.query?.id
537
+ || location?.params?.id
538
+ || location?.pathname?.includes('/edit/');
539
+ const hasTemplateData = templateData && !isEmpty(templateData);
540
+ const isEditMode = hasParamsId || hasTemplateData;
541
+
542
+ // If we're creating a new template (no templateData and no params.id), reset selectedCreateMode
543
+ // BUT only if we're in MODE_SELECTION step (navigating back to start)
544
+ // DO NOT reset in CREATE_TEMPLATE_CONTENT - that's where we need selectedCreateMode to render the editor!
545
+ // Also DO NOT reset if emailCreateMode is set - it means user has made a selection
546
+ if (!isEditMode && !hasTemplateData && selectedCreateMode && currentStep === STEPS.MODE_SELECTION && !emailCreateMode) {
547
+ // Reset only when returning to MODE_SELECTION step
548
+ // This preserves user selection while in content creation
549
+ setSelectedCreateMode('');
550
+ }
551
+ }, [templateData, params?.id, location?.query?.id, location?.params?.id, location?.pathname, selectedCreateMode, templateName, currentStep, emailCreateMode]);
552
+
258
553
  // Derived state
259
- const isShowEmailCreate = !isEmpty(selectedCreateMode) && (!isEmpty(EmailLayout) || SelectedEdmDefaultTemplate);
554
+ const supportCKEditorFlag = hasSupportCKEditor();
260
555
 
261
- // Memoize static data
262
- const modes = useMemo(() => [
263
- {
264
- title: formatMessage(messages.zipUpload),
265
- content: formatMessage(messages.zipUploadDesc),
266
- value: EMAIL_CREATE_MODES.UPLOAD,
267
- },
268
- {
269
- title: formatMessage(messages.useEditor),
270
- content: formatMessage(messages.useEditorDesc),
271
- value: EMAIL_CREATE_MODES.EDITOR,
272
- },
273
- ], [formatMessage]);
274
-
275
- // Prepare props for Email component
276
- const emailProps = useMemo(() => ({
277
- setIsLoadingContent,
278
- key: "email-create-template",
279
- location: routeParams,
280
- route: { name: 'email' },
281
- params: {},
282
- isGetFormData,
283
- getFormdata,
284
- getFormSubscriptionData: getFormdata,
285
- getDefaultTags: type,
286
- isFullMode,
287
- defaultData: { 'template-name': templateName },
288
- cap,
289
- showTemplateName,
290
- showLiquidErrorInFooter,
291
- onValidationFail,
292
- forwardedTags,
293
- selectedOfferDetails,
294
- onPreviewContentClicked,
295
- onTestContentClicked,
296
- editor,
297
- moduleType,
298
- eventContextTags,
299
- isLoyaltyModule,
300
- showTestAndPreviewSlidebox,
301
- handleTestAndPreview,
302
- handleCloseTestAndPreview,
303
- isTestAndPreviewMode,
304
- }), [
556
+ // Prepare props for Email component - MOVED BEFORE isShowEmailCreate to avoid circular dependency
557
+ const emailProps = useMemo(() => {
558
+ // Determine editor type and mode based on selectedCreateMode
559
+ let editorType = editor;
560
+ let selectedEditorMode = null;
561
+
562
+ if (!supportCKEditorFlag) {
563
+ // CRITICAL: Check selectedCreateMode FIRST to prioritize user's explicit selection
564
+ // This ensures DRAG_DROP selection takes precedence over edit mode detection
565
+ // even if templateDetails persists from a previous template
566
+ if (selectedCreateMode === EMAIL_CREATE_MODES.DRAG_DROP) {
567
+ // CRITICAL: DRAG_DROP mode always uses BEE editor
568
+ // This takes precedence over edit mode detection
569
+ editorType = 'BEE';
570
+ selectedEditorMode = null; // BEE uses existing flow (null indicates BEE editor)
571
+ } else if (selectedCreateMode === EMAIL_CREATE_MODES.HTML_EDITOR) {
572
+ // HTML_EDITOR mode: Always use HTML editor
573
+ editorType = 'HTML';
574
+ selectedEditorMode = EMAIL_CREATE_MODES.HTML_EDITOR;
575
+ } else {
576
+ // Check if we're editing an existing template
577
+ // CRITICAL: Only treat as edit mode if we have params.id (actual edit URL) or templateData prop
578
+ // Don't use templateDetails existence alone, as it might persist from previous template
579
+ const hasParamsId = params?.id || location?.query?.id || location?.params?.id || location?.pathname?.includes('/edit/');
580
+ const hasTemplateDetails = Email?.templateDetails && !isEmpty(Email.templateDetails);
581
+ const hasBEETemplate = Email?.BEETemplate && !isEmpty(Email.BEETemplate);
582
+ const hasTemplateDataProp = templateData && !isEmpty(templateData);
583
+ // CRITICAL: Consider it edit mode if we have params.id OR templateData prop (library mode)
584
+ // This allows editor type determination even when template data is still loading
585
+ const isEditMode = hasParamsId || hasTemplateDataProp;
586
+
587
+ if (isEditMode) {
588
+ // Edit mode: Determine editor based on template data
589
+ // Check if template was created in BEE editor
590
+ // Priority: Email.templateDetails > Email.BEETemplate > templateData prop
591
+ const editTemplateData = Email?.templateDetails || Email?.BEETemplate || templateData;
592
+
593
+ // Helper function to safely get is_drag_drop from various possible paths
594
+ const getIsDragDrop = (data) => {
595
+ if (!data) return false;
596
+
597
+ // Check common paths for is_drag_drop
598
+ // Path 1: versions.base.is_drag_drop (most common)
599
+ const baseDragDrop = get(data, 'versions.base.is_drag_drop', false);
600
+ if (baseDragDrop === true || baseDragDrop === 1) return true;
601
+
602
+ // Path 2: versions.base[activeTab].is_drag_drop (language-specific)
603
+ const activeTab = get(data, 'versions.base.activeTab', 'en');
604
+ const activeTabDragDrop = get(data, `versions.base.${activeTab}.is_drag_drop`, false);
605
+ if (activeTabDragDrop === true || activeTabDragDrop === 1) return true;
606
+
607
+ // Path 3: base.is_drag_drop (alternative structure)
608
+ const baseLevelDragDrop = get(data, 'base.is_drag_drop', false);
609
+ if (baseLevelDragDrop === true || baseLevelDragDrop === 1) return true;
610
+
611
+ // Path 4: is_drag_drop (root level)
612
+ const rootDragDrop = get(data, 'is_drag_drop', false);
613
+ if (rootDragDrop === true || rootDragDrop === 1) return true;
614
+
615
+ // Path 5: Check all language tabs in versions.base
616
+ const baseVersions = get(data, 'versions.base', {});
617
+ if (baseVersions && typeof baseVersions === 'object') {
618
+ for (const key in baseVersions) {
619
+ if (key !== 'activeTab' && typeof baseVersions[key] === 'object') {
620
+ const langDragDrop = get(baseVersions[key], 'is_drag_drop', false);
621
+ if (langDragDrop === true || langDragDrop === 1) return true;
622
+ }
623
+ }
624
+ }
625
+
626
+ return false;
627
+ };
628
+
629
+ const isDragDrop = getIsDragDrop(editTemplateData);
630
+
631
+ // Check if BEE is enabled for org (equivalent to checkBeeEditorAllowedForLibrary)
632
+ // For editor selection:
633
+ // - In full mode: BEE is always enabled
634
+ // - In library mode: Check API response, but if API hasn't responded yet and template is BEE, allow BEE (optimistic)
635
+ // - Also check if editor prop is explicitly "BEE"
636
+ const beeEnabledFromAPI = checkBeeEditorEnabled();
637
+ const isAPIResponsePending = isBeeEditorEnabled === null;
638
+ const isBeeEnabled = isFullMode
639
+ || (editor === "BEE" && !isFullMode)
640
+ || beeEnabledFromAPI
641
+ || (isAPIResponsePending && isDragDrop && !isFullMode); // Optimistic: if template is BEE and API pending, allow BEE
642
+
643
+ // If template was created in BEE AND BEE is enabled → open in BEE editor
644
+ // Otherwise → open in HTML editor (fallback)
645
+ // IMPORTANT: When supportCKEditor is false, default to HTML editor unless explicitly BEE
646
+ if (isDragDrop && isBeeEnabled) {
647
+ editorType = 'BEE';
648
+ selectedEditorMode = null; // BEE uses existing flow
649
+ } else {
650
+ // Fallback to HTML editor if BEE not enabled or template not created in BEE
651
+ // This ensures HTML editor is used when supportCKEditor is false
652
+ editorType = 'HTML';
653
+ selectedEditorMode = EMAIL_CREATE_MODES.HTML_EDITOR;
654
+ }
655
+ } else if (selectedCreateMode === EMAIL_CREATE_MODES.EDITOR) {
656
+ // EDITOR mode: Check if selected template is a BEE template
657
+ // When a default template is selected, it's stored in Templates.BEETemplate
658
+ const beeTemplate = Email?.BEETemplate || SelectedEdmDefaultTemplate;
659
+ const isBEETemplate = beeTemplate && (
660
+ get(beeTemplate, 'versions.base.is_drag_drop') === true
661
+ || get(beeTemplate, 'base.is_drag_drop') === true
662
+ || beeTemplate.is_drag_drop === true
663
+ );
664
+
665
+ if (isBEETemplate && checkBeeEditorEnabled()) {
666
+ // Template is BEE and BEE is enabled → use BEE editor
667
+ editorType = 'BEE';
668
+ selectedEditorMode = null; // BEE uses existing flow
669
+ } else {
670
+ // Template is not BEE or BEE is disabled → use HTML editor
671
+ editorType = 'HTML';
672
+ selectedEditorMode = EMAIL_CREATE_MODES.HTML_EDITOR;
673
+ }
674
+ } else {
675
+ // Default: When supportCKEditor is false and no mode selected, use HTML editor
676
+ editorType = 'HTML';
677
+ selectedEditorMode = EMAIL_CREATE_MODES.HTML_EDITOR;
678
+ }
679
+ }
680
+ // UPLOAD mode uses existing editor prop
681
+ }
682
+ // Legacy flow (supportCKEditor is true): Use existing editor prop as-is - no changes
683
+
684
+ // Determine template name for edit mode
685
+ let finalTemplateName = templateName;
686
+ if (Email?.templateDetails?.name) {
687
+ finalTemplateName = Email.templateDetails.name;
688
+ } else if (templateData?.name) {
689
+ finalTemplateName = templateData.name;
690
+ }
691
+
692
+ // Determine params - include id for edit mode
693
+ const emailParams = {};
694
+ if (params?.id) {
695
+ emailParams.id = params.id;
696
+ } else if (location?.query?.id) {
697
+ emailParams.id = location.query.id;
698
+ } else if (location?.params?.id) {
699
+ emailParams.id = location.params.id;
700
+ } else if (location?.pathname?.includes('/edit/')) {
701
+ // Extract id from pathname if it's in the format /edit/:id
702
+ const match = location.pathname.match(/\/edit\/([^/]+)/);
703
+ if (match) {
704
+ emailParams.id = match[1];
705
+ }
706
+ }
707
+
708
+ return {
709
+ setIsLoadingContent,
710
+ key: "email-create-template",
711
+ location: routeParams,
712
+ route: { name: 'email' },
713
+ params: emailParams,
714
+ isGetFormData,
715
+ getFormdata,
716
+ getFormSubscriptionData: getFormdata,
717
+ getDefaultTags: type,
718
+ isFullMode,
719
+ defaultData: { 'template-name': finalTemplateName },
720
+ cap,
721
+ showTemplateName,
722
+ showLiquidErrorInFooter,
723
+ onValidationFail,
724
+ forwardedTags,
725
+ selectedOfferDetails,
726
+ onPreviewContentClicked,
727
+ onTestContentClicked,
728
+ editor: editorType,
729
+ selectedEditorMode, // Pass selected mode to Email component (only for HTML_EDITOR)
730
+ moduleType,
731
+ eventContextTags,
732
+ isLoyaltyModule,
733
+ showTestAndPreviewSlidebox,
734
+ handleTestAndPreview,
735
+ handleCloseTestAndPreview,
736
+ isTestAndPreviewMode,
737
+ };
738
+ }, [
305
739
  setIsLoadingContent,
306
740
  routeParams,
741
+ Email?.BEETemplate,
742
+ Email?.templateDetails, // Include templateDetails so editor type recalculates when template loads
743
+ SelectedEdmDefaultTemplate,
744
+ checkBeeEditorEnabled,
307
745
  isGetFormData,
308
746
  getFormdata,
309
747
  type,
@@ -325,8 +763,118 @@ const useEmailWrapper = ({
325
763
  handleTestAndPreview,
326
764
  handleCloseTestAndPreview,
327
765
  isTestAndPreviewMode,
766
+ selectedCreateMode,
767
+ supportCKEditorFlag,
768
+ checkBeeEditorEnabled,
769
+ isBeeEditorEnabled, // Include to recalculate when API response arrives
770
+ Email,
771
+ location,
772
+ params,
773
+ editor,
774
+ isFullMode,
775
+ templateData,
776
+ templateName,
328
777
  ]);
329
778
 
779
+ const isShowEmailCreate = useMemo(() => {
780
+ // Check if we're in edit mode (templateDetails or BEETemplate exists, or params.id exists)
781
+ const hasTemplateDetails = Email?.templateDetails && !isEmpty(Email.templateDetails);
782
+ const hasBEETemplate = Email?.BEETemplate && !isEmpty(Email.BEETemplate);
783
+ const hasParamsId = params?.id || location?.query?.id || location?.params?.id || location?.pathname?.includes('/edit/');
784
+ const isEditMode = hasTemplateDetails || hasBEETemplate || hasParamsId;
785
+
786
+ // In edit mode (when supportCKEditor is false), always show editor
787
+ if (!supportCKEditorFlag && isEditMode) {
788
+ // Check if it's explicitly BEE editor
789
+ const isExplicitlyBEE = emailCreateMode === EMAIL_CREATE_MODES.DRAG_DROP
790
+ || (emailProps?.editor === 'BEE' && emailProps?.selectedEditorMode === null);
791
+ // Show editor for both BEE and HTML in edit mode
792
+ return true;
793
+ }
794
+
795
+ if (!selectedCreateMode) return false;
796
+
797
+ // For HTML Editor (new flow): Always show editor directly without template selection
798
+ // This takes precedence over step check to ensure HTML Editor is shown even if step is temporarily TEMPLATE_SELECTION
799
+ if (!supportCKEditorFlag && selectedCreateMode === EMAIL_CREATE_MODES.HTML_EDITOR) {
800
+ return true;
801
+ }
802
+
803
+ // CRITICAL: For DRAG_DROP mode, show template selection first (CmsTemplatesComponent)
804
+ // Only show editor (Email component with BEE) after template is selected
805
+ if (emailCreateMode === EMAIL_CREATE_MODES.DRAG_DROP || selectedCreateMode === EMAIL_CREATE_MODES.DRAG_DROP) {
806
+ // If we're in TEMPLATE_SELECTION step, show template selection (not email editor)
807
+ if (currentStep === STEPS.TEMPLATE_SELECTION) {
808
+ return false;
809
+ }
810
+ // After template selection, show editor when template is selected
811
+ return !isEmpty(SelectedEdmDefaultTemplate);
812
+ }
813
+
814
+ // If we're in TEMPLATE_SELECTION step, show template selection (not email editor)
815
+ // This applies to legacy Editor modes
816
+ if (currentStep === STEPS.TEMPLATE_SELECTION) {
817
+ return false;
818
+ }
819
+
820
+ // For Upload: Show editor when EmailLayout exists
821
+ if (emailCreateMode === EMAIL_CREATE_MODES.UPLOAD) {
822
+ return !isEmpty(EmailLayout);
823
+ }
824
+
825
+ // For Editor: Show editor when template is selected
826
+ return !isEmpty(SelectedEdmDefaultTemplate);
827
+ }, [currentStep, selectedCreateMode, supportCKEditorFlag, emailCreateMode, EmailLayout, SelectedEdmDefaultTemplate, Email?.templateDetails, Email?.BEETemplate, params?.id, location?.query?.id, location?.params?.id, location?.pathname, emailProps?.editor, emailProps?.selectedEditorMode]);
828
+
829
+ // Memoize static data
830
+ const modes = useMemo(() => {
831
+ const supportCKEditor = hasSupportCKEditor();
832
+ const isBeeEditorEnabledValue = checkBeeEditorEnabled();
833
+
834
+ if (supportCKEditor) {
835
+ // Legacy flow: Show only 2 options (Upload Zip, Use Editor)
836
+ return [
837
+ {
838
+ title: formatMessage(messages.zipUpload),
839
+ content: formatMessage(messages.zipUploadDesc),
840
+ value: EMAIL_CREATE_MODES.UPLOAD,
841
+ },
842
+ {
843
+ title: formatMessage(messages.useEditor),
844
+ content: formatMessage(messages.useEditorDesc),
845
+ value: EMAIL_CREATE_MODES.EDITOR,
846
+ },
847
+ ];
848
+ }
849
+
850
+ // New flow: Show 3 options (HTML Editor, Drag & Drop, Upload Zip)
851
+ return [
852
+ {
853
+ title: formatMessage(messages.htmlEditorTitle),
854
+ content: formatMessage(messages.htmlEditorDesc),
855
+ value: EMAIL_CREATE_MODES.HTML_EDITOR,
856
+ icon: <CapIcon type="code" />,
857
+ },
858
+ {
859
+ title: formatMessage(messages.dragDropEditorTitle),
860
+ content: formatMessage(messages.dragDropEditorDesc),
861
+ value: EMAIL_CREATE_MODES.DRAG_DROP,
862
+ icon: <CapIcon type="draggable" svgProps={{ fill: 'currentColor' }} />,
863
+ disabled: !isBeeEditorEnabledValue,
864
+ tooltipProps: !isBeeEditorEnabledValue ? {
865
+ title: formatMessage(messages.beeEditorDisabledTooltip),
866
+ placement: 'top',
867
+ } : undefined,
868
+ },
869
+ {
870
+ title: formatMessage(messages.uploadZipTitle),
871
+ content: formatMessage(messages.uploadZipDesc),
872
+ value: EMAIL_CREATE_MODES.UPLOAD,
873
+ icon: <CapIcon type="file" />,
874
+ },
875
+ ];
876
+ }, [formatMessage, checkBeeEditorEnabled]);
877
+
330
878
  // Prepare props for CmsTemplatesComponent
331
879
  const cmsTemplatesProps = useMemo(() => ({
332
880
  cmsTemplates: CmsTemplates,
@@ -358,4 +906,4 @@ const useEmailWrapper = ({
358
906
  };
359
907
  };
360
908
 
361
- export default useEmailWrapper;
909
+ export default useEmailWrapper;