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