@capillarytech/creatives-library 8.0.113 → 8.0.114-alpha.1
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/containers/App/test/saga.test.js +1 -1
- package/containers/Assets/Gallery/tests/__snapshots__/reducer.test.js.snap +1 -1
- package/containers/Assets/Gallery/tests/actions.test.js +2 -3
- package/containers/Assets/Gallery/tests/reducer.test.js +7 -7
- package/containers/Assets/Gallery/tests/saga.test.js +9 -9
- package/containers/Dashboard/test/saga.test.js +1 -1
- package/containers/Ebill/test/saga.test.js +1 -1
- package/containers/Email/test/saga.test.js +33 -33
- package/containers/LanguageProvider/tests/actions.test.js +1 -1
- package/containers/LanguageProvider/tests/reducer.test.js +2 -2
- package/containers/LanguageProvider/tests/selectors.test.js +1 -1
- package/containers/Line/Create/tests/saga.test.js +2 -9
- package/containers/Line/Edit/test/saga.test.js +10 -14
- package/containers/MobilePush/Create/test/saga.test.js +2 -2
- package/containers/MobilePush/Edit/tests/saga.test.js +14 -14
- package/containers/Sms/Create/test/saga.test.js +4 -5
- package/containers/Sms/Edit/test/saga.test.js +1 -1
- package/containers/Templates/test/saga.test.js +14 -17
- package/containers/WeChat/MapTemplates/test/saga.test.js +9 -13
- package/containers/WeChat/RichmediaTemplates/Create/test/saga.test.js +1 -1
- package/containers/WeChat/RichmediaTemplates/Edit/test/saga.test.js +1 -1
- package/package.json +1 -1
- package/tests/integration/TemplateCreation/TemplateCreation.integration.test.js +8 -9
- package/utils/commonUtils.js +359 -3
- package/utils/tagValidations.js +20 -5
- package/utils/tests/authWrapper.test.js +2 -2
- package/utils/tests/cdnTransformation.test.js +16 -15
- package/utils/tests/commonUtil.test.js +474 -171
- package/utils/tests/tagValidations.test.js +89 -2
- package/v2Components/CapVideoUpload/tests/index.test.js +1 -1
- package/v2Components/CapWhatsappCTA/tests/index.test.js +1 -2
- package/v2Components/ErrorInfoNote/ErrorTypeRenderer.js +127 -0
- package/v2Components/ErrorInfoNote/ErrorTypeRenderer.test.js +147 -0
- package/v2Components/ErrorInfoNote/index.js +114 -46
- package/v2Components/ErrorInfoNote/messages.js +25 -0
- package/v2Components/ErrorInfoNote/style.scss +14 -1
- package/v2Components/ErrorInfoNote/utils.js +38 -0
- package/v2Components/ErrorInfoNote/utils.test.js +156 -0
- package/v2Components/FormBuilder/index.js +204 -127
- package/v2Components/FormBuilder/messages.js +1 -1
- package/v2Components/MarketingObjective/test/index.test.js +1 -1
- package/v2Components/NavigationBar/tests/saga.test.js +2 -3
- package/v2Containers/Assets/Gallery/tests/__snapshots__/reducer.test.js.snap +1 -1
- package/v2Containers/Assets/Gallery/tests/actions.test.js +2 -3
- package/v2Containers/Assets/Gallery/tests/reducer.test.js +7 -7
- package/v2Containers/Assets/Gallery/tests/saga.test.js +2 -2
- package/v2Containers/BeeEditor/test/saga.test.js +1 -1
- package/v2Containers/CallTask/test/saga.test.js +1 -1
- package/v2Containers/Cap/reducer.js +4 -4
- package/v2Containers/Cap/tests/actions.test.js +1 -1
- package/v2Containers/Cap/tests/reducer.test.js +11 -11
- package/v2Containers/Cap/tests/saga.test.js +1 -1
- package/v2Containers/Cap/tests/selectors.test.js +3 -3
- package/v2Containers/CapFacebookPreview/tests/saga.test.js +1 -1
- package/v2Containers/CreativesContainer/SlideBoxContent.js +23 -3
- package/v2Containers/CreativesContainer/SlideBoxFooter.js +3 -1
- package/v2Containers/CreativesContainer/constants.js +4 -1
- package/v2Containers/CreativesContainer/index.js +44 -19
- package/v2Containers/CreativesContainer/messages.js +4 -0
- package/v2Containers/CreativesContainer/tests/__snapshots__/index.test.js.snap +21 -3
- package/v2Containers/Ebill/index.js +3 -3
- package/v2Containers/Ebill/test/saga.test.js +1 -1
- package/v2Containers/Email/tests/__snapshots__/reducer.test.js.snap +4 -4
- package/v2Containers/Email/tests/actions.test.js +1 -1
- package/v2Containers/Email/tests/reducer.test.js +2 -2
- package/v2Containers/EmailWrapper/components/EmailWrapperView.js +1 -1
- package/v2Containers/FTP/test/saga.test.js +1 -1
- package/v2Containers/Facebook/test/saga.test.js +7 -7
- package/v2Containers/InApp/index.js +123 -50
- package/v2Containers/InApp/tests/action.test.js +7 -7
- package/v2Containers/InApp/tests/index.test.js +2 -4
- package/v2Containers/InApp/tests/reducer.test.js +175 -89
- package/v2Containers/InApp/tests/sagas.test.js +1 -1
- package/v2Containers/InApp/tests/utils.test.js +41 -0
- package/v2Containers/InApp/utils.js +37 -0
- package/v2Containers/LanguageProvider/tests/actions.test.js +1 -1
- package/v2Containers/LanguageProvider/tests/reducer.test.js +3 -3
- package/v2Containers/LanguageProvider/tests/saga.test.js +2 -2
- package/v2Containers/LanguageProvider/tests/selectors.test.js +1 -1
- package/v2Containers/Line/Container/ImageCarousel/tests/utils.test.js +3 -3
- package/v2Containers/Line/Container/Sticker/tests/utils.test.js +6 -6
- package/v2Containers/MobilePush/Create/index.js +24 -20
- package/v2Containers/MobilePush/Create/test/saga.test.js +2 -2
- package/v2Containers/MobilePush/Edit/index.js +6 -2
- package/v2Containers/MobilePush/Edit/test/saga.test.js +14 -14
- package/v2Containers/MobilepushWrapper/index.js +2 -0
- package/v2Containers/Rcs/tests/saga.test.js +1 -1
- package/v2Containers/Sms/Create/index.js +1 -0
- package/v2Containers/Sms/Create/test/saga.test.js +1 -1
- package/v2Containers/Sms/Edit/index.js +2 -0
- package/v2Containers/Sms/Edit/test/saga.test.js +5 -5
- package/v2Containers/SmsTrai/Create/tests/saga.test.js +1 -1
- package/v2Containers/SmsTrai/Create/tests/selectors.test.js +1 -1
- package/v2Containers/SmsWrapper/index.js +2 -0
- package/v2Containers/TagList/tests/TagList.test.js +1 -3
- package/v2Containers/TagList/tests/utils.test.js +3 -3
- package/v2Containers/Templates/tests/actions.test.js +1 -1
- package/v2Containers/Templates/tests/reducer.test.js +8 -8
- package/v2Containers/Templates/tests/sagas.test.js +2 -4
- package/v2Containers/WeChat/MapTemplates/test/saga.test.js +9 -13
- package/v2Containers/WeChat/RichmediaTemplates/Create/test/saga.test.js +1 -1
- package/v2Containers/WeChat/RichmediaTemplates/Edit/test/saga.test.js +1 -1
- package/v2Containers/Whatsapp/tests/__snapshots__/utils.test.js.snap +9 -9
- package/v2Containers/Whatsapp/tests/actions.test.js +3 -3
- package/v2Containers/Whatsapp/tests/reducer.test.js +32 -36
- package/v2Containers/Whatsapp/tests/utils.test.js +19 -19
- package/v2Containers/Zalo/tests/actions.test.js +3 -3
- package/v2Containers/Zalo/tests/reducer.test.js +72 -42
|
@@ -49,10 +49,10 @@ import * as actions from "../../v2Containers/Cap/actions";
|
|
|
49
49
|
import './_formBuilder.scss';
|
|
50
50
|
import {updateCharCount, checkUnicode} from "../../utils/smsCharCountV2";
|
|
51
51
|
import { checkSupport, extractNames, preprocessHtml, validateIfTagClosed } from '../../utils/tagValidations';
|
|
52
|
-
import { SMS, MOBILE_PUSH, LINE, ENABLE_AI_SUGGESTIONS,AI_CONTENT_BOT_DISABLED, EMAIL, LIQUID_SUPPORTED_CHANNELS } from '../../v2Containers/CreativesContainer/constants';
|
|
52
|
+
import { SMS, MOBILE_PUSH, LINE, ENABLE_AI_SUGGESTIONS,AI_CONTENT_BOT_DISABLED, EMAIL, LIQUID_SUPPORTED_CHANNELS, INAPP } from '../../v2Containers/CreativesContainer/constants';
|
|
53
53
|
import globalMessages from '../../v2Containers/Cap/messages';
|
|
54
54
|
import { convert } from 'html-to-text';
|
|
55
|
-
import {
|
|
55
|
+
import { OUTBOUND } from './constants';
|
|
56
56
|
import { GET_TRANSLATION_MAPPED } from '../../containers/TagList/constants';
|
|
57
57
|
import moment from 'moment';
|
|
58
58
|
import { CUSTOMER_BARCODE_TAG , COPY_OF, ENTRY_TRIGGER_TAG_REGEX} from '../../containers/App/constants';
|
|
@@ -60,7 +60,7 @@ import { REQUEST } from '../../v2Containers/Cap/constants'
|
|
|
60
60
|
import { hasLiquidSupportFeature, isEmailUnsubscribeTagMandatory } from '../../utils/common';
|
|
61
61
|
import { isUrl } from '../../v2Containers/Line/Container/Wrapper/utils';
|
|
62
62
|
import { bindActionCreators } from 'redux';
|
|
63
|
-
|
|
63
|
+
import { getChannelData, validateLiquidTemplateContent, validateMobilePushContent } from '../../utils/commonUtils';
|
|
64
64
|
const TabPane = Tabs.TabPane;
|
|
65
65
|
const {Column} = Table;
|
|
66
66
|
const {TextArea} = CapInput;
|
|
@@ -135,7 +135,12 @@ class FormBuilder extends React.Component { // eslint-disable-line react/prefer-
|
|
|
135
135
|
this.handleSetRadioValue = this.handleSetRadioValue.bind(this);
|
|
136
136
|
this.formElements = [];
|
|
137
137
|
// Check if the liquid flow feature is supported and the channel is in the supported list.
|
|
138
|
-
this.liquidFlow =
|
|
138
|
+
this.liquidFlow = this.isLiquidFlowSupported.bind(this);
|
|
139
|
+
this.onSubmitWrapper = this.onSubmitWrapper.bind(this);
|
|
140
|
+
|
|
141
|
+
}
|
|
142
|
+
isLiquidFlowSupported = () => {
|
|
143
|
+
return Boolean(LIQUID_SUPPORTED_CHANNELS.includes(this.props?.schema?.channel?.toUpperCase()) && hasLiquidSupportFeature());
|
|
139
144
|
}
|
|
140
145
|
|
|
141
146
|
componentWillMount() {
|
|
@@ -538,6 +543,7 @@ class FormBuilder extends React.Component { // eslint-disable-line react/prefer-
|
|
|
538
543
|
} else {
|
|
539
544
|
errorData['template-name'] = false;
|
|
540
545
|
}
|
|
546
|
+
isLiquidValid = isValid;
|
|
541
547
|
}
|
|
542
548
|
|
|
543
549
|
//validation for LINE
|
|
@@ -653,20 +659,21 @@ class FormBuilder extends React.Component { // eslint-disable-line react/prefer-
|
|
|
653
659
|
let isOnlyAndroid = false, isOnlyIos = false;
|
|
654
660
|
const { TAG_BRACKET_COUNT_MISMATCH_ERROR } = errorMessageForTags;
|
|
655
661
|
const androidData = {};
|
|
656
|
-
|
|
657
|
-
|
|
658
|
-
|
|
662
|
+
if (this.state.formData && this.state.formData[0]) {
|
|
663
|
+
for(let data in this.state.formData[0]){
|
|
664
|
+
if(!!this.state.formData[0][data] && data !== "tabKey" && data !== "base"){
|
|
665
|
+
androidData[data] = this.state.formData[0][data];
|
|
666
|
+
}
|
|
659
667
|
}
|
|
660
|
-
}
|
|
661
668
|
if(_.isEmpty(androidData)){
|
|
662
669
|
isOnlyIos = true;
|
|
663
670
|
}
|
|
664
671
|
const iosData = {};
|
|
665
|
-
|
|
666
|
-
|
|
667
|
-
|
|
672
|
+
for(let data in this.state.formData[1]){
|
|
673
|
+
if(!!this.state.formData[1][data] && data !== "tabKey" && data !== "base"){
|
|
674
|
+
iosData[data] = this.state.formData[1][data];
|
|
675
|
+
}
|
|
668
676
|
}
|
|
669
|
-
}
|
|
670
677
|
if(_.isEmpty(iosData)){
|
|
671
678
|
isOnlyAndroid = true;
|
|
672
679
|
}
|
|
@@ -701,17 +708,19 @@ class FormBuilder extends React.Component { // eslint-disable-line react/prefer-
|
|
|
701
708
|
errorData[parseInt(index)]['invalid-tags'] = tagValidationResponse.unsupportedTags;
|
|
702
709
|
errorData[parseInt(index)][`bracket-error`] = isBraceError && TAG_BRACKET_COUNT_MISMATCH_ERROR;
|
|
703
710
|
isValid = false;
|
|
711
|
+
isCurrentTabValid = false;
|
|
704
712
|
}
|
|
705
713
|
}
|
|
706
714
|
|
|
707
715
|
} else {
|
|
708
|
-
|
|
709
|
-
|
|
710
|
-
|
|
716
|
+
|
|
717
|
+
errorData[parseInt(index)][`message-editor${selector}`] = true;
|
|
718
|
+
isValid = false;
|
|
719
|
+
isCurrentTabValid = false;
|
|
711
720
|
}
|
|
712
721
|
|
|
713
|
-
|
|
714
722
|
|
|
723
|
+
|
|
715
724
|
let title = tab[`message-title${selector}`]
|
|
716
725
|
if(title){
|
|
717
726
|
title = title.trim();
|
|
@@ -730,6 +739,7 @@ class FormBuilder extends React.Component { // eslint-disable-line react/prefer-
|
|
|
730
739
|
errorData[parseInt(index)][`message-title${selector}`] = isBraceError ? TAG_BRACKET_COUNT_MISMATCH_ERROR : true;
|
|
731
740
|
errorData[parseInt(index)][`bracket-error`] = isBraceError && TAG_BRACKET_COUNT_MISMATCH_ERROR;
|
|
732
741
|
isValid = false;
|
|
742
|
+
isCurrentTabValid = false;
|
|
733
743
|
}
|
|
734
744
|
}
|
|
735
745
|
} else {
|
|
@@ -858,9 +868,9 @@ class FormBuilder extends React.Component { // eslint-disable-line react/prefer-
|
|
|
858
868
|
isCurrentTabValid = false;
|
|
859
869
|
}else {
|
|
860
870
|
errorData[parseInt(index)][key] = false;
|
|
861
|
-
|
|
862
|
-
|
|
863
|
-
|
|
871
|
+
}
|
|
872
|
+
}
|
|
873
|
+
});
|
|
864
874
|
}
|
|
865
875
|
}
|
|
866
876
|
if(index == 0){
|
|
@@ -873,7 +883,7 @@ class FormBuilder extends React.Component { // eslint-disable-line react/prefer-
|
|
|
873
883
|
errorData['template-name'] = true;
|
|
874
884
|
isValid = false;
|
|
875
885
|
androidValid = false;
|
|
876
|
-
iosValid = false
|
|
886
|
+
iosValid = false;
|
|
877
887
|
} else {
|
|
878
888
|
errorData['template-name'] = false;
|
|
879
889
|
}
|
|
@@ -893,7 +903,7 @@ class FormBuilder extends React.Component { // eslint-disable-line react/prefer-
|
|
|
893
903
|
// modal.body = "Android template is not configured. Save without Android template";
|
|
894
904
|
// modal.id = "ios";
|
|
895
905
|
// modal.type = 'confirm';
|
|
896
|
-
return;
|
|
906
|
+
return; //returning from here will not call the liquid middleware
|
|
897
907
|
}
|
|
898
908
|
const iosData = {};
|
|
899
909
|
for(let data in this.state.formData[1]){
|
|
@@ -909,7 +919,7 @@ class FormBuilder extends React.Component { // eslint-disable-line react/prefer-
|
|
|
909
919
|
// modal.id = 'android';
|
|
910
920
|
// modal.type = 'confirm';
|
|
911
921
|
// this.setState({modal, showModal: true, androidValid, iosValid});
|
|
912
|
-
return;
|
|
922
|
+
return; //returning from here will not call the liquid middleware
|
|
913
923
|
}
|
|
914
924
|
}
|
|
915
925
|
if (!androidValid || !iosValid) {
|
|
@@ -922,7 +932,9 @@ class FormBuilder extends React.Component { // eslint-disable-line react/prefer-
|
|
|
922
932
|
} else if (!isOnlyIos && !isOnlyAndroid && androidValid && iosValid) {
|
|
923
933
|
isValid = isValid && true;
|
|
924
934
|
}
|
|
935
|
+
isLiquidValid = isValid;
|
|
925
936
|
}
|
|
937
|
+
}
|
|
926
938
|
|
|
927
939
|
// Form Data Validation for Email Channel
|
|
928
940
|
if (this.props?.schema?.channel?.toUpperCase() === EMAIL) {
|
|
@@ -983,7 +995,7 @@ class FormBuilder extends React.Component { // eslint-disable-line react/prefer-
|
|
|
983
995
|
errorData[index][currentLang]['template-content'] = true;
|
|
984
996
|
isValid = false;
|
|
985
997
|
isLiquidValid = false;
|
|
986
|
-
if ((showMessages && !isNaN(index)) || this.liquidFlow) {
|
|
998
|
+
if ((showMessages && !isNaN(index)) || this.liquidFlow()) {
|
|
987
999
|
if (tagValidationResponse?.missingTags?.length > 0 || tagValidationResponse?.unsupportedTags?.length > 0) {
|
|
988
1000
|
errorString += `${this.props.intl.formatMessage(messages.contentNotValidLanguage)} ${currentLang}\n`;
|
|
989
1001
|
}
|
|
@@ -999,7 +1011,7 @@ class FormBuilder extends React.Component { // eslint-disable-line react/prefer-
|
|
|
999
1011
|
if (tagValidationResponse?.isContentEmpty) {
|
|
1000
1012
|
errorString += this.props.intl.formatMessage(messages.emailBodyEmptyError);
|
|
1001
1013
|
// Adds a bypass for cases where content is initially empty in the creation flow.
|
|
1002
|
-
if(this.liquidFlow){
|
|
1014
|
+
if(this.liquidFlow()){
|
|
1003
1015
|
errorString = "";
|
|
1004
1016
|
isLiquidValid = true;
|
|
1005
1017
|
}
|
|
@@ -1007,8 +1019,8 @@ class FormBuilder extends React.Component { // eslint-disable-line react/prefer-
|
|
|
1007
1019
|
}
|
|
1008
1020
|
}
|
|
1009
1021
|
}
|
|
1010
|
-
if (errorString
|
|
1011
|
-
if (this.liquidFlow) {
|
|
1022
|
+
if (errorString) {
|
|
1023
|
+
if (this.liquidFlow()) {
|
|
1012
1024
|
this.setState(
|
|
1013
1025
|
(prevState) => ({
|
|
1014
1026
|
liquidErrorMessage: {
|
|
@@ -1018,7 +1030,7 @@ class FormBuilder extends React.Component { // eslint-disable-line react/prefer-
|
|
|
1018
1030
|
}),
|
|
1019
1031
|
() => {
|
|
1020
1032
|
// Callback after the state is updated
|
|
1021
|
-
this.props.showLiquidErrorInFooter(this.state.liquidErrorMessage);
|
|
1033
|
+
this.props.showLiquidErrorInFooter(this.state.liquidErrorMessage, this.props.channel === SMS? null: this.state.currentTab);
|
|
1022
1034
|
}
|
|
1023
1035
|
);
|
|
1024
1036
|
} else {
|
|
@@ -1034,7 +1046,7 @@ class FormBuilder extends React.Component { // eslint-disable-line react/prefer-
|
|
|
1034
1046
|
});
|
|
1035
1047
|
}
|
|
1036
1048
|
|
|
1037
|
-
const isTemplateValid = this.liquidFlow ? isLiquidValid : isValid;
|
|
1049
|
+
const isTemplateValid = this.liquidFlow() ? isLiquidValid : isValid;
|
|
1038
1050
|
//Updating the state with the error data
|
|
1039
1051
|
this.setState((prevState) => ({
|
|
1040
1052
|
isFormValid: isTemplateValid,
|
|
@@ -1046,126 +1058,175 @@ class FormBuilder extends React.Component { // eslint-disable-line react/prefer-
|
|
|
1046
1058
|
},
|
|
1047
1059
|
errorData,
|
|
1048
1060
|
}), () => {
|
|
1049
|
-
this.props.showLiquidErrorInFooter(this.state.liquidErrorMessage);
|
|
1061
|
+
this.props.showLiquidErrorInFooter(this.state.liquidErrorMessage, this.props.channel === SMS? null: this.state.currentTab);
|
|
1062
|
+
|
|
1050
1063
|
if (onValidationComplete) {
|
|
1064
|
+
|
|
1051
1065
|
onValidationComplete();
|
|
1052
1066
|
}
|
|
1053
1067
|
});
|
|
1054
1068
|
|
|
1069
|
+
|
|
1055
1070
|
this.props.onFormValidityChange(isTemplateValid, errorData);
|
|
1056
1071
|
return isTemplateValid;
|
|
1057
|
-
|
|
1072
|
+
}
|
|
1058
1073
|
|
|
1059
1074
|
indexOfEnd(targetString, string) {
|
|
1060
1075
|
var io = targetString.indexOf(string);
|
|
1061
1076
|
return io == -1 ? -1 : io + string.length;
|
|
1062
1077
|
}
|
|
1063
|
-
continueSaveForm = (id) => {
|
|
1064
1078
|
|
|
1065
|
-
|
|
1066
|
-
|
|
1067
|
-
|
|
1068
|
-
|
|
1069
|
-
|
|
1070
|
-
|
|
1071
|
-
|
|
1072
|
-
...prevState?.formData
|
|
1073
|
-
|
|
1074
|
-
...prevState?.formData?.base
|
|
1075
|
-
|
|
1079
|
+
handleLiquidTemplateSubmit = (templateContent) => {
|
|
1080
|
+
const channel = this.props.channel || this.props?.schema?.channel?.toUpperCase();
|
|
1081
|
+
|
|
1082
|
+
if (templateContent && channel === EMAIL) {
|
|
1083
|
+
this.setState((prevState) => {
|
|
1084
|
+
return {
|
|
1085
|
+
formData: {
|
|
1086
|
+
...prevState?.formData,
|
|
1087
|
+
base: {
|
|
1088
|
+
...prevState?.formData?.base,
|
|
1089
|
+
[this.props.baseLanguage]: {
|
|
1090
|
+
...prevState?.formData?.base?.[this.props.baseLanguage],
|
|
1091
|
+
"template-content": preprocessHtml(templateContent)
|
|
1092
|
+
}
|
|
1076
1093
|
}
|
|
1077
1094
|
}
|
|
1095
|
+
};
|
|
1096
|
+
}, () => {
|
|
1097
|
+
if (this.props.onSubmit) {
|
|
1098
|
+
this.props.onSubmit(this.state.formData);
|
|
1078
1099
|
}
|
|
1079
|
-
};
|
|
1080
|
-
}
|
|
1081
|
-
|
|
1082
|
-
|
|
1100
|
+
});
|
|
1101
|
+
} else {
|
|
1102
|
+
// For all other channels
|
|
1103
|
+
this.props.onSubmit(this.state.formData);
|
|
1104
|
+
}
|
|
1105
|
+
}
|
|
1106
|
+
onSubmitWrapper = (props) => {
|
|
1107
|
+
const {singleTab = null} = props || {};
|
|
1108
|
+
if (this.liquidFlow()) {
|
|
1109
|
+
// For MPUSH, we need to validate both Android and iOS content separately
|
|
1110
|
+
if (this.props.channel === MOBILE_PUSH || this.props?.schema?.channel?.toUpperCase() === MOBILE_PUSH) {
|
|
1111
|
+
this.validateFormBuilderMPush(this.state.formData, singleTab);
|
|
1112
|
+
return;
|
|
1083
1113
|
}
|
|
1084
|
-
|
|
1114
|
+
|
|
1115
|
+
// For other channels (EMAIL, SMS, INAPP)
|
|
1116
|
+
const content = getChannelData(this.props.schema.channel || this.props.channel, this.state.formData,this.props.baseLanguage);
|
|
1117
|
+
|
|
1118
|
+
// Set up callbacks for error and success handling
|
|
1119
|
+
const onError = ({ standardErrors, liquidErrors }) => {
|
|
1120
|
+
this.setState(
|
|
1121
|
+
(prevState) => ({
|
|
1122
|
+
liquidErrorMessage: {
|
|
1123
|
+
...prevState.liquidErrorMessage,
|
|
1124
|
+
STANDARD_ERROR_MSG: standardErrors,
|
|
1125
|
+
LIQUID_ERROR_MSG: liquidErrors,
|
|
1126
|
+
},
|
|
1127
|
+
}),
|
|
1128
|
+
() => {
|
|
1129
|
+
this.props.showLiquidErrorInFooter(this.state.liquidErrorMessage);
|
|
1130
|
+
this.props.stopValidation();
|
|
1131
|
+
}
|
|
1132
|
+
);
|
|
1133
|
+
};
|
|
1134
|
+
|
|
1135
|
+
const onSuccess = (contentToSubmit) => {
|
|
1136
|
+
this.handleLiquidTemplateSubmit(contentToSubmit);
|
|
1137
|
+
};
|
|
1138
|
+
|
|
1139
|
+
// Call the common validation function
|
|
1140
|
+
validateLiquidTemplateContent(content, this.props.schema.channel || this.props.channel, {
|
|
1141
|
+
getLiquidTags: this.props.actions.getLiquidTags,
|
|
1142
|
+
formatMessage: this.props.intl.formatMessage,
|
|
1143
|
+
messages,
|
|
1144
|
+
onError,
|
|
1145
|
+
onSuccess,
|
|
1146
|
+
tagLookupMap: this.props?.metaEntities?.tagLookupMap,
|
|
1147
|
+
eventContextTags: this.props?.eventContextTags,
|
|
1148
|
+
isLiquidFlow: this.liquidFlow(),
|
|
1149
|
+
forwardedTags: this.props?.isLoyaltyModule ? this.props?.forwardedTags : {},
|
|
1150
|
+
skipTags: this.skipTags.bind(this)
|
|
1151
|
+
});
|
|
1152
|
+
} else {
|
|
1153
|
+
this.props.onSubmit(this.state.formData);
|
|
1154
|
+
}
|
|
1085
1155
|
}
|
|
1086
|
-
|
|
1156
|
+
|
|
1087
1157
|
saveForm(saveForm) {
|
|
1088
1158
|
if (this.props.isNewVersionFlow && !saveForm) {
|
|
1089
1159
|
this.props.getValidationData();
|
|
1090
1160
|
return;
|
|
1091
1161
|
}
|
|
1092
1162
|
if ( this.state.isFormValid ) {
|
|
1093
|
-
|
|
1094
|
-
|
|
1095
|
-
//Converts given HTML content to plain text string.
|
|
1096
|
-
const content = convert(
|
|
1097
|
-
templateContent, GLOBAL_CONVERT_OPTIONS
|
|
1098
|
-
);
|
|
1099
|
-
/*
|
|
1100
|
-
The `handleResult` function is used as a callback for `getLiquidTags` to handle the results post-processing.
|
|
1101
|
-
It checks for errors and unsupported tags in the fetched liquid tags, displays any necessary validation messages,
|
|
1102
|
-
and proceeds with form submission if all checks pass.
|
|
1103
|
-
*/
|
|
1104
|
-
const handleResult = (result) => {
|
|
1105
|
-
const {formatMessage} = this.props.intl;
|
|
1106
|
-
// Checks for errors in the result and displays them if any are found.
|
|
1107
|
-
const validString = /\S/.test(content);
|
|
1108
|
-
// If the content is empty or there are errors in the result, display the necessary validation messages.
|
|
1109
|
-
if (result?.errors?.length > 0 || !validString) {
|
|
1110
|
-
this.setState((prevState) => ({
|
|
1111
|
-
liquidErrorMessage: {
|
|
1112
|
-
...prevState.liquidErrorMessage,
|
|
1113
|
-
STANDARD_ERROR_MSG: !validString ? [...(prevState.liquidErrorMessage?.STANDARD_ERROR_MSG || []), formatMessage(messages.emailBodyEmptyError)] : prevState.liquidErrorMessage?.STANDARD_ERROR_MSG,
|
|
1114
|
-
LIQUID_ERROR_MSG: result?.errors?.map(error => error?.message) ?? [formatMessage(messages.somethingWentWrong)],
|
|
1115
|
-
}
|
|
1116
|
-
}), () => {
|
|
1117
|
-
this.props.showLiquidErrorInFooter(this.state.liquidErrorMessage);
|
|
1118
|
-
});
|
|
1119
|
-
this.props.stopValidation();
|
|
1120
|
-
return;
|
|
1121
|
-
}
|
|
1122
|
-
// Extracts the supported liquid tags from the given content and do the necessary checks.
|
|
1123
|
-
else {
|
|
1124
|
-
const extractedLiquidTags = extractNames(result?.data || []);
|
|
1125
|
-
// Extracts the supported liquid tags from the given content.
|
|
1126
|
-
const supportedLiquidTags = checkSupport(
|
|
1127
|
-
result,
|
|
1128
|
-
this.props?.metaEntities?.tagLookupMap,
|
|
1129
|
-
this.props?.eventContextTags,
|
|
1130
|
-
this.liquidFlow,
|
|
1131
|
-
this.props?.isLoyaltyModule ? this.props?.forwardedTags : {}
|
|
1132
|
-
);
|
|
1133
|
-
const unsupportedLiquidTags = extractedLiquidTags?.filter(
|
|
1134
|
-
(tag) => !supportedLiquidTags?.includes(tag) && !this.skipTags(tag)
|
|
1135
|
-
);
|
|
1136
|
-
if (
|
|
1137
|
-
unsupportedLiquidTags?.length > 0
|
|
1138
|
-
) {
|
|
1139
|
-
this.setState(
|
|
1140
|
-
(prevState) => ({
|
|
1141
|
-
liquidErrorMessage: {
|
|
1142
|
-
...prevState.liquidErrorMessage,
|
|
1143
|
-
LIQUID_ERROR_MSG: [formatMessage(messages.unsupportedTagsValidationError, {
|
|
1144
|
-
unsupportedTags: unsupportedLiquidTags.join(", ")})],
|
|
1145
|
-
},
|
|
1146
|
-
}),
|
|
1147
|
-
() => {
|
|
1148
|
-
this.props.showLiquidErrorInFooter(
|
|
1149
|
-
this.state.liquidErrorMessage
|
|
1150
|
-
);
|
|
1151
|
-
}
|
|
1152
|
-
);
|
|
1153
|
-
this.props.stopValidation();
|
|
1154
|
-
return;
|
|
1155
|
-
}
|
|
1156
|
-
this.handleLiquidTemplateSubmit(templateContent);
|
|
1157
|
-
}
|
|
1158
|
-
};
|
|
1159
|
-
this.props.actions.getLiquidTags(preprocessHtml(content), handleResult);
|
|
1160
|
-
} else {
|
|
1161
|
-
this.props.onSubmit(this.state.formData);
|
|
1162
|
-
}
|
|
1163
|
+
this.onSubmitWrapper();
|
|
1164
|
+
|
|
1163
1165
|
} else {
|
|
1164
1166
|
this.setState({checkValidation: true});
|
|
1165
1167
|
this.validateForm(null, null, true);
|
|
1166
1168
|
}
|
|
1167
1169
|
}
|
|
1168
1170
|
|
|
1171
|
+
|
|
1172
|
+
// New function to handle MPUSH content validation for both Android and iOS
|
|
1173
|
+
validateFormBuilderMPush = (formData,singleTab) => {
|
|
1174
|
+
const currentTab = this.state.currentTab;
|
|
1175
|
+
|
|
1176
|
+
// Set up callbacks for error and success handling
|
|
1177
|
+
const onLiquidError = ({ standardErrors, liquidErrors }) => {
|
|
1178
|
+
console.log("onLiquidError.....", standardErrors, liquidErrors);
|
|
1179
|
+
this.setState(
|
|
1180
|
+
(prevState) => ({
|
|
1181
|
+
liquidErrorMessage: {
|
|
1182
|
+
...prevState.liquidErrorMessage,
|
|
1183
|
+
STANDARD_ERROR_MSG: standardErrors,
|
|
1184
|
+
LIQUID_ERROR_MSG: liquidErrors,
|
|
1185
|
+
},
|
|
1186
|
+
}),
|
|
1187
|
+
() => {
|
|
1188
|
+
this.props.showLiquidErrorInFooter(this.state.liquidErrorMessage, this.state.currentTab);
|
|
1189
|
+
this.props.stopValidation();
|
|
1190
|
+
}
|
|
1191
|
+
);
|
|
1192
|
+
};
|
|
1193
|
+
|
|
1194
|
+
const onSuccess = (contentToSubmit) => {
|
|
1195
|
+
// Clear any previous errors
|
|
1196
|
+
this.setState(
|
|
1197
|
+
(prevState) => ({
|
|
1198
|
+
liquidErrorMessage: {
|
|
1199
|
+
...prevState.liquidErrorMessage,
|
|
1200
|
+
STANDARD_ERROR_MSG: [],
|
|
1201
|
+
LIQUID_ERROR_MSG: [],
|
|
1202
|
+
},
|
|
1203
|
+
}),
|
|
1204
|
+
() => {
|
|
1205
|
+
// Format depends on the tabType
|
|
1206
|
+
this.handleLiquidTemplateSubmit(contentToSubmit);
|
|
1207
|
+
}
|
|
1208
|
+
);
|
|
1209
|
+
};
|
|
1210
|
+
|
|
1211
|
+
// Call the utility function with our callbacks
|
|
1212
|
+
validateMobilePushContent(formData, {
|
|
1213
|
+
currentTab,
|
|
1214
|
+
onError: onLiquidError,
|
|
1215
|
+
onSuccess,
|
|
1216
|
+
getLiquidTags: this.props.actions.getLiquidTags,
|
|
1217
|
+
formatMessage: this.props.intl.formatMessage,
|
|
1218
|
+
messages: messages,
|
|
1219
|
+
tagLookupMap: this.props?.metaEntities?.tagLookupMap,
|
|
1220
|
+
eventContextTags: this.props?.eventContextTags,
|
|
1221
|
+
isLiquidFlow: this.liquidFlow(), // Use the method instead of props
|
|
1222
|
+
forwardedTags: this.props?.isLoyaltyModule ? this.props?.forwardedTags : {},
|
|
1223
|
+
skipTags: this.skipTags.bind(this),
|
|
1224
|
+
extractNames,
|
|
1225
|
+
checkSupport,
|
|
1226
|
+
singleTab: singleTab?.toUpperCase(),
|
|
1227
|
+
});
|
|
1228
|
+
}
|
|
1229
|
+
|
|
1169
1230
|
transformInjectedTags(tags) {
|
|
1170
1231
|
_.forEach(tags, (tag) => {
|
|
1171
1232
|
const temp = tag;
|
|
@@ -1304,7 +1365,7 @@ class FormBuilder extends React.Component { // eslint-disable-line react/prefer-
|
|
|
1304
1365
|
});
|
|
1305
1366
|
|
|
1306
1367
|
ifSupported = ifSupported || this.checkIfSupportedTag(tagValue, injectedTags);
|
|
1307
|
-
if (!ifSupported && !this.liquidFlow) {
|
|
1368
|
+
if (!ifSupported && !this.liquidFlow()) {
|
|
1308
1369
|
response.unsupportedTags.push(tagValue);
|
|
1309
1370
|
response.valid = false;
|
|
1310
1371
|
}
|
|
@@ -2278,12 +2339,11 @@ class FormBuilder extends React.Component { // eslint-disable-line react/prefer-
|
|
|
2278
2339
|
};
|
|
2279
2340
|
handleOk = (ev) => {
|
|
2280
2341
|
const id = ev.target.id;
|
|
2281
|
-
|
|
2282
2342
|
this.setState({showModal: false});
|
|
2283
2343
|
if (id === "android" && this.state.androidValid) {
|
|
2284
|
-
this.
|
|
2344
|
+
this.onSubmitWrapper({singleTab: id});
|
|
2285
2345
|
} else if (id === "ios" && this.state.iosValid) {
|
|
2286
|
-
this.
|
|
2346
|
+
this.onSubmitWrapper({singleTab: id});
|
|
2287
2347
|
} else if (id === "sms-version-modal") {
|
|
2288
2348
|
this.state.currentEvent.call(this.props.parent, this.state.currentEventData, this.state.currentTab);
|
|
2289
2349
|
this.setState({currentEvent: {}, currentEventData: {}});
|
|
@@ -2483,6 +2543,19 @@ class FormBuilder extends React.Component { // eslint-disable-line react/prefer-
|
|
|
2483
2543
|
default:
|
|
2484
2544
|
break;
|
|
2485
2545
|
}
|
|
2546
|
+
const prevErrorMessage = this.state.liquidErrorMessage?.STANDARD_ERROR_MSG?.[0];
|
|
2547
|
+
if (prevErrorMessage !== errorMessageText && errorMessageText && this.liquidFlow()) {
|
|
2548
|
+
this.setState((prevState) => ({
|
|
2549
|
+
liquidErrorMessage: {
|
|
2550
|
+
...prevState.liquidErrorMessage,
|
|
2551
|
+
STANDARD_ERROR_MSG: [errorMessageText],
|
|
2552
|
+
}
|
|
2553
|
+
}), () => {
|
|
2554
|
+
|
|
2555
|
+
this.props.showLiquidErrorInFooter(this.state.liquidErrorMessage, this.props.channel === SMS? null: this.state.currentTab);
|
|
2556
|
+
});
|
|
2557
|
+
}
|
|
2558
|
+
else{
|
|
2486
2559
|
if (styling === 'semantic') {
|
|
2487
2560
|
columns.push(
|
|
2488
2561
|
<CapColumn key="input" span={val.width} offset={offset}>
|
|
@@ -2490,7 +2563,7 @@ class FormBuilder extends React.Component { // eslint-disable-line react/prefer-
|
|
|
2490
2563
|
id={val.id}
|
|
2491
2564
|
placeholder={val.placeholder ? val.placeholder : ''}
|
|
2492
2565
|
className={`${ifError ? 'error-form-builder' : ''}`}
|
|
2493
|
-
errorMessage={errorMessageText}
|
|
2566
|
+
errorMessage={errorMessageText && !this.liquidFlow() ? errorMessageText : ''}
|
|
2494
2567
|
label={val.label}
|
|
2495
2568
|
autosize={val.autosize ? val.autosizeParams : false}
|
|
2496
2569
|
onChange={(e) => this.updateFormData(e.target.value, val)}
|
|
@@ -2520,8 +2593,10 @@ class FormBuilder extends React.Component { // eslint-disable-line react/prefer-
|
|
|
2520
2593
|
</CapColumn>
|
|
2521
2594
|
);
|
|
2522
2595
|
}
|
|
2596
|
+
}
|
|
2523
2597
|
};
|
|
2524
2598
|
|
|
2599
|
+
|
|
2525
2600
|
renderColLabelSection(section, childIndex) {
|
|
2526
2601
|
// const schema = this.props.schema
|
|
2527
2602
|
const fields = [];
|
|
@@ -3465,7 +3540,7 @@ class FormBuilder extends React.Component { // eslint-disable-line react/prefer-
|
|
|
3465
3540
|
<CapColumn
|
|
3466
3541
|
style={val.colStyle ? val.colStyle : {border : ""}}
|
|
3467
3542
|
span={val.width}
|
|
3468
|
-
className={`${(this.state.liquidErrorMessage?.LIQUID_ERROR_MSG?.length || this.state.liquidErrorMessage?.STANDARD_ERROR_MSG?.length) && this.liquidFlow && "error-boundary"} `}
|
|
3543
|
+
className={`${(this.state.liquidErrorMessage?.LIQUID_ERROR_MSG?.length || this.state.liquidErrorMessage?.STANDARD_ERROR_MSG?.length) && this.liquidFlow() && "error-boundary"} `}
|
|
3469
3544
|
>
|
|
3470
3545
|
<CKEditor
|
|
3471
3546
|
id={val.id}
|
|
@@ -3509,7 +3584,7 @@ class FormBuilder extends React.Component { // eslint-disable-line react/prefer-
|
|
|
3509
3584
|
isModuleFilterEnabled = this.props.isFullMode;
|
|
3510
3585
|
}
|
|
3511
3586
|
columns.push(
|
|
3512
|
-
<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"}`}>
|
|
3587
|
+
<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"}`}>
|
|
3513
3588
|
<BeeEditor
|
|
3514
3589
|
uid={uuid}
|
|
3515
3590
|
tokenData={beeToken}
|
|
@@ -3795,7 +3870,7 @@ class FormBuilder extends React.Component { // eslint-disable-line react/prefer-
|
|
|
3795
3870
|
|
|
3796
3871
|
|
|
3797
3872
|
return (
|
|
3798
|
-
<CapSpin spinning={Boolean((this.liquidFlow && this.props.liquidExtractionInProgress) || this.props.metaDataStatus === REQUEST)} tip={this.props.intl.formatMessage(messages.liquidSpinText)} >
|
|
3873
|
+
<CapSpin spinning={Boolean((this.liquidFlow() && this.props.liquidExtractionInProgress) || this.props.metaDataStatus === REQUEST)} tip={this.props.intl.formatMessage(messages.liquidSpinText)} >
|
|
3799
3874
|
<CapRow>
|
|
3800
3875
|
{this.props.schema && this.renderForm()}
|
|
3801
3876
|
<SlideBox
|
|
@@ -3877,7 +3952,8 @@ FormBuilder.propTypes = {
|
|
|
3877
3952
|
isFullMode: PropTypes.bool,
|
|
3878
3953
|
currentOrgDetails: PropTypes.object,
|
|
3879
3954
|
liquidExtractionInProgress: PropTypes.bool,
|
|
3880
|
-
showLiquidErrorInFooter: PropTypes.func
|
|
3955
|
+
showLiquidErrorInFooter: PropTypes.func,
|
|
3956
|
+
channel: PropTypes.string,
|
|
3881
3957
|
};
|
|
3882
3958
|
|
|
3883
3959
|
const mapStateToProps = createStructuredSelector({
|
|
@@ -3894,3 +3970,4 @@ function mapDispatchToProps(dispatch) {
|
|
|
3894
3970
|
}
|
|
3895
3971
|
|
|
3896
3972
|
export default connect(mapStateToProps,mapDispatchToProps)(injectIntl(FormBuilder));
|
|
3973
|
+
|
|
@@ -94,7 +94,7 @@ export default defineMessages({
|
|
|
94
94
|
id: 'creatives.componentsV2.FormBuilder.somethingWentWrong',
|
|
95
95
|
defaultMessage: 'Something went wrong while validating content, please try again later',
|
|
96
96
|
},
|
|
97
|
-
liquidSpinText:{
|
|
97
|
+
liquidSpinText: {
|
|
98
98
|
id: 'creatives.componentsV2.FormBuilder.liquidSpinText',
|
|
99
99
|
defaultMessage: 'Validating the template, it might take a few seconds',
|
|
100
100
|
},
|
|
@@ -26,7 +26,7 @@ const initializeComponent = () => {
|
|
|
26
26
|
describe('renders a MarketingObjective', () => {
|
|
27
27
|
it("Test if MarketingObjective component renders", () => {
|
|
28
28
|
initializeComponent();
|
|
29
|
-
const button = screen.
|
|
29
|
+
const button = screen.getByText('Done');
|
|
30
30
|
expect(button).toBeInTheDocument();
|
|
31
31
|
fireEvent.click(button);
|
|
32
32
|
});
|
|
@@ -5,11 +5,10 @@ import CapCollapsibleLeftNavigationSagas from '@capillarytech/cap-ui-library/Cap
|
|
|
5
5
|
import { analyticsBotSaga } from "@capillarytech/cap-ui-library/CapAskAira";
|
|
6
6
|
|
|
7
7
|
describe("analyticsBotSagaFn", () => {
|
|
8
|
-
|
|
8
|
+
test.concurrent("should call all analytics bot sagas", () => {
|
|
9
9
|
const { saga: analyticsBotSagaFn } = rootSagas.find(
|
|
10
10
|
s => s.key === "analyticsBotSaga"
|
|
11
11
|
);
|
|
12
|
-
|
|
13
12
|
return expectSaga(analyticsBotSagaFn)
|
|
14
13
|
.provide([
|
|
15
14
|
[matchers.call.fn(analyticsBotSaga[0]), undefined],
|
|
@@ -20,7 +19,7 @@ describe("analyticsBotSagaFn", () => {
|
|
|
20
19
|
});
|
|
21
20
|
|
|
22
21
|
describe("navigationConfigSaga", () => {
|
|
23
|
-
it("should call all analytics bot sagas", () => {
|
|
22
|
+
it.concurrent("should call all analytics bot sagas", () => {
|
|
24
23
|
const { saga: navigationConfigSaga } = rootSagas.find(
|
|
25
24
|
s => s.key === "navigation"
|
|
26
25
|
);
|
|
@@ -1,10 +1,9 @@
|
|
|
1
|
-
|
|
2
1
|
import * as actions from '../actions';
|
|
3
2
|
import * as types from '../constants';
|
|
4
3
|
|
|
5
4
|
describe('Gallery actions', () => {
|
|
6
5
|
describe('uploadAsset', () => {
|
|
7
|
-
|
|
6
|
+
test.concurrent('has a type of UPLOAD_ASSET_REQUEST', () => {
|
|
8
7
|
const expected = {
|
|
9
8
|
type: types.UPLOAD_ASSET_REQUEST,
|
|
10
9
|
file: 'test',
|
|
@@ -15,7 +14,7 @@ describe('Gallery actions', () => {
|
|
|
15
14
|
});
|
|
16
15
|
|
|
17
16
|
describe('getAllAssets', () => {
|
|
18
|
-
|
|
17
|
+
test.concurrent('has a type of GET_ALL_ASSETS_REQUEST', () => {
|
|
19
18
|
const expected = {
|
|
20
19
|
type: types.GET_ALL_ASSETS_REQUEST,
|
|
21
20
|
assetType: 'IMAGE',
|