@capillarytech/creatives-library 8.0.290-alpha.3 → 8.0.290

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.
Files changed (76) hide show
  1. package/constants/unified.js +1 -0
  2. package/initialState.js +2 -0
  3. package/package.json +1 -1
  4. package/utils/common.js +8 -5
  5. package/utils/commonUtils.js +85 -4
  6. package/utils/tagValidations.js +222 -84
  7. package/utils/tests/commonUtil.test.js +124 -147
  8. package/utils/tests/tagValidations.test.js +358 -280
  9. package/v2Components/CommonTestAndPreview/DeliverySettings/DeliverySettings.scss +33 -0
  10. package/v2Components/CommonTestAndPreview/DeliverySettings/ModifyDeliverySettings.js +397 -0
  11. package/v2Components/CommonTestAndPreview/DeliverySettings/ModifyDeliverySettings.scss +35 -0
  12. package/v2Components/CommonTestAndPreview/DeliverySettings/TECH_DETAILING_DELIVERY_SETTINGS.md +725 -0
  13. package/v2Components/CommonTestAndPreview/DeliverySettings/constants.js +92 -0
  14. package/v2Components/CommonTestAndPreview/DeliverySettings/index.js +243 -0
  15. package/v2Components/CommonTestAndPreview/DeliverySettings/messages.js +111 -0
  16. package/v2Components/CommonTestAndPreview/DeliverySettings/utils/parseSenderDetailsResponse.js +91 -0
  17. package/v2Components/CommonTestAndPreview/SendTestMessage.js +33 -1
  18. package/v2Components/CommonTestAndPreview/actions.js +20 -0
  19. package/v2Components/CommonTestAndPreview/constants.js +10 -0
  20. package/v2Components/CommonTestAndPreview/index.js +133 -15
  21. package/v2Components/CommonTestAndPreview/reducer.js +47 -0
  22. package/v2Components/CommonTestAndPreview/sagas.js +60 -0
  23. package/v2Components/CommonTestAndPreview/selectors.js +51 -0
  24. package/v2Components/CommonTestAndPreview/tests/DeliverySettings/ModifyDeliverySettings.test.js +782 -0
  25. package/v2Components/CommonTestAndPreview/tests/DeliverySettings/index.test.js +200 -0
  26. package/v2Components/CommonTestAndPreview/tests/DeliverySettings/utils/parseSenderDetailsResponse.test.js +235 -0
  27. package/v2Components/CommonTestAndPreview/tests/SendTestMessage.test.js +127 -0
  28. package/v2Components/CommonTestAndPreview/tests/actions.test.js +50 -0
  29. package/v2Components/CommonTestAndPreview/tests/constants.test.js +18 -0
  30. package/v2Components/CommonTestAndPreview/tests/index.test.js +214 -1
  31. package/v2Components/CommonTestAndPreview/tests/reducer.test.js +118 -0
  32. package/v2Components/CommonTestAndPreview/tests/sagas.test.js +145 -0
  33. package/v2Components/CommonTestAndPreview/tests/selectors.test.js +146 -0
  34. package/v2Components/ErrorInfoNote/index.js +5 -2
  35. package/v2Components/FormBuilder/index.js +162 -84
  36. package/v2Components/FormBuilder/messages.js +8 -0
  37. package/v2Components/HtmlEditor/HTMLEditor.js +5 -0
  38. package/v2Components/HtmlEditor/__tests__/HTMLEditor.apiErrors.test.js +1 -0
  39. package/v2Components/HtmlEditor/__tests__/HTMLEditor.test.js +15 -0
  40. package/v2Components/HtmlEditor/components/CodeEditorPane/index.js +2 -1
  41. package/v2Components/TestAndPreviewSlidebox/index.js +14 -0
  42. package/v2Containers/Cap/mockData.js +14 -0
  43. package/v2Containers/Cap/reducer.js +55 -3
  44. package/v2Containers/Cap/tests/reducer.test.js +102 -0
  45. package/v2Containers/CreativesContainer/SlideBoxFooter.js +1 -3
  46. package/v2Containers/CreativesContainer/index.js +6 -19
  47. package/v2Containers/Email/index.js +5 -1
  48. package/v2Containers/EmailWrapper/components/EmailHTMLEditor.js +62 -10
  49. package/v2Containers/EmailWrapper/components/__tests__/EmailHTMLEditor.test.js +115 -12
  50. package/v2Containers/FTP/index.js +51 -2
  51. package/v2Containers/FTP/messages.js +4 -0
  52. package/v2Containers/InApp/index.js +96 -1
  53. package/v2Containers/InApp/tests/index.test.js +6 -17
  54. package/v2Containers/InappAdvance/index.js +103 -2
  55. package/v2Containers/Line/Container/ImageCarousel/tests/__snapshots__/content.test.js.snap +24 -3
  56. package/v2Containers/Line/Container/Text/index.js +1 -0
  57. package/v2Containers/MobilePush/Create/index.js +16 -6
  58. package/v2Containers/MobilePush/Edit/index.js +16 -6
  59. package/v2Containers/MobilePushNew/index.js +33 -2
  60. package/v2Containers/Rcs/index.js +37 -12
  61. package/v2Containers/Rcs/tests/__snapshots__/index.test.js.snap +667 -16
  62. package/v2Containers/Sms/Create/index.js +3 -35
  63. package/v2Containers/Sms/Create/messages.js +0 -4
  64. package/v2Containers/Sms/Edit/index.js +3 -33
  65. package/v2Containers/Sms/commonMethods.js +6 -6
  66. package/v2Containers/SmsTrai/Edit/index.js +47 -6
  67. package/v2Containers/SmsTrai/Edit/tests/__snapshots__/index.test.js.snap +147 -6
  68. package/v2Containers/Viber/index.js +1 -0
  69. package/v2Containers/WebPush/Create/hooks/useTagManagement.js +3 -1
  70. package/v2Containers/WebPush/Create/hooks/useTagManagement.test.js +7 -0
  71. package/v2Containers/WebPush/Create/index.js +2 -2
  72. package/v2Containers/WebPush/Create/utils/validation.js +2 -17
  73. package/v2Containers/WebPush/Create/utils/validation.test.js +24 -0
  74. package/v2Containers/Whatsapp/index.js +18 -10
  75. package/v2Containers/Whatsapp/tests/__snapshots__/index.test.js.snap +25849 -3524
  76. package/v2Containers/Zalo/index.js +11 -3
@@ -50,7 +50,9 @@ 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";
53
54
  import { validateInAppContent } from "../../utils/commonUtils";
55
+ import { hasLiquidSupportFeature } from "../../utils/common";
54
56
  import formBuilderMessages from "../../v2Components/FormBuilder/messages";
55
57
  import { getSingleTab, hasAnyErrors } from "../InApp/utils";
56
58
  import ErrorInfoNote from "../../v2Components/ErrorInfoNote";
@@ -815,9 +817,11 @@ export const InappAdvanced = (props) => {
815
817
  const latestHtmlValues = await saveAllBeeInstances();
816
818
  const payload = createPayload(latestHtmlValues);
817
819
 
820
+ // Validate the INAPP content
821
+ const isLiquidFlow = hasLiquidSupportFeature();
818
822
  // Skip validation if no tags are available (e.g., in tests or when tags haven't loaded)
819
823
  const hasTags = tags && tags.length > 0;
820
- if (hasTags) {
824
+ if (isLiquidFlow && hasTags) {
821
825
  validateInAppContent(payload, {
822
826
  currentTab: panes === ANDROID ? 1 : 2, // Convert ANDROID/IOS to tab numbers
823
827
  onError,
@@ -825,6 +829,10 @@ export const InappAdvanced = (props) => {
825
829
  getLiquidTags: (content, callback) => globalActions.getLiquidTags(content, callback),
826
830
  formatMessage,
827
831
  messages: formBuilderMessages,
832
+ tagLookupMap: metaEntities?.tagLookupMap || {},
833
+ eventContextTags: metaEntities?.eventContextTags || [],
834
+ isLiquidFlow,
835
+ forwardedTags: {},
828
836
  skipTags: (tag) => {
829
837
  // Skip certain tags if needed
830
838
  const skipRegexes = [
@@ -839,7 +847,92 @@ export const InappAdvanced = (props) => {
839
847
  },
840
848
  singleTab: getSingleTab(accountData),
841
849
  });
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
+ }
842
934
  } else {
935
+ // No tags available, skip validation and proceed directly
843
936
  onSuccess();
844
937
  }
845
938
  };
@@ -945,7 +1038,15 @@ export const InappAdvanced = (props) => {
945
1038
  )}
946
1039
  <CapButton
947
1040
  onClick={async () => {
948
- await liquidMiddleWare();
1041
+ const isLiquidFlow = hasLiquidSupportFeature();
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
+ }
949
1050
  }}
950
1051
  disabled={isDisableDone()}
951
1052
  className="inapp-create-btn"
@@ -3117,6 +3117,7 @@ new message content.",
3117
3117
  },
3118
3118
  ]
3119
3119
  }
3120
+ showTruncatedTooltip={false}
3120
3121
  size="large"
3121
3122
  style={
3122
3123
  Object {
@@ -3135,6 +3136,7 @@ new message content.",
3135
3136
  />
3136
3137
  }
3137
3138
  onChange={[Function]}
3139
+ onDropdownVisibleChange={[Function]}
3138
3140
  removeIcon={
3139
3141
  <CapIcon
3140
3142
  size="s"
@@ -3199,6 +3201,7 @@ new message content.",
3199
3201
  onBlur={[Function]}
3200
3202
  onChange={[Function]}
3201
3203
  onDeselect={[Function]}
3204
+ onDropdownVisibleChange={[Function]}
3202
3205
  onFocus={[Function]}
3203
3206
  onInputKeyDown={[Function]}
3204
3207
  onSearch={[Function]}
@@ -3437,7 +3440,11 @@ new message content.",
3437
3440
  }
3438
3441
  }
3439
3442
  title=""
3440
- />
3443
+ >
3444
+ <div
3445
+ className="cap-select-option-tooltip"
3446
+ />
3447
+ </div>
3441
3448
  </div>
3442
3449
  <span
3443
3450
  className="ant-select-arrow"
@@ -6940,6 +6947,7 @@ new message content.",
6940
6947
  },
6941
6948
  ]
6942
6949
  }
6950
+ showTruncatedTooltip={false}
6943
6951
  size="large"
6944
6952
  style={
6945
6953
  Object {
@@ -6958,6 +6966,7 @@ new message content.",
6958
6966
  />
6959
6967
  }
6960
6968
  onChange={[Function]}
6969
+ onDropdownVisibleChange={[Function]}
6961
6970
  removeIcon={
6962
6971
  <CapIcon
6963
6972
  size="s"
@@ -7022,6 +7031,7 @@ new message content.",
7022
7031
  onBlur={[Function]}
7023
7032
  onChange={[Function]}
7024
7033
  onDeselect={[Function]}
7034
+ onDropdownVisibleChange={[Function]}
7025
7035
  onFocus={[Function]}
7026
7036
  onInputKeyDown={[Function]}
7027
7037
  onSearch={[Function]}
@@ -7260,7 +7270,11 @@ new message content.",
7260
7270
  }
7261
7271
  }
7262
7272
  title=""
7263
- />
7273
+ >
7274
+ <div
7275
+ className="cap-select-option-tooltip"
7276
+ />
7277
+ </div>
7264
7278
  </div>
7265
7279
  <span
7266
7280
  className="ant-select-arrow"
@@ -10707,6 +10721,7 @@ new message content.",
10707
10721
  },
10708
10722
  ]
10709
10723
  }
10724
+ showTruncatedTooltip={false}
10710
10725
  size="large"
10711
10726
  style={
10712
10727
  Object {
@@ -10725,6 +10740,7 @@ new message content.",
10725
10740
  />
10726
10741
  }
10727
10742
  onChange={[Function]}
10743
+ onDropdownVisibleChange={[Function]}
10728
10744
  removeIcon={
10729
10745
  <CapIcon
10730
10746
  size="s"
@@ -10789,6 +10805,7 @@ new message content.",
10789
10805
  onBlur={[Function]}
10790
10806
  onChange={[Function]}
10791
10807
  onDeselect={[Function]}
10808
+ onDropdownVisibleChange={[Function]}
10792
10809
  onFocus={[Function]}
10793
10810
  onInputKeyDown={[Function]}
10794
10811
  onSearch={[Function]}
@@ -11027,7 +11044,11 @@ new message content.",
11027
11044
  }
11028
11045
  }
11029
11046
  title=""
11030
- />
11047
+ >
11048
+ <div
11049
+ className="cap-select-option-tooltip"
11050
+ />
11051
+ </div>
11031
11052
  </div>
11032
11053
  <span
11033
11054
  className="ant-select-arrow"
@@ -137,6 +137,7 @@ export const LineText = ({
137
137
  const { valid, isBraceError } = validateTags({
138
138
  content: value,
139
139
  tagsParam: tags,
140
+ injectedTagsParams: injectedTags,
140
141
  location,
141
142
  tagModule: 'outbound',
142
143
  isFullMode,
@@ -678,21 +678,31 @@ export class Create extends React.Component { // eslint-disable-line react/prefe
678
678
  }
679
679
  showError = () => {
680
680
  const {intl} = this.props;
681
- const {errorData, schema} = this.state;
681
+ const {errorData} = this.state;
682
682
  const errorMessage = {key: 'validation-error', message: intl.formatMessage(messages.validationError)};
683
683
  if (!isEmpty(this.state.formData) && !this.state.isFormValid) {
684
684
  let tab = this.state.currentTab;
685
- const isAndroidInvalid = Object.values(errorData[0] || {}).includes(true);
686
- const isIosInvalid = Object.values(errorData[1] || {}).includes(true);
687
- const isIosTabVisible = get(schema, 'containers[0].panes[1].isSupported', true) !== false;
685
+ const isAndroidInvalid = Object.values(errorData[0]).includes(true);
686
+ const isIosInvalid = Object.values(errorData[1]).includes(true);
687
+ let isTagErrorExist = false;
688
688
  if (isAndroidInvalid) {
689
689
  tab = 1;
690
690
  errorMessage.description = intl.formatMessage(messages.invalidAndroidMessage);
691
- } else if (isIosInvalid && isIosTabVisible) {
691
+ const invalidTags = errorData[0]['invalid-tags'];
692
+ if (!isEmpty(invalidTags)) {
693
+ isTagErrorExist = true;
694
+ errorMessage.description = `${intl.formatMessage(messages.invalidAndroidMessage)} ${intl.formatMessage(messages.invalidTags)}: ${invalidTags.join(',')} `;
695
+ }
696
+ } else if (isIosInvalid) {
692
697
  tab = 2;
693
698
  errorMessage.description = intl.formatMessage(messages.invalidIosMessage);
699
+ const invalidTags = errorData[1]['invalid-tags'];
700
+ if (!isEmpty(invalidTags)) {
701
+ isTagErrorExist = true;
702
+ errorMessage.description = `${intl.formatMessage(messages.invalidIosMessage)} ${intl.formatMessage(messages.invalidTags)}: ${invalidTags.join(',')} `;
703
+ }
694
704
  }
695
- if (tab !== this.state.currentTab) {
705
+ if (tab !== this.state.currentTab || isTagErrorExist) {
696
706
  CapNotification.error(errorMessage);
697
707
  }
698
708
  }
@@ -705,22 +705,32 @@ export class Edit extends React.Component { // eslint-disable-line react/prefer-
705
705
  // eslint-disable-next-line react/sort-comp
706
706
  showError = () => {
707
707
  const {intl} = this.props;
708
- const {errorData, schema} = this.state;
708
+ const {errorData} = this.state;
709
709
  const errorMessage = {key: 'validation-error', message: intl.formatMessage(messages.validationError)};
710
+ let isTagErrorExist = false;
710
711
  if (!_.isEmpty(this.state.formData) && !this.state.isFormValid) {
711
712
  let tab = this.state.currentTab;
712
- const isAndroidInvalid = Object.values(errorData[0] || {}).includes(true);
713
- const isIosInvalid = Object.values(errorData[1] || {}).includes(true);
714
- const isIosTabVisible = get(schema, 'containers[0].panes[1].isSupported', true) !== false;
713
+ const isAndroidInvalid = Object.values(errorData[0]).includes(true);
714
+ const isIosInvalid = Object.values(errorData[1]).includes(true);
715
715
  if (isAndroidInvalid) {
716
716
  tab = 1;
717
717
  errorMessage.description = intl.formatMessage(messages.invalidAndroidMessage);
718
- } else if (isIosInvalid && isIosTabVisible) {
718
+ const invalidTags = errorData[0]['invalid-tags'];
719
+ if (!_.isEmpty(invalidTags)) {
720
+ isTagErrorExist = true;
721
+ errorMessage.description = `${intl.formatMessage(messages.invalidAndroidMessage)} ${intl.formatMessage(messages.invalidTags)}: ${invalidTags.join(',')} `;
722
+ }
723
+ } else if (isIosInvalid) {
719
724
  tab = 2;
720
725
  errorMessage.description = intl.formatMessage(messages.invalidIosMessage);
726
+ const invalidTags = errorData[1]['invalid-tags'];
727
+ if (!_.isEmpty(invalidTags)) {
728
+ isTagErrorExist = true;
729
+ errorMessage.description = `${intl.formatMessage(messages.invalidIosMessage)} ${intl.formatMessage(messages.invalidTags)}: ${invalidTags.join(',')} `;
730
+ }
721
731
  }
722
732
 
723
- if (tab !== this.state.currentTab) {
733
+ if (tab !== this.state.currentTab || isTagErrorExist) {
724
734
  CapNotification.error(errorMessage);
725
735
  }
726
736
  }
@@ -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";
@@ -802,9 +803,10 @@ const MobilePushNew = ({
802
803
  (value) => {
803
804
  let errorTemplateDescMessage = "";
804
805
 
805
- const { isBraceError } = validateTags({
806
+ const { unsupportedTags, isBraceError } = validateTags({
806
807
  content: value,
807
808
  tagsParam: tags,
809
+ injectedTagsParams: injectedTags,
808
810
  location,
809
811
  tagModule: getDefaultTags,
810
812
  isFullMode,
@@ -814,6 +816,14 @@ const MobilePushNew = ({
814
816
  messages.emptyTemplateDescErrorMessage
815
817
  );
816
818
  }
819
+ if (unsupportedTags?.length > 0) {
820
+ errorTemplateDescMessage = formatMessage(
821
+ globalMessages.unsupportedTagsValidationError,
822
+ {
823
+ unsupportedTags,
824
+ }
825
+ );
826
+ }
817
827
  if (isBraceError) {
818
828
  errorTemplateDescMessage = formatMessage(
819
829
  globalMessages.unbalanacedCurlyBraces
@@ -2649,6 +2659,20 @@ const MobilePushNew = ({
2649
2659
  getLiquidTags: globalActionsProps.getLiquidTags,
2650
2660
  formatMessage,
2651
2661
  messages: formBuilderMessages,
2662
+ tagLookupMap: metaEntities?.tagLookupMap || {},
2663
+ eventContextTags: metaEntities?.eventContextTags || [],
2664
+ isLiquidFlow: hasLiquidSupportFeature(),
2665
+ forwardedTags: {},
2666
+ skipTags: (tag) => {
2667
+ const skipRegexes = [
2668
+ /dynamic_expiry_date_after_\d+_days\.FORMAT_\d/,
2669
+ /unsubscribe\(#[a-zA-Z\d]{6}\)/,
2670
+ /Link_to_[a-zA-z]/,
2671
+ /SURVEY.*\.TOKEN/,
2672
+ /^[A-Za-z].*\([a-zA-Z\d]*\)/,
2673
+ ];
2674
+ return skipRegexes.some((regex) => regex.test(tag));
2675
+ },
2652
2676
  singleTab: getSingleTab(accountData),
2653
2677
  });
2654
2678
  }, [
@@ -2657,9 +2681,12 @@ const MobilePushNew = ({
2657
2681
  activeTab,
2658
2682
  globalActionsProps,
2659
2683
  formatMessage,
2684
+ metaEntities,
2660
2685
  accountData,
2661
2686
  ]);
2662
2687
 
2688
+ const isLiquidFlow = hasLiquidSupportFeature();
2689
+
2663
2690
  useEffect(() => {
2664
2691
  // Always map to { label } for both platforms
2665
2692
  const newButtons = Array.isArray(ctaData)
@@ -3056,7 +3083,11 @@ const MobilePushNew = ({
3056
3083
  <CapButton
3057
3084
  type="primary"
3058
3085
  onClick={() => {
3059
- liquidMiddleWare();
3086
+ if (isLiquidFlow) {
3087
+ liquidMiddleWare();
3088
+ } else {
3089
+ handleSave();
3090
+ }
3060
3091
  }}
3061
3092
  className="save-button"
3062
3093
  disabled={isSaveDisabled}
@@ -394,15 +394,23 @@ export const Rcs = (props) => {
394
394
  const validationResponse =
395
395
  validateTags({
396
396
  content: contentForValidation,
397
- tagsParam: tags,
398
- location,
399
- tagModule: getDefaultTags,
400
- isFullMode,
401
- }) || {};
402
- const errorMsg =
403
- (validationResponse?.isBraceError &&
404
- formatMessage(globalMessages.unbalanacedCurlyBraces)) ||
405
- false;
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
- return formatMessage(messages.fallbackMsgLenError);
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 false;
890
+ return errorMessage;
866
891
  };
867
892
 
868
893
  // Check for forbidden characters: square brackets [] and single curly braces {}