@capillarytech/creatives-library 8.0.213 → 8.0.214-beta.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/HOW_BEE_EDITOR_WORKS.md +375 -0
- package/constants/unified.js +1 -0
- package/package.json +1 -1
- package/services/api.js +5 -0
- package/utils/common.js +6 -1
- package/v2Components/CapTagList/index.js +2 -1
- package/v2Components/CapTagListWithInput/index.js +5 -1
- package/v2Components/CapTagListWithInput/messages.js +1 -1
- package/v2Components/ErrorInfoNote/style.scss +1 -1
- package/v2Components/HtmlEditor/HTMLEditor.js +86 -14
- package/v2Components/HtmlEditor/_htmlEditor.scss +4 -4
- package/v2Components/HtmlEditor/_index.lazy.scss +1 -1
- package/v2Components/HtmlEditor/components/CodeEditorPane/_codeEditorPane.scss +107 -96
- package/v2Components/HtmlEditor/components/CodeEditorPane/index.js +68 -92
- package/v2Components/HtmlEditor/components/SplitContainer/_splitContainer.scss +1 -1
- package/v2Components/HtmlEditor/hooks/useEditorContent.js +5 -2
- package/v2Containers/CreativesContainer/SlideBoxContent.js +85 -35
- package/v2Containers/CreativesContainer/SlideBoxFooter.js +9 -3
- package/v2Containers/CreativesContainer/index.js +107 -35
- package/v2Containers/CreativesContainer/messages.js +4 -0
- package/v2Containers/Email/actions.js +7 -0
- package/v2Containers/Email/constants.js +5 -1
- package/v2Containers/Email/index.js +13 -0
- package/v2Containers/Email/messages.js +32 -0
- package/v2Containers/Email/reducer.js +12 -1
- package/v2Containers/Email/sagas.js +17 -0
- package/v2Containers/EmailWrapper/components/EmailHTMLEditor.js +1005 -0
- package/v2Containers/EmailWrapper/components/EmailWrapperView.js +193 -7
- package/v2Containers/EmailWrapper/constants.js +2 -0
- package/v2Containers/EmailWrapper/hooks/useEmailWrapper.js +470 -71
- package/v2Containers/EmailWrapper/index.js +102 -23
- package/v2Containers/EmailWrapper/messages.js +61 -1
- package/v2Containers/EmailWrapper/tests/EmailHTMLEditor.test.js +177 -0
- package/v2Containers/EmailWrapper/tests/EmailHTMLEditorValidation.test.js +90 -0
- package/v2Containers/EmailWrapper/tests/useEmailWrapper.test.js +49 -49
- package/v2Containers/TagList/index.js +2 -0
- package/v2Containers/Templates/index.js +5 -0
|
@@ -1,16 +1,19 @@
|
|
|
1
|
-
import
|
|
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';
|
|
9
|
+
import CapIcon from '@capillarytech/cap-ui-library/CapIcon';
|
|
7
10
|
import { CHANNEL_CREATE_TRACK_MAPPING } 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';
|
|
14
17
|
|
|
15
18
|
/**
|
|
16
19
|
* Custom hook to handle EmailWrapper component business logic
|
|
@@ -56,12 +59,21 @@ const useEmailWrapper = ({
|
|
|
56
59
|
handleTestAndPreview,
|
|
57
60
|
handleCloseTestAndPreview,
|
|
58
61
|
isTestAndPreviewMode,
|
|
62
|
+
// Props for BEE enabled check
|
|
63
|
+
location,
|
|
64
|
+
emailActions,
|
|
65
|
+
Email,
|
|
66
|
+
templateData,
|
|
67
|
+
params,
|
|
59
68
|
}) => {
|
|
60
69
|
// State management
|
|
61
70
|
const [templateName, setTemplateName] = useState('');
|
|
62
71
|
const [isTemplateNameEmpty, setIsTemplateNameEmpty] = useState(true);
|
|
63
72
|
const [selectedCreateMode, setSelectedCreateMode] = useState('');
|
|
64
73
|
const [modeContent, setModeContent] = useState({});
|
|
74
|
+
const [isBeeEditorEnabled, setIsBeeEditorEnabled] = useState(null); // null = not checked yet, true/false = checked
|
|
75
|
+
const beeStatusCheckRef = useRef(false); // Track if we've made the API call for current step
|
|
76
|
+
const defaultTemplatesFetchedRef = useRef(false);
|
|
65
77
|
const [routeParams] = useState({
|
|
66
78
|
pathname: `/email/create`,
|
|
67
79
|
query: { module: 'library', type: 'embedded' },
|
|
@@ -76,7 +88,7 @@ const useEmailWrapper = ({
|
|
|
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,124 @@ 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
|
+
// If we have checked the API and got a response, use that
|
|
108
|
+
if (isBeeEditorEnabled !== null) {
|
|
109
|
+
return isBeeEditorEnabled;
|
|
110
|
+
}
|
|
111
|
+
// If we haven't checked yet, return false (disabled) until API responds
|
|
112
|
+
return false;
|
|
113
|
+
}, [isBeeEditorEnabled]);
|
|
114
|
+
|
|
115
|
+
// Helper function to convert numeric templateStep to string step
|
|
116
|
+
const getStepFromTemplateStep = useCallback((templateStepValue) => {
|
|
117
|
+
// templateStep is numeric: 1 = modeSelection, 2 = templateSelection, 3 = createTemplateContent
|
|
118
|
+
if (typeof templateStepValue === 'number') {
|
|
119
|
+
switch (templateStepValue) {
|
|
120
|
+
case 1:
|
|
121
|
+
return STEPS.MODE_SELECTION;
|
|
122
|
+
case 2:
|
|
123
|
+
return STEPS.TEMPLATE_SELECTION;
|
|
124
|
+
case 3:
|
|
125
|
+
return STEPS.CREATE_TEMPLATE_CONTENT;
|
|
126
|
+
default:
|
|
127
|
+
return STEPS.MODE_SELECTION;
|
|
128
|
+
}
|
|
129
|
+
}
|
|
130
|
+
// If it's already a string, return as-is
|
|
131
|
+
return templateStepValue || STEPS.MODE_SELECTION;
|
|
132
|
+
}, []);
|
|
133
|
+
|
|
134
|
+
// Convert step to string format if it's numeric
|
|
135
|
+
const currentStep = useMemo(() => getStepFromTemplateStep(step), [step, getStepFromTemplateStep]);
|
|
136
|
+
|
|
137
|
+
// Effect to check BEE enabled status via new API when entering MODE_SELECTION step
|
|
138
|
+
useEffect(() => {
|
|
139
|
+
const supportCKEditor = hasSupportCKEditor();
|
|
140
|
+
// Only check BEE enabled status for new flow (when supportCKEditor is false)
|
|
141
|
+
// Reset the ref when step changes to MODE_SELECTION to allow API call
|
|
142
|
+
if (currentStep === STEPS.MODE_SELECTION) {
|
|
143
|
+
beeStatusCheckRef.current = false;
|
|
144
|
+
}
|
|
145
|
+
|
|
146
|
+
// Only check BEE enabled status for new flow (when supportCKEditor is false)
|
|
147
|
+
// Check all conditions
|
|
148
|
+
const shouldMakeCall = !supportCKEditor
|
|
149
|
+
&& currentStep === STEPS.MODE_SELECTION
|
|
150
|
+
&& !beeStatusCheckRef.current
|
|
151
|
+
&& emailActions;
|
|
152
|
+
|
|
153
|
+
if (shouldMakeCall) {
|
|
154
|
+
// Mark that we've made the API call
|
|
155
|
+
beeStatusCheckRef.current = true;
|
|
156
|
+
|
|
157
|
+
// Make API call to check BEE enabled status using new endpoint
|
|
158
|
+
emailActions.getCmsAccounts('BEE_PLUGIN');
|
|
159
|
+
}
|
|
160
|
+
}, [currentStep, emailActions]);
|
|
161
|
+
|
|
162
|
+
// Effect to update isBeeEditorEnabled based on new API response
|
|
163
|
+
// This effect watches for isBeeEnabled from the new API response
|
|
164
|
+
useEffect(() => {
|
|
165
|
+
// Only process if we're in MODE_SELECTION step (when we're checking BEE status)
|
|
166
|
+
// Also check if we've made the API call (beeStatusCheckRef.current === true)
|
|
167
|
+
if (currentStep === STEPS.MODE_SELECTION && beeStatusCheckRef.current) {
|
|
168
|
+
// Use isBeeEnabled from the new API response
|
|
169
|
+
if (Email?.isBeeEnabled !== undefined) {
|
|
170
|
+
setIsBeeEditorEnabled(Email.isBeeEnabled);
|
|
171
|
+
}
|
|
172
|
+
}
|
|
173
|
+
// If API call fails, treat as disabled
|
|
174
|
+
if (Email?.fetchingCmsAccountsError && beeStatusCheckRef.current) {
|
|
175
|
+
setIsBeeEditorEnabled(false);
|
|
176
|
+
}
|
|
177
|
+
}, [Email?.isBeeEnabled, Email?.fetchingCmsAccountsError, currentStep]);
|
|
178
|
+
|
|
91
179
|
const onChange = useCallback((e) => {
|
|
92
|
-
|
|
93
|
-
|
|
180
|
+
const { target: { value } } = e;
|
|
181
|
+
|
|
182
|
+
// Prevent selection if Drag & Drop is selected but BEE editor is not enabled
|
|
183
|
+
if (value === EMAIL_CREATE_MODES.DRAG_DROP && !checkBeeEditorEnabled()) {
|
|
184
|
+
return; // Ignore selection if BEE editor is disabled
|
|
185
|
+
}
|
|
186
|
+
|
|
187
|
+
// CRITICAL: When DRAG_DROP is selected, set selectedCreateMode to DRAG_DROP
|
|
188
|
+
// This ensures emailProps will have editor: 'BEE' and selectedEditorMode: null
|
|
189
|
+
if (value === EMAIL_CREATE_MODES.DRAG_DROP) {
|
|
190
|
+
setSelectedCreateMode(EMAIL_CREATE_MODES.DRAG_DROP);
|
|
191
|
+
} else {
|
|
192
|
+
setSelectedCreateMode(value);
|
|
193
|
+
}
|
|
194
|
+
|
|
195
|
+
const supportCKEditor = hasSupportCKEditor();
|
|
196
|
+
|
|
197
|
+
// Map new modes to existing modes for backwards compatibility
|
|
198
|
+
let mappedValue = value;
|
|
199
|
+
|
|
200
|
+
if (!supportCKEditor) {
|
|
201
|
+
// New flow: Handle HTML Editor, Drag & Drop, and Upload Zip
|
|
202
|
+
// Don't auto-navigate - wait for Next button click
|
|
203
|
+
if (value === EMAIL_CREATE_MODES.HTML_EDITOR) {
|
|
204
|
+
// HTML Editor: Map to EDITOR but skip template selection
|
|
205
|
+
mappedValue = EMAIL_CREATE_MODES.EDITOR;
|
|
206
|
+
setModeContent({ skipTemplateSelection: true });
|
|
207
|
+
} else if (value === EMAIL_CREATE_MODES.DRAG_DROP) {
|
|
208
|
+
// Drag & Drop: Map to EDITOR and show template selection
|
|
209
|
+
mappedValue = EMAIL_CREATE_MODES.EDITOR;
|
|
210
|
+
} else if (value === EMAIL_CREATE_MODES.UPLOAD) {
|
|
211
|
+
// Upload Zip: Keep as UPLOAD
|
|
212
|
+
mappedValue = EMAIL_CREATE_MODES.UPLOAD;
|
|
213
|
+
}
|
|
214
|
+
} else if (value === EMAIL_CREATE_MODES.EDITOR && showNextStep) {
|
|
215
|
+
// Legacy flow: Auto-navigate immediately (existing behavior)
|
|
216
|
+
showNextStep();
|
|
217
|
+
}
|
|
218
|
+
|
|
219
|
+
onEmailModeChange(mappedValue, value); // Pass both mapped value and original selected mode
|
|
220
|
+
}, [onEmailModeChange, showNextStep, checkBeeEditorEnabled]);
|
|
94
221
|
|
|
95
222
|
const handleZipUploadError = useCallback(() => {
|
|
96
223
|
const message = {
|
|
@@ -168,10 +295,10 @@ const useEmailWrapper = ({
|
|
|
168
295
|
handleZipUploadError();
|
|
169
296
|
return;
|
|
170
297
|
}
|
|
171
|
-
|
|
298
|
+
|
|
172
299
|
// Check for base64 images in HTML content
|
|
173
|
-
containsBase64Images({content:text, CapNotification});
|
|
174
|
-
|
|
300
|
+
containsBase64Images({ content: text, CapNotification });
|
|
301
|
+
|
|
175
302
|
setModeContent({ file });
|
|
176
303
|
templatesActions.handleHtmlUpload(text);
|
|
177
304
|
};
|
|
@@ -194,8 +321,12 @@ const useEmailWrapper = ({
|
|
|
194
321
|
const data = find(CmsTemplates, { _id: id });
|
|
195
322
|
templatesActions.setEdmTemplate(data);
|
|
196
323
|
templatesActions.setBEETemplate(data);
|
|
197
|
-
|
|
198
|
-
|
|
324
|
+
// Don't override selectedCreateMode - preserve DRAG_DROP or EDITOR mode
|
|
325
|
+
// Only set if not already set
|
|
326
|
+
if (!selectedCreateMode) {
|
|
327
|
+
setSelectedCreateMode(EMAIL_CREATE_MODES.EDITOR);
|
|
328
|
+
}
|
|
329
|
+
}, [CmsTemplates, templatesActions, selectedCreateMode]);
|
|
199
330
|
|
|
200
331
|
const useFileUpload = useCallback(({ file }) => {
|
|
201
332
|
setModeContent({});
|
|
@@ -207,43 +338,84 @@ const useEmailWrapper = ({
|
|
|
207
338
|
showNextStep();
|
|
208
339
|
}, [showNextStep]);
|
|
209
340
|
|
|
341
|
+
const handleNextClick = useCallback(() => {
|
|
342
|
+
const supportCKEditor = hasSupportCKEditor();
|
|
343
|
+
if (!supportCKEditor && selectedCreateMode) {
|
|
344
|
+
if ([EMAIL_CREATE_MODES.HTML_EDITOR, EMAIL_CREATE_MODES.DRAG_DROP].includes(selectedCreateMode)) {
|
|
345
|
+
showNextStep();
|
|
346
|
+
}
|
|
347
|
+
}
|
|
348
|
+
}, [selectedCreateMode, showNextStep]);
|
|
349
|
+
|
|
210
350
|
// Main logic effect - MOVED AFTER function declarations
|
|
211
351
|
useEffect(() => {
|
|
212
|
-
|
|
213
|
-
if (selectedCreateMode) return;
|
|
352
|
+
const supportCKEditor = hasSupportCKEditor();
|
|
214
353
|
|
|
215
354
|
// Handle different steps
|
|
216
|
-
switch (
|
|
355
|
+
switch (currentStep) {
|
|
217
356
|
case STEPS.MODE_SELECTION:
|
|
218
357
|
if (emailCreateMode === EMAIL_CREATE_MODES.UPLOAD && !EmailLayout) {
|
|
219
358
|
// Commented out: document.getElementById('upload-email-template').click();
|
|
220
359
|
}
|
|
221
360
|
break;
|
|
222
361
|
|
|
223
|
-
case STEPS.TEMPLATE_SELECTION:
|
|
224
|
-
|
|
225
|
-
|
|
226
|
-
|
|
362
|
+
case STEPS.TEMPLATE_SELECTION: {
|
|
363
|
+
// Template selection is needed for:
|
|
364
|
+
// 1. Legacy EDITOR mode (when supportCKEditor is true)
|
|
365
|
+
// 2. New DRAG_DROP mode (when supportCKEditor is false)
|
|
366
|
+
// NOT needed for HTML_EDITOR (goes directly to editor)
|
|
367
|
+
|
|
368
|
+
let needsTemplates = false;
|
|
369
|
+
if (supportCKEditor) {
|
|
370
|
+
// Legacy flow: only for EDITOR mode
|
|
371
|
+
needsTemplates = emailCreateMode === EMAIL_CREATE_MODES.EDITOR
|
|
372
|
+
&& !CmsTemplates
|
|
373
|
+
&& !getCmsTemplatesInProgress;
|
|
374
|
+
} else {
|
|
375
|
+
// New flow: for DRAG_DROP only (not HTML_EDITOR)
|
|
376
|
+
needsTemplates = selectedCreateMode === EMAIL_CREATE_MODES.DRAG_DROP
|
|
377
|
+
&& !CmsTemplates
|
|
378
|
+
&& !getCmsTemplatesInProgress;
|
|
379
|
+
}
|
|
227
380
|
|
|
228
|
-
if (needsTemplates) {
|
|
381
|
+
if (needsTemplates && !defaultTemplatesFetchedRef.current) {
|
|
229
382
|
templatesActions.getDefaultBeeTemplates();
|
|
383
|
+
defaultTemplatesFetchedRef.current = true;
|
|
230
384
|
}
|
|
231
385
|
break;
|
|
386
|
+
}
|
|
232
387
|
|
|
233
|
-
case STEPS.CREATE_TEMPLATE_CONTENT:
|
|
388
|
+
case STEPS.CREATE_TEMPLATE_CONTENT: {
|
|
234
389
|
if (emailCreateMode === EMAIL_CREATE_MODES.UPLOAD && !isEmpty(EmailLayout)) {
|
|
235
390
|
setSelectedCreateMode(EMAIL_CREATE_MODES.UPLOAD);
|
|
236
|
-
} else if (emailCreateMode === EMAIL_CREATE_MODES.EDITOR
|
|
237
|
-
|
|
391
|
+
} else if (emailCreateMode === EMAIL_CREATE_MODES.EDITOR
|
|
392
|
+
|| emailCreateMode === EMAIL_CREATE_MODES.DRAG_DROP
|
|
393
|
+
|| selectedCreateMode === EMAIL_CREATE_MODES.EDITOR
|
|
394
|
+
|| selectedCreateMode === EMAIL_CREATE_MODES.DRAG_DROP) {
|
|
395
|
+
if (!supportCKEditor && selectedCreateMode === EMAIL_CREATE_MODES.HTML_EDITOR) {
|
|
396
|
+
// HTML Editor mode: Skip template selection, go directly to editor
|
|
397
|
+
setSelectedCreateMode(EMAIL_CREATE_MODES.HTML_EDITOR);
|
|
398
|
+
} else if (isEmpty(SelectedEdmDefaultTemplate) && modeContent.id) {
|
|
399
|
+
// Legacy EDITOR or DRAG_DROP: Need template selection
|
|
400
|
+
handleEdmDefaultTemplateSelection(modeContent.id);
|
|
401
|
+
} else if (!supportCKEditor && selectedCreateMode === EMAIL_CREATE_MODES.DRAG_DROP) {
|
|
402
|
+
// CRITICAL: Template already selected for DRAG_DROP - ensure selectedCreateMode is DRAG_DROP
|
|
403
|
+
// This ensures emailProps will have editor: 'BEE' and selectedEditorMode: null
|
|
404
|
+
setSelectedCreateMode(EMAIL_CREATE_MODES.DRAG_DROP);
|
|
405
|
+
} else {
|
|
406
|
+
// Template already selected for legacy EDITOR
|
|
407
|
+
setSelectedCreateMode(EMAIL_CREATE_MODES.EDITOR);
|
|
408
|
+
}
|
|
238
409
|
}
|
|
239
410
|
break;
|
|
411
|
+
}
|
|
240
412
|
|
|
241
413
|
default:
|
|
242
414
|
// No operation for other steps
|
|
243
415
|
break;
|
|
244
416
|
}
|
|
245
417
|
}, [
|
|
246
|
-
|
|
418
|
+
currentStep,
|
|
247
419
|
selectedCreateMode,
|
|
248
420
|
emailCreateMode,
|
|
249
421
|
EmailLayout,
|
|
@@ -252,58 +424,154 @@ const useEmailWrapper = ({
|
|
|
252
424
|
modeContent.id,
|
|
253
425
|
SelectedEdmDefaultTemplate,
|
|
254
426
|
templatesActions,
|
|
255
|
-
handleEdmDefaultTemplateSelection
|
|
427
|
+
handleEdmDefaultTemplateSelection,
|
|
256
428
|
]);
|
|
257
429
|
|
|
430
|
+
// CRITICAL: Reset selectedCreateMode when templateData is cleared (new template creation)
|
|
431
|
+
// This ensures that when user creates a new template after editing, selectedCreateMode is reset
|
|
432
|
+
useEffect(() => {
|
|
433
|
+
// If templateData is cleared/null and we're not in edit mode, reset selectedCreateMode
|
|
434
|
+
const hasParamsId = params?.id
|
|
435
|
+
|| location?.query?.id
|
|
436
|
+
|| location?.params?.id
|
|
437
|
+
|| location?.pathname?.includes('/edit/');
|
|
438
|
+
const hasTemplateData = templateData && !isEmpty(templateData);
|
|
439
|
+
const isEditMode = hasParamsId || hasTemplateData;
|
|
440
|
+
|
|
441
|
+
// If we're creating a new template (no templateData and no params.id), reset selectedCreateMode
|
|
442
|
+
if (!isEditMode && !hasTemplateData && selectedCreateMode) {
|
|
443
|
+
// Only reset if we're actually in create mode (not just initial load)
|
|
444
|
+
// Check if we have templateName or other create-mode indicators
|
|
445
|
+
if (templateName || currentStep === STEPS.MODE_SELECTION) {
|
|
446
|
+
setSelectedCreateMode('');
|
|
447
|
+
}
|
|
448
|
+
}
|
|
449
|
+
}, [templateData, params?.id, location?.query?.id, location?.params?.id, location?.pathname, selectedCreateMode, templateName, currentStep]);
|
|
450
|
+
|
|
258
451
|
// Derived state
|
|
259
|
-
const
|
|
452
|
+
const supportCKEditorFlag = hasSupportCKEditor();
|
|
260
453
|
|
|
261
|
-
//
|
|
262
|
-
const
|
|
263
|
-
|
|
264
|
-
|
|
265
|
-
|
|
266
|
-
|
|
267
|
-
|
|
268
|
-
|
|
269
|
-
|
|
270
|
-
|
|
271
|
-
|
|
272
|
-
|
|
273
|
-
|
|
274
|
-
|
|
275
|
-
|
|
276
|
-
|
|
277
|
-
|
|
278
|
-
|
|
279
|
-
|
|
280
|
-
|
|
281
|
-
|
|
282
|
-
|
|
283
|
-
|
|
284
|
-
|
|
285
|
-
|
|
286
|
-
|
|
287
|
-
|
|
288
|
-
|
|
289
|
-
|
|
290
|
-
|
|
291
|
-
|
|
292
|
-
|
|
293
|
-
|
|
294
|
-
|
|
295
|
-
|
|
296
|
-
|
|
297
|
-
|
|
298
|
-
|
|
299
|
-
|
|
300
|
-
|
|
301
|
-
|
|
302
|
-
|
|
303
|
-
|
|
304
|
-
|
|
454
|
+
// Prepare props for Email component - MOVED BEFORE isShowEmailCreate to avoid circular dependency
|
|
455
|
+
const emailProps = useMemo(() => {
|
|
456
|
+
// Determine editor type and mode based on selectedCreateMode
|
|
457
|
+
let editorType = editor;
|
|
458
|
+
let selectedEditorMode = null;
|
|
459
|
+
|
|
460
|
+
if (!supportCKEditorFlag) {
|
|
461
|
+
// CRITICAL: Check selectedCreateMode FIRST to prioritize user's explicit selection
|
|
462
|
+
// This ensures DRAG_DROP selection takes precedence over edit mode detection
|
|
463
|
+
// even if templateDetails persists from a previous template
|
|
464
|
+
if (selectedCreateMode === EMAIL_CREATE_MODES.DRAG_DROP) {
|
|
465
|
+
// CRITICAL: DRAG_DROP mode always uses BEE editor
|
|
466
|
+
// This takes precedence over edit mode detection
|
|
467
|
+
editorType = 'BEE';
|
|
468
|
+
selectedEditorMode = null; // BEE uses existing flow (null indicates BEE editor)
|
|
469
|
+
} else if (selectedCreateMode === EMAIL_CREATE_MODES.HTML_EDITOR) {
|
|
470
|
+
// HTML_EDITOR mode: Always use HTML editor
|
|
471
|
+
editorType = 'HTML';
|
|
472
|
+
selectedEditorMode = EMAIL_CREATE_MODES.HTML_EDITOR;
|
|
473
|
+
} else {
|
|
474
|
+
// Check if we're editing an existing template
|
|
475
|
+
// CRITICAL: Only treat as edit mode if we have params.id (actual edit URL)
|
|
476
|
+
// Don't use templateDetails existence alone, as it might persist from previous template
|
|
477
|
+
const hasParamsId = params?.id || location?.query?.id || location?.params?.id || location?.pathname?.includes('/edit/');
|
|
478
|
+
const hasTemplateDetails = Email?.templateDetails && !isEmpty(Email.templateDetails);
|
|
479
|
+
const hasBEETemplate = Email?.BEETemplate && !isEmpty(Email.BEETemplate);
|
|
480
|
+
// CRITICAL: Only consider it edit mode if we have params.id (actual edit URL)
|
|
481
|
+
// This prevents false edit mode detection when templateDetails persists in Redux from previous template
|
|
482
|
+
const isEditMode = hasParamsId && (hasTemplateDetails || hasBEETemplate);
|
|
483
|
+
|
|
484
|
+
if (isEditMode) {
|
|
485
|
+
// Edit mode: Determine editor based on template data
|
|
486
|
+
// Check if template was created in BEE editor
|
|
487
|
+
const editTemplateData = Email?.templateDetails || Email?.BEETemplate || templateData;
|
|
488
|
+
const isDragDrop = get(editTemplateData, 'versions.base.is_drag_drop', false)
|
|
489
|
+
|| get(editTemplateData, 'base.is_drag_drop', false)
|
|
490
|
+
|| get(editTemplateData, 'is_drag_drop', false)
|
|
491
|
+
|| get(editTemplateData, 'versions.base[0].is_drag_drop', false);
|
|
492
|
+
|
|
493
|
+
// Check if BEE is enabled for org (equivalent to checkBeeEditorAllowedForLibrary)
|
|
494
|
+
// For library mode: BEE is enabled if editor prop is "BEE"
|
|
495
|
+
// For full mode: BEE is always enabled
|
|
496
|
+
const isBeeEnabled = isFullMode || (editor === "BEE" && !isFullMode) || checkBeeEditorEnabled();
|
|
497
|
+
|
|
498
|
+
// If template was created in BEE AND BEE is enabled → open in BEE editor
|
|
499
|
+
// Otherwise → open in HTML editor (fallback)
|
|
500
|
+
// IMPORTANT: When supportCKEditor is false, default to HTML editor unless explicitly BEE
|
|
501
|
+
if (isDragDrop && isBeeEnabled) {
|
|
502
|
+
editorType = 'BEE';
|
|
503
|
+
selectedEditorMode = null; // BEE uses existing flow
|
|
504
|
+
} else {
|
|
505
|
+
// Fallback to HTML editor if BEE not enabled or template not created in BEE
|
|
506
|
+
// This ensures HTML editor is used when supportCKEditor is false
|
|
507
|
+
editorType = 'HTML';
|
|
508
|
+
selectedEditorMode = EMAIL_CREATE_MODES.HTML_EDITOR;
|
|
509
|
+
}
|
|
510
|
+
} else if (selectedCreateMode === EMAIL_CREATE_MODES.EDITOR) {
|
|
511
|
+
// EDITOR mode: Check if selected template is a BEE template
|
|
512
|
+
// When a default template is selected, it's stored in Templates.BEETemplate
|
|
513
|
+
const beeTemplate = Email?.BEETemplate || SelectedEdmDefaultTemplate;
|
|
514
|
+
const isBEETemplate = beeTemplate && (
|
|
515
|
+
get(beeTemplate, 'versions.base.is_drag_drop') === true
|
|
516
|
+
|| get(beeTemplate, 'base.is_drag_drop') === true
|
|
517
|
+
|| beeTemplate.is_drag_drop === true
|
|
518
|
+
);
|
|
519
|
+
|
|
520
|
+
if (isBEETemplate && checkBeeEditorEnabled()) {
|
|
521
|
+
// Template is BEE and BEE is enabled → use BEE editor
|
|
522
|
+
editorType = 'BEE';
|
|
523
|
+
selectedEditorMode = null; // BEE uses existing flow
|
|
524
|
+
} else {
|
|
525
|
+
// Template is not BEE or BEE is disabled → use HTML editor
|
|
526
|
+
editorType = 'HTML';
|
|
527
|
+
selectedEditorMode = EMAIL_CREATE_MODES.HTML_EDITOR;
|
|
528
|
+
}
|
|
529
|
+
} else {
|
|
530
|
+
// Default: When supportCKEditor is false and no mode selected, use HTML editor
|
|
531
|
+
editorType = 'HTML';
|
|
532
|
+
selectedEditorMode = EMAIL_CREATE_MODES.HTML_EDITOR;
|
|
533
|
+
}
|
|
534
|
+
}
|
|
535
|
+
// UPLOAD mode uses existing editor prop
|
|
536
|
+
}
|
|
537
|
+
// Legacy flow (supportCKEditor is true): Use existing editor prop as-is - no changes
|
|
538
|
+
|
|
539
|
+
return {
|
|
540
|
+
setIsLoadingContent,
|
|
541
|
+
key: "email-create-template",
|
|
542
|
+
location: routeParams,
|
|
543
|
+
route: { name: 'email' },
|
|
544
|
+
params: {},
|
|
545
|
+
isGetFormData,
|
|
546
|
+
getFormdata,
|
|
547
|
+
getFormSubscriptionData: getFormdata,
|
|
548
|
+
getDefaultTags: type,
|
|
549
|
+
isFullMode,
|
|
550
|
+
defaultData: { 'template-name': templateName },
|
|
551
|
+
cap,
|
|
552
|
+
showTemplateName,
|
|
553
|
+
showLiquidErrorInFooter,
|
|
554
|
+
onValidationFail,
|
|
555
|
+
forwardedTags,
|
|
556
|
+
selectedOfferDetails,
|
|
557
|
+
onPreviewContentClicked,
|
|
558
|
+
onTestContentClicked,
|
|
559
|
+
editor: editorType,
|
|
560
|
+
selectedEditorMode, // Pass selected mode to Email component (only for HTML_EDITOR)
|
|
561
|
+
moduleType,
|
|
562
|
+
eventContextTags,
|
|
563
|
+
isLoyaltyModule,
|
|
564
|
+
showTestAndPreviewSlidebox,
|
|
565
|
+
handleTestAndPreview,
|
|
566
|
+
handleCloseTestAndPreview,
|
|
567
|
+
isTestAndPreviewMode,
|
|
568
|
+
};
|
|
569
|
+
}, [
|
|
305
570
|
setIsLoadingContent,
|
|
306
571
|
routeParams,
|
|
572
|
+
Email?.BEETemplate,
|
|
573
|
+
SelectedEdmDefaultTemplate,
|
|
574
|
+
checkBeeEditorEnabled,
|
|
307
575
|
isGetFormData,
|
|
308
576
|
getFormdata,
|
|
309
577
|
type,
|
|
@@ -325,8 +593,118 @@ const useEmailWrapper = ({
|
|
|
325
593
|
handleTestAndPreview,
|
|
326
594
|
handleCloseTestAndPreview,
|
|
327
595
|
isTestAndPreviewMode,
|
|
596
|
+
selectedCreateMode,
|
|
597
|
+
supportCKEditorFlag,
|
|
598
|
+
checkBeeEditorEnabled,
|
|
599
|
+
Email,
|
|
600
|
+
location,
|
|
601
|
+
params,
|
|
602
|
+
editor,
|
|
603
|
+
isFullMode,
|
|
604
|
+
templateData,
|
|
328
605
|
]);
|
|
329
606
|
|
|
607
|
+
const isShowEmailCreate = useMemo(() => {
|
|
608
|
+
// Check if we're in edit mode (templateDetails or BEETemplate exists, or params.id exists)
|
|
609
|
+
const hasTemplateDetails = Email?.templateDetails && !isEmpty(Email.templateDetails);
|
|
610
|
+
const hasBEETemplate = Email?.BEETemplate && !isEmpty(Email.BEETemplate);
|
|
611
|
+
const hasParamsId = params?.id || location?.query?.id || location?.params?.id || location?.pathname?.includes('/edit/');
|
|
612
|
+
const isEditMode = hasTemplateDetails || hasBEETemplate || hasParamsId;
|
|
613
|
+
|
|
614
|
+
// In edit mode with HTML editor (when supportCKEditor is false), always show editor
|
|
615
|
+
if (!supportCKEditorFlag && isEditMode) {
|
|
616
|
+
// Check if it's explicitly BEE editor
|
|
617
|
+
const isExplicitlyBEE = emailCreateMode === EMAIL_CREATE_MODES.DRAG_DROP
|
|
618
|
+
|| (emailProps?.editor === 'BEE' && emailProps?.selectedEditorMode === null);
|
|
619
|
+
// If not BEE, show HTML editor
|
|
620
|
+
if (!isExplicitlyBEE) {
|
|
621
|
+
return true;
|
|
622
|
+
}
|
|
623
|
+
}
|
|
624
|
+
|
|
625
|
+
if (!selectedCreateMode) return false;
|
|
626
|
+
|
|
627
|
+
// For HTML Editor (new flow): Always show editor directly without template selection
|
|
628
|
+
// This takes precedence over step check to ensure HTML Editor is shown even if step is temporarily TEMPLATE_SELECTION
|
|
629
|
+
if (!supportCKEditorFlag && selectedCreateMode === EMAIL_CREATE_MODES.HTML_EDITOR) {
|
|
630
|
+
return true;
|
|
631
|
+
}
|
|
632
|
+
|
|
633
|
+
// CRITICAL: For DRAG_DROP mode, show template selection first (CmsTemplatesComponent)
|
|
634
|
+
// Only show editor (Email component with BEE) after template is selected
|
|
635
|
+
if (emailCreateMode === EMAIL_CREATE_MODES.DRAG_DROP || selectedCreateMode === EMAIL_CREATE_MODES.DRAG_DROP) {
|
|
636
|
+
// If we're in TEMPLATE_SELECTION step, show template selection (not email editor)
|
|
637
|
+
if (currentStep === STEPS.TEMPLATE_SELECTION) {
|
|
638
|
+
return false;
|
|
639
|
+
}
|
|
640
|
+
// After template selection, show editor when template is selected
|
|
641
|
+
return !isEmpty(SelectedEdmDefaultTemplate);
|
|
642
|
+
}
|
|
643
|
+
|
|
644
|
+
// If we're in TEMPLATE_SELECTION step, show template selection (not email editor)
|
|
645
|
+
// This applies to legacy Editor modes
|
|
646
|
+
if (currentStep === STEPS.TEMPLATE_SELECTION) {
|
|
647
|
+
return false;
|
|
648
|
+
}
|
|
649
|
+
|
|
650
|
+
// For Upload: Show editor when EmailLayout exists
|
|
651
|
+
if (emailCreateMode === EMAIL_CREATE_MODES.UPLOAD) {
|
|
652
|
+
return !isEmpty(EmailLayout);
|
|
653
|
+
}
|
|
654
|
+
|
|
655
|
+
// For Editor: Show editor when template is selected
|
|
656
|
+
return !isEmpty(SelectedEdmDefaultTemplate);
|
|
657
|
+
}, [currentStep, selectedCreateMode, supportCKEditorFlag, emailCreateMode, EmailLayout, SelectedEdmDefaultTemplate, Email?.templateDetails, Email?.BEETemplate, params?.id, location?.query?.id, location?.params?.id, location?.pathname, emailProps?.editor, emailProps?.selectedEditorMode]);
|
|
658
|
+
|
|
659
|
+
// Memoize static data
|
|
660
|
+
const modes = useMemo(() => {
|
|
661
|
+
const supportCKEditor = hasSupportCKEditor();
|
|
662
|
+
const isBeeEditorEnabledValue = checkBeeEditorEnabled();
|
|
663
|
+
|
|
664
|
+
if (supportCKEditor) {
|
|
665
|
+
// Legacy flow: Show only 2 options (Upload Zip, Use Editor)
|
|
666
|
+
return [
|
|
667
|
+
{
|
|
668
|
+
title: formatMessage(messages.zipUpload),
|
|
669
|
+
content: formatMessage(messages.zipUploadDesc),
|
|
670
|
+
value: EMAIL_CREATE_MODES.UPLOAD,
|
|
671
|
+
},
|
|
672
|
+
{
|
|
673
|
+
title: formatMessage(messages.useEditor),
|
|
674
|
+
content: formatMessage(messages.useEditorDesc),
|
|
675
|
+
value: EMAIL_CREATE_MODES.EDITOR,
|
|
676
|
+
},
|
|
677
|
+
];
|
|
678
|
+
}
|
|
679
|
+
|
|
680
|
+
// New flow: Show 3 options (HTML Editor, Drag & Drop, Upload Zip)
|
|
681
|
+
return [
|
|
682
|
+
{
|
|
683
|
+
title: formatMessage(messages.htmlEditorTitle),
|
|
684
|
+
content: formatMessage(messages.htmlEditorDesc),
|
|
685
|
+
value: EMAIL_CREATE_MODES.HTML_EDITOR,
|
|
686
|
+
icon: <CapIcon type="code" />,
|
|
687
|
+
},
|
|
688
|
+
{
|
|
689
|
+
title: formatMessage(messages.dragDropEditorTitle),
|
|
690
|
+
content: formatMessage(messages.dragDropEditorDesc),
|
|
691
|
+
value: EMAIL_CREATE_MODES.DRAG_DROP,
|
|
692
|
+
icon: <CapIcon type="draggable" svgProps={{ fill: 'currentColor' }} />,
|
|
693
|
+
disabled: !isBeeEditorEnabledValue,
|
|
694
|
+
tooltipProps: !isBeeEditorEnabledValue ? {
|
|
695
|
+
title: formatMessage(messages.beeEditorDisabledTooltip),
|
|
696
|
+
placement: 'top',
|
|
697
|
+
} : undefined,
|
|
698
|
+
},
|
|
699
|
+
{
|
|
700
|
+
title: formatMessage(messages.uploadZipTitle),
|
|
701
|
+
content: formatMessage(messages.uploadZipDesc),
|
|
702
|
+
value: EMAIL_CREATE_MODES.UPLOAD,
|
|
703
|
+
icon: <CapIcon type="file" />,
|
|
704
|
+
},
|
|
705
|
+
];
|
|
706
|
+
}, [formatMessage, checkBeeEditorEnabled]);
|
|
707
|
+
|
|
330
708
|
// Prepare props for CmsTemplatesComponent
|
|
331
709
|
const cmsTemplatesProps = useMemo(() => ({
|
|
332
710
|
cmsTemplates: CmsTemplates,
|
|
@@ -335,6 +713,24 @@ const useEmailWrapper = ({
|
|
|
335
713
|
currentOrgDetails: currentOrgDetails || cap?.currentOrgDetails,
|
|
336
714
|
}), [CmsTemplates, useEditor, cmsTemplatesLoader, currentOrgDetails, cap]);
|
|
337
715
|
|
|
716
|
+
// Check if Next button should be shown (only for new flow)
|
|
717
|
+
const showNextButton = useMemo(() => !hasSupportCKEditor(), []);
|
|
718
|
+
|
|
719
|
+
// Check if Next button should be enabled (for new flow only)
|
|
720
|
+
const isNextButtonEnabled = useMemo(() => {
|
|
721
|
+
const supportCKEditor = hasSupportCKEditor();
|
|
722
|
+
if (supportCKEditor) {
|
|
723
|
+
// Legacy flow: No Next button, always enabled for auto-navigation
|
|
724
|
+
return false;
|
|
725
|
+
}
|
|
726
|
+
// New flow: Enable only when both template name and editor type are selected
|
|
727
|
+
// In library mode (isFullMode=false), template name is not required
|
|
728
|
+
// In full mode (isFullMode=true), template name is required
|
|
729
|
+
const hasTemplateName = !isFullMode || !isTemplateNameEmpty;
|
|
730
|
+
const hasEditorSelection = !!selectedCreateMode;
|
|
731
|
+
return hasTemplateName && hasEditorSelection;
|
|
732
|
+
}, [isTemplateNameEmpty, isFullMode, selectedCreateMode]);
|
|
733
|
+
|
|
338
734
|
// Upload button label
|
|
339
735
|
const uploadButtonLabel = formatMessage(messages.upload);
|
|
340
736
|
|
|
@@ -350,12 +746,15 @@ const useEmailWrapper = ({
|
|
|
350
746
|
emailProps,
|
|
351
747
|
cmsTemplatesProps,
|
|
352
748
|
uploadButtonLabel,
|
|
749
|
+
showNextButton,
|
|
750
|
+
isNextButtonEnabled,
|
|
353
751
|
|
|
354
752
|
// Event handlers
|
|
355
753
|
onTemplateNameChange,
|
|
356
754
|
onChange,
|
|
357
755
|
useFileUpload,
|
|
756
|
+
handleNextClick,
|
|
358
757
|
};
|
|
359
758
|
};
|
|
360
759
|
|
|
361
|
-
export default useEmailWrapper;
|
|
760
|
+
export default useEmailWrapper;
|