@capillarytech/creatives-library 8.0.285-alpha.0 → 8.0.285
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/package.json +1 -1
- package/utils/common.js +7 -0
- package/utils/commonUtils.js +79 -2
- package/utils/tagValidations.js +71 -92
- package/utils/tests/commonUtil.test.js +32 -79
- package/utils/tests/tagValidations.test.js +37 -18
- package/v2Components/FormBuilder/index.js +126 -47
- package/v2Containers/CreativesContainer/index.js +1 -0
- package/v2Containers/Email/index.js +5 -1
- package/v2Containers/EmailWrapper/components/EmailHTMLEditor.js +18 -6
- package/v2Containers/EmailWrapper/components/__tests__/EmailHTMLEditor.test.js +106 -8
- package/v2Containers/FTP/index.js +51 -2
- package/v2Containers/InApp/index.js +23 -2
- package/v2Containers/InApp/tests/index.test.js +6 -17
- package/v2Containers/InappAdvance/index.js +24 -3
- package/v2Containers/Line/Container/ImageCarousel/tests/__snapshots__/content.test.js.snap +24 -3
- package/v2Containers/Line/Container/Text/index.js +1 -0
- package/v2Containers/MobilePushNew/index.js +24 -4
- package/v2Containers/Rcs/index.js +37 -12
- package/v2Containers/Rcs/tests/__snapshots__/index.test.js.snap +18 -4
- package/v2Containers/SmsTrai/Create/index.scss +1 -1
- package/v2Containers/SmsTrai/Edit/index.js +17 -4
- package/v2Containers/SmsTrai/Edit/tests/__snapshots__/index.test.js.snap +0 -9
- package/v2Containers/Viber/index.js +1 -0
- package/v2Containers/Viber/index.scss +1 -1
- 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 +2 -2
- package/v2Containers/WebPush/Create/utils/validation.js +9 -18
- package/v2Containers/WebPush/Create/utils/validation.test.js +24 -0
- package/v2Containers/Whatsapp/index.js +17 -6
- package/v2Containers/Whatsapp/tests/__snapshots__/index.test.js.snap +624 -248
- package/v2Containers/Zalo/index.js +11 -3
|
@@ -77,6 +77,7 @@ 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";
|
|
80
81
|
import formBuilderMessages from "../../v2Components/FormBuilder/messages";
|
|
81
82
|
import { validateMobilePushContent } from "../../utils/commonUtils";
|
|
82
83
|
import { getSingleTab } from "../InApp/utils";
|
|
@@ -93,7 +94,7 @@ import createMobilePushPayloadWithIntl from "../../utils/createMobilePushPayload
|
|
|
93
94
|
import { MOBILEPUSH } from "../../v2Components/CapVideoUpload/constants";
|
|
94
95
|
import { StyledCapTab } from "./style";
|
|
95
96
|
import TestAndPreviewSlidebox from "../../v2Components/TestAndPreviewSlidebox";
|
|
96
|
-
import {
|
|
97
|
+
import { MOBILE_PUSH } from "../CreativesContainer/constants";
|
|
97
98
|
import creativesMessages from "../CreativesContainer/messages";
|
|
98
99
|
|
|
99
100
|
// Helper function to extract deep link keys from URL where value equals key
|
|
@@ -798,9 +799,10 @@ const MobilePushNew = ({
|
|
|
798
799
|
(value) => {
|
|
799
800
|
let errorTemplateDescMessage = "";
|
|
800
801
|
|
|
801
|
-
const { isBraceError } = validateTags({
|
|
802
|
+
const { unsupportedTags, isBraceError } = validateTags({
|
|
802
803
|
content: value,
|
|
803
804
|
tagsParam: tags,
|
|
805
|
+
injectedTagsParams: injectedTags,
|
|
804
806
|
location,
|
|
805
807
|
tagModule: getDefaultTags,
|
|
806
808
|
isFullMode,
|
|
@@ -810,6 +812,14 @@ const MobilePushNew = ({
|
|
|
810
812
|
messages.emptyTemplateDescErrorMessage
|
|
811
813
|
);
|
|
812
814
|
}
|
|
815
|
+
if (unsupportedTags?.length > 0) {
|
|
816
|
+
errorTemplateDescMessage = formatMessage(
|
|
817
|
+
globalMessages.unsupportedTagsValidationError,
|
|
818
|
+
{
|
|
819
|
+
unsupportedTags,
|
|
820
|
+
}
|
|
821
|
+
);
|
|
822
|
+
}
|
|
813
823
|
if (isBraceError) {
|
|
814
824
|
errorTemplateDescMessage = formatMessage(
|
|
815
825
|
globalMessages.unbalanacedCurlyBraces
|
|
@@ -2598,8 +2608,18 @@ const MobilePushNew = ({
|
|
|
2598
2608
|
messages: formBuilderMessages,
|
|
2599
2609
|
tagLookupMap: metaEntities?.tagLookupMap || {},
|
|
2600
2610
|
eventContextTags: metaEntities?.eventContextTags || [],
|
|
2601
|
-
isLiquidFlow:
|
|
2611
|
+
isLiquidFlow: hasLiquidSupportFeature(),
|
|
2602
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
|
+
},
|
|
2603
2623
|
singleTab: getSingleTab(accountData),
|
|
2604
2624
|
});
|
|
2605
2625
|
}, [
|
|
@@ -2612,7 +2632,7 @@ const MobilePushNew = ({
|
|
|
2612
2632
|
accountData,
|
|
2613
2633
|
]);
|
|
2614
2634
|
|
|
2615
|
-
const isLiquidFlow =
|
|
2635
|
+
const isLiquidFlow = hasLiquidSupportFeature();
|
|
2616
2636
|
|
|
2617
2637
|
useEffect(() => {
|
|
2618
2638
|
// Always map to { label } for both platforms
|
|
@@ -394,15 +394,23 @@ export const Rcs = (props) => {
|
|
|
394
394
|
const validationResponse =
|
|
395
395
|
validateTags({
|
|
396
396
|
content: contentForValidation,
|
|
397
|
-
|
|
398
|
-
|
|
399
|
-
|
|
400
|
-
|
|
401
|
-
|
|
402
|
-
|
|
403
|
-
|
|
404
|
-
|
|
405
|
-
|
|
397
|
+
tagsParam: tags,
|
|
398
|
+
injectedTagsParams: injectedTags,
|
|
399
|
+
location,
|
|
400
|
+
tagModule: getDefaultTags,
|
|
401
|
+
eventContextTags,
|
|
402
|
+
isFullMode,
|
|
403
|
+
}) || {};
|
|
404
|
+
const unsupportedTagsLengthCheck =
|
|
405
|
+
validationResponse?.unsupportedTags?.length > 0;
|
|
406
|
+
const errorMsg =
|
|
407
|
+
(unsupportedTagsLengthCheck &&
|
|
408
|
+
formatMessage(globalMessages.unsupportedTagsValidationError, {
|
|
409
|
+
unsupportedTags: validationResponse.unsupportedTags,
|
|
410
|
+
})) ||
|
|
411
|
+
(validationResponse.isBraceError &&
|
|
412
|
+
formatMessage(globalMessages.unbalanacedCurlyBraces)) ||
|
|
413
|
+
false;
|
|
406
414
|
if (type === TITLE_TEXT) setTemplateTitleError(errorMsg);
|
|
407
415
|
if (type === MESSAGE_TEXT) setTemplateDescError(errorMsg);
|
|
408
416
|
};
|
|
@@ -827,9 +835,10 @@ export const Rcs = (props) => {
|
|
|
827
835
|
|
|
828
836
|
const templateDescErrorHandler = (value) => {
|
|
829
837
|
let errorMessage = false;
|
|
830
|
-
const { isBraceError } = validateTags({
|
|
838
|
+
const { unsupportedTags, isBraceError } = validateTags({
|
|
831
839
|
content: value,
|
|
832
840
|
tagsParam: tags,
|
|
841
|
+
injectedTagsParams: injectedTags,
|
|
833
842
|
location,
|
|
834
843
|
tagModule: getDefaultTags,
|
|
835
844
|
isFullMode,
|
|
@@ -859,10 +868,26 @@ export const Rcs = (props) => {
|
|
|
859
868
|
};
|
|
860
869
|
|
|
861
870
|
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
|
+
}) || {};
|
|
862
880
|
if (value?.length > FALLBACK_MESSAGE_MAX_LENGTH) {
|
|
863
|
-
|
|
881
|
+
errorMessage = formatMessage(messages.fallbackMsgLenError);
|
|
882
|
+
} else if (unsupportedTags?.length > 0) {
|
|
883
|
+
errorMessage = formatMessage(
|
|
884
|
+
globalMessages.unsupportedTagsValidationError,
|
|
885
|
+
{
|
|
886
|
+
unsupportedTags,
|
|
887
|
+
},
|
|
888
|
+
);
|
|
864
889
|
}
|
|
865
|
-
return
|
|
890
|
+
return errorMessage;
|
|
866
891
|
};
|
|
867
892
|
|
|
868
893
|
// Check for forbidden characters: square brackets [] and single curly braces {}
|
|
@@ -86505,6 +86505,7 @@ new message content.",
|
|
|
86505
86505
|
},
|
|
86506
86506
|
]
|
|
86507
86507
|
}
|
|
86508
|
+
showTruncatedTooltip={false}
|
|
86508
86509
|
size="large"
|
|
86509
86510
|
style={
|
|
86510
86511
|
Object {
|
|
@@ -86524,6 +86525,7 @@ new message content.",
|
|
|
86524
86525
|
/>
|
|
86525
86526
|
}
|
|
86526
86527
|
onChange={[Function]}
|
|
86528
|
+
onDropdownVisibleChange={[Function]}
|
|
86527
86529
|
removeIcon={
|
|
86528
86530
|
<_default
|
|
86529
86531
|
size="s"
|
|
@@ -86589,6 +86591,7 @@ new message content.",
|
|
|
86589
86591
|
onBlur={[Function]}
|
|
86590
86592
|
onChange={[Function]}
|
|
86591
86593
|
onDeselect={[Function]}
|
|
86594
|
+
onDropdownVisibleChange={[Function]}
|
|
86592
86595
|
onFocus={[Function]}
|
|
86593
86596
|
onInputKeyDown={[Function]}
|
|
86594
86597
|
onSearch={[Function]}
|
|
@@ -86827,9 +86830,13 @@ new message content.",
|
|
|
86827
86830
|
"opacity": 1,
|
|
86828
86831
|
}
|
|
86829
86832
|
}
|
|
86830
|
-
title="
|
|
86833
|
+
title=""
|
|
86831
86834
|
>
|
|
86832
|
-
|
|
86835
|
+
<div
|
|
86836
|
+
className="cap-select-option-tooltip"
|
|
86837
|
+
>
|
|
86838
|
+
Vertical Medium
|
|
86839
|
+
</div>
|
|
86833
86840
|
</div>
|
|
86834
86841
|
</div>
|
|
86835
86842
|
<span
|
|
@@ -105847,6 +105854,7 @@ new message content.",
|
|
|
105847
105854
|
},
|
|
105848
105855
|
]
|
|
105849
105856
|
}
|
|
105857
|
+
showTruncatedTooltip={false}
|
|
105850
105858
|
size="large"
|
|
105851
105859
|
style={
|
|
105852
105860
|
Object {
|
|
@@ -105866,6 +105874,7 @@ new message content.",
|
|
|
105866
105874
|
/>
|
|
105867
105875
|
}
|
|
105868
105876
|
onChange={[Function]}
|
|
105877
|
+
onDropdownVisibleChange={[Function]}
|
|
105869
105878
|
removeIcon={
|
|
105870
105879
|
<_default
|
|
105871
105880
|
size="s"
|
|
@@ -105931,6 +105940,7 @@ new message content.",
|
|
|
105931
105940
|
onBlur={[Function]}
|
|
105932
105941
|
onChange={[Function]}
|
|
105933
105942
|
onDeselect={[Function]}
|
|
105943
|
+
onDropdownVisibleChange={[Function]}
|
|
105934
105944
|
onFocus={[Function]}
|
|
105935
105945
|
onInputKeyDown={[Function]}
|
|
105936
105946
|
onSearch={[Function]}
|
|
@@ -106169,9 +106179,13 @@ new message content.",
|
|
|
106169
106179
|
"opacity": 1,
|
|
106170
106180
|
}
|
|
106171
106181
|
}
|
|
106172
|
-
title="
|
|
106182
|
+
title=""
|
|
106173
106183
|
>
|
|
106174
|
-
|
|
106184
|
+
<div
|
|
106185
|
+
className="cap-select-option-tooltip"
|
|
106186
|
+
>
|
|
106187
|
+
Vertical Medium
|
|
106188
|
+
</div>
|
|
106175
106189
|
</div>
|
|
106176
106190
|
</div>
|
|
106177
106191
|
<span
|
|
@@ -51,11 +51,11 @@ import {
|
|
|
51
51
|
ALL,
|
|
52
52
|
LIBRARY,
|
|
53
53
|
} from './constants';
|
|
54
|
-
import { LIQUID_SUPPORTED_CHANNELS } from '../../CreativesContainer/constants';
|
|
55
54
|
import v2EditSmsReducer from '../../Sms/Edit/reducer';
|
|
56
55
|
import { v2SmsEditSagas } from '../../Sms/Edit/sagas';
|
|
57
56
|
import ErrorInfoNote from '../../../v2Components/ErrorInfoNote';
|
|
58
57
|
import { validateLiquidTemplateContent } from '../../../utils/commonUtils';
|
|
58
|
+
import { hasLiquidSupportFeature } from '../../../utils/common';
|
|
59
59
|
import { ANDROID } from '../../../v2Components/CommonTestAndPreview/constants';
|
|
60
60
|
|
|
61
61
|
let varMap = {};
|
|
@@ -240,11 +240,15 @@ export const SmsTraiEdit = (props) => {
|
|
|
240
240
|
validateTags({
|
|
241
241
|
content: updatedSmsEditor.join(''),
|
|
242
242
|
tagsParam: tags,
|
|
243
|
+
injectedTagsParams: injectedTags,
|
|
243
244
|
location,
|
|
244
245
|
tagModule: getDefaultTags,
|
|
246
|
+
eventContextTags,
|
|
245
247
|
isFullMode,
|
|
246
248
|
}) || {};
|
|
247
|
-
updateIsTagValidationError(
|
|
249
|
+
updateIsTagValidationError(
|
|
250
|
+
tagValidationResponse.unsupportedTags.length > 0,
|
|
251
|
+
);
|
|
248
252
|
}
|
|
249
253
|
}, [updatedSmsEditor, tags]);
|
|
250
254
|
|
|
@@ -544,7 +548,16 @@ export const SmsTraiEdit = (props) => {
|
|
|
544
548
|
return countVarChar;
|
|
545
549
|
};
|
|
546
550
|
|
|
547
|
-
const tagValidationErrorMessage = () =>
|
|
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
|
+
};
|
|
548
561
|
|
|
549
562
|
const disablehandler = () => {
|
|
550
563
|
if (traiData && !isEmpty(traiData)) {
|
|
@@ -591,7 +604,7 @@ export const SmsTraiEdit = (props) => {
|
|
|
591
604
|
setShowTestAndPreviewSlidebox(false);
|
|
592
605
|
};
|
|
593
606
|
|
|
594
|
-
const isLiquidSupportFeatureEnabled =
|
|
607
|
+
const isLiquidSupportFeatureEnabled = hasLiquidSupportFeature();
|
|
595
608
|
return (
|
|
596
609
|
<>
|
|
597
610
|
<CapSpin spinning={loading || fetchingLiquidTags} tip={fetchingLiquidTags && formatMessage(formBuilderMessages.liquidSpinText)}>
|
|
@@ -5817,7 +5817,6 @@ FREE GIFTS-
|
|
|
5817
5817
|
</CapButton>
|
|
5818
5818
|
<CapButton
|
|
5819
5819
|
className="create-msg"
|
|
5820
|
-
disabled={true}
|
|
5821
5820
|
isAddBtn={false}
|
|
5822
5821
|
onClick={[Function]}
|
|
5823
5822
|
type="primary"
|
|
@@ -5825,7 +5824,6 @@ FREE GIFTS-
|
|
|
5825
5824
|
<Button
|
|
5826
5825
|
block={false}
|
|
5827
5826
|
className="cap-button-v2 create-msg"
|
|
5828
|
-
disabled={true}
|
|
5829
5827
|
ghost={false}
|
|
5830
5828
|
htmlType="button"
|
|
5831
5829
|
loading={false}
|
|
@@ -5835,7 +5833,6 @@ FREE GIFTS-
|
|
|
5835
5833
|
<Wave>
|
|
5836
5834
|
<button
|
|
5837
5835
|
className="ant-btn cap-button-v2 create-msg ant-btn-primary"
|
|
5838
|
-
disabled={true}
|
|
5839
5836
|
onClick={[Function]}
|
|
5840
5837
|
type="button"
|
|
5841
5838
|
>
|
|
@@ -16731,7 +16728,6 @@ FREE GIFTS-
|
|
|
16731
16728
|
</CapButton>
|
|
16732
16729
|
<CapButton
|
|
16733
16730
|
className="create-msg"
|
|
16734
|
-
disabled={true}
|
|
16735
16731
|
isAddBtn={false}
|
|
16736
16732
|
onClick={[Function]}
|
|
16737
16733
|
type="primary"
|
|
@@ -16739,7 +16735,6 @@ FREE GIFTS-
|
|
|
16739
16735
|
<Button
|
|
16740
16736
|
block={false}
|
|
16741
16737
|
className="cap-button-v2 create-msg"
|
|
16742
|
-
disabled={true}
|
|
16743
16738
|
ghost={false}
|
|
16744
16739
|
htmlType="button"
|
|
16745
16740
|
loading={false}
|
|
@@ -16749,7 +16744,6 @@ FREE GIFTS-
|
|
|
16749
16744
|
<Wave>
|
|
16750
16745
|
<button
|
|
16751
16746
|
className="ant-btn cap-button-v2 create-msg ant-btn-primary"
|
|
16752
|
-
disabled={true}
|
|
16753
16747
|
onClick={[Function]}
|
|
16754
16748
|
type="button"
|
|
16755
16749
|
>
|
|
@@ -27735,7 +27729,6 @@ FREE GIFTS-
|
|
|
27735
27729
|
</CapButton>
|
|
27736
27730
|
<CapButton
|
|
27737
27731
|
className="create-msg"
|
|
27738
|
-
disabled={true}
|
|
27739
27732
|
isAddBtn={false}
|
|
27740
27733
|
onClick={[Function]}
|
|
27741
27734
|
type="primary"
|
|
@@ -27743,7 +27736,6 @@ FREE GIFTS-
|
|
|
27743
27736
|
<Button
|
|
27744
27737
|
block={false}
|
|
27745
27738
|
className="cap-button-v2 create-msg"
|
|
27746
|
-
disabled={true}
|
|
27747
27739
|
ghost={false}
|
|
27748
27740
|
htmlType="button"
|
|
27749
27741
|
loading={false}
|
|
@@ -27753,7 +27745,6 @@ FREE GIFTS-
|
|
|
27753
27745
|
<Wave>
|
|
27754
27746
|
<button
|
|
27755
27747
|
className="ant-btn cap-button-v2 create-msg ant-btn-primary"
|
|
27756
|
-
disabled={true}
|
|
27757
27748
|
onClick={[Function]}
|
|
27758
27749
|
type="button"
|
|
27759
27750
|
>
|
|
@@ -105,10 +105,12 @@ export const useTagManagement = ({
|
|
|
105
105
|
const validationConfig = useMemo(
|
|
106
106
|
() => ({
|
|
107
107
|
tagsParam: tags,
|
|
108
|
+
injectedTagsParams: injectedTags,
|
|
108
109
|
location,
|
|
109
110
|
tagModule: getDefaultTags,
|
|
111
|
+
eventContextTags,
|
|
110
112
|
}),
|
|
111
|
-
[tags, location, getDefaultTags],
|
|
113
|
+
[tags, injectedTags, location, getDefaultTags, eventContextTags],
|
|
112
114
|
);
|
|
113
115
|
|
|
114
116
|
return {
|
|
@@ -528,19 +528,26 @@ 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
|
+
|
|
531
534
|
const { result } = renderHook(() =>
|
|
532
535
|
useTagManagement({
|
|
533
536
|
location: defaultLocation,
|
|
534
537
|
globalActions: mockGlobalActions,
|
|
535
538
|
metaEntities: defaultMetaEntities,
|
|
539
|
+
injectedTags,
|
|
540
|
+
eventContextTags,
|
|
536
541
|
getDefaultTags: 'custom',
|
|
537
542
|
})
|
|
538
543
|
);
|
|
539
544
|
|
|
540
545
|
expect(result.current.validationConfig).toEqual({
|
|
541
546
|
tagsParam: defaultMetaEntities.tags.standard,
|
|
547
|
+
injectedTagsParams: injectedTags,
|
|
542
548
|
location: defaultLocation,
|
|
543
549
|
tagModule: 'custom',
|
|
550
|
+
eventContextTags,
|
|
544
551
|
});
|
|
545
552
|
});
|
|
546
553
|
|
|
@@ -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),
|
|
289
|
+
[formatMessage],
|
|
290
290
|
);
|
|
291
291
|
|
|
292
292
|
const validateUrl = useCallback(
|
|
@@ -10,31 +10,16 @@ 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
|
|
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
|
|
19
17
|
* @returns {string} Error message if invalid, empty string if valid
|
|
20
18
|
*/
|
|
21
|
-
export const validateTitle = (value, formatMessage, messages
|
|
19
|
+
export const validateTitle = (value, formatMessage, messages) => {
|
|
22
20
|
if (!value || value.trim() === '') {
|
|
23
21
|
return formatMessage(messages.titleRequired);
|
|
24
22
|
}
|
|
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
|
-
|
|
38
23
|
return '';
|
|
39
24
|
};
|
|
40
25
|
|
|
@@ -75,7 +60,13 @@ export const validateMessageContent = (value, formatMessage, messages, validatio
|
|
|
75
60
|
...validationConfig,
|
|
76
61
|
isFullMode,
|
|
77
62
|
}) || {};
|
|
78
|
-
|
|
63
|
+
|
|
64
|
+
if (validationResponse?.unsupportedTags?.length) {
|
|
65
|
+
return formatMessage(globalMessages.unsupportedTagsValidationError, {
|
|
66
|
+
unsupportedTags: validationResponse.unsupportedTags.join(', '),
|
|
67
|
+
});
|
|
68
|
+
}
|
|
69
|
+
|
|
79
70
|
if (validationResponse?.isBraceError) {
|
|
80
71
|
return formatMessage(globalMessages.unbalanacedCurlyBraces);
|
|
81
72
|
}
|
|
@@ -169,8 +169,10 @@ describe('validation', () => {
|
|
|
169
169
|
describe('validateMessageContent', () => {
|
|
170
170
|
const mockValidationConfig = {
|
|
171
171
|
tagsParam: [],
|
|
172
|
+
injectedTagsParams: [],
|
|
172
173
|
location: {},
|
|
173
174
|
tagModule: '',
|
|
175
|
+
eventContextTags: [],
|
|
174
176
|
};
|
|
175
177
|
|
|
176
178
|
beforeEach(() => {
|
|
@@ -209,6 +211,17 @@ describe('validation', () => {
|
|
|
209
211
|
});
|
|
210
212
|
});
|
|
211
213
|
|
|
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
|
+
|
|
212
225
|
it('should return error message for unbalanced curly braces', () => {
|
|
213
226
|
validateTags.mockReturnValue({
|
|
214
227
|
isBraceError: true,
|
|
@@ -218,11 +231,22 @@ describe('validation', () => {
|
|
|
218
231
|
expect(mockFormatMessage).toHaveBeenCalledWith(globalMessages.unbalanacedCurlyBraces);
|
|
219
232
|
});
|
|
220
233
|
|
|
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
|
+
|
|
221
243
|
it('should pass validation config to validateTags', () => {
|
|
222
244
|
const customConfig = {
|
|
223
245
|
tagsParam: [{ id: 1, name: 'Tag1' }],
|
|
246
|
+
injectedTagsParams: [{ id: 2, name: 'Tag2' }],
|
|
224
247
|
location: { query: { type: 'test' } },
|
|
225
248
|
tagModule: 'custom',
|
|
249
|
+
eventContextTags: [{ id: 3, name: 'Tag3' }],
|
|
226
250
|
};
|
|
227
251
|
validateTags.mockReturnValue({});
|
|
228
252
|
validateMessageContent('Valid message', mockFormatMessage, mockMessages, customConfig);
|
|
@@ -637,18 +637,22 @@ export const Whatsapp = (props) => {
|
|
|
637
637
|
validateTags({
|
|
638
638
|
content: contentData.join(""),
|
|
639
639
|
tagsParam: tags,
|
|
640
|
+
injectedTagsParams: injectedTags,
|
|
640
641
|
location,
|
|
641
642
|
tagModule: getDefaultTags,
|
|
643
|
+
eventContextTags,
|
|
642
644
|
isFullMode,
|
|
643
645
|
}) || {};
|
|
646
|
+
const unsupportedTagsLengthCheck =
|
|
647
|
+
validationResponse?.unsupportedTags?.length > 0;
|
|
644
648
|
if (type === HEADER_TEXT) {
|
|
645
649
|
headerTagValidationResponse = validationResponse;
|
|
646
|
-
updateIsHeaderTagValidationError(
|
|
650
|
+
updateIsHeaderTagValidationError(unsupportedTagsLengthCheck);
|
|
647
651
|
} else if (type === CAROUSEL_TEXT) {
|
|
648
|
-
return [{fieldName: "carouselTagValidationErrMessage", value: validationResponse}, {fieldName: "carouselTagValidationErr", value:
|
|
652
|
+
return [{fieldName: "carouselTagValidationErrMessage", value: validationResponse}, {fieldName: "carouselTagValidationErr", value: unsupportedTagsLengthCheck}];
|
|
649
653
|
} else {
|
|
650
654
|
tagValidationResponse = validationResponse;
|
|
651
|
-
updateIsTagValidationError(
|
|
655
|
+
updateIsTagValidationError(unsupportedTagsLengthCheck);
|
|
652
656
|
}
|
|
653
657
|
}
|
|
654
658
|
};
|
|
@@ -2678,11 +2682,18 @@ const isAuthenticationTemplate = isEqual(templateCategory, WHATSAPP_CATEGORIES.a
|
|
|
2678
2682
|
} else {
|
|
2679
2683
|
validationResponse = tagValidationResponse;
|
|
2680
2684
|
}
|
|
2681
|
-
const { isBraceError } = validationResponse
|
|
2685
|
+
const { unsupportedTags = [], isBraceError } = validationResponse;
|
|
2686
|
+
|
|
2687
|
+
let tagError = "";
|
|
2688
|
+
if (unsupportedTags.length > 0) {
|
|
2689
|
+
tagError = formatMessage(globalMessages.unsupportedTagsValidationError, {
|
|
2690
|
+
unsupportedTags,
|
|
2691
|
+
});
|
|
2692
|
+
}
|
|
2682
2693
|
if (isBraceError) {
|
|
2683
|
-
|
|
2694
|
+
tagError = formatMessage(globalMessages.unbalanacedCurlyBraces);
|
|
2684
2695
|
}
|
|
2685
|
-
return
|
|
2696
|
+
return <CapError>{tagError}</CapError>;
|
|
2686
2697
|
};
|
|
2687
2698
|
|
|
2688
2699
|
const editModeContent = () => (
|