@capillarytech/creatives-library 8.0.287-alpha.3 → 8.0.288

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (65) 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 +111 -2
  6. package/utils/tagValidations.js +222 -84
  7. package/utils/tests/commonUtil.test.js +118 -147
  8. package/utils/tests/tagValidations.test.js +358 -280
  9. package/v2Components/CapTagList/index.js +7 -2
  10. package/v2Components/CapTagListWithInput/index.js +4 -0
  11. package/v2Components/ErrorInfoNote/index.js +5 -2
  12. package/v2Components/FormBuilder/index.js +187 -74
  13. package/v2Components/FormBuilder/messages.js +12 -0
  14. package/v2Components/HtmlEditor/HTMLEditor.js +5 -0
  15. package/v2Components/HtmlEditor/__tests__/HTMLEditor.apiErrors.test.js +1 -0
  16. package/v2Components/HtmlEditor/__tests__/HTMLEditor.test.js +15 -0
  17. package/v2Components/HtmlEditor/components/CodeEditorPane/index.js +2 -1
  18. package/v2Containers/Cap/mockData.js +14 -0
  19. package/v2Containers/Cap/reducer.js +55 -3
  20. package/v2Containers/Cap/tests/reducer.test.js +102 -0
  21. package/v2Containers/CreativesContainer/SlideBoxContent.js +20 -0
  22. package/v2Containers/CreativesContainer/SlideBoxFooter.js +40 -6
  23. package/v2Containers/CreativesContainer/constants.js +6 -0
  24. package/v2Containers/CreativesContainer/index.js +36 -5
  25. package/v2Containers/CreativesContainer/messages.js +12 -0
  26. package/v2Containers/CreativesContainer/tests/SlideBoxFooter.test.js +339 -0
  27. package/v2Containers/CreativesContainer/tests/__snapshots__/SlideBoxContent.test.js.snap +18 -0
  28. package/v2Containers/CreativesContainer/tests/__snapshots__/index.test.js.snap +37 -0
  29. package/v2Containers/Email/index.js +5 -1
  30. package/v2Containers/EmailWrapper/components/EmailHTMLEditor.js +62 -10
  31. package/v2Containers/EmailWrapper/components/__tests__/EmailHTMLEditor.test.js +115 -12
  32. package/v2Containers/FTP/index.js +51 -2
  33. package/v2Containers/FTP/messages.js +4 -0
  34. package/v2Containers/InApp/index.js +96 -1
  35. package/v2Containers/InApp/tests/index.test.js +6 -17
  36. package/v2Containers/InappAdvance/index.js +103 -2
  37. package/v2Containers/Line/Container/Text/index.js +1 -0
  38. package/v2Containers/MobilePush/Create/index.js +37 -1
  39. package/v2Containers/MobilePush/Create/messages.js +4 -0
  40. package/v2Containers/MobilePush/Edit/index.js +37 -2
  41. package/v2Containers/MobilePush/Edit/messages.js +4 -0
  42. package/v2Containers/MobilePushNew/components/PlatformContentFields.js +36 -12
  43. package/v2Containers/MobilePushNew/components/tests/PlatformContentFields.test.js +68 -27
  44. package/v2Containers/MobilePushNew/index.js +92 -5
  45. package/v2Containers/MobilePushNew/messages.js +8 -0
  46. package/v2Containers/MobilepushWrapper/index.js +7 -1
  47. package/v2Containers/Rcs/index.js +37 -12
  48. package/v2Containers/Sms/Create/index.js +3 -31
  49. package/v2Containers/Sms/Create/messages.js +0 -4
  50. package/v2Containers/Sms/Edit/index.js +3 -29
  51. package/v2Containers/Sms/commonMethods.js +6 -6
  52. package/v2Containers/SmsTrai/Edit/index.js +47 -6
  53. package/v2Containers/SmsTrai/Edit/tests/__snapshots__/index.test.js.snap +6 -6
  54. package/v2Containers/TagList/index.js +17 -1
  55. package/v2Containers/TagList/messages.js +4 -0
  56. package/v2Containers/TemplatesV2/index.js +43 -23
  57. package/v2Containers/Viber/index.js +1 -0
  58. package/v2Containers/WebPush/Create/hooks/useTagManagement.js +3 -1
  59. package/v2Containers/WebPush/Create/hooks/useTagManagement.test.js +7 -0
  60. package/v2Containers/WebPush/Create/index.js +25 -6
  61. package/v2Containers/WebPush/Create/messages.js +8 -1
  62. package/v2Containers/WebPush/Create/utils/validation.js +20 -22
  63. package/v2Containers/WebPush/Create/utils/validation.test.js +52 -0
  64. package/v2Containers/Whatsapp/index.js +17 -9
  65. 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"
@@ -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,
@@ -38,6 +38,7 @@ import v2MobilePushCreateReducer from './reducer';
38
38
  import { v2MobilePushWatchDuplicateTemplateSaga } from './sagas';
39
39
  import { EXTERNAL_LINK_LOWERCASE } from './constants';
40
40
  import TestAndPreviewSlidebox from '../../../v2Components/TestAndPreviewSlidebox';
41
+ import { checkForPersonalizationTokens } from '../../../utils/commonUtils';
41
42
 
42
43
  const PrefixWrapper = styled.div`
43
44
  margin-right: 16px;
@@ -161,6 +162,15 @@ export class Create extends React.Component { // eslint-disable-line react/prefe
161
162
  const newFormData = cloneDeep(formData);
162
163
  const {templateCta} = this.state;
163
164
  const { defaultData = {}, isFullMode, showTemplateName} = this.props;
165
+
166
+ // Check for personalization tokens if restriction is enabled and notify parent
167
+ if (this.props.restrictPersonalization) {
168
+ const hasTokens = checkForPersonalizationTokens(newFormData);
169
+ if (this.props.onPersonalizationTokensChange) {
170
+ this.props.onPersonalizationTokensChange(hasTokens);
171
+ }
172
+ }
173
+
164
174
  if (!isEmpty(templateCta)) {
165
175
  newFormData[this.state.currentTab - 1][`secondary-cta-${this.state.currentTab - 1}-label`] = get(templateCta, 'name');
166
176
  newFormData[this.state.currentTab - 1][`secondary-cta-${this.state.currentTab - 1}-action`] = get(templateCta, 'ctaTemplateDetails[0].buttonText');
@@ -674,14 +684,25 @@ export class Create extends React.Component { // eslint-disable-line react/prefe
674
684
  let tab = this.state.currentTab;
675
685
  const isAndroidInvalid = Object.values(errorData[0]).includes(true);
676
686
  const isIosInvalid = Object.values(errorData[1]).includes(true);
687
+ let isTagErrorExist = false;
677
688
  if (isAndroidInvalid) {
678
689
  tab = 1;
679
690
  errorMessage.description = intl.formatMessage(messages.invalidAndroidMessage);
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
+ }
680
696
  } else if (isIosInvalid) {
681
697
  tab = 2;
682
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
+ }
683
704
  }
684
- if (tab !== this.state.currentTab) {
705
+ if (tab !== this.state.currentTab || isTagErrorExist) {
685
706
  CapNotification.error(errorMessage);
686
707
  }
687
708
  }
@@ -1493,6 +1514,17 @@ export class Create extends React.Component { // eslint-disable-line react/prefe
1493
1514
 
1494
1515
  saveFormData = (formData) => {
1495
1516
  //this function gets called from form bulder only when the form data is valid
1517
+
1518
+ // Check for personalization tokens if restriction is enabled
1519
+ if (this.props.restrictPersonalization) {
1520
+ const hasTokens = checkForPersonalizationTokens(formData);
1521
+ if (hasTokens) {
1522
+ const message = this.props.intl.formatMessage(messages.personalizationTokensErrorMessage);
1523
+ CapNotification.error({message, key: 'personalizationTokensError'});
1524
+ return;
1525
+ }
1526
+ }
1527
+
1496
1528
  const obj = this.getTransformedData(formData);
1497
1529
  const content = getContent(obj);
1498
1530
  const {
@@ -1896,6 +1928,7 @@ export class Create extends React.Component { // eslint-disable-line react/prefe
1896
1928
  isFullMode={this.props.isFullMode}
1897
1929
  eventContextTags={this.props?.eventContextTags}
1898
1930
  messageDetails={this.props?.messageDetails}
1931
+ restrictPersonalization={this.props.restrictPersonalization}
1899
1932
  />
1900
1933
  </CapColumn>
1901
1934
  {this.props.iosCtasData && this.state.showIosCtaTable &&
@@ -2000,6 +2033,9 @@ Create.propTypes = {
2000
2033
  showTestAndPreviewSlidebox: PropTypes.bool,
2001
2034
  handleTestAndPreview: PropTypes.func,
2002
2035
  handleCloseTestAndPreview: PropTypes.func,
2036
+ restrictPersonalization: PropTypes.bool,
2037
+ isAnonymousType: PropTypes.bool,
2038
+ onPersonalizationTokensChange: PropTypes.func,
2003
2039
  };
2004
2040
 
2005
2041
  const mapStateToProps = createStructuredSelector({
@@ -342,4 +342,8 @@ export default defineMessages({
342
342
  id: 'creatives.containersV2.MobilePush.Create.thisSectionDisabledHoverText',
343
343
  defaultMessage: 'This section is being revamped. Till then it will remain disabled.',
344
344
  },
345
+ "personalizationTokensErrorMessage": {
346
+ id: 'creatives.containersV2.MobilePush.Create.personalizationTokensErrorMessage',
347
+ defaultMessage: 'Personalization tags are not supported for anonymous customers, please remove the tags.',
348
+ },
345
349
  });
@@ -39,7 +39,7 @@ import { v2MobilePushEditSagas } from './sagas';
39
39
  import v2MobilePushEditReducer from './reducer';
40
40
  import * as globalActions from '../../Cap/actions';
41
41
  import { MAPP_SDK } from './constants';
42
- import { isEmbeddedEditOrPreview } from '../../../utils/commonUtils';
42
+ import { checkForPersonalizationTokens, isEmbeddedEditOrPreview } from '../../../utils/commonUtils';
43
43
  import { EMBEDDED } from '../../Whatsapp/constants';
44
44
  import { OUTBOUND } from '../../../v2Components/FormBuilder/constants';
45
45
  import TestAndPreviewSlidebox from '../../../v2Components/TestAndPreviewSlidebox';
@@ -246,6 +246,15 @@ export class Edit extends React.Component { // eslint-disable-line react/prefer-
246
246
  onFormDataChange = (formData, tabCount, currentTab, inputField) => {
247
247
  const newFormData = _.cloneDeep(formData);
248
248
  const {templateCta} = this.state;
249
+
250
+ // Check for personalization tokens if restriction is enabled and notify parent
251
+ if (this.props.restrictPersonalization) {
252
+ const hasTokens = checkForPersonalizationTokens(newFormData);
253
+ if (this.props.onPersonalizationTokensChange) {
254
+ this.props.onPersonalizationTokensChange(hasTokens);
255
+ }
256
+ }
257
+
249
258
  if (!_.isEmpty(templateCta) && this.state.currentTab === 2) {
250
259
  newFormData[this.state.currentTab - 1][`secondary-cta-${this.state.currentTab - 1}-label`] = get(templateCta, 'name');
251
260
  newFormData[this.state.currentTab - 1][`secondary-cta-${this.state.currentTab - 1}-action`] = get(templateCta, 'ctaTemplateDetails[0].buttonText');
@@ -698,6 +707,7 @@ export class Edit extends React.Component { // eslint-disable-line react/prefer-
698
707
  const {intl} = this.props;
699
708
  const {errorData} = this.state;
700
709
  const errorMessage = {key: 'validation-error', message: intl.formatMessage(messages.validationError)};
710
+ let isTagErrorExist = false;
701
711
  if (!_.isEmpty(this.state.formData) && !this.state.isFormValid) {
702
712
  let tab = this.state.currentTab;
703
713
  const isAndroidInvalid = Object.values(errorData[0]).includes(true);
@@ -705,12 +715,22 @@ export class Edit extends React.Component { // eslint-disable-line react/prefer-
705
715
  if (isAndroidInvalid) {
706
716
  tab = 1;
707
717
  errorMessage.description = intl.formatMessage(messages.invalidAndroidMessage);
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
+ }
708
723
  } else if (isIosInvalid) {
709
724
  tab = 2;
710
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
+ }
711
731
  }
712
732
 
713
- if (tab !== this.state.currentTab) {
733
+ if (tab !== this.state.currentTab || isTagErrorExist) {
714
734
  CapNotification.error(errorMessage);
715
735
  }
716
736
  }
@@ -1676,10 +1696,21 @@ export class Edit extends React.Component { // eslint-disable-line react/prefer-
1676
1696
  };
1677
1697
 
1678
1698
  saveFormData = (formData) => {
1699
+ // Check for personalization tokens if restriction is enabled
1700
+ if (this.props.restrictPersonalization) {
1701
+ const hasTokens = checkForPersonalizationTokens(formData);
1702
+ if (hasTokens) {
1703
+ const message = this.props.intl.formatMessage(messages.personalizationTokensErrorMessage);
1704
+ CapNotification.error({message, key: 'personalizationTokensError'});
1705
+ return;
1706
+ }
1707
+ }
1708
+
1679
1709
  const obj = this.getTransformedData(formData);
1680
1710
 
1681
1711
  this.props.actions.editTemplate(obj, this.onUpdateTemplateComplete);
1682
1712
  };
1713
+
1683
1714
  handleFrameTasks = (e) => {
1684
1715
  //
1685
1716
  const type = e.data;
@@ -2175,6 +2206,7 @@ export class Edit extends React.Component { // eslint-disable-line react/prefer-
2175
2206
  hideTestAndPreviewBtn={this.props.hideTestAndPreviewBtn}
2176
2207
  isFullMode={this.props.isFullMode}
2177
2208
  eventContextTags={this.props?.eventContextTags}
2209
+ restrictPersonalization={this.props.restrictPersonalization}
2178
2210
  />;
2179
2211
  })()}
2180
2212
  </CapColumn>
@@ -2284,6 +2316,9 @@ Edit.propTypes = {
2284
2316
  showTestAndPreviewSlidebox: PropTypes.bool,
2285
2317
  handleTestAndPreview: PropTypes.func,
2286
2318
  handleCloseTestAndPreview: PropTypes.func,
2319
+ restrictPersonalization: PropTypes.bool,
2320
+ isAnonymousType: PropTypes.bool,
2321
+ onPersonalizationTokensChange: PropTypes.func,
2287
2322
  };
2288
2323
 
2289
2324
  const mapStateToProps = createStructuredSelector({
@@ -334,4 +334,8 @@ export default defineMessages({
334
334
  id: 'creatives.containersV2.MobilePush.Edit.thisSectionDisabledHoverText',
335
335
  defaultMessage: 'This section is being revamped. Till then it will remain disabled.',
336
336
  },
337
+ "personalizationTokensErrorMessage": {
338
+ id: 'creatives.containersV2.MobilePush.Edit.personalizationTokensErrorMessage',
339
+ defaultMessage: 'Personalization tags are not supported for anonymous customers, please remove the tags.',
340
+ },
337
341
  });
@@ -24,6 +24,7 @@ import {
24
24
  import messages from "../messages";
25
25
  import MediaUploaders from "./MediaUploaders";
26
26
  import CtaButtons from "./CtaButtons";
27
+ import { hasPersonalizationTags } from "../../../utils/commonUtils";
27
28
 
28
29
  const PlatformContentFields = ({
29
30
  deviceType,
@@ -40,8 +41,17 @@ const PlatformContentFields = ({
40
41
  tags,
41
42
  injectedTags,
42
43
  selectedOfferDetails,
44
+ // new prop to disable personalization features for anonymous users
45
+ restrictPersonalization = false,
43
46
  }) => {
44
47
  const { title: titleError, message: messageError } = errors;
48
+
49
+ const titleErrorToShow = titleError || (restrictPersonalization && hasPersonalizationTags(content.title)
50
+ ? formatMessage(messages.personalizationTagsErrorMessage)
51
+ : "");
52
+ const messageErrorToShow = messageError || (restrictPersonalization && hasPersonalizationTags(content.message)
53
+ ? formatMessage(messages.personalizationTagsErrorMessage)
54
+ : "");
45
55
  const {
46
56
  handleTitleChange,
47
57
  handleMessageChange,
@@ -139,14 +149,19 @@ const PlatformContentFields = ({
139
149
  );
140
150
 
141
151
  const getTagList = useCallback(
142
- (index) => (
143
- <TagList
144
- {...tagListProps}
145
- onTagSelect={(value) => onTagSelect(value, index)}
146
- onContextChange={handleOnTagsContextChange}
147
- />
148
- ),
149
- [tagListProps, onTagSelect, handleOnTagsContextChange]
152
+ (index) => {
153
+ const disableMsg = restrictPersonalization ? formatMessage(messages.personalizationNotSupportedAnonymous) : undefined;
154
+ return (
155
+ <TagList
156
+ {...tagListProps}
157
+ disabled={restrictPersonalization}
158
+ disableTooltipMsg={disableMsg}
159
+ onTagSelect={(value) => onTagSelect(value, index)}
160
+ onContextChange={handleOnTagsContextChange}
161
+ />
162
+ );
163
+ },
164
+ [tagListProps, onTagSelect, handleOnTagsContextChange, restrictPersonalization, formatMessage]
150
165
  );
151
166
 
152
167
  const onButtonTagSelect = useCallback(
@@ -178,9 +193,9 @@ const PlatformContentFields = ({
178
193
  size="default"
179
194
  isRequired
180
195
  errorMessage={
181
- titleError && (
196
+ titleErrorToShow && (
182
197
  <CapError className="mobile-push-template-title-error">
183
- {titleError}
198
+ {titleErrorToShow}
184
199
  </CapError>
185
200
  )
186
201
  }
@@ -202,9 +217,9 @@ const PlatformContentFields = ({
202
217
  size="default"
203
218
  isRequired
204
219
  errorMessage={
205
- messageError && (
220
+ messageErrorToShow && (
206
221
  <CapError className="mobile-push-template-message-error">
207
- {messageError}
222
+ {messageErrorToShow}
208
223
  </CapError>
209
224
  )
210
225
  }
@@ -314,6 +329,10 @@ const PlatformContentFields = ({
314
329
  tags={tags}
315
330
  injectedTags={injectedTags}
316
331
  selectedOfferDetails={selectedOfferDetails}
332
+ disabled={restrictPersonalization}
333
+ disableTooltipMsg={
334
+ restrictPersonalization ? formatMessage(messages.personalizationNotSupportedAnonymous) : undefined
335
+ }
317
336
  />
318
337
  </CapRow>
319
338
  <CapInput
@@ -389,6 +408,11 @@ PlatformContentFields.propTypes = {
389
408
  linkProps: PropTypes.object.isRequired,
390
409
  sameContent: PropTypes.bool.isRequired,
391
410
  formatMessage: PropTypes.func.isRequired,
411
+ restrictPersonalization: PropTypes.bool,
412
+ };
413
+
414
+ PlatformContentFields.defaultProps = {
415
+ restrictPersonalization: false,
392
416
  };
393
417
 
394
418
  export default PlatformContentFields;