cap-creatives-ui 8.0.280 → 8.0.321

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 (247) hide show
  1. package/.github/workflows/pr-title-check.yml +88 -0
  2. package/app/constants/unified.js +21 -1
  3. package/app/containers/App/constants.js +0 -1
  4. package/app/containers/Login/test/index.test.js +123 -0
  5. package/app/containers/Login/test/selectors.test.js +165 -0
  6. package/app/initialState.js +0 -2
  7. package/app/services/api.js +6 -0
  8. package/app/services/tests/api.test.js +7 -0
  9. package/app/services/tests/getSchema.test.js +95 -0
  10. package/app/utils/common.js +23 -9
  11. package/app/utils/commonUtils.js +64 -93
  12. package/app/utils/tagValidations.js +83 -219
  13. package/app/utils/templateVarUtils.js +172 -0
  14. package/app/utils/tests/common.test.js +265 -323
  15. package/app/utils/tests/commonUtil.test.js +461 -118
  16. package/app/utils/tests/commonUtils.test.js +581 -0
  17. package/app/utils/tests/messageUtils.test.js +95 -0
  18. package/app/utils/tests/smsCharCount.test.js +304 -0
  19. package/app/utils/tests/smsCharCountV2.test.js +213 -10
  20. package/app/utils/tests/tagValidations.test.js +474 -357
  21. package/app/utils/tests/templateVarUtils.test.js +160 -0
  22. package/app/v2Components/CapDeviceContent/index.js +10 -7
  23. package/app/v2Components/CapTagList/index.js +32 -24
  24. package/app/v2Components/CapTagList/style.scss +48 -0
  25. package/app/v2Components/CapTagListWithInput/__tests__/CapTagListWithInput.test.js +63 -0
  26. package/app/v2Components/CapTagListWithInput/index.js +8 -0
  27. package/app/v2Components/CapWhatsappCTA/index.js +2 -0
  28. package/app/v2Components/CapWhatsappCarouselButton/index.js +32 -14
  29. package/app/v2Components/CapWhatsappCarouselButton/tests/index.test.js +120 -2
  30. package/app/v2Components/CommonTestAndPreview/CustomValuesEditor.js +70 -49
  31. package/app/v2Components/CommonTestAndPreview/DeliverySettings/DeliverySettings.scss +39 -0
  32. package/app/v2Components/CommonTestAndPreview/DeliverySettings/ModifyDeliverySettings.js +606 -0
  33. package/app/v2Components/CommonTestAndPreview/DeliverySettings/ModifyDeliverySettings.scss +36 -0
  34. package/app/v2Components/CommonTestAndPreview/DeliverySettings/constants.js +79 -0
  35. package/app/v2Components/CommonTestAndPreview/DeliverySettings/index.js +314 -0
  36. package/app/v2Components/CommonTestAndPreview/DeliverySettings/messages.js +141 -0
  37. package/app/v2Components/CommonTestAndPreview/DeliverySettings/utils/parseSenderDetailsResponse.js +156 -0
  38. package/app/v2Components/CommonTestAndPreview/SendTestMessage.js +57 -1
  39. package/app/v2Components/CommonTestAndPreview/UnifiedPreview/_unifiedPreview.scss +20 -1
  40. package/app/v2Components/CommonTestAndPreview/UnifiedPreview/index.js +133 -4
  41. package/app/v2Components/CommonTestAndPreview/_commonTestAndPreview.scss +210 -4
  42. package/app/v2Components/CommonTestAndPreview/actions.js +20 -0
  43. package/app/v2Components/CommonTestAndPreview/constants.js +57 -1
  44. package/app/v2Components/CommonTestAndPreview/index.js +878 -156
  45. package/app/v2Components/CommonTestAndPreview/messages.js +41 -3
  46. package/app/v2Components/CommonTestAndPreview/previewApiUtils.js +59 -0
  47. package/app/v2Components/CommonTestAndPreview/reducer.js +47 -0
  48. package/app/v2Components/CommonTestAndPreview/sagas.js +75 -5
  49. package/app/v2Components/CommonTestAndPreview/selectors.js +51 -0
  50. package/app/v2Components/CommonTestAndPreview/tests/CustomValuesEditor.test.js +352 -0
  51. package/app/v2Components/CommonTestAndPreview/tests/DeliverySettings/ModifyDeliverySettings.test.js +1156 -0
  52. package/app/v2Components/CommonTestAndPreview/tests/DeliverySettings/index.test.js +334 -0
  53. package/app/v2Components/CommonTestAndPreview/tests/DeliverySettings/utils/parseSenderDetailsResponse.test.js +576 -0
  54. package/app/v2Components/CommonTestAndPreview/tests/SendTestMessage.test.js +156 -0
  55. package/app/v2Components/CommonTestAndPreview/tests/UnifiedPreview/index.test.js +199 -1
  56. package/app/v2Components/CommonTestAndPreview/tests/actions.test.js +50 -0
  57. package/app/v2Components/CommonTestAndPreview/tests/constants.test.js +18 -7
  58. package/app/v2Components/CommonTestAndPreview/tests/index.test.js +914 -5
  59. package/app/v2Components/CommonTestAndPreview/tests/previewApiUtils.test.js +67 -0
  60. package/app/v2Components/CommonTestAndPreview/tests/reducer.test.js +118 -0
  61. package/app/v2Components/CommonTestAndPreview/tests/sagas.test.js +146 -378
  62. package/app/v2Components/CommonTestAndPreview/tests/selectors.test.js +146 -0
  63. package/app/v2Components/ErrorInfoNote/index.js +24 -26
  64. package/app/v2Components/FormBuilder/index.js +182 -204
  65. package/app/v2Components/FormBuilder/messages.js +4 -8
  66. package/app/v2Components/HtmlEditor/HTMLEditor.js +7 -6
  67. package/app/v2Components/HtmlEditor/__tests__/HTMLEditor.apiErrors.test.js +1 -1
  68. package/app/v2Components/HtmlEditor/__tests__/HTMLEditor.test.js +928 -17
  69. package/app/v2Components/HtmlEditor/components/CodeEditorPane/index.js +4 -2
  70. package/app/v2Components/HtmlEditor/hooks/__tests__/useValidation.test.js +452 -3
  71. package/app/v2Components/HtmlEditor/hooks/useValidation.js +12 -9
  72. package/app/v2Components/HtmlEditor/utils/__tests__/htmlValidator.enhanced.test.js +132 -0
  73. package/app/v2Components/HtmlEditor/utils/htmlValidator.js +4 -2
  74. package/app/v2Components/SmsFallback/SmsFallbackLocalSelector.js +87 -0
  75. package/app/v2Components/SmsFallback/constants.js +73 -0
  76. package/app/v2Components/SmsFallback/index.js +956 -0
  77. package/app/v2Components/SmsFallback/index.scss +265 -0
  78. package/app/v2Components/SmsFallback/messages.js +78 -0
  79. package/app/v2Components/SmsFallback/smsFallbackUtils.js +107 -0
  80. package/app/v2Components/SmsFallback/tests/SmsFallbackLocalSelector.test.js +50 -0
  81. package/app/v2Components/SmsFallback/tests/rcsSmsFallback.acceptance.test.js +147 -0
  82. package/app/v2Components/SmsFallback/tests/smsFallbackHandlers.test.js +304 -0
  83. package/app/v2Components/SmsFallback/tests/smsFallbackUi.test.js +197 -0
  84. package/app/v2Components/SmsFallback/tests/smsFallbackUtils.test.js +261 -0
  85. package/app/v2Components/SmsFallback/tests/useLocalTemplateList.test.js +422 -0
  86. package/app/v2Components/SmsFallback/useLocalTemplateList.js +92 -0
  87. package/app/v2Components/TestAndPreviewSlidebox/index.js +22 -1
  88. package/app/v2Components/TestAndPreviewSlidebox/sagas.js +11 -4
  89. package/app/v2Components/TestAndPreviewSlidebox/tests/saga.test.js +3 -1
  90. package/app/v2Components/VarSegmentMessageEditor/constants.js +2 -0
  91. package/app/v2Components/VarSegmentMessageEditor/index.js +125 -0
  92. package/app/v2Components/VarSegmentMessageEditor/index.scss +46 -0
  93. package/app/v2Containers/BeeEditor/index.js +3 -0
  94. package/app/v2Containers/BeePopupEditor/index.js +9 -2
  95. package/app/v2Containers/Cap/mockData.js +0 -14
  96. package/app/v2Containers/Cap/reducer.js +3 -55
  97. package/app/v2Containers/Cap/tests/reducer.test.js +0 -102
  98. package/app/v2Containers/CommunicationFlow/CommunicationFlow.js +291 -0
  99. package/app/v2Containers/CommunicationFlow/CommunicationFlow.scss +25 -0
  100. package/app/v2Containers/CommunicationFlow/Tests/CommunicationFlow.test.js +255 -0
  101. package/app/v2Containers/CommunicationFlow/constants.js +200 -0
  102. package/app/v2Containers/CommunicationFlow/index.js +102 -0
  103. package/app/v2Containers/CommunicationFlow/messages.js +346 -0
  104. package/app/v2Containers/CommunicationFlow/steps/ChannelSelectionStep/ChannelSelectionStep.js +522 -0
  105. package/app/v2Containers/CommunicationFlow/steps/ChannelSelectionStep/ChannelSelectionStep.scss +170 -0
  106. package/app/v2Containers/CommunicationFlow/steps/ChannelSelectionStep/Tests/ChannelSelectionStep.test.js +796 -0
  107. package/app/v2Containers/CommunicationFlow/steps/ChannelSelectionStep/index.js +5 -0
  108. package/app/v2Containers/CommunicationFlow/steps/CommunicationStrategyStep/CommunicationStrategyStep.js +95 -0
  109. package/app/v2Containers/CommunicationFlow/steps/CommunicationStrategyStep/Tests/CommunicationStrategyStep.test.js +133 -0
  110. package/app/v2Containers/CommunicationFlow/steps/CommunicationStrategyStep/index.js +5 -0
  111. package/app/v2Containers/CommunicationFlow/steps/DeliverySettingsStep/DeliverySettingsSection.js +289 -0
  112. package/app/v2Containers/CommunicationFlow/steps/DeliverySettingsStep/DeliverySettingsSection.scss +70 -0
  113. package/app/v2Containers/CommunicationFlow/steps/DeliverySettingsStep/SenderDetails.js +319 -0
  114. package/app/v2Containers/CommunicationFlow/steps/DeliverySettingsStep/SenderDetails.scss +69 -0
  115. package/app/v2Containers/CommunicationFlow/steps/DeliverySettingsStep/Tests/DeliverySettingsSection.test.js +616 -0
  116. package/app/v2Containers/CommunicationFlow/steps/DeliverySettingsStep/Tests/SenderDetails.test.js +577 -0
  117. package/app/v2Containers/CommunicationFlow/steps/DeliverySettingsStep/Tests/deliverySettingsConfig.test.js +1111 -0
  118. package/app/v2Containers/CommunicationFlow/steps/DeliverySettingsStep/deliverySettingsConfig.js +696 -0
  119. package/app/v2Containers/CommunicationFlow/steps/DeliverySettingsStep/index.js +7 -0
  120. package/app/v2Containers/CommunicationFlow/steps/DynamicControlsStep/DynamicControlsStep.js +102 -0
  121. package/app/v2Containers/CommunicationFlow/steps/DynamicControlsStep/DynamicControlsStep.scss +36 -0
  122. package/app/v2Containers/CommunicationFlow/steps/DynamicControlsStep/Tests/DynamicControlsStep.test.js +91 -0
  123. package/app/v2Containers/CommunicationFlow/steps/DynamicControlsStep/index.js +5 -0
  124. package/app/v2Containers/CommunicationFlow/steps/MessageTypeStep/MessageTypeStep.js +86 -0
  125. package/app/v2Containers/CommunicationFlow/steps/MessageTypeStep/Tests/MessageTypeStep.test.js +100 -0
  126. package/app/v2Containers/CommunicationFlow/steps/MessageTypeStep/index.js +5 -0
  127. package/app/v2Containers/CommunicationFlow/utils/getEnabledSteps.js +30 -0
  128. package/app/v2Containers/CreativesContainer/CreativesSlideBoxWrapper.js +43 -0
  129. package/app/v2Containers/CreativesContainer/SlideBoxContent.js +127 -11
  130. package/app/v2Containers/CreativesContainer/SlideBoxFooter.js +62 -9
  131. package/app/v2Containers/CreativesContainer/SlideBoxHeader.js +29 -4
  132. package/app/v2Containers/CreativesContainer/constants.js +24 -0
  133. package/app/v2Containers/CreativesContainer/embeddedSlideboxUtils.js +67 -0
  134. package/app/v2Containers/CreativesContainer/index.js +346 -71
  135. package/app/v2Containers/CreativesContainer/index.scss +51 -1
  136. package/app/v2Containers/CreativesContainer/messages.js +12 -0
  137. package/app/v2Containers/CreativesContainer/tests/SlideBoxContent.localTemplates.test.js +90 -0
  138. package/app/v2Containers/CreativesContainer/tests/SlideBoxContent.test.js +69 -1
  139. package/app/v2Containers/CreativesContainer/tests/SlideBoxFooter.test.js +443 -0
  140. package/app/v2Containers/CreativesContainer/tests/SlideBoxHeader.test.js +110 -0
  141. package/app/v2Containers/CreativesContainer/tests/__snapshots__/SlideBoxContent.test.js.snap +147 -4
  142. package/app/v2Containers/CreativesContainer/tests/__snapshots__/SlideBoxHeader.test.js.snap +363 -0
  143. package/app/v2Containers/CreativesContainer/tests/__snapshots__/index.test.js.snap +57 -10
  144. package/app/v2Containers/CreativesContainer/tests/embeddedSlideboxUtils.test.js +258 -0
  145. package/app/v2Containers/CreativesContainer/tests/index.test.js +71 -9
  146. package/app/v2Containers/CreativesContainer/tests/useLocalTemplatesProp.test.js +125 -0
  147. package/app/v2Containers/Email/index.js +2 -5
  148. package/app/v2Containers/EmailWrapper/components/EmailHTMLEditor.js +58 -77
  149. package/app/v2Containers/EmailWrapper/components/EmailWrapperView.js +3 -0
  150. package/app/v2Containers/EmailWrapper/components/__tests__/EmailHTMLEditor.test.js +158 -89
  151. package/app/v2Containers/EmailWrapper/components/__tests__/EmailWrapperView.test.js +16 -1
  152. package/app/v2Containers/EmailWrapper/hooks/useEmailWrapper.js +17 -12
  153. package/app/v2Containers/EmailWrapper/index.js +4 -0
  154. package/app/v2Containers/EmailWrapper/tests/useEmailWrapper.edgeCases.test.js +1 -0
  155. package/app/v2Containers/EmailWrapper/tests/useEmailWrapper.test.js +133 -0
  156. package/app/v2Containers/FTP/index.js +2 -51
  157. package/app/v2Containers/FTP/messages.js +0 -4
  158. package/app/v2Containers/InApp/__tests__/InAppHTMLEditor.test.js +110 -155
  159. package/app/v2Containers/InApp/index.js +297 -118
  160. package/app/v2Containers/InApp/tests/index.test.js +17 -6
  161. package/app/v2Containers/InApp/tests/mockData.js +1 -1
  162. package/app/v2Containers/InAppWrapper/hooks/__tests__/useInAppWrapper.test.js +19 -0
  163. package/app/v2Containers/InAppWrapper/hooks/useInAppWrapper.js +3 -0
  164. package/app/v2Containers/InAppWrapper/index.js +3 -0
  165. package/app/v2Containers/InappAdvance/index.js +5 -104
  166. package/app/v2Containers/InappAdvance/tests/index.test.js +2 -0
  167. package/app/v2Containers/Line/Container/ImageCarousel/tests/__snapshots__/content.test.js.snap +24 -3
  168. package/app/v2Containers/Line/Container/Text/index.js +0 -1
  169. package/app/v2Containers/MobilePush/Create/index.js +105 -28
  170. package/app/v2Containers/MobilePush/Create/messages.js +4 -0
  171. package/app/v2Containers/MobilePush/Edit/index.js +250 -68
  172. package/app/v2Containers/MobilePush/Edit/messages.js +4 -0
  173. package/app/v2Containers/MobilePushNew/components/PlatformContentFields.js +36 -12
  174. package/app/v2Containers/MobilePushNew/components/tests/PlatformContentFields.test.js +68 -27
  175. package/app/v2Containers/MobilePushNew/index.js +78 -35
  176. package/app/v2Containers/MobilePushNew/messages.js +8 -0
  177. package/app/v2Containers/MobilepushWrapper/index.js +11 -1
  178. package/app/v2Containers/Rcs/constants.js +32 -1
  179. package/app/v2Containers/Rcs/index.js +963 -916
  180. package/app/v2Containers/Rcs/index.scss +85 -6
  181. package/app/v2Containers/Rcs/messages.js +10 -1
  182. package/app/v2Containers/Rcs/rcsLibraryHydrationUtils.js +205 -0
  183. package/app/v2Containers/Rcs/tests/__snapshots__/index.test.js.snap +41136 -1566
  184. package/app/v2Containers/Rcs/tests/__snapshots__/utils.test.js.snap +0 -5
  185. package/app/v2Containers/Rcs/tests/index.test.js +41 -38
  186. package/app/v2Containers/Rcs/tests/mockData.js +38 -0
  187. package/app/v2Containers/Rcs/tests/rcsLibraryHydrationUtils.test.js +251 -0
  188. package/app/v2Containers/Rcs/tests/utils.test.js +379 -1
  189. package/app/v2Containers/Rcs/utils.js +358 -10
  190. package/app/v2Containers/Sms/Create/index.js +122 -39
  191. package/app/v2Containers/Sms/Create/messages.js +4 -0
  192. package/app/v2Containers/Sms/Edit/index.js +37 -3
  193. package/app/v2Containers/Sms/commonMethods.js +3 -6
  194. package/app/v2Containers/Sms/smsFormDataHelpers.js +67 -0
  195. package/app/v2Containers/Sms/tests/commonMethods.test.js +122 -0
  196. package/app/v2Containers/Sms/tests/smsFormDataHelpers.test.js +253 -0
  197. package/app/v2Containers/SmsTrai/Create/index.js +9 -4
  198. package/app/v2Containers/SmsTrai/Create/index.scss +1 -1
  199. package/app/v2Containers/SmsTrai/Edit/constants.js +2 -0
  200. package/app/v2Containers/SmsTrai/Edit/index.js +667 -160
  201. package/app/v2Containers/SmsTrai/Edit/index.scss +121 -0
  202. package/app/v2Containers/SmsTrai/Edit/messages.js +9 -4
  203. package/app/v2Containers/SmsTrai/Edit/tests/__snapshots__/index.test.js.snap +4590 -2436
  204. package/app/v2Containers/SmsWrapper/index.js +41 -8
  205. package/app/v2Containers/TagList/index.js +63 -2
  206. package/app/v2Containers/TagList/messages.js +8 -0
  207. package/app/v2Containers/TagList/tests/TagList.test.js +122 -20
  208. package/app/v2Containers/TagList/tests/mockdata.js +17 -0
  209. package/app/v2Containers/Templates/TemplatesActionBar.js +101 -0
  210. package/app/v2Containers/Templates/_templates.scss +61 -2
  211. package/app/v2Containers/Templates/actions.js +11 -0
  212. package/app/v2Containers/Templates/constants.js +2 -0
  213. package/app/v2Containers/Templates/index.js +90 -40
  214. package/app/v2Containers/Templates/reducer.js +3 -1
  215. package/app/v2Containers/Templates/sagas.js +57 -12
  216. package/app/v2Containers/Templates/tests/TemplatesActionBar.test.js +120 -0
  217. package/app/v2Containers/Templates/tests/__snapshots__/index.test.js.snap +1043 -1079
  218. package/app/v2Containers/Templates/tests/reducer.test.js +12 -0
  219. package/app/v2Containers/Templates/tests/sagas.test.js +193 -12
  220. package/app/v2Containers/Templates/tests/smsTemplatesListApi.test.js +180 -0
  221. package/app/v2Containers/Templates/utils/smsTemplatesListApi.js +79 -0
  222. package/app/v2Containers/TemplatesV2/TemplatesV2.style.js +72 -1
  223. package/app/v2Containers/TemplatesV2/index.js +147 -49
  224. package/app/v2Containers/TemplatesV2/tests/TemplatesV2.localTemplates.test.js +131 -0
  225. package/app/v2Containers/Viber/index.js +9 -10
  226. package/app/v2Containers/Viber/index.scss +1 -1
  227. package/app/v2Containers/WebPush/Create/components/BrandIconSection.test.js +264 -0
  228. package/app/v2Containers/WebPush/Create/components/MessageSection.js +78 -19
  229. package/app/v2Containers/WebPush/Create/components/MessageSection.test.js +82 -0
  230. package/app/v2Containers/WebPush/Create/components/__snapshots__/BrandIconSection.test.js.snap +187 -0
  231. package/app/v2Containers/WebPush/Create/components/__snapshots__/MessageSection.test.js.snap +25 -17
  232. package/app/v2Containers/WebPush/Create/hooks/useAiraTriggerPosition.js +80 -0
  233. package/app/v2Containers/WebPush/Create/hooks/useAiraTriggerPosition.test.js +210 -0
  234. package/app/v2Containers/WebPush/Create/hooks/useTagManagement.js +1 -5
  235. package/app/v2Containers/WebPush/Create/hooks/useTagManagement.test.js +0 -7
  236. package/app/v2Containers/WebPush/Create/index.js +36 -6
  237. package/app/v2Containers/WebPush/Create/index.scss +5 -0
  238. package/app/v2Containers/WebPush/Create/messages.js +8 -1
  239. package/app/v2Containers/WebPush/Create/preview/tests/NotificationContainer.test.js +269 -0
  240. package/app/v2Containers/WebPush/Create/utils/validation.js +31 -15
  241. package/app/v2Containers/WebPush/Create/utils/validation.test.js +72 -24
  242. package/app/v2Containers/Whatsapp/index.js +28 -53
  243. package/app/v2Containers/Whatsapp/tests/__snapshots__/index.test.js.snap +26939 -3982
  244. package/app/v2Containers/Whatsapp/tests/index.test.js +172 -0
  245. package/app/v2Containers/Zalo/index.js +5 -11
  246. package/package.json +2 -2
  247. package/version +9 -0
@@ -72,6 +72,7 @@ import {
72
72
  } from '../../Cap/selectors';
73
73
  import './index.scss';
74
74
  import { WEBPUSH } from '../../CreativesContainer/constants';
75
+ import { isAiContentBotDisabled } from '../../../utils/common';
75
76
 
76
77
  // Memoized TagList wrapper components for better performance
77
78
  const MemoizedTagList = memo(({
@@ -83,8 +84,12 @@ const MemoizedTagList = memo(({
83
84
  injectedTags,
84
85
  selectedOfferDetails,
85
86
  eventContextTags,
87
+ waitEventContextTags,
86
88
  forwardedTags,
87
89
  onTagSelect,
90
+ restrictPersonalization = false,
91
+ disabled = false,
92
+ disableTooltipMsg,
88
93
  }) => (
89
94
  <TagList
90
95
  moduleFilterEnabled={moduleFilterEnabled}
@@ -95,8 +100,12 @@ const MemoizedTagList = memo(({
95
100
  injectedTags={injectedTags}
96
101
  selectedOfferDetails={selectedOfferDetails}
97
102
  eventContextTags={eventContextTags}
103
+ waitEventContextTags={waitEventContextTags}
98
104
  forwardedTags={forwardedTags}
99
105
  onTagSelect={onTagSelect}
106
+ restrictPersonalization={restrictPersonalization}
107
+ disabled={disabled || restrictPersonalization}
108
+ disableTooltipMsg={disableTooltipMsg}
100
109
  />
101
110
  ), (prevProps, nextProps) => {
102
111
  // Custom comparison function for better memoization
@@ -109,8 +118,12 @@ const MemoizedTagList = memo(({
109
118
  && prevProps.injectedTags === nextProps.injectedTags
110
119
  && prevProps.selectedOfferDetails === nextProps.selectedOfferDetails
111
120
  && prevProps.eventContextTags === nextProps.eventContextTags
121
+ && prevProps.waitEventContextTags === nextProps.waitEventContextTags
112
122
  && prevProps.forwardedTags === nextProps.forwardedTags
113
123
  && prevProps.onTagSelect === nextProps.onTagSelect
124
+ && prevProps.restrictPersonalization === nextProps.restrictPersonalization
125
+ && prevProps.disabled === nextProps.disabled
126
+ && prevProps.disableTooltipMsg === nextProps.disableTooltipMsg
114
127
  );
115
128
  });
116
129
 
@@ -142,10 +155,13 @@ const WebPushCreate = ({
142
155
  forwardedTags,
143
156
  selectedOfferDetails = [],
144
157
  eventContextTags = [],
158
+ waitEventContextTags = {},
145
159
  templateActions: templateActionsProps,
146
160
  Templates,
161
+ restrictPersonalization = false,
147
162
  }) => {
148
163
  const { formatMessage } = intl;
164
+ const aiContentBotDisabled = isAiContentBotDisabled();
149
165
 
150
166
  // Form state - kept in main component for now
151
167
  const [templateName, setTemplateName] = useState('');
@@ -220,6 +236,7 @@ const WebPushCreate = ({
220
236
  supportedTags: memoizedSupportedTags,
221
237
  injectedTags,
222
238
  eventContextTags,
239
+ waitEventContextTags,
223
240
  });
224
241
  const { tags, handleOnTagsContextChange, validationConfig } = tagState;
225
242
  const { weCrmAccounts } = Templates;
@@ -285,8 +302,8 @@ const WebPushCreate = ({
285
302
  const validateTemplateName = useCallback((value) => validateTemplateNameUtil(value), []);
286
303
 
287
304
  const validateTitle = useCallback(
288
- (value) => validateTitleUtil(value, formatMessage, messages),
289
- [formatMessage],
305
+ (value) => validateTitleUtil(value, formatMessage, messages, restrictPersonalization, validationConfig, isFullMode),
306
+ [formatMessage, restrictPersonalization, validationConfig, isFullMode],
290
307
  );
291
308
 
292
309
  const validateUrl = useCallback(
@@ -309,8 +326,8 @@ const WebPushCreate = ({
309
326
 
310
327
 
311
328
  const validateMessageContent = useCallback(
312
- (value) => validateMessageContentUtil(value, formatMessage, messages, validationConfig, isFullMode),
313
- [formatMessage, validationConfig, isFullMode],
329
+ (value) => validateMessageContentUtil(value, formatMessage, messages, validationConfig, isFullMode, restrictPersonalization),
330
+ [formatMessage, validationConfig, isFullMode, restrictPersonalization],
314
331
  );
315
332
 
316
333
  useEffect(() => {
@@ -546,7 +563,7 @@ const WebPushCreate = ({
546
563
  // Pure validator that returns boolean without setting error state
547
564
  const validateFormSilent = () => {
548
565
  const templateNameInvalid = isFullMode && validateTemplateName(templateName);
549
- const titleValidation = validateTitle(notificationTitle);
566
+ const titleValidation = validateTitle(notificationTitle, restrictPersonalization);
550
567
  const messageValidation = validateMessageContent(message);
551
568
 
552
569
  return !(templateNameInvalid || titleValidation || messageValidation);
@@ -569,6 +586,7 @@ const WebPushCreate = ({
569
586
  return;
570
587
  }
571
588
 
589
+
572
590
  // Set flag to indicate save/edit operation has been initiated
573
591
  saveInitiatedRef.current = true;
574
592
 
@@ -824,9 +842,13 @@ const WebPushCreate = ({
824
842
  injectedTags,
825
843
  selectedOfferDetails,
826
844
  eventContextTags,
845
+ waitEventContextTags,
827
846
  forwardedTags,
847
+ restrictPersonalization,
848
+ disabled: restrictPersonalization,
849
+ disableTooltipMsg: restrictPersonalization ? formatMessage(messages.personalizationNotSupportedAnonymous) : undefined,
828
850
  }),
829
- [tags, injectedTags, selectedOfferDetails, eventContextTags, forwardedTags],
851
+ [tags, injectedTags, selectedOfferDetails, eventContextTags, waitEventContextTags, forwardedTags, restrictPersonalization, formatMessage],
830
852
  );
831
853
 
832
854
  // Memoized TagList components with optimized props
@@ -881,6 +903,7 @@ const WebPushCreate = ({
881
903
  )
882
904
  )
883
905
  || (onClickBehaviour === ON_CLICK_BEHAVIOUR_OPTIONS.REDIRECT_TO_URL && (!redirectUrl.trim() || redirectUrlError))
906
+ || !!titleError || !!messageError
884
907
  ),
885
908
  [
886
909
  createTemplateInProgress,
@@ -906,6 +929,8 @@ const WebPushCreate = ({
906
929
  onClickBehaviour,
907
930
  redirectUrl,
908
931
  redirectUrlError,
932
+ titleError,
933
+ messageError,
909
934
  ],
910
935
  );
911
936
 
@@ -980,6 +1005,7 @@ const WebPushCreate = ({
980
1005
  messageCountRef={messageCountRef}
981
1006
  messageTextAreaRef={messageTextAreaRef}
982
1007
  handleMessageTextAreaRef={handleMessageTextAreaRef}
1008
+ isAiContentBotDisabled={aiContentBotDisabled}
983
1009
  />
984
1010
  <MediaSection
985
1011
  mediaType={mediaType}
@@ -1063,7 +1089,9 @@ WebPushCreate.propTypes = {
1063
1089
  forwardedTags: PropTypes.object,
1064
1090
  selectedOfferDetails: PropTypes.array,
1065
1091
  eventContextTags: PropTypes.array,
1092
+ waitEventContextTags: PropTypes.object,
1066
1093
  templateActions: PropTypes.object,
1094
+ restrictPersonalization: PropTypes.bool,
1067
1095
  };
1068
1096
 
1069
1097
  WebPushCreate.defaultProps = {
@@ -1090,8 +1118,10 @@ WebPushCreate.defaultProps = {
1090
1118
  forwardedTags: {},
1091
1119
  selectedOfferDetails: [],
1092
1120
  eventContextTags: [],
1121
+ waitEventContextTags: {},
1093
1122
  templateActions: {},
1094
1123
  Templates: {},
1124
+ restrictPersonalization: false,
1095
1125
  };
1096
1126
 
1097
1127
  const mapStateToProps = createStructuredSelector({
@@ -81,6 +81,11 @@
81
81
  margin-bottom: -2.5625rem; // approx -41px
82
82
  }
83
83
 
84
+ .webpush-message-input-wrapper {
85
+ position: relative;
86
+ width: 100%;
87
+ }
88
+
84
89
  .webpush-buttons-section-heading {
85
90
  font-weight: $FONT_WEIGHT_MEDIUM;
86
91
  color: $CAP_G16;
@@ -207,5 +207,12 @@ export default defineMessages({
207
207
  id: `${scope}.templateIdMissingError`,
208
208
  defaultMessage: 'Unable to save template: Template ID is missing. Please refresh the page and try again.',
209
209
  },
210
+ personalizationTokensErrorMessage: {
211
+ id: `${scope}.personalizationTokensErrorMessage`,
212
+ defaultMessage: 'Personalization tags are not supported for anonymous customers, please remove the tags.',
213
+ },
214
+ personalizationNotSupportedAnonymous: {
215
+ id: `${scope}.personalizationNotSupportedAnonymous`,
216
+ defaultMessage: 'Personalization tags are not supported for anonymous customers',
217
+ },
210
218
  });
211
-
@@ -1016,6 +1016,275 @@ describe('NotificationContainer', () => {
1016
1016
  });
1017
1017
  });
1018
1018
 
1019
+ describe('platform.browser getter — 2-part vs 3-part class names', () => {
1020
+ it('derives browser from 2-part class name (macos-chrome → parts[1])', () => {
1021
+ // 'macos-chrome'.split('-') = ['macos', 'chrome'] → length=2 → browser = parts[1] = 'chrome'
1022
+ const wrapper = mountWithIntl(
1023
+ <NotificationContainer {...defaultProps} selectedOS={OS_MACOS} selectedBrowser={BROWSER_CHROME} />
1024
+ );
1025
+ expect(wrapper.find('.notification-container').hasClass('macos-chrome')).toBe(true);
1026
+ });
1027
+
1028
+ it('derives browser from 3-part class name (android-mobile-chrome → parts[2])', () => {
1029
+ // 'android-mobile-chrome'.split('-') = ['android', 'mobile', 'chrome'] → length=3 → browser = parts[2] = 'chrome'
1030
+ const wrapper = mountWithIntl(
1031
+ <NotificationContainer {...defaultProps} selectedOS={OS_ANDROID_MOBILE} selectedBrowser={BROWSER_CHROME} />
1032
+ );
1033
+ expect(wrapper.find('.notification-container').hasClass('android-mobile-chrome')).toBe(true);
1034
+ });
1035
+
1036
+ it('derives browser from 3-part class name for Android Tablet (android-tablet-firefox → parts[2])', () => {
1037
+ const wrapper = mountWithIntl(
1038
+ <NotificationContainer {...defaultProps} selectedOS={OS_ANDROID_TABLET} selectedBrowser={BROWSER_FIREFOX} />
1039
+ );
1040
+ expect(wrapper.find('.notification-container').hasClass('android-tablet-firefox')).toBe(true);
1041
+ });
1042
+ });
1043
+
1044
+ describe('platform.isIOS getter (selectedOS === OS_IOS)', () => {
1045
+ it('is true for iOS — renders IOSHeader', () => {
1046
+ const wrapper = mountWithIntl(
1047
+ <NotificationContainer {...defaultProps} selectedOS={OS_IOS} selectedBrowser={BROWSER_CHROME} />
1048
+ );
1049
+ expect(wrapper.find(IOSHeader).exists()).toBe(true);
1050
+ });
1051
+
1052
+ it('is false for macOS — does not render IOSHeader', () => {
1053
+ const wrapper = mountWithIntl(
1054
+ <NotificationContainer {...defaultProps} selectedOS={OS_MACOS} selectedBrowser={BROWSER_CHROME} />
1055
+ );
1056
+ expect(wrapper.find(IOSHeader).exists()).toBe(false);
1057
+ });
1058
+
1059
+ it('is false for Android Mobile — does not render IOSHeader', () => {
1060
+ const wrapper = mountWithIntl(
1061
+ <NotificationContainer {...defaultProps} selectedOS={OS_ANDROID_MOBILE} selectedBrowser={BROWSER_CHROME} />
1062
+ );
1063
+ expect(wrapper.find(IOSHeader).exists()).toBe(false);
1064
+ });
1065
+
1066
+ it('is false for Windows — does not render IOSHeader', () => {
1067
+ const wrapper = mountWithIntl(
1068
+ <NotificationContainer {...defaultProps} selectedOS={OS_WINDOWS} selectedBrowser={BROWSER_CHROME} />
1069
+ );
1070
+ expect(wrapper.find(IOSHeader).exists()).toBe(false);
1071
+ });
1072
+ });
1073
+
1074
+ describe('platform.isIPadOS getter (selectedOS === OS_IPADOS)', () => {
1075
+ it('is true for iPadOS — renders IOSHeader', () => {
1076
+ const wrapper = mountWithIntl(
1077
+ <NotificationContainer {...defaultProps} selectedOS={OS_IPADOS} selectedBrowser={BROWSER_CHROME} />
1078
+ );
1079
+ expect(wrapper.find(IOSHeader).exists()).toBe(true);
1080
+ });
1081
+
1082
+ it('is false for Android Tablet — does not render IOSHeader', () => {
1083
+ const wrapper = mountWithIntl(
1084
+ <NotificationContainer {...defaultProps} selectedOS={OS_ANDROID_TABLET} selectedBrowser={BROWSER_CHROME} />
1085
+ );
1086
+ expect(wrapper.find(IOSHeader).exists()).toBe(false);
1087
+ expect(wrapper.find(AndroidMobileChromeHeader).exists()).toBe(true);
1088
+ });
1089
+
1090
+ it('is false for Windows — does not render IOSHeader', () => {
1091
+ const wrapper = mountWithIntl(
1092
+ <NotificationContainer {...defaultProps} selectedOS={OS_WINDOWS} selectedBrowser={BROWSER_CHROME} />
1093
+ );
1094
+ expect(wrapper.find(IOSHeader).exists()).toBe(false);
1095
+ });
1096
+
1097
+ it('is false for macOS — does not render IOSHeader', () => {
1098
+ const wrapper = mountWithIntl(
1099
+ <NotificationContainer {...defaultProps} selectedOS={OS_MACOS} selectedBrowser={BROWSER_SAFARI} />
1100
+ );
1101
+ expect(wrapper.find(IOSHeader).exists()).toBe(false);
1102
+ });
1103
+ });
1104
+
1105
+ describe('platform.isMacOsBrandIconBrowser getter (isMacOs && supportsBrandIcon)', () => {
1106
+ it('is true for macOS + Chrome (Chrome is in BRAND_ICON_SUPPORTED_BROWSERS) — shows brand icon in expanded', () => {
1107
+ const wrapper = mountWithIntl(
1108
+ <NotificationContainer
1109
+ {...defaultProps}
1110
+ selectedOS={OS_MACOS}
1111
+ selectedBrowser={BROWSER_CHROME}
1112
+ notificationState={NOTIFICATION_STATE_EXPANDED}
1113
+ brandIcon="brand.png"
1114
+ enableBrandIconPreview={true}
1115
+ />
1116
+ );
1117
+ expect(wrapper.find(NotificationExpandedContent).prop('shouldShowBrandIconInExpandedMac')).toBe(true);
1118
+ });
1119
+
1120
+ it('is true for macOS + Edge (Edge is in BRAND_ICON_SUPPORTED_BROWSERS)', () => {
1121
+ const wrapper = mountWithIntl(
1122
+ <NotificationContainer
1123
+ {...defaultProps}
1124
+ selectedOS={OS_MACOS}
1125
+ selectedBrowser={BROWSER_EDGE}
1126
+ notificationState={NOTIFICATION_STATE_EXPANDED}
1127
+ brandIcon="brand.png"
1128
+ enableBrandIconPreview={true}
1129
+ />
1130
+ );
1131
+ expect(wrapper.find(NotificationExpandedContent).prop('shouldShowBrandIconInExpandedMac')).toBe(true);
1132
+ });
1133
+
1134
+ it('is true for macOS + Opera (Opera is in BRAND_ICON_SUPPORTED_BROWSERS)', () => {
1135
+ const wrapper = mountWithIntl(
1136
+ <NotificationContainer
1137
+ {...defaultProps}
1138
+ selectedOS={OS_MACOS}
1139
+ selectedBrowser={BROWSER_OPERA}
1140
+ notificationState={NOTIFICATION_STATE_EXPANDED}
1141
+ brandIcon="brand.png"
1142
+ enableBrandIconPreview={true}
1143
+ />
1144
+ );
1145
+ expect(wrapper.find(NotificationExpandedContent).prop('shouldShowBrandIconInExpandedMac')).toBe(true);
1146
+ });
1147
+
1148
+ it('is false for macOS + Safari (Safari is NOT in BRAND_ICON_SUPPORTED_BROWSERS)', () => {
1149
+ const wrapper = mountWithIntl(
1150
+ <NotificationContainer
1151
+ {...defaultProps}
1152
+ selectedOS={OS_MACOS}
1153
+ selectedBrowser={BROWSER_SAFARI}
1154
+ notificationState={NOTIFICATION_STATE_EXPANDED}
1155
+ brandIcon="brand.png"
1156
+ enableBrandIconPreview={true}
1157
+ />
1158
+ );
1159
+ expect(wrapper.find(NotificationExpandedContent).prop('shouldShowBrandIconInExpandedMac')).toBe(false);
1160
+ });
1161
+
1162
+ it('is false for Windows + Chrome (not macOS) — renders WindowsChromeExpanded instead', () => {
1163
+ const wrapper = mountWithIntl(
1164
+ <NotificationContainer
1165
+ {...defaultProps}
1166
+ selectedOS={OS_WINDOWS}
1167
+ selectedBrowser={BROWSER_CHROME}
1168
+ notificationState={NOTIFICATION_STATE_EXPANDED}
1169
+ brandIcon="brand.png"
1170
+ enableBrandIconPreview={true}
1171
+ />
1172
+ );
1173
+ expect(wrapper.find(NotificationExpandedContent).exists()).toBe(false);
1174
+ expect(wrapper.find(WindowsChromeExpanded).exists()).toBe(true);
1175
+ });
1176
+
1177
+ it('is false for macOS + Chrome when brandIcon is empty', () => {
1178
+ const wrapper = mountWithIntl(
1179
+ <NotificationContainer
1180
+ {...defaultProps}
1181
+ selectedOS={OS_MACOS}
1182
+ selectedBrowser={BROWSER_CHROME}
1183
+ notificationState={NOTIFICATION_STATE_EXPANDED}
1184
+ brandIcon=""
1185
+ enableBrandIconPreview={true}
1186
+ />
1187
+ );
1188
+ expect(wrapper.find(NotificationExpandedContent).prop('shouldShowBrandIconInExpandedMac')).toBe(false);
1189
+ });
1190
+ });
1191
+
1192
+ describe('shouldRenderSeparateIOSCTAs behavior', () => {
1193
+ const iosCollapsedWithCTAs = {
1194
+ ...defaultProps,
1195
+ selectedOS: OS_IOS,
1196
+ selectedBrowser: BROWSER_CHROME,
1197
+ notificationState: NOTIFICATION_STATE_COLLAPSED,
1198
+ showSeparateIOSCTAs: true,
1199
+ enableCtas: true,
1200
+ buttons: [{ text: 'Accept' }, { text: 'Dismiss' }],
1201
+ };
1202
+
1203
+ it('renders ios-notification-wrapper when all conditions are satisfied', () => {
1204
+ const wrapper = mountWithIntl(<NotificationContainer {...iosCollapsedWithCTAs} />);
1205
+ expect(wrapper.find('.ios-notification-wrapper').exists()).toBe(true);
1206
+ });
1207
+
1208
+ it('renders ios-cta-container inside the wrapper', () => {
1209
+ const wrapper = mountWithIntl(<NotificationContainer {...iosCollapsedWithCTAs} />);
1210
+ expect(wrapper.find('.ios-cta-container').exists()).toBe(true);
1211
+ });
1212
+
1213
+ it('renders one ios-cta-button per button', () => {
1214
+ const wrapper = mountWithIntl(<NotificationContainer {...iosCollapsedWithCTAs} />);
1215
+ expect(wrapper.find('.ios-cta-button').length).toBe(2);
1216
+ });
1217
+
1218
+ it('renders the correct button label text', () => {
1219
+ const wrapper = mountWithIntl(
1220
+ <NotificationContainer
1221
+ {...iosCollapsedWithCTAs}
1222
+ buttons={[{ text: 'Confirm' }]}
1223
+ />
1224
+ );
1225
+ expect(wrapper.find('.ios-cta-button').first().text()).toBe('Confirm');
1226
+ });
1227
+
1228
+ it('still renders the notification-container inside the wrapper', () => {
1229
+ const wrapper = mountWithIntl(<NotificationContainer {...iosCollapsedWithCTAs} />);
1230
+ const iosWrapper = wrapper.find('.ios-notification-wrapper');
1231
+ expect(iosWrapper.find('.notification-container').exists()).toBe(true);
1232
+ });
1233
+
1234
+ it('does NOT render ios-notification-wrapper when showSeparateIOSCTAs is false', () => {
1235
+ const wrapper = mountWithIntl(
1236
+ <NotificationContainer {...iosCollapsedWithCTAs} showSeparateIOSCTAs={false} />
1237
+ );
1238
+ expect(wrapper.find('.ios-notification-wrapper').exists()).toBe(false);
1239
+ });
1240
+
1241
+ it('does NOT render ios-notification-wrapper when expanded (isExpanded is true)', () => {
1242
+ const wrapper = mountWithIntl(
1243
+ <NotificationContainer
1244
+ {...iosCollapsedWithCTAs}
1245
+ notificationState={NOTIFICATION_STATE_EXPANDED}
1246
+ supportsExpanded={true}
1247
+ />
1248
+ );
1249
+ expect(wrapper.find('.ios-notification-wrapper').exists()).toBe(false);
1250
+ });
1251
+
1252
+ it('does NOT render ios-notification-wrapper when enableCtas is false', () => {
1253
+ const wrapper = mountWithIntl(
1254
+ <NotificationContainer {...iosCollapsedWithCTAs} enableCtas={false} />
1255
+ );
1256
+ expect(wrapper.find('.ios-notification-wrapper').exists()).toBe(false);
1257
+ });
1258
+
1259
+ it('does NOT render ios-notification-wrapper when buttons array is empty', () => {
1260
+ const wrapper = mountWithIntl(
1261
+ <NotificationContainer {...iosCollapsedWithCTAs} buttons={[]} />
1262
+ );
1263
+ expect(wrapper.find('.ios-notification-wrapper').exists()).toBe(false);
1264
+ });
1265
+
1266
+ it('does NOT render ios-notification-wrapper for iPadOS (not an iOS browser)', () => {
1267
+ const wrapper = mountWithIntl(
1268
+ <NotificationContainer {...iosCollapsedWithCTAs} selectedOS={OS_IPADOS} />
1269
+ );
1270
+ expect(wrapper.find('.ios-notification-wrapper').exists()).toBe(false);
1271
+ });
1272
+
1273
+ it('does NOT render ios-notification-wrapper for macOS', () => {
1274
+ const wrapper = mountWithIntl(
1275
+ <NotificationContainer {...iosCollapsedWithCTAs} selectedOS={OS_MACOS} />
1276
+ );
1277
+ expect(wrapper.find('.ios-notification-wrapper').exists()).toBe(false);
1278
+ });
1279
+
1280
+ it('does NOT render ios-notification-wrapper for Android Mobile', () => {
1281
+ const wrapper = mountWithIntl(
1282
+ <NotificationContainer {...iosCollapsedWithCTAs} selectedOS={OS_ANDROID_MOBILE} />
1283
+ );
1284
+ expect(wrapper.find('.ios-notification-wrapper').exists()).toBe(false);
1285
+ });
1286
+ });
1287
+
1019
1288
  describe('Snapshot Tests', () => {
1020
1289
  it('should match snapshot for macOS Chrome collapsed', () => {
1021
1290
  const wrapper = shallowWithIntl(
@@ -1,6 +1,7 @@
1
1
  import { isValidHttpUrl } from './urlValidation';
2
2
  import { validateTags } from '../../../../utils/tagValidations';
3
3
  import globalMessages from '../../../Cap/messages';
4
+ import { hasPersonalizationTags } from '../../../../utils/commonUtils';
4
5
 
5
6
  /**
6
7
  * Validates template name (checks if empty)
@@ -10,16 +11,34 @@ import globalMessages from '../../../Cap/messages';
10
11
  export const validateTemplateName = (value) => !value || value.trim() === '';
11
12
 
12
13
  /**
13
- * Validates notification title
14
+ * Validates notification title (required and optional tag validation)
14
15
  * @param {string} value - The title value
15
16
  * @param {Function} formatMessage - i18n format message function
16
17
  * @param {Object} messages - Message definitions
18
+ * @param {Object} [validationConfig] - Optional config for tag validation
19
+ * @param {boolean} [isFullMode] - Optional; when set with validationConfig, runs tag validation
17
20
  * @returns {string} Error message if invalid, empty string if valid
18
21
  */
19
- export const validateTitle = (value, formatMessage, messages) => {
22
+ export const validateTitle = (value, formatMessage, messages, restrictPersonalization, validationConfig, isFullMode) => {
20
23
  if (!value || value.trim() === '') {
21
24
  return formatMessage(messages.titleRequired);
22
25
  }
26
+ if (restrictPersonalization && hasPersonalizationTags(value)) {
27
+ return formatMessage(messages.personalizationTokensErrorMessage);
28
+ }
29
+
30
+ if (validationConfig != null) {
31
+ const validationResponse = validateTags({
32
+ content: value,
33
+ ...validationConfig,
34
+ isFullMode,
35
+ }) || {};
36
+
37
+ if (validationResponse?.isBraceError) {
38
+ return formatMessage(globalMessages.unbalanacedCurlyBraces);
39
+ }
40
+ }
41
+
23
42
  return '';
24
43
  };
25
44
 
@@ -34,11 +53,11 @@ export const validateUrl = (value, formatMessage, messages) => {
34
53
  if (!value || value.trim() === '') {
35
54
  return formatMessage(messages.urlRequired);
36
55
  }
37
-
56
+
38
57
  if (!isValidHttpUrl(value)) {
39
58
  return formatMessage(messages.urlInvalid);
40
59
  }
41
-
60
+
42
61
  return '';
43
62
  };
44
63
 
@@ -50,27 +69,24 @@ export const validateUrl = (value, formatMessage, messages) => {
50
69
  * @param {Object} validationConfig - Configuration for tag validation
51
70
  * @returns {string} Error message if invalid, empty string if valid
52
71
  */
53
- export const validateMessageContent = (value, formatMessage, messages, validationConfig, isFullMode) => {
72
+ export const validateMessageContent = (value, formatMessage, messages, validationConfig, isFullMode, restrictPersonalization) => {
54
73
  if (!value || value.trim() === '') {
55
74
  return formatMessage(messages.messageRequired);
56
75
  }
57
-
76
+
58
77
  const validationResponse = validateTags({
59
78
  content: value,
60
79
  ...validationConfig,
61
80
  isFullMode,
62
81
  }) || {};
63
-
64
- if (validationResponse?.unsupportedTags?.length) {
65
- return formatMessage(globalMessages.unsupportedTagsValidationError, {
66
- unsupportedTags: validationResponse.unsupportedTags.join(', '),
67
- });
68
- }
69
-
82
+
70
83
  if (validationResponse?.isBraceError) {
71
84
  return formatMessage(globalMessages.unbalanacedCurlyBraces);
72
85
  }
73
-
86
+
87
+ if (restrictPersonalization && hasPersonalizationTags(value)) {
88
+ return formatMessage(messages.personalizationTokensErrorMessage);
89
+ }
90
+
74
91
  return '';
75
92
  };
76
-