@capillarytech/creatives-library 8.0.287-alpha.3 → 8.0.288
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/constants/unified.js +1 -0
- package/initialState.js +2 -0
- package/package.json +1 -1
- package/utils/common.js +8 -5
- package/utils/commonUtils.js +111 -2
- package/utils/tagValidations.js +222 -84
- package/utils/tests/commonUtil.test.js +118 -147
- package/utils/tests/tagValidations.test.js +358 -280
- package/v2Components/CapTagList/index.js +7 -2
- package/v2Components/CapTagListWithInput/index.js +4 -0
- package/v2Components/ErrorInfoNote/index.js +5 -2
- package/v2Components/FormBuilder/index.js +187 -74
- package/v2Components/FormBuilder/messages.js +12 -0
- package/v2Components/HtmlEditor/HTMLEditor.js +5 -0
- package/v2Components/HtmlEditor/__tests__/HTMLEditor.apiErrors.test.js +1 -0
- package/v2Components/HtmlEditor/__tests__/HTMLEditor.test.js +15 -0
- package/v2Components/HtmlEditor/components/CodeEditorPane/index.js +2 -1
- package/v2Containers/Cap/mockData.js +14 -0
- package/v2Containers/Cap/reducer.js +55 -3
- package/v2Containers/Cap/tests/reducer.test.js +102 -0
- package/v2Containers/CreativesContainer/SlideBoxContent.js +20 -0
- package/v2Containers/CreativesContainer/SlideBoxFooter.js +40 -6
- package/v2Containers/CreativesContainer/constants.js +6 -0
- package/v2Containers/CreativesContainer/index.js +36 -5
- package/v2Containers/CreativesContainer/messages.js +12 -0
- package/v2Containers/CreativesContainer/tests/SlideBoxFooter.test.js +339 -0
- package/v2Containers/CreativesContainer/tests/__snapshots__/SlideBoxContent.test.js.snap +18 -0
- package/v2Containers/CreativesContainer/tests/__snapshots__/index.test.js.snap +37 -0
- package/v2Containers/Email/index.js +5 -1
- package/v2Containers/EmailWrapper/components/EmailHTMLEditor.js +62 -10
- package/v2Containers/EmailWrapper/components/__tests__/EmailHTMLEditor.test.js +115 -12
- package/v2Containers/FTP/index.js +51 -2
- package/v2Containers/FTP/messages.js +4 -0
- package/v2Containers/InApp/index.js +96 -1
- package/v2Containers/InApp/tests/index.test.js +6 -17
- package/v2Containers/InappAdvance/index.js +103 -2
- package/v2Containers/Line/Container/Text/index.js +1 -0
- package/v2Containers/MobilePush/Create/index.js +37 -1
- package/v2Containers/MobilePush/Create/messages.js +4 -0
- package/v2Containers/MobilePush/Edit/index.js +37 -2
- package/v2Containers/MobilePush/Edit/messages.js +4 -0
- package/v2Containers/MobilePushNew/components/PlatformContentFields.js +36 -12
- package/v2Containers/MobilePushNew/components/tests/PlatformContentFields.test.js +68 -27
- package/v2Containers/MobilePushNew/index.js +92 -5
- package/v2Containers/MobilePushNew/messages.js +8 -0
- package/v2Containers/MobilepushWrapper/index.js +7 -1
- package/v2Containers/Rcs/index.js +37 -12
- package/v2Containers/Sms/Create/index.js +3 -31
- package/v2Containers/Sms/Create/messages.js +0 -4
- package/v2Containers/Sms/Edit/index.js +3 -29
- package/v2Containers/Sms/commonMethods.js +6 -6
- package/v2Containers/SmsTrai/Edit/index.js +47 -6
- package/v2Containers/SmsTrai/Edit/tests/__snapshots__/index.test.js.snap +6 -6
- package/v2Containers/TagList/index.js +17 -1
- package/v2Containers/TagList/messages.js +4 -0
- package/v2Containers/TemplatesV2/index.js +43 -23
- package/v2Containers/Viber/index.js +1 -0
- package/v2Containers/WebPush/Create/hooks/useTagManagement.js +3 -1
- package/v2Containers/WebPush/Create/hooks/useTagManagement.test.js +7 -0
- package/v2Containers/WebPush/Create/index.js +25 -6
- package/v2Containers/WebPush/Create/messages.js +8 -1
- package/v2Containers/WebPush/Create/utils/validation.js +20 -22
- package/v2Containers/WebPush/Create/utils/validation.test.js +52 -0
- package/v2Containers/Whatsapp/index.js +17 -9
- package/v2Containers/Zalo/index.js +11 -3
|
@@ -456,6 +456,7 @@ class CapTagList extends React.Component { // eslint-disable-line react/prefer-s
|
|
|
456
456
|
</CapSpin>
|
|
457
457
|
</CapRow>
|
|
458
458
|
);
|
|
459
|
+
const {disableTooltipMsg, disabled} = this.props || {};
|
|
459
460
|
return (
|
|
460
461
|
<>
|
|
461
462
|
{hidePopover ? (
|
|
@@ -476,7 +477,9 @@ class CapTagList extends React.Component { // eslint-disable-line react/prefer-s
|
|
|
476
477
|
>
|
|
477
478
|
<CapTooltip
|
|
478
479
|
title={
|
|
479
|
-
|
|
480
|
+
disableTooltipMsg && disabled ? (
|
|
481
|
+
disableTooltipMsg
|
|
482
|
+
) : fetchingSchemaError ? (
|
|
480
483
|
<CapRow className="tooltip-text-container">
|
|
481
484
|
<CapLabel className="tooltip-text1">
|
|
482
485
|
{formatMessage(messages.somethingWentWrong)}
|
|
@@ -485,7 +488,7 @@ class CapTagList extends React.Component { // eslint-disable-line react/prefer-s
|
|
|
485
488
|
{formatMessage(messages.labelFetchErrorMsg)}
|
|
486
489
|
</CapLabel>
|
|
487
490
|
</CapRow>
|
|
488
|
-
)
|
|
491
|
+
) : null
|
|
489
492
|
}
|
|
490
493
|
placement="right"
|
|
491
494
|
>
|
|
@@ -538,6 +541,8 @@ CapTagList.propTypes = {
|
|
|
538
541
|
currentOrgDetails: PropTypes.object,
|
|
539
542
|
channel: PropTypes.string,
|
|
540
543
|
disabled: PropTypes.bool,
|
|
544
|
+
// Optional custom tooltip message when disabled (used for personalization restriction)
|
|
545
|
+
disableTooltipMsg: PropTypes.string,
|
|
541
546
|
fetchingSchemaError: PropTypes.bool,
|
|
542
547
|
popoverPlacement: PropTypes.string,
|
|
543
548
|
};
|
|
@@ -26,6 +26,7 @@ export const CapTagListWithInput = (props) => {
|
|
|
26
26
|
className = '',
|
|
27
27
|
userLocale = 'en',
|
|
28
28
|
eventContextTags = [],
|
|
29
|
+
restrictPersonalization = false,
|
|
29
30
|
// CapInput props
|
|
30
31
|
inputId,
|
|
31
32
|
inputValue = '',
|
|
@@ -78,6 +79,7 @@ export const CapTagListWithInput = (props) => {
|
|
|
78
79
|
eventContextTags={eventContextTags}
|
|
79
80
|
style={tagListStyle}
|
|
80
81
|
popoverPlacement={popoverPlacement}
|
|
82
|
+
restrictPersonalization={restrictPersonalization}
|
|
81
83
|
/>
|
|
82
84
|
)}
|
|
83
85
|
</CapRow>
|
|
@@ -113,6 +115,7 @@ CapTagListWithInput.propTypes = {
|
|
|
113
115
|
className: PropTypes.string,
|
|
114
116
|
userLocale: PropTypes.string,
|
|
115
117
|
eventContextTags: PropTypes.array,
|
|
118
|
+
restrictPersonalization: PropTypes.bool,
|
|
116
119
|
|
|
117
120
|
// CapInput props
|
|
118
121
|
inputId: PropTypes.string.isRequired,
|
|
@@ -150,6 +153,7 @@ CapTagListWithInput.defaultProps = {
|
|
|
150
153
|
className: '',
|
|
151
154
|
userLocale: 'en',
|
|
152
155
|
eventContextTags: [],
|
|
156
|
+
restrictPersonalization: false,
|
|
153
157
|
inputValue: '',
|
|
154
158
|
inputSize: 'default',
|
|
155
159
|
inputRequired: false,
|
|
@@ -186,6 +186,7 @@ export const ErrorInfoNote = (props) => {
|
|
|
186
186
|
errorMessages,
|
|
187
187
|
onErrorClick,
|
|
188
188
|
onClose,
|
|
189
|
+
isLiquidEnabled = true,
|
|
189
190
|
intl,
|
|
190
191
|
useLegacyDisplay = false, // Use simple list display instead of tabs (for BEE Editor)
|
|
191
192
|
} = props;
|
|
@@ -229,7 +230,7 @@ export const ErrorInfoNote = (props) => {
|
|
|
229
230
|
const standardErrors = Array.isArray(rawStandardErrors) ? rawStandardErrors : [];
|
|
230
231
|
const liquidErrors = Array.isArray(rawLiquidErrors) ? rawLiquidErrors : [];
|
|
231
232
|
const hasStandardErrors = standardErrors.length > 0;
|
|
232
|
-
const hasLiquidErrors = liquidErrors.length > 0;
|
|
233
|
+
const hasLiquidErrors = liquidErrors.length > 0 && isLiquidEnabled;
|
|
233
234
|
|
|
234
235
|
if (!hasStandardErrors && !hasLiquidErrors) {
|
|
235
236
|
return null;
|
|
@@ -356,7 +357,7 @@ export const ErrorInfoNote = (props) => {
|
|
|
356
357
|
className="error-info-note__tabs"
|
|
357
358
|
/>
|
|
358
359
|
<CapRow className="error-info-note__actions">
|
|
359
|
-
{hasLiquidErrors && (
|
|
360
|
+
{hasLiquidErrors && isLiquidEnabled && (
|
|
360
361
|
<CapButton
|
|
361
362
|
type="flat"
|
|
362
363
|
className="error-info-note__liquid-doc"
|
|
@@ -451,6 +452,7 @@ ErrorInfoNote.defaultProps = {
|
|
|
451
452
|
},
|
|
452
453
|
onErrorClick: null,
|
|
453
454
|
onClose: null,
|
|
455
|
+
isLiquidEnabled: true,
|
|
454
456
|
intl: null,
|
|
455
457
|
useLegacyDisplay: false, // Use simple list display for BEE Editor
|
|
456
458
|
};
|
|
@@ -477,6 +479,7 @@ ErrorInfoNote.propTypes = {
|
|
|
477
479
|
}),
|
|
478
480
|
onErrorClick: PropTypes.func,
|
|
479
481
|
onClose: PropTypes.func,
|
|
482
|
+
isLiquidEnabled: PropTypes.bool,
|
|
480
483
|
intl: PropTypes.object,
|
|
481
484
|
useLegacyDisplay: PropTypes.bool, // Use simple list display for BEE Editor
|
|
482
485
|
};
|
|
@@ -50,7 +50,7 @@ import { makeSelectMetaEntities, selectCurrentOrgDetails, selectLiquidStateDetai
|
|
|
50
50
|
import * as actions from "../../v2Containers/Cap/actions";
|
|
51
51
|
import './_formBuilder.scss';
|
|
52
52
|
import {updateCharCount, checkUnicode} from "../../utils/smsCharCountV2";
|
|
53
|
-
import { preprocessHtml,
|
|
53
|
+
import { checkSupport, extractNames, preprocessHtml, validateIfTagClosed, isInsideLiquidBlock} from '../../utils/tagValidations';
|
|
54
54
|
import { containsBase64Images } from '../../utils/content';
|
|
55
55
|
import { SMS, MOBILE_PUSH, LINE, ENABLE_AI_SUGGESTIONS,AI_CONTENT_BOT_DISABLED, EMAIL, LIQUID_SUPPORTED_CHANNELS, INAPP } from '../../v2Containers/CreativesContainer/constants';
|
|
56
56
|
import globalMessages from '../../v2Containers/Cap/messages';
|
|
@@ -60,10 +60,10 @@ import { GET_TRANSLATION_MAPPED } from '../../constants/unified';
|
|
|
60
60
|
import moment from 'moment';
|
|
61
61
|
import { CUSTOMER_BARCODE_TAG , COPY_OF, ENTRY_TRIGGER_TAG_REGEX, SKIP_TAGS_REGEX_GROUPS} from '../../constants/unified';
|
|
62
62
|
import { REQUEST } from '../../v2Containers/Cap/constants'
|
|
63
|
-
import {
|
|
63
|
+
import { hasLiquidSupportFeature, isEmailUnsubscribeTagMandatory } from '../../utils/common';
|
|
64
64
|
import { isUrl } from '../../v2Containers/Line/Container/Wrapper/utils';
|
|
65
65
|
import { bindActionCreators } from 'redux';
|
|
66
|
-
import { getChannelData, validateLiquidTemplateContent, validateMobilePushContent } from '../../utils/commonUtils';
|
|
66
|
+
import { getChannelData, hasPersonalizationTags, validateLiquidTemplateContent, validateMobilePushContent } from '../../utils/commonUtils';
|
|
67
67
|
const TabPane = Tabs.TabPane;
|
|
68
68
|
const {Column} = Table;
|
|
69
69
|
const {TextArea} = CapInput;
|
|
@@ -72,8 +72,10 @@ const {CapRadioGroup} = CapRadio;
|
|
|
72
72
|
|
|
73
73
|
const tagsTypes = {
|
|
74
74
|
MISSING_TAGS: 'missingTags',
|
|
75
|
+
UNSUPPORTED_TAGS: 'unsupportedTags',
|
|
75
76
|
};
|
|
76
77
|
const errorMessageForTags = {
|
|
78
|
+
UNSUPPORTED_TAG_ERROR: 'unsupportedTagsError',
|
|
77
79
|
MISSING_TAG_ERROR: 'missingTagsError',
|
|
78
80
|
GENERIC_VALIDATION_ERROR: 'genericValidationError',
|
|
79
81
|
TAG_BRACKET_COUNT_MISMATCH_ERROR: 'tagBracketCountMismatchError'
|
|
@@ -136,7 +138,7 @@ class FormBuilder extends React.Component { // eslint-disable-line react/prefer-
|
|
|
136
138
|
this.handleSetRadioValue = this.handleSetRadioValue.bind(this);
|
|
137
139
|
this.formElements = [];
|
|
138
140
|
// Check if the liquid flow feature is supported and the channel is in the supported list.
|
|
139
|
-
this.
|
|
141
|
+
this.liquidFlow = this.isLiquidFlowSupported.bind(this);
|
|
140
142
|
this.onSubmitWrapper = this.onSubmitWrapper.bind(this);
|
|
141
143
|
|
|
142
144
|
// Performance optimization: Debounced functions for high-frequency updates
|
|
@@ -328,8 +330,8 @@ class FormBuilder extends React.Component { // eslint-disable-line react/prefer-
|
|
|
328
330
|
return updatedFormData;
|
|
329
331
|
}
|
|
330
332
|
|
|
331
|
-
|
|
332
|
-
return Boolean(LIQUID_SUPPORTED_CHANNELS.includes(this.props?.schema?.channel?.toUpperCase()));
|
|
333
|
+
isLiquidFlowSupported = () => {
|
|
334
|
+
return Boolean(LIQUID_SUPPORTED_CHANNELS.includes(this.props?.schema?.channel?.toUpperCase()) && hasLiquidSupportFeature());
|
|
333
335
|
}
|
|
334
336
|
|
|
335
337
|
componentWillMount() {
|
|
@@ -712,9 +714,7 @@ class FormBuilder extends React.Component { // eslint-disable-line react/prefer-
|
|
|
712
714
|
if (channel && channel.toUpperCase() === SMS) {
|
|
713
715
|
for (let count = 0; count < this.state.tabCount; count += 1) {
|
|
714
716
|
if (_.isEmpty(errorData[count])) {
|
|
715
|
-
|
|
716
|
-
// prevents onFormValidityChange from firing, which makes Done appear unresponsive.
|
|
717
|
-
errorData[count] = {};
|
|
717
|
+
return;
|
|
718
718
|
}
|
|
719
719
|
const index = count + 1;
|
|
720
720
|
if (!this.state.formData[count]) {
|
|
@@ -726,19 +726,17 @@ class FormBuilder extends React.Component { // eslint-disable-line react/prefer-
|
|
|
726
726
|
|
|
727
727
|
let tagValidationResponse = false;
|
|
728
728
|
if (content) {
|
|
729
|
-
tagValidationResponse = this.validateTags(content, tags, false, this.props?.isFullMode);
|
|
729
|
+
tagValidationResponse = this.validateTags(content, tags, injectedTags, false, this.props?.isFullMode);
|
|
730
730
|
}
|
|
731
|
-
|
|
732
|
-
|
|
733
|
-
? tagValidationResponse
|
|
734
|
-
: { valid: false, missingTags: [], isBraceError: false };
|
|
735
|
-
if (tagResult.valid) {
|
|
731
|
+
|
|
732
|
+
if (tagValidationResponse.valid) {
|
|
736
733
|
errorData[count][`sms-editor${index > 1 ? index : ''}`] = false;
|
|
737
734
|
} else {
|
|
738
|
-
|
|
739
|
-
const {
|
|
740
|
-
|
|
741
|
-
errorData[count][`
|
|
735
|
+
errorData[count]['invalid-tags'] = tagValidationResponse.unsupportedTags;
|
|
736
|
+
const { MISSING_TAG_ERROR, UNSUPPORTED_TAG_ERROR, GENERIC_VALIDATION_ERROR, TAG_BRACKET_COUNT_MISMATCH_ERROR } = errorMessageForTags || {};
|
|
737
|
+
const { missingTags, unsupportedTags, isBraceError} = tagValidationResponse;
|
|
738
|
+
errorData[count][`sms-editor${index > 1 ? index : ''}`] = missingTags && missingTags.length ? MISSING_TAG_ERROR : ( unsupportedTags && unsupportedTags.length ? UNSUPPORTED_TAG_ERROR : (isBraceError ? TAG_BRACKET_COUNT_MISMATCH_ERROR : GENERIC_VALIDATION_ERROR));
|
|
739
|
+
errorData[count][`bracket-error`] = tagValidationResponse.isBraceError && TAG_BRACKET_COUNT_MISMATCH_ERROR;
|
|
742
740
|
isValid = false;
|
|
743
741
|
}
|
|
744
742
|
if(content !== '' && (ifUnicode && !unicodeCheck)) {
|
|
@@ -766,7 +764,7 @@ class FormBuilder extends React.Component { // eslint-disable-line react/prefer-
|
|
|
766
764
|
if (this.state.formData['message-editor'] !== undefined ) {
|
|
767
765
|
const content = this.state.formData['0']['message-editor'] || '';
|
|
768
766
|
|
|
769
|
-
const tagValidationResponse = this.validateTags((content), tags, false, this.props?.isFullMode);
|
|
767
|
+
const tagValidationResponse = this.validateTags((content), tags, injectedTags, false, this.props?.isFullMode);
|
|
770
768
|
|
|
771
769
|
if (tagValidationResponse.valid) {
|
|
772
770
|
errorData = {
|
|
@@ -849,7 +847,7 @@ class FormBuilder extends React.Component { // eslint-disable-line react/prefer-
|
|
|
849
847
|
errorData[index] = true;
|
|
850
848
|
isValid = false;
|
|
851
849
|
} else {
|
|
852
|
-
const tagValidationResponse = this.validateTags(content, tags, false, this.props?.isFullMode);
|
|
850
|
+
const tagValidationResponse = this.validateTags(content, tags, injectedTags, false, this.props?.isFullMode);
|
|
853
851
|
|
|
854
852
|
if (tagValidationResponse.valid) {
|
|
855
853
|
errorData[index] = false;
|
|
@@ -905,20 +903,24 @@ class FormBuilder extends React.Component { // eslint-disable-line react/prefer-
|
|
|
905
903
|
if (errorData[parseInt(index)]) {
|
|
906
904
|
if (message) {
|
|
907
905
|
message = message.trim();
|
|
908
|
-
|
|
909
906
|
if (message === "") {
|
|
910
907
|
errorData[parseInt(index)][`message-editor${selector}`] = true;
|
|
911
908
|
isValid = false;
|
|
912
909
|
isCurrentTabValid = false;
|
|
910
|
+
} else if (this.props.restrictPersonalization && hasPersonalizationTags(message)) {
|
|
911
|
+
errorData[parseInt(index)][`message-editor${selector}`] = true;
|
|
912
|
+
isValid = false;
|
|
913
|
+
isCurrentTabValid = false;
|
|
913
914
|
} else {
|
|
914
915
|
errorData[parseInt(index)][`message-editor${selector}`] = false;
|
|
915
|
-
const tagValidationResponse = this.validateTags(message, tags, false, this.props?.isFullMode);
|
|
916
|
+
const tagValidationResponse = this.validateTags(message, tags, injectedTags, false, this.props?.isFullMode);
|
|
916
917
|
|
|
917
918
|
if (tagValidationResponse.valid) {
|
|
918
919
|
errorData[parseInt(index)][`message-editor${selector}`] = false;
|
|
919
920
|
} else {
|
|
920
|
-
const {
|
|
921
|
+
const {isBraceError} = tagValidationResponse;
|
|
921
922
|
errorData[parseInt(index)][`message-editor${selector}`] = isBraceError ? TAG_BRACKET_COUNT_MISMATCH_ERROR : true;
|
|
923
|
+
errorData[parseInt(index)]['invalid-tags'] = tagValidationResponse.unsupportedTags;
|
|
922
924
|
errorData[parseInt(index)][`bracket-error`] = isBraceError && TAG_BRACKET_COUNT_MISMATCH_ERROR;
|
|
923
925
|
isValid = false;
|
|
924
926
|
}
|
|
@@ -938,9 +940,13 @@ class FormBuilder extends React.Component { // eslint-disable-line react/prefer-
|
|
|
938
940
|
errorData[parseInt(index)][`message-title${selector}`] = true;
|
|
939
941
|
isValid = false;
|
|
940
942
|
isCurrentTabValid = false;
|
|
943
|
+
} else if (this.props.restrictPersonalization && hasPersonalizationTags(title)) {
|
|
944
|
+
errorData[parseInt(index)][`message-title${selector}`] = true;
|
|
945
|
+
isValid = false;
|
|
946
|
+
isCurrentTabValid = false;
|
|
941
947
|
} else {
|
|
942
948
|
errorData[parseInt(index)][`message-title${selector}`] = false;
|
|
943
|
-
const tagValidationResponse = this.validateTags(title, tags, false, this.props?.isFullMode);
|
|
949
|
+
const tagValidationResponse = this.validateTags(title, tags, injectedTags, false, this.props?.isFullMode);
|
|
944
950
|
|
|
945
951
|
if (tagValidationResponse.valid) {
|
|
946
952
|
errorData[parseInt(index)][`message-title${selector}`] = false;
|
|
@@ -1194,7 +1200,8 @@ class FormBuilder extends React.Component { // eslint-disable-line react/prefer-
|
|
|
1194
1200
|
if (!content) {
|
|
1195
1201
|
return false;
|
|
1196
1202
|
}
|
|
1197
|
-
const tagValidationResponse = this.validateTags(content, tags, isEmail, this.props?.isFullMode);
|
|
1203
|
+
const tagValidationResponse = this.validateTags(content, tags, injectedTags, isEmail, this.props?.isFullMode);
|
|
1204
|
+
|
|
1198
1205
|
// Check for base64 images in email content
|
|
1199
1206
|
isEmail && containsBase64Images({content, callback:()=>{
|
|
1200
1207
|
tagValidationResponse.valid = false;
|
|
@@ -1210,20 +1217,23 @@ class FormBuilder extends React.Component { // eslint-disable-line react/prefer-
|
|
|
1210
1217
|
errorData[index][currentLang]['template-content'] = true;
|
|
1211
1218
|
isValid = false;
|
|
1212
1219
|
isLiquidValid = false;
|
|
1213
|
-
if ((showMessages && !isNaN(index)) || this.
|
|
1214
|
-
if (tagValidationResponse?.missingTags?.length > 0) {
|
|
1220
|
+
if ((showMessages && !isNaN(index)) || this.liquidFlow()) {
|
|
1221
|
+
if (tagValidationResponse?.missingTags?.length > 0 || tagValidationResponse?.unsupportedTags?.length > 0) {
|
|
1215
1222
|
errorString += `${this.props.intl.formatMessage(messages.contentNotValidLanguage)} ${currentLang}\n`;
|
|
1216
1223
|
}
|
|
1217
1224
|
if (tagValidationResponse?.missingTags?.length > 0) {
|
|
1218
1225
|
errorString += `${this.props.intl.formatMessage(messages.missingTags)} ${tagValidationResponse.missingTags.toString()}\n`;
|
|
1219
1226
|
}
|
|
1227
|
+
if (tagValidationResponse?.unsupportedTags?.length > 0) {
|
|
1228
|
+
errorString += `${this.props.intl.formatMessage(messages.unsupportedTags)} ${tagValidationResponse.unsupportedTags.toString()}\n`;
|
|
1229
|
+
}
|
|
1220
1230
|
if (tagValidationResponse?.isBraceError){
|
|
1221
1231
|
errorString += this.props.intl.formatMessage(globalMessages.unbalanacedCurlyBraces);
|
|
1222
1232
|
}
|
|
1223
1233
|
if (tagValidationResponse?.isContentEmpty) {
|
|
1224
1234
|
errorString += this.props.intl.formatMessage(messages.emailBodyEmptyError);
|
|
1225
1235
|
// Adds a bypass for cases where content is initially empty in the creation flow.
|
|
1226
|
-
if(this.
|
|
1236
|
+
if(this.liquidFlow()){
|
|
1227
1237
|
errorString = "";
|
|
1228
1238
|
isLiquidValid = true;
|
|
1229
1239
|
}
|
|
@@ -1235,7 +1245,7 @@ class FormBuilder extends React.Component { // eslint-disable-line react/prefer-
|
|
|
1235
1245
|
}
|
|
1236
1246
|
}
|
|
1237
1247
|
if (errorString) {
|
|
1238
|
-
if (this.
|
|
1248
|
+
if (this.liquidFlow()) {
|
|
1239
1249
|
this.setState(
|
|
1240
1250
|
(prevState) => ({
|
|
1241
1251
|
liquidErrorMessage: {
|
|
@@ -1262,7 +1272,7 @@ class FormBuilder extends React.Component { // eslint-disable-line react/prefer-
|
|
|
1262
1272
|
});
|
|
1263
1273
|
}
|
|
1264
1274
|
|
|
1265
|
-
const isTemplateValid = this.
|
|
1275
|
+
const isTemplateValid = this.liquidFlow() ? isLiquidValid : isValid;
|
|
1266
1276
|
//Updating the state with the error data
|
|
1267
1277
|
this.setState((prevState) => ({
|
|
1268
1278
|
isFormValid: isTemplateValid,
|
|
@@ -1321,7 +1331,7 @@ class FormBuilder extends React.Component { // eslint-disable-line react/prefer-
|
|
|
1321
1331
|
}
|
|
1322
1332
|
onSubmitWrapper = (args) => {
|
|
1323
1333
|
const {singleTab = null} = args || {};
|
|
1324
|
-
if (this.
|
|
1334
|
+
if (this.liquidFlow()) {
|
|
1325
1335
|
// For MPUSH, we need to validate both Android and iOS content separately
|
|
1326
1336
|
if (this.props.channel === MOBILE_PUSH || this.props?.schema?.channel?.toUpperCase() === MOBILE_PUSH) {
|
|
1327
1337
|
this.validateFormBuilderMPush(this.state.formData, singleTab);
|
|
@@ -1365,6 +1375,10 @@ class FormBuilder extends React.Component { // eslint-disable-line react/prefer-
|
|
|
1365
1375
|
messages,
|
|
1366
1376
|
onError,
|
|
1367
1377
|
onSuccess,
|
|
1378
|
+
tagLookupMap: this.props?.metaEntities?.tagLookupMap,
|
|
1379
|
+
eventContextTags: this.props?.eventContextTags,
|
|
1380
|
+
isLiquidFlow: this.liquidFlow(),
|
|
1381
|
+
forwardedTags: this.props?.isLoyaltyModule ? this.props?.forwardedTags : {},
|
|
1368
1382
|
skipTags: this.skipTags.bind(this)
|
|
1369
1383
|
});
|
|
1370
1384
|
} else {
|
|
@@ -1433,6 +1447,13 @@ class FormBuilder extends React.Component { // eslint-disable-line react/prefer-
|
|
|
1433
1447
|
getLiquidTags: this.props.actions.getLiquidTags,
|
|
1434
1448
|
formatMessage: this.props.intl.formatMessage,
|
|
1435
1449
|
messages: messages,
|
|
1450
|
+
tagLookupMap: this.props?.metaEntities?.tagLookupMap,
|
|
1451
|
+
eventContextTags: this.props?.eventContextTags,
|
|
1452
|
+
isLiquidFlow: this.liquidFlow(), // Use the method instead of props
|
|
1453
|
+
forwardedTags: this.props?.isLoyaltyModule ? this.props?.forwardedTags : {},
|
|
1454
|
+
skipTags: this.skipTags.bind(this),
|
|
1455
|
+
extractNames,
|
|
1456
|
+
checkSupport,
|
|
1436
1457
|
singleTab: singleTab?.toUpperCase(),
|
|
1437
1458
|
});
|
|
1438
1459
|
}
|
|
@@ -1487,41 +1508,116 @@ class FormBuilder extends React.Component { // eslint-disable-line react/prefer-
|
|
|
1487
1508
|
});
|
|
1488
1509
|
}
|
|
1489
1510
|
|
|
1490
|
-
validateTags(content, tagsParam, isEmail = false, isFullMode = this.props?.isFullMode) {
|
|
1511
|
+
validateTags(content, tagsParam, injectedTagsParams, isEmail = false, isFullMode = this.props?.isFullMode) {
|
|
1512
|
+
const type = (this.props.location && this.props.location.query.type) ? this.props.location.query.type : 'full';
|
|
1491
1513
|
let currentModule = this.props.location.query.module ? this.props.location.query.module : 'default';
|
|
1492
1514
|
if (this.props.tagModule) {
|
|
1493
1515
|
currentModule = this.props.tagModule;
|
|
1494
1516
|
}
|
|
1495
1517
|
const tags = tagsParam ? tagsParam : this.props.tags;
|
|
1496
|
-
const
|
|
1497
|
-
const
|
|
1498
|
-
|
|
1499
|
-
|
|
1500
|
-
|
|
1501
|
-
|
|
1502
|
-
|
|
1503
|
-
|
|
1504
|
-
|
|
1505
|
-
|
|
1506
|
-
|
|
1507
|
-
|
|
1508
|
-
|
|
1509
|
-
|
|
1510
|
-
|
|
1511
|
-
|
|
1512
|
-
|
|
1513
|
-
|
|
1514
|
-
|
|
1515
|
-
|
|
1516
|
-
|
|
1517
|
-
|
|
1518
|
-
|
|
1519
|
-
|
|
1518
|
+
const injectedTags = this.transformInjectedTags(injectedTagsParams ? injectedTagsParams : this.props.injectedTags);
|
|
1519
|
+
const excludedTags = ['user_id_b64', 'outbox_id_b64'];
|
|
1520
|
+
|
|
1521
|
+
|
|
1522
|
+
const response = {};
|
|
1523
|
+
response.valid = true;
|
|
1524
|
+
response.missingTags = [];
|
|
1525
|
+
response.unsupportedTags = [];
|
|
1526
|
+
response.isBraceError = false;
|
|
1527
|
+
response.isContentEmpty = false;
|
|
1528
|
+
const contentForValidation = isEmail ? convert(content, GLOBAL_CONVERT_OPTIONS) : content ;
|
|
1529
|
+
const isModuleTypeOutbound = (this.props?.moduleType || '').toUpperCase() === OUTBOUND;
|
|
1530
|
+
// Run tag validation (missing + unsupported): library mode, or full mode with liquid support, or
|
|
1531
|
+
// legacy Email (CK Editor) when unsubscribe is required (EMAIL_UNSUBSCRIBE_TAG_MANDATORY false) so missing-unsubscribe error shows
|
|
1532
|
+
const shouldRunTagValidation = !isFullMode
|
|
1533
|
+
|| (isEmail && hasLiquidSupportFeature())
|
|
1534
|
+
|| (isEmail && !isEmailUnsubscribeTagMandatory() && isModuleTypeOutbound);
|
|
1535
|
+
if (tags && tags.length && !isFullMode) {
|
|
1536
|
+
_.forEach(tags, (tag) => {
|
|
1537
|
+
_.forEach(tag.definition.supportedModules, (module) => {
|
|
1538
|
+
if (module.mandatory && (currentModule === module.context)) {
|
|
1539
|
+
if (content.indexOf(`{{${tag.definition.value}}}`) === -1) {
|
|
1540
|
+
response.valid = false;
|
|
1541
|
+
response.missingTags.push(tag.definition.value);
|
|
1542
|
+
}
|
|
1543
|
+
}
|
|
1544
|
+
});
|
|
1545
|
+
});
|
|
1546
|
+
// Legacy Email (CK Editor): when unsubscribe is required, ensure we validate it even if tag schema didn't mark it mandatory for this module
|
|
1547
|
+
if (isEmail && !isEmailUnsubscribeTagMandatory() && isModuleTypeOutbound) {
|
|
1548
|
+
const hasUnsubscribeInContent = /{{unsubscribe(\(#[a-zA-Z\d]{6}\))?}}/g.test(content);
|
|
1549
|
+
if (!hasUnsubscribeInContent && response.missingTags.indexOf('unsubscribe') === -1) {
|
|
1550
|
+
response.valid = false;
|
|
1551
|
+
response.missingTags.push('unsubscribe');
|
|
1552
|
+
}
|
|
1553
|
+
}
|
|
1554
|
+
const regex = /{{[(A-Z\w+(\s\w+)*$\(\)@!#$%^&*~.,/\\]+}}/g;
|
|
1555
|
+
let match = regex.exec(content);
|
|
1556
|
+
const regexImgSrc=/<img[^>]*\bsrc\s*=\s*"[^"]*{{customer_barcode}}[^"]*"/;
|
|
1557
|
+
let matchImg = regexImgSrc.exec(content);
|
|
1558
|
+
const regexCustomerBarcode = /{{customer_barcode}}(?![^<]*>)/g;
|
|
1559
|
+
let matchCustomerBarcode = regexCustomerBarcode.exec(content);
|
|
1560
|
+
// \S matches anything other than a space, a tab, a newline, or a carriage return.
|
|
1561
|
+
const validString= /\S/.test(contentForValidation);
|
|
1562
|
+
if (isEmailUnsubscribeTagMandatory() && isEmail && isModuleTypeOutbound) {
|
|
1563
|
+
const missingTagIndex = response?.missingTags?.indexOf("unsubscribe");
|
|
1564
|
+
if(missingTagIndex != -1) { //skip regex tags for mandatory tags also
|
|
1565
|
+
response?.missingTags?.splice(missingTagIndex, 1);
|
|
1566
|
+
}
|
|
1567
|
+
if (validString) {
|
|
1568
|
+
response.valid = true;
|
|
1569
|
+
} else {
|
|
1570
|
+
response.isContentEmpty = true;
|
|
1571
|
+
}
|
|
1520
1572
|
}
|
|
1521
|
-
|
|
1522
|
-
|
|
1573
|
+
while (match !== null ) {
|
|
1574
|
+
const tagValue = match[0].substring(this.indexOfEnd(match[0], '{{'), match[0].indexOf('}}'));
|
|
1575
|
+
const tagIndex = match?.index;
|
|
1576
|
+
match = regex.exec(content);
|
|
1577
|
+
let ifSupported = false;
|
|
1578
|
+
_.forEach(tags, (tag) => {
|
|
1579
|
+
if (tag.definition.value === tagValue) {
|
|
1580
|
+
ifSupported = true;
|
|
1581
|
+
}
|
|
1582
|
+
if(tagValue === CUSTOMER_BARCODE_TAG && (matchImg === null || matchCustomerBarcode !== null)){
|
|
1583
|
+
ifSupported = false;
|
|
1584
|
+
}
|
|
1585
|
+
});
|
|
1586
|
+
const ifSkipped = this.skipTags(tagValue);
|
|
1587
|
+
if (ifSkipped) {
|
|
1588
|
+
ifSupported = true;
|
|
1589
|
+
let isUnsubscribeSkipped = tagValue.indexOf("unsubscribe") != -1 ;
|
|
1590
|
+
if (isUnsubscribeSkipped) {
|
|
1591
|
+
const missingTagIndex = response.missingTags.indexOf("unsubscribe");
|
|
1592
|
+
if(missingTagIndex != -1) { //skip regex tags for mandatory tags also
|
|
1593
|
+
response.missingTags.splice(missingTagIndex, 1);
|
|
1594
|
+
}
|
|
1595
|
+
}
|
|
1596
|
+
}
|
|
1597
|
+
|
|
1598
|
+
// Event Context Tags support
|
|
1599
|
+
this.props?.eventContextTags?.forEach((tag) => {
|
|
1600
|
+
if (tagValue === tag?.tagName) {
|
|
1601
|
+
ifSupported = true;
|
|
1602
|
+
}
|
|
1603
|
+
});
|
|
1604
|
+
|
|
1605
|
+
ifSupported = ifSupported || this.checkIfSupportedTag(tagValue, injectedTags);
|
|
1606
|
+
// Only add to unsupportedTags if not inside a {% ... %} block (scenario 3: liquid orgs also get unsupported-tag errors)
|
|
1607
|
+
if (!ifSupported && !isInsideLiquidBlock(content, tagIndex)) {
|
|
1608
|
+
response.unsupportedTags.push(tagValue);
|
|
1609
|
+
response.valid = false;
|
|
1610
|
+
}
|
|
1611
|
+
|
|
1612
|
+
if (response?.unsupportedTags?.length == 0 && response?.missingTags?.length == 0 ) {
|
|
1613
|
+
response.valid = true;
|
|
1614
|
+
}
|
|
1523
1615
|
}
|
|
1524
1616
|
}
|
|
1617
|
+
if(!validateIfTagClosed(contentForValidation)){
|
|
1618
|
+
response.isBraceError = true;
|
|
1619
|
+
response.valid = false;
|
|
1620
|
+
}
|
|
1525
1621
|
return response;
|
|
1526
1622
|
}
|
|
1527
1623
|
/* eslint-enable */
|
|
@@ -2754,21 +2850,21 @@ class FormBuilder extends React.Component { // eslint-disable-line react/prefer-
|
|
|
2754
2850
|
|
|
2755
2851
|
|
|
2756
2852
|
getMissingOrUnsupportedTagsName = (content = '', type) => {
|
|
2757
|
-
const { MISSING_TAGS } = tagsTypes;
|
|
2853
|
+
const { MISSING_TAGS, UNSUPPORTED_TAGS} = tagsTypes;
|
|
2758
2854
|
const tagValidationResponse = this.validateTags(content);
|
|
2759
|
-
if (type && type === MISSING_TAGS) {
|
|
2760
|
-
return
|
|
2855
|
+
if (type && (type === MISSING_TAGS || type === UNSUPPORTED_TAGS)) {
|
|
2856
|
+
return tagValidationResponse[type].join(', ').toString();
|
|
2761
2857
|
}
|
|
2762
2858
|
return null;
|
|
2763
2859
|
};
|
|
2764
2860
|
|
|
2765
2861
|
renderTextAreaContent = (styling, columns, val, isVersionEnable, rows, cols, offset = 0) => {
|
|
2766
2862
|
const { checkValidation, errorData, currentTab, formData } = this.state;
|
|
2767
|
-
const { MISSING_TAGS } = tagsTypes;
|
|
2863
|
+
const { MISSING_TAGS, UNSUPPORTED_TAGS } = tagsTypes;
|
|
2768
2864
|
const errorType = (isVersionEnable ? errorData[`${currentTab - 1}`][val.id] : errorData[val.id]);
|
|
2769
2865
|
const ifError = checkValidation && errorType;
|
|
2770
2866
|
const messageContent = isVersionEnable ? formData[`${currentTab - 1}`][val.id] : formData[val.id];
|
|
2771
|
-
const { MISSING_TAG_ERROR, TAG_BRACKET_COUNT_MISMATCH_ERROR } = errorMessageForTags;
|
|
2867
|
+
const { MISSING_TAG_ERROR, UNSUPPORTED_TAG_ERROR, TAG_BRACKET_COUNT_MISMATCH_ERROR } = errorMessageForTags;
|
|
2772
2868
|
const { formatMessage } = this.props.intl;
|
|
2773
2869
|
|
|
2774
2870
|
const { accessibleFeatures = [] } = this.props.currentOrgDetails || {};
|
|
@@ -2781,6 +2877,9 @@ class FormBuilder extends React.Component { // eslint-disable-line react/prefer-
|
|
|
2781
2877
|
case MISSING_TAG_ERROR:
|
|
2782
2878
|
errorMessageText = formatMessage(messages.missingTagsValidationError, {missingTags: this.getMissingOrUnsupportedTagsName(messageContent, MISSING_TAGS)});
|
|
2783
2879
|
break;
|
|
2880
|
+
case UNSUPPORTED_TAG_ERROR:
|
|
2881
|
+
errorMessageText = formatMessage(messages.unsupportedTagsValidationError, {unsupportedTags: this.getMissingOrUnsupportedTagsName(messageContent, UNSUPPORTED_TAGS)});
|
|
2882
|
+
break;
|
|
2784
2883
|
case TAG_BRACKET_COUNT_MISMATCH_ERROR:
|
|
2785
2884
|
errorMessageText = formatMessage(globalMessages.unbalanacedCurlyBraces);
|
|
2786
2885
|
break;
|
|
@@ -2790,8 +2889,12 @@ class FormBuilder extends React.Component { // eslint-disable-line react/prefer-
|
|
|
2790
2889
|
default:
|
|
2791
2890
|
break;
|
|
2792
2891
|
}
|
|
2892
|
+
|
|
2893
|
+
if (this.props.restrictPersonalization && hasPersonalizationTags(messageContent)) {
|
|
2894
|
+
errorMessageText = formatMessage(messages.personalizationTagsErrorMessage);
|
|
2895
|
+
}
|
|
2793
2896
|
const prevErrorMessage = this.state.liquidErrorMessage?.STANDARD_ERROR_MSG?.[0];
|
|
2794
|
-
if (prevErrorMessage !== errorMessageText && errorMessageText && this.
|
|
2897
|
+
if (prevErrorMessage !== errorMessageText && errorMessageText && this.liquidFlow()) {
|
|
2795
2898
|
this.setState((prevState) => ({
|
|
2796
2899
|
liquidErrorMessage: {
|
|
2797
2900
|
...prevState.liquidErrorMessage,
|
|
@@ -2802,10 +2905,7 @@ class FormBuilder extends React.Component { // eslint-disable-line react/prefer-
|
|
|
2802
2905
|
this.props.showLiquidErrorInFooter(this.state.liquidErrorMessage, this.props.channel === SMS? null: this.state.currentTab);
|
|
2803
2906
|
});
|
|
2804
2907
|
}
|
|
2805
|
-
|
|
2806
|
-
// Previously the textarea was inside the `else` branch, so it was not rendered during the
|
|
2807
|
-
// one render cycle when the liquid error message was first set – causing the input to lose
|
|
2808
|
-
// focus whenever a brace/tag error first appeared.
|
|
2908
|
+
else{
|
|
2809
2909
|
if (styling === 'semantic') {
|
|
2810
2910
|
columns.push(
|
|
2811
2911
|
<CapColumn key="input" span={val.width} offset={offset}>
|
|
@@ -2813,7 +2913,7 @@ class FormBuilder extends React.Component { // eslint-disable-line react/prefer-
|
|
|
2813
2913
|
id={val.id}
|
|
2814
2914
|
placeholder={val.placeholder ? val.placeholder : ''}
|
|
2815
2915
|
className={`${ifError ? 'error-form-builder' : ''}`}
|
|
2816
|
-
errorMessage={errorMessageText && !this.
|
|
2916
|
+
errorMessage={errorMessageText && !this.liquidFlow() ? errorMessageText : ''}
|
|
2817
2917
|
label={val.label}
|
|
2818
2918
|
autosize={val.autosize ? val.autosizeParams : false}
|
|
2819
2919
|
onChange={(e) => this.updateFormData(e.target.value, val)}
|
|
@@ -2844,6 +2944,7 @@ class FormBuilder extends React.Component { // eslint-disable-line react/prefer-
|
|
|
2844
2944
|
</CapColumn>
|
|
2845
2945
|
);
|
|
2846
2946
|
}
|
|
2947
|
+
}
|
|
2847
2948
|
};
|
|
2848
2949
|
|
|
2849
2950
|
|
|
@@ -2957,6 +3058,7 @@ class FormBuilder extends React.Component { // eslint-disable-line react/prefer-
|
|
|
2957
3058
|
userLocale={this.props.userLocale}
|
|
2958
3059
|
selectedOfferDetails={this.props.selectedOfferDetails}
|
|
2959
3060
|
eventContextTags={this.props?.eventContextTags}
|
|
3061
|
+
restrictPersonalization={this.props.restrictPersonalization}
|
|
2960
3062
|
/>
|
|
2961
3063
|
</CapColumn>
|
|
2962
3064
|
);
|
|
@@ -2991,6 +3093,7 @@ class FormBuilder extends React.Component { // eslint-disable-line react/prefer-
|
|
|
2991
3093
|
inputProps={val.inputProps || {}}
|
|
2992
3094
|
showInput={val.showInput !== false}
|
|
2993
3095
|
showTagList={val.showTagList !== false}
|
|
3096
|
+
restrictPersonalization={this.props.restrictPersonalization}
|
|
2994
3097
|
/>
|
|
2995
3098
|
</CapColumn>
|
|
2996
3099
|
);
|
|
@@ -3367,8 +3470,15 @@ class FormBuilder extends React.Component { // eslint-disable-line react/prefer-
|
|
|
3367
3470
|
ifError = this.state.checkValidation && (isVersionEnable ? this.state.errorData[`${this.state.currentTab - 1}`][val.id] : this.state.errorData[val.id]);
|
|
3368
3471
|
const { TAG_BRACKET_COUNT_MISMATCH_ERROR } = errorMessageForTags;
|
|
3369
3472
|
const { formatMessage } = this.props.intl;
|
|
3370
|
-
let errorMessageText = errorType === TAG_BRACKET_COUNT_MISMATCH_ERROR ? formatMessage(globalMessages.unbalanacedCurlyBraces) :(val.errorMessage && ifError ? val.errorMessage : '');
|
|
3371
3473
|
const value = isVersionEnable ? this.state.formData[`${this.state.currentTab - 1}`][val.id] : this.state.formData[val.id];
|
|
3474
|
+
// Show personalization error for title field inline (same as message textarea) when restrictPersonalization is true
|
|
3475
|
+
const hasPersonalizationError = this.props.restrictPersonalization && hasPersonalizationTags(value);
|
|
3476
|
+
if (hasPersonalizationError) {
|
|
3477
|
+
ifError = true;
|
|
3478
|
+
}
|
|
3479
|
+
let errorMessageText = hasPersonalizationError
|
|
3480
|
+
? formatMessage(messages.personalizationTagsErrorMessage)
|
|
3481
|
+
: (errorType === TAG_BRACKET_COUNT_MISMATCH_ERROR ? formatMessage(globalMessages.unbalanacedCurlyBraces) : (val.errorMessage && ifError ? val.errorMessage : ''));
|
|
3372
3482
|
if (styling === 'semantic') {
|
|
3373
3483
|
columns.push(
|
|
3374
3484
|
<CapColumn key={val.id} span={val.width} offset={val.offset} style={val.style || {}}>
|
|
@@ -3619,6 +3729,7 @@ class FormBuilder extends React.Component { // eslint-disable-line react/prefer-
|
|
|
3619
3729
|
selectedOfferDetails={this.props.selectedOfferDetails}
|
|
3620
3730
|
channel={channel}
|
|
3621
3731
|
eventContextTags={this.props?.eventContextTags}
|
|
3732
|
+
restrictPersonalization={this.props.restrictPersonalization}
|
|
3622
3733
|
/>
|
|
3623
3734
|
</CapColumn>
|
|
3624
3735
|
);
|
|
@@ -3670,6 +3781,7 @@ class FormBuilder extends React.Component { // eslint-disable-line react/prefer-
|
|
|
3670
3781
|
inputProps={val.inputProps || {}}
|
|
3671
3782
|
showInput={val.showInput !== false}
|
|
3672
3783
|
showTagList={val.showTagList !== false}
|
|
3784
|
+
restrictPersonalization={this.props.restrictPersonalization}
|
|
3673
3785
|
/>
|
|
3674
3786
|
</CapColumn>
|
|
3675
3787
|
);
|
|
@@ -3895,7 +4007,7 @@ class FormBuilder extends React.Component { // eslint-disable-line react/prefer-
|
|
|
3895
4007
|
<CapColumn
|
|
3896
4008
|
style={val.colStyle ? val.colStyle : {border : ""}}
|
|
3897
4009
|
span={val.width}
|
|
3898
|
-
className={(this.state.liquidErrorMessage?.LIQUID_ERROR_MSG?.length || this.state.liquidErrorMessage?.STANDARD_ERROR_MSG?.length) && this.
|
|
4010
|
+
className={`${(this.state.liquidErrorMessage?.LIQUID_ERROR_MSG?.length || this.state.liquidErrorMessage?.STANDARD_ERROR_MSG?.length) && this.liquidFlow() && "error-boundary"} `}
|
|
3899
4011
|
>
|
|
3900
4012
|
<CKEditor
|
|
3901
4013
|
id={val.id}
|
|
@@ -3939,7 +4051,7 @@ class FormBuilder extends React.Component { // eslint-disable-line react/prefer-
|
|
|
3939
4051
|
isModuleFilterEnabled = this.props.isFullMode;
|
|
3940
4052
|
}
|
|
3941
4053
|
columns.push(
|
|
3942
|
-
<CapColumn style={val.colStyle ? val.colStyle : {}} span={val.width} className={(this.state.liquidErrorMessage?.LIQUID_ERROR_MSG?.length || this.state.liquidErrorMessage?.STANDARD_ERROR_MSG?.length) && this.
|
|
4054
|
+
<CapColumn style={val.colStyle ? val.colStyle : {}} span={val.width} className={`${(this.state.liquidErrorMessage?.LIQUID_ERROR_MSG?.length || this.state.liquidErrorMessage?.STANDARD_ERROR_MSG?.length) && this.liquidFlow() && "error-boundary"}`}>
|
|
3943
4055
|
<BeeEditor
|
|
3944
4056
|
uid={uuid}
|
|
3945
4057
|
tokenData={beeToken}
|
|
@@ -4225,7 +4337,7 @@ class FormBuilder extends React.Component { // eslint-disable-line react/prefer-
|
|
|
4225
4337
|
|
|
4226
4338
|
|
|
4227
4339
|
return (
|
|
4228
|
-
<CapSpin spinning={Boolean((this.
|
|
4340
|
+
<CapSpin spinning={Boolean((this.liquidFlow() && this.props.liquidExtractionInProgress) || this.props.metaDataStatus === REQUEST)} tip={this.props.intl.formatMessage(messages.liquidSpinText)} >
|
|
4229
4341
|
<CapRow>
|
|
4230
4342
|
{this.props.schema && this.renderForm()}
|
|
4231
4343
|
<SlideBox
|
|
@@ -4313,6 +4425,7 @@ FormBuilder.propTypes = {
|
|
|
4313
4425
|
forwardedTags: PropTypes.object.isRequired,
|
|
4314
4426
|
isLoyaltyModule: PropTypes.bool.isRequired,
|
|
4315
4427
|
isTestAndPreviewMode: PropTypes.bool, // Add new prop type
|
|
4428
|
+
restrictPersonalization: PropTypes.bool,
|
|
4316
4429
|
};
|
|
4317
4430
|
|
|
4318
4431
|
const mapStateToProps = createStructuredSelector({
|