@capillarytech/creatives-library 8.0.285 → 8.0.287-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/constants/unified.js +0 -1
- package/initialState.js +0 -2
- package/package.json +1 -1
- package/utils/common.js +5 -8
- package/utils/commonUtils.js +2 -83
- package/utils/tagValidations.js +84 -222
- package/utils/tests/commonUtil.test.js +147 -118
- package/utils/tests/tagValidations.test.js +280 -358
- package/v2Components/ErrorInfoNote/index.js +2 -5
- package/v2Components/FormBuilder/index.js +64 -158
- package/v2Components/FormBuilder/messages.js +0 -8
- package/v2Components/HtmlEditor/HTMLEditor.js +0 -5
- package/v2Components/HtmlEditor/__tests__/HTMLEditor.apiErrors.test.js +0 -1
- package/v2Components/HtmlEditor/__tests__/HTMLEditor.test.js +0 -15
- package/v2Components/HtmlEditor/components/CodeEditorPane/index.js +1 -2
- package/v2Containers/Cap/mockData.js +0 -14
- package/v2Containers/Cap/reducer.js +3 -55
- package/v2Containers/Cap/tests/reducer.test.js +0 -102
- package/v2Containers/CreativesContainer/index.js +0 -1
- package/v2Containers/Email/index.js +1 -5
- package/v2Containers/EmailWrapper/components/EmailHTMLEditor.js +10 -62
- package/v2Containers/EmailWrapper/components/__tests__/EmailHTMLEditor.test.js +12 -115
- package/v2Containers/FTP/index.js +2 -51
- package/v2Containers/FTP/messages.js +0 -4
- package/v2Containers/InApp/index.js +1 -96
- package/v2Containers/InApp/tests/index.test.js +17 -6
- package/v2Containers/InappAdvance/index.js +2 -103
- package/v2Containers/Line/Container/Text/index.js +0 -1
- package/v2Containers/MobilePushNew/index.js +2 -33
- package/v2Containers/Rcs/index.js +12 -37
- package/v2Containers/SmsTrai/Create/index.scss +1 -1
- package/v2Containers/SmsTrai/Edit/index.js +6 -47
- package/v2Containers/SmsTrai/Edit/tests/__snapshots__/index.test.js.snap +6 -6
- package/v2Containers/Viber/index.js +0 -1
- package/v2Containers/Viber/index.scss +1 -1
- package/v2Containers/WebPush/Create/hooks/useTagManagement.js +1 -3
- package/v2Containers/WebPush/Create/hooks/useTagManagement.test.js +0 -7
- package/v2Containers/WebPush/Create/index.js +2 -2
- package/v2Containers/WebPush/Create/utils/validation.js +18 -9
- package/v2Containers/WebPush/Create/utils/validation.test.js +0 -24
- package/v2Containers/Whatsapp/index.js +9 -17
- package/v2Containers/Zalo/index.js +3 -11
|
@@ -50,9 +50,7 @@ import injectReducer from '../../utils/injectReducer';
|
|
|
50
50
|
import v2InAppReducer from '../InApp/reducer';
|
|
51
51
|
import { v2InAppSagas } from '../InApp/sagas';
|
|
52
52
|
import injectSaga from '../../utils/injectSaga';
|
|
53
|
-
import { validateTags } from "../../utils/tagValidations";
|
|
54
53
|
import { validateInAppContent } from "../../utils/commonUtils";
|
|
55
|
-
import { hasLiquidSupportFeature } from "../../utils/common";
|
|
56
54
|
import formBuilderMessages from "../../v2Components/FormBuilder/messages";
|
|
57
55
|
import { getSingleTab, hasAnyErrors } from "../InApp/utils";
|
|
58
56
|
import ErrorInfoNote from "../../v2Components/ErrorInfoNote";
|
|
@@ -817,11 +815,9 @@ export const InappAdvanced = (props) => {
|
|
|
817
815
|
const latestHtmlValues = await saveAllBeeInstances();
|
|
818
816
|
const payload = createPayload(latestHtmlValues);
|
|
819
817
|
|
|
820
|
-
// Validate the INAPP content
|
|
821
|
-
const isLiquidFlow = hasLiquidSupportFeature();
|
|
822
818
|
// Skip validation if no tags are available (e.g., in tests or when tags haven't loaded)
|
|
823
819
|
const hasTags = tags && tags.length > 0;
|
|
824
|
-
if (
|
|
820
|
+
if (hasTags) {
|
|
825
821
|
validateInAppContent(payload, {
|
|
826
822
|
currentTab: panes === ANDROID ? 1 : 2, // Convert ANDROID/IOS to tab numbers
|
|
827
823
|
onError,
|
|
@@ -829,10 +825,6 @@ export const InappAdvanced = (props) => {
|
|
|
829
825
|
getLiquidTags: (content, callback) => globalActions.getLiquidTags(content, callback),
|
|
830
826
|
formatMessage,
|
|
831
827
|
messages: formBuilderMessages,
|
|
832
|
-
tagLookupMap: metaEntities?.tagLookupMap || {},
|
|
833
|
-
eventContextTags: metaEntities?.eventContextTags || [],
|
|
834
|
-
isLiquidFlow,
|
|
835
|
-
forwardedTags: {},
|
|
836
828
|
skipTags: (tag) => {
|
|
837
829
|
// Skip certain tags if needed
|
|
838
830
|
const skipRegexes = [
|
|
@@ -847,92 +839,7 @@ export const InappAdvanced = (props) => {
|
|
|
847
839
|
},
|
|
848
840
|
singleTab: getSingleTab(accountData),
|
|
849
841
|
});
|
|
850
|
-
} else if (hasTags) {
|
|
851
|
-
// For non-liquid flow, validate tags using validateTags (only if tags are available)
|
|
852
|
-
const androidContent = latestHtmlValues?.android || (androidBeeHtml?.value || (typeof androidBeeHtml === 'string' ? androidBeeHtml : ''));
|
|
853
|
-
const iosContent = latestHtmlValues?.ios || (iosBeeHtml?.value || (typeof iosBeeHtml === 'string' ? iosBeeHtml : ''));
|
|
854
|
-
|
|
855
|
-
const androidSupported = get(accountData, 'selectedWeChatAccount.configs.android') === DEVICE_SUPPORTED || get(editContent, 'ANDROID.deviceType') === ANDROID;
|
|
856
|
-
const iosSupported = get(accountData, 'selectedWeChatAccount.configs.ios') === DEVICE_SUPPORTED || get(editContent, 'IOS.deviceType') === IOS_CAPITAL;
|
|
857
|
-
|
|
858
|
-
let hasErrors = false;
|
|
859
|
-
const newErrors = {
|
|
860
|
-
STANDARD_ERROR_MSG: {
|
|
861
|
-
ANDROID: [],
|
|
862
|
-
IOS: [],
|
|
863
|
-
GENERIC: [],
|
|
864
|
-
},
|
|
865
|
-
LIQUID_ERROR_MSG: {
|
|
866
|
-
ANDROID: [],
|
|
867
|
-
IOS: [],
|
|
868
|
-
GENERIC: [],
|
|
869
|
-
},
|
|
870
|
-
};
|
|
871
|
-
|
|
872
|
-
// Validate Android content
|
|
873
|
-
if (androidSupported && androidContent && androidContent?.trim() !== '') {
|
|
874
|
-
const validationResponse = validateTags({
|
|
875
|
-
content: androidContent,
|
|
876
|
-
tagsParam: tags,
|
|
877
|
-
injectedTagsParams: injectedTags || {},
|
|
878
|
-
location,
|
|
879
|
-
tagModule: getDefaultTags,
|
|
880
|
-
eventContextTags: metaEntities?.eventContextTags || [],
|
|
881
|
-
isFullMode,
|
|
882
|
-
}) || {};
|
|
883
|
-
|
|
884
|
-
if (validationResponse?.unsupportedTags?.length > 0) {
|
|
885
|
-
hasErrors = true;
|
|
886
|
-
newErrors.LIQUID_ERROR_MSG.ANDROID.push(
|
|
887
|
-
formatMessage(globalMessages.unsupportedTagsValidationError, {
|
|
888
|
-
unsupportedTags: validationResponse.unsupportedTags.join(", "),
|
|
889
|
-
})
|
|
890
|
-
);
|
|
891
|
-
}
|
|
892
|
-
if (validationResponse?.isBraceError) {
|
|
893
|
-
hasErrors = true;
|
|
894
|
-
newErrors.LIQUID_ERROR_MSG.ANDROID.push(
|
|
895
|
-
formatMessage(globalMessages.unbalanacedCurlyBraces)
|
|
896
|
-
);
|
|
897
|
-
}
|
|
898
|
-
}
|
|
899
|
-
|
|
900
|
-
// Validate iOS content
|
|
901
|
-
if (iosSupported && iosContent && iosContent?.trim() !== '') {
|
|
902
|
-
const validationResponse = validateTags({
|
|
903
|
-
content: iosContent,
|
|
904
|
-
tagsParam: tags,
|
|
905
|
-
injectedTagsParams: injectedTags || {},
|
|
906
|
-
location,
|
|
907
|
-
tagModule: getDefaultTags,
|
|
908
|
-
eventContextTags: metaEntities?.eventContextTags || [],
|
|
909
|
-
isFullMode,
|
|
910
|
-
}) || {};
|
|
911
|
-
|
|
912
|
-
if (validationResponse?.unsupportedTags?.length > 0) {
|
|
913
|
-
hasErrors = true;
|
|
914
|
-
newErrors.LIQUID_ERROR_MSG.IOS.push(
|
|
915
|
-
formatMessage(globalMessages.unsupportedTagsValidationError, {
|
|
916
|
-
unsupportedTags: validationResponse.unsupportedTags.join(", "),
|
|
917
|
-
})
|
|
918
|
-
);
|
|
919
|
-
}
|
|
920
|
-
if (validationResponse?.isBraceError) {
|
|
921
|
-
hasErrors = true;
|
|
922
|
-
newErrors.LIQUID_ERROR_MSG.IOS.push(
|
|
923
|
-
formatMessage(globalMessages.unbalanacedCurlyBraces)
|
|
924
|
-
);
|
|
925
|
-
}
|
|
926
|
-
}
|
|
927
|
-
|
|
928
|
-
if (hasErrors) {
|
|
929
|
-
setErrorMessage(newErrors);
|
|
930
|
-
} else {
|
|
931
|
-
// No errors, proceed with submission
|
|
932
|
-
onSuccess();
|
|
933
|
-
}
|
|
934
842
|
} else {
|
|
935
|
-
// No tags available, skip validation and proceed directly
|
|
936
843
|
onSuccess();
|
|
937
844
|
}
|
|
938
845
|
};
|
|
@@ -1038,15 +945,7 @@ export const InappAdvanced = (props) => {
|
|
|
1038
945
|
)}
|
|
1039
946
|
<CapButton
|
|
1040
947
|
onClick={async () => {
|
|
1041
|
-
|
|
1042
|
-
const hasTags = tags && tags?.length > 0;
|
|
1043
|
-
if (isLiquidFlow || hasTags) {
|
|
1044
|
-
// Use validation middleware for tag validation
|
|
1045
|
-
await liquidMiddleWare();
|
|
1046
|
-
} else {
|
|
1047
|
-
// No validation needed, proceed directly
|
|
1048
|
-
await onDoneCallback();
|
|
1049
|
-
}
|
|
948
|
+
await liquidMiddleWare();
|
|
1050
949
|
}}
|
|
1051
950
|
disabled={isDisableDone()}
|
|
1052
951
|
className="inapp-create-btn"
|
|
@@ -77,7 +77,6 @@ import { getContent } from "../MobilePush/commonMethods";
|
|
|
77
77
|
import { getMessageObject } from "../../utils/messageUtils";
|
|
78
78
|
import { gtmPush } from "../../utils/gtmTrackers";
|
|
79
79
|
import mobilePushReducer from "./reducer";
|
|
80
|
-
import { hasLiquidSupportFeature } from "../../utils/common";
|
|
81
80
|
import formBuilderMessages from "../../v2Components/FormBuilder/messages";
|
|
82
81
|
import { validateMobilePushContent } from "../../utils/commonUtils";
|
|
83
82
|
import { getSingleTab } from "../InApp/utils";
|
|
@@ -799,10 +798,9 @@ const MobilePushNew = ({
|
|
|
799
798
|
(value) => {
|
|
800
799
|
let errorTemplateDescMessage = "";
|
|
801
800
|
|
|
802
|
-
const {
|
|
801
|
+
const { isBraceError } = validateTags({
|
|
803
802
|
content: value,
|
|
804
803
|
tagsParam: tags,
|
|
805
|
-
injectedTagsParams: injectedTags,
|
|
806
804
|
location,
|
|
807
805
|
tagModule: getDefaultTags,
|
|
808
806
|
isFullMode,
|
|
@@ -812,14 +810,6 @@ const MobilePushNew = ({
|
|
|
812
810
|
messages.emptyTemplateDescErrorMessage
|
|
813
811
|
);
|
|
814
812
|
}
|
|
815
|
-
if (unsupportedTags?.length > 0) {
|
|
816
|
-
errorTemplateDescMessage = formatMessage(
|
|
817
|
-
globalMessages.unsupportedTagsValidationError,
|
|
818
|
-
{
|
|
819
|
-
unsupportedTags,
|
|
820
|
-
}
|
|
821
|
-
);
|
|
822
|
-
}
|
|
823
813
|
if (isBraceError) {
|
|
824
814
|
errorTemplateDescMessage = formatMessage(
|
|
825
815
|
globalMessages.unbalanacedCurlyBraces
|
|
@@ -2606,20 +2596,6 @@ const MobilePushNew = ({
|
|
|
2606
2596
|
getLiquidTags: globalActionsProps.getLiquidTags,
|
|
2607
2597
|
formatMessage,
|
|
2608
2598
|
messages: formBuilderMessages,
|
|
2609
|
-
tagLookupMap: metaEntities?.tagLookupMap || {},
|
|
2610
|
-
eventContextTags: metaEntities?.eventContextTags || [],
|
|
2611
|
-
isLiquidFlow: hasLiquidSupportFeature(),
|
|
2612
|
-
forwardedTags: {},
|
|
2613
|
-
skipTags: (tag) => {
|
|
2614
|
-
const skipRegexes = [
|
|
2615
|
-
/dynamic_expiry_date_after_\d+_days\.FORMAT_\d/,
|
|
2616
|
-
/unsubscribe\(#[a-zA-Z\d]{6}\)/,
|
|
2617
|
-
/Link_to_[a-zA-z]/,
|
|
2618
|
-
/SURVEY.*\.TOKEN/,
|
|
2619
|
-
/^[A-Za-z].*\([a-zA-Z\d]*\)/,
|
|
2620
|
-
];
|
|
2621
|
-
return skipRegexes.some((regex) => regex.test(tag));
|
|
2622
|
-
},
|
|
2623
2599
|
singleTab: getSingleTab(accountData),
|
|
2624
2600
|
});
|
|
2625
2601
|
}, [
|
|
@@ -2628,12 +2604,9 @@ const MobilePushNew = ({
|
|
|
2628
2604
|
activeTab,
|
|
2629
2605
|
globalActionsProps,
|
|
2630
2606
|
formatMessage,
|
|
2631
|
-
metaEntities,
|
|
2632
2607
|
accountData,
|
|
2633
2608
|
]);
|
|
2634
2609
|
|
|
2635
|
-
const isLiquidFlow = hasLiquidSupportFeature();
|
|
2636
|
-
|
|
2637
2610
|
useEffect(() => {
|
|
2638
2611
|
// Always map to { label } for both platforms
|
|
2639
2612
|
const newButtons = Array.isArray(ctaData)
|
|
@@ -3030,11 +3003,7 @@ const MobilePushNew = ({
|
|
|
3030
3003
|
<CapButton
|
|
3031
3004
|
type="primary"
|
|
3032
3005
|
onClick={() => {
|
|
3033
|
-
|
|
3034
|
-
liquidMiddleWare();
|
|
3035
|
-
} else {
|
|
3036
|
-
handleSave();
|
|
3037
|
-
}
|
|
3006
|
+
liquidMiddleWare();
|
|
3038
3007
|
}}
|
|
3039
3008
|
className="save-button"
|
|
3040
3009
|
disabled={isSaveDisabled}
|
|
@@ -394,23 +394,15 @@ export const Rcs = (props) => {
|
|
|
394
394
|
const validationResponse =
|
|
395
395
|
validateTags({
|
|
396
396
|
content: contentForValidation,
|
|
397
|
-
|
|
398
|
-
|
|
399
|
-
|
|
400
|
-
|
|
401
|
-
|
|
402
|
-
|
|
403
|
-
|
|
404
|
-
|
|
405
|
-
|
|
406
|
-
const errorMsg =
|
|
407
|
-
(unsupportedTagsLengthCheck &&
|
|
408
|
-
formatMessage(globalMessages.unsupportedTagsValidationError, {
|
|
409
|
-
unsupportedTags: validationResponse.unsupportedTags,
|
|
410
|
-
})) ||
|
|
411
|
-
(validationResponse.isBraceError &&
|
|
412
|
-
formatMessage(globalMessages.unbalanacedCurlyBraces)) ||
|
|
413
|
-
false;
|
|
397
|
+
tagsParam: tags,
|
|
398
|
+
location,
|
|
399
|
+
tagModule: getDefaultTags,
|
|
400
|
+
isFullMode,
|
|
401
|
+
}) || {};
|
|
402
|
+
const errorMsg =
|
|
403
|
+
(validationResponse?.isBraceError &&
|
|
404
|
+
formatMessage(globalMessages.unbalanacedCurlyBraces)) ||
|
|
405
|
+
false;
|
|
414
406
|
if (type === TITLE_TEXT) setTemplateTitleError(errorMsg);
|
|
415
407
|
if (type === MESSAGE_TEXT) setTemplateDescError(errorMsg);
|
|
416
408
|
};
|
|
@@ -835,10 +827,9 @@ export const Rcs = (props) => {
|
|
|
835
827
|
|
|
836
828
|
const templateDescErrorHandler = (value) => {
|
|
837
829
|
let errorMessage = false;
|
|
838
|
-
const {
|
|
830
|
+
const { isBraceError } = validateTags({
|
|
839
831
|
content: value,
|
|
840
832
|
tagsParam: tags,
|
|
841
|
-
injectedTagsParams: injectedTags,
|
|
842
833
|
location,
|
|
843
834
|
tagModule: getDefaultTags,
|
|
844
835
|
isFullMode,
|
|
@@ -868,26 +859,10 @@ export const Rcs = (props) => {
|
|
|
868
859
|
};
|
|
869
860
|
|
|
870
861
|
const fallbackMessageErrorHandler = (value) => {
|
|
871
|
-
let errorMessage = false;
|
|
872
|
-
const { unsupportedTags } = validateTags({
|
|
873
|
-
content: value,
|
|
874
|
-
tagsParam: tags,
|
|
875
|
-
injectedTagsParams: injectedTags,
|
|
876
|
-
location,
|
|
877
|
-
tagModule: getDefaultTags,
|
|
878
|
-
isFullMode,
|
|
879
|
-
}) || {};
|
|
880
862
|
if (value?.length > FALLBACK_MESSAGE_MAX_LENGTH) {
|
|
881
|
-
|
|
882
|
-
} else if (unsupportedTags?.length > 0) {
|
|
883
|
-
errorMessage = formatMessage(
|
|
884
|
-
globalMessages.unsupportedTagsValidationError,
|
|
885
|
-
{
|
|
886
|
-
unsupportedTags,
|
|
887
|
-
},
|
|
888
|
-
);
|
|
863
|
+
return formatMessage(messages.fallbackMsgLenError);
|
|
889
864
|
}
|
|
890
|
-
return
|
|
865
|
+
return false;
|
|
891
866
|
};
|
|
892
867
|
|
|
893
868
|
// Check for forbidden characters: square brackets [] and single curly braces {}
|
|
@@ -39,10 +39,8 @@ import formBuilderMessages from '../../../v2Components/FormBuilder/messages';
|
|
|
39
39
|
import UnifiedPreview from '../../../v2Components/CommonTestAndPreview/UnifiedPreview';
|
|
40
40
|
import TestAndPreviewSlidebox from '../../../v2Components/TestAndPreviewSlidebox';
|
|
41
41
|
import withCreatives from '../../../hoc/withCreatives';
|
|
42
|
-
import { validateTags } from '../../../utils/tagValidations';
|
|
43
42
|
import {
|
|
44
43
|
CHARLIMIT,
|
|
45
|
-
SMS,
|
|
46
44
|
SMS_TRAI_VAR,
|
|
47
45
|
TAG,
|
|
48
46
|
EMBEDDED,
|
|
@@ -51,16 +49,15 @@ import {
|
|
|
51
49
|
ALL,
|
|
52
50
|
LIBRARY,
|
|
53
51
|
} from './constants';
|
|
52
|
+
import { SMS } from '../../CreativesContainer/constants';
|
|
54
53
|
import v2EditSmsReducer from '../../Sms/Edit/reducer';
|
|
55
54
|
import { v2SmsEditSagas } from '../../Sms/Edit/sagas';
|
|
56
55
|
import ErrorInfoNote from '../../../v2Components/ErrorInfoNote';
|
|
57
56
|
import { validateLiquidTemplateContent } from '../../../utils/commonUtils';
|
|
58
|
-
import { hasLiquidSupportFeature } from '../../../utils/common';
|
|
59
57
|
import { ANDROID } from '../../../v2Components/CommonTestAndPreview/constants';
|
|
60
58
|
|
|
61
59
|
let varMap = {};
|
|
62
60
|
let traiData = {};
|
|
63
|
-
let tagValidationResponse = {};
|
|
64
61
|
const { TextArea } = CapInput;
|
|
65
62
|
const { CapLabelInline } = CapLabel;
|
|
66
63
|
|
|
@@ -94,7 +91,6 @@ export const SmsTraiEdit = (props) => {
|
|
|
94
91
|
const [tags, updateTags] = useState([]);
|
|
95
92
|
const [textAreaId, updateTextAreaId] = useState();
|
|
96
93
|
const [isValidationError, updateIsValidationError] = useState(false);
|
|
97
|
-
const [isTagValidationError, updateIsTagValidationError] = useState(false);
|
|
98
94
|
const [totalMessageLength, setTotalMessageLength] = useState(0);
|
|
99
95
|
const [isUnicodeAllowed, updateIsUnicodeAllowed] = useState(true);
|
|
100
96
|
const [showMsgLengthNote, updateshowMsgLengthNote] = useState(false);
|
|
@@ -229,29 +225,6 @@ export const SmsTraiEdit = (props) => {
|
|
|
229
225
|
}
|
|
230
226
|
}, []);
|
|
231
227
|
|
|
232
|
-
//performs tag validation
|
|
233
|
-
useEffect(() => {
|
|
234
|
-
if (
|
|
235
|
-
!isFullMode &&
|
|
236
|
-
updatedSmsEditor?.length > 0 &&
|
|
237
|
-
!updatedSmsEditor.includes(SMS_TRAI_VAR)
|
|
238
|
-
) {
|
|
239
|
-
tagValidationResponse =
|
|
240
|
-
validateTags({
|
|
241
|
-
content: updatedSmsEditor.join(''),
|
|
242
|
-
tagsParam: tags,
|
|
243
|
-
injectedTagsParams: injectedTags,
|
|
244
|
-
location,
|
|
245
|
-
tagModule: getDefaultTags,
|
|
246
|
-
eventContextTags,
|
|
247
|
-
isFullMode,
|
|
248
|
-
}) || {};
|
|
249
|
-
updateIsTagValidationError(
|
|
250
|
-
tagValidationResponse.unsupportedTags.length > 0,
|
|
251
|
-
);
|
|
252
|
-
}
|
|
253
|
-
}, [updatedSmsEditor, tags]);
|
|
254
|
-
|
|
255
228
|
const computeUpdatedSmsEditor = () => {
|
|
256
229
|
const arr = [...tempMsgArray];
|
|
257
230
|
const varMapKeys = Object.keys(varMap)?.map((key) => Number(key.slice(8)))?.sort((a, b) => a - b) || [];
|
|
@@ -288,6 +261,8 @@ export const SmsTraiEdit = (props) => {
|
|
|
288
261
|
};
|
|
289
262
|
|
|
290
263
|
const onSubmitWrapper = () => {
|
|
264
|
+
setIsLiquidValidationError(false);
|
|
265
|
+
setLiquidErrorMessages({});
|
|
291
266
|
const content = updatedSmsEditor.join('');
|
|
292
267
|
const onError = ({ standardErrors, liquidErrors }) => {
|
|
293
268
|
setLiquidErrorMessages({
|
|
@@ -298,6 +273,8 @@ export const SmsTraiEdit = (props) => {
|
|
|
298
273
|
};
|
|
299
274
|
|
|
300
275
|
const onSuccess = () => {
|
|
276
|
+
setIsLiquidValidationError(false);
|
|
277
|
+
setLiquidErrorMessages({});
|
|
301
278
|
onDoneCallback();
|
|
302
279
|
};
|
|
303
280
|
validateLiquidTemplateContent(content, {
|
|
@@ -306,10 +283,6 @@ export const SmsTraiEdit = (props) => {
|
|
|
306
283
|
messages: formBuilderMessages,
|
|
307
284
|
onError,
|
|
308
285
|
onSuccess,
|
|
309
|
-
tagLookupMap: metaEntities?.tagLookupMap,
|
|
310
|
-
eventContextTags,
|
|
311
|
-
isLiquidFlow: true,
|
|
312
|
-
forwardedTags: {},
|
|
313
286
|
});
|
|
314
287
|
};
|
|
315
288
|
|
|
@@ -548,17 +521,6 @@ export const SmsTraiEdit = (props) => {
|
|
|
548
521
|
return countVarChar;
|
|
549
522
|
};
|
|
550
523
|
|
|
551
|
-
const tagValidationErrorMessage = () => {
|
|
552
|
-
const { unsupportedTags = [] } = tagValidationResponse;
|
|
553
|
-
let tagError = '';
|
|
554
|
-
if (unsupportedTags.length > 0) {
|
|
555
|
-
tagError = formatMessage(messages.unsupportedTagsValidationError, {
|
|
556
|
-
unsupportedTags,
|
|
557
|
-
});
|
|
558
|
-
}
|
|
559
|
-
return <CapError>{tagError}</CapError>;
|
|
560
|
-
};
|
|
561
|
-
|
|
562
524
|
const disablehandler = () => {
|
|
563
525
|
if (traiData && !isEmpty(traiData)) {
|
|
564
526
|
const msg = get(traiData, `versions.base.sms-editor`, '');
|
|
@@ -604,7 +566,6 @@ export const SmsTraiEdit = (props) => {
|
|
|
604
566
|
setShowTestAndPreviewSlidebox(false);
|
|
605
567
|
};
|
|
606
568
|
|
|
607
|
-
const isLiquidSupportFeatureEnabled = hasLiquidSupportFeature();
|
|
608
569
|
return (
|
|
609
570
|
<>
|
|
610
571
|
<CapSpin spinning={loading || fetchingLiquidTags} tip={fetchingLiquidTags && formatMessage(formBuilderMessages.liquidSpinText)}>
|
|
@@ -662,7 +623,6 @@ export const SmsTraiEdit = (props) => {
|
|
|
662
623
|
<CapRow>
|
|
663
624
|
{smsLengthForVar()}
|
|
664
625
|
</CapRow>
|
|
665
|
-
{isTagValidationError && tagValidationErrorMessage()}
|
|
666
626
|
<CapCheckbox onChange={unicodeHandler} checked={isUnicodeAllowed} disabled={disablehandler()}>
|
|
667
627
|
{formatMessage(messages.unicodeLabel)}
|
|
668
628
|
</CapCheckbox>
|
|
@@ -693,9 +653,8 @@ export const SmsTraiEdit = (props) => {
|
|
|
693
653
|
<FormattedMessage {...messages.testAndPreviewButtonLabel} />
|
|
694
654
|
</CapButton>
|
|
695
655
|
<CapButton
|
|
696
|
-
onClick={
|
|
656
|
+
onClick={onSubmitWrapper}
|
|
697
657
|
className="create-msg"
|
|
698
|
-
disabled={isTagValidationError || (isLiquidSupportFeatureEnabled && !isObject(metaEntities?.tagLookupMap))}
|
|
699
658
|
>
|
|
700
659
|
<FormattedMessage {...messages.saveButtonLabel} />
|
|
701
660
|
</CapButton>
|
|
@@ -4265,7 +4265,7 @@ FREE GIFTS-
|
|
|
4265
4265
|
<CapCheckbox
|
|
4266
4266
|
checked={false}
|
|
4267
4267
|
disabled={false}
|
|
4268
|
-
key=".
|
|
4268
|
+
key=".3"
|
|
4269
4269
|
labelType="h4"
|
|
4270
4270
|
onChange={[Function]}
|
|
4271
4271
|
>
|
|
@@ -4327,7 +4327,7 @@ FREE GIFTS-
|
|
|
4327
4327
|
</div>
|
|
4328
4328
|
</CapCheckbox>
|
|
4329
4329
|
<div
|
|
4330
|
-
key=".
|
|
4330
|
+
key=".5"
|
|
4331
4331
|
style={
|
|
4332
4332
|
Object {
|
|
4333
4333
|
"marginBottom": "100px",
|
|
@@ -15176,7 +15176,7 @@ FREE GIFTS-
|
|
|
15176
15176
|
<CapCheckbox
|
|
15177
15177
|
checked={false}
|
|
15178
15178
|
disabled={false}
|
|
15179
|
-
key=".
|
|
15179
|
+
key=".3"
|
|
15180
15180
|
labelType="h4"
|
|
15181
15181
|
onChange={[Function]}
|
|
15182
15182
|
>
|
|
@@ -15238,7 +15238,7 @@ FREE GIFTS-
|
|
|
15238
15238
|
</div>
|
|
15239
15239
|
</CapCheckbox>
|
|
15240
15240
|
<div
|
|
15241
|
-
key=".
|
|
15241
|
+
key=".5"
|
|
15242
15242
|
style={
|
|
15243
15243
|
Object {
|
|
15244
15244
|
"marginBottom": "100px",
|
|
@@ -26117,7 +26117,7 @@ FREE GIFTS-
|
|
|
26117
26117
|
<CapCheckbox
|
|
26118
26118
|
checked={false}
|
|
26119
26119
|
disabled={false}
|
|
26120
|
-
key=".
|
|
26120
|
+
key=".3"
|
|
26121
26121
|
labelType="h4"
|
|
26122
26122
|
onChange={[Function]}
|
|
26123
26123
|
>
|
|
@@ -26179,7 +26179,7 @@ FREE GIFTS-
|
|
|
26179
26179
|
</div>
|
|
26180
26180
|
</CapCheckbox>
|
|
26181
26181
|
<div
|
|
26182
|
-
key=".
|
|
26182
|
+
key=".5"
|
|
26183
26183
|
style={
|
|
26184
26184
|
Object {
|
|
26185
26185
|
"marginBottom": "100px",
|
|
@@ -105,12 +105,10 @@ export const useTagManagement = ({
|
|
|
105
105
|
const validationConfig = useMemo(
|
|
106
106
|
() => ({
|
|
107
107
|
tagsParam: tags,
|
|
108
|
-
injectedTagsParams: injectedTags,
|
|
109
108
|
location,
|
|
110
109
|
tagModule: getDefaultTags,
|
|
111
|
-
eventContextTags,
|
|
112
110
|
}),
|
|
113
|
-
[tags,
|
|
111
|
+
[tags, location, getDefaultTags],
|
|
114
112
|
);
|
|
115
113
|
|
|
116
114
|
return {
|
|
@@ -528,26 +528,19 @@ describe('useTagManagement', () => {
|
|
|
528
528
|
|
|
529
529
|
describe('validationConfig', () => {
|
|
530
530
|
it('should return validation config with tags', () => {
|
|
531
|
-
const injectedTags = [{ id: 5, name: 'Injected Tag' }];
|
|
532
|
-
const eventContextTags = [{ id: 6, name: 'Event Tag' }];
|
|
533
|
-
|
|
534
531
|
const { result } = renderHook(() =>
|
|
535
532
|
useTagManagement({
|
|
536
533
|
location: defaultLocation,
|
|
537
534
|
globalActions: mockGlobalActions,
|
|
538
535
|
metaEntities: defaultMetaEntities,
|
|
539
|
-
injectedTags,
|
|
540
|
-
eventContextTags,
|
|
541
536
|
getDefaultTags: 'custom',
|
|
542
537
|
})
|
|
543
538
|
);
|
|
544
539
|
|
|
545
540
|
expect(result.current.validationConfig).toEqual({
|
|
546
541
|
tagsParam: defaultMetaEntities.tags.standard,
|
|
547
|
-
injectedTagsParams: injectedTags,
|
|
548
542
|
location: defaultLocation,
|
|
549
543
|
tagModule: 'custom',
|
|
550
|
-
eventContextTags,
|
|
551
544
|
});
|
|
552
545
|
});
|
|
553
546
|
|
|
@@ -285,8 +285,8 @@ const WebPushCreate = ({
|
|
|
285
285
|
const validateTemplateName = useCallback((value) => validateTemplateNameUtil(value), []);
|
|
286
286
|
|
|
287
287
|
const validateTitle = useCallback(
|
|
288
|
-
(value) => validateTitleUtil(value, formatMessage, messages),
|
|
289
|
-
[formatMessage],
|
|
288
|
+
(value) => validateTitleUtil(value, formatMessage, messages, validationConfig, isFullMode),
|
|
289
|
+
[formatMessage, validationConfig, isFullMode],
|
|
290
290
|
);
|
|
291
291
|
|
|
292
292
|
const validateUrl = useCallback(
|
|
@@ -10,16 +10,31 @@ import globalMessages from '../../../Cap/messages';
|
|
|
10
10
|
export const validateTemplateName = (value) => !value || value.trim() === '';
|
|
11
11
|
|
|
12
12
|
/**
|
|
13
|
-
* Validates notification title
|
|
13
|
+
* Validates notification title (required and optional tag validation)
|
|
14
14
|
* @param {string} value - The title value
|
|
15
15
|
* @param {Function} formatMessage - i18n format message function
|
|
16
16
|
* @param {Object} messages - Message definitions
|
|
17
|
+
* @param {Object} [validationConfig] - Optional config for tag validation
|
|
18
|
+
* @param {boolean} [isFullMode] - Optional; when set with validationConfig, runs tag validation
|
|
17
19
|
* @returns {string} Error message if invalid, empty string if valid
|
|
18
20
|
*/
|
|
19
|
-
export const validateTitle = (value, formatMessage, messages) => {
|
|
21
|
+
export const validateTitle = (value, formatMessage, messages, validationConfig, isFullMode) => {
|
|
20
22
|
if (!value || value.trim() === '') {
|
|
21
23
|
return formatMessage(messages.titleRequired);
|
|
22
24
|
}
|
|
25
|
+
|
|
26
|
+
if (validationConfig != null) {
|
|
27
|
+
const validationResponse = validateTags({
|
|
28
|
+
content: value,
|
|
29
|
+
...validationConfig,
|
|
30
|
+
isFullMode,
|
|
31
|
+
}) || {};
|
|
32
|
+
|
|
33
|
+
if (validationResponse?.isBraceError) {
|
|
34
|
+
return formatMessage(globalMessages.unbalanacedCurlyBraces);
|
|
35
|
+
}
|
|
36
|
+
}
|
|
37
|
+
|
|
23
38
|
return '';
|
|
24
39
|
};
|
|
25
40
|
|
|
@@ -60,13 +75,7 @@ export const validateMessageContent = (value, formatMessage, messages, validatio
|
|
|
60
75
|
...validationConfig,
|
|
61
76
|
isFullMode,
|
|
62
77
|
}) || {};
|
|
63
|
-
|
|
64
|
-
if (validationResponse?.unsupportedTags?.length) {
|
|
65
|
-
return formatMessage(globalMessages.unsupportedTagsValidationError, {
|
|
66
|
-
unsupportedTags: validationResponse.unsupportedTags.join(', '),
|
|
67
|
-
});
|
|
68
|
-
}
|
|
69
|
-
|
|
78
|
+
|
|
70
79
|
if (validationResponse?.isBraceError) {
|
|
71
80
|
return formatMessage(globalMessages.unbalanacedCurlyBraces);
|
|
72
81
|
}
|
|
@@ -169,10 +169,8 @@ describe('validation', () => {
|
|
|
169
169
|
describe('validateMessageContent', () => {
|
|
170
170
|
const mockValidationConfig = {
|
|
171
171
|
tagsParam: [],
|
|
172
|
-
injectedTagsParams: [],
|
|
173
172
|
location: {},
|
|
174
173
|
tagModule: '',
|
|
175
|
-
eventContextTags: [],
|
|
176
174
|
};
|
|
177
175
|
|
|
178
176
|
beforeEach(() => {
|
|
@@ -211,17 +209,6 @@ describe('validation', () => {
|
|
|
211
209
|
});
|
|
212
210
|
});
|
|
213
211
|
|
|
214
|
-
it('should return error message for unsupported tags', () => {
|
|
215
|
-
validateTags.mockReturnValue({
|
|
216
|
-
unsupportedTags: ['tag1', 'tag2'],
|
|
217
|
-
});
|
|
218
|
-
const result = validateMessageContent('Message with {tag1} and {tag2}', mockFormatMessage, mockMessages, mockValidationConfig);
|
|
219
|
-
expect(result).toBe('Unsupported tags: tag1, tag2');
|
|
220
|
-
expect(mockFormatMessage).toHaveBeenCalledWith(globalMessages.unsupportedTagsValidationError, {
|
|
221
|
-
unsupportedTags: 'tag1, tag2',
|
|
222
|
-
});
|
|
223
|
-
});
|
|
224
|
-
|
|
225
212
|
it('should return error message for unbalanced curly braces', () => {
|
|
226
213
|
validateTags.mockReturnValue({
|
|
227
214
|
isBraceError: true,
|
|
@@ -231,22 +218,11 @@ describe('validation', () => {
|
|
|
231
218
|
expect(mockFormatMessage).toHaveBeenCalledWith(globalMessages.unbalanacedCurlyBraces);
|
|
232
219
|
});
|
|
233
220
|
|
|
234
|
-
it('should return error message for both unsupported tags and brace error (unsupported tags takes precedence)', () => {
|
|
235
|
-
validateTags.mockReturnValue({
|
|
236
|
-
unsupportedTags: ['tag1'],
|
|
237
|
-
isBraceError: true,
|
|
238
|
-
});
|
|
239
|
-
const result = validateMessageContent('Message with {tag1}', mockFormatMessage, mockMessages, mockValidationConfig);
|
|
240
|
-
expect(result).toBe('Unsupported tags: tag1');
|
|
241
|
-
});
|
|
242
|
-
|
|
243
221
|
it('should pass validation config to validateTags', () => {
|
|
244
222
|
const customConfig = {
|
|
245
223
|
tagsParam: [{ id: 1, name: 'Tag1' }],
|
|
246
|
-
injectedTagsParams: [{ id: 2, name: 'Tag2' }],
|
|
247
224
|
location: { query: { type: 'test' } },
|
|
248
225
|
tagModule: 'custom',
|
|
249
|
-
eventContextTags: [{ id: 3, name: 'Tag3' }],
|
|
250
226
|
};
|
|
251
227
|
validateTags.mockReturnValue({});
|
|
252
228
|
validateMessageContent('Valid message', mockFormatMessage, mockMessages, customConfig);
|