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
@@ -50,9 +50,7 @@ import injectReducer from '../../utils/injectReducer';
50
50
  import v2InAppReducer from '../InApp/reducer';
51
51
  import { v2InAppSagas } from '../InApp/sagas';
52
52
  import injectSaga from '../../utils/injectSaga';
53
- import { validateTags } from "../../utils/tagValidations";
54
53
  import { validateInAppContent } from "../../utils/commonUtils";
55
- import { hasLiquidSupportFeature } from "../../utils/common";
56
54
  import formBuilderMessages from "../../v2Components/FormBuilder/messages";
57
55
  import { getSingleTab, hasAnyErrors } from "../InApp/utils";
58
56
  import ErrorInfoNote from "../../v2Components/ErrorInfoNote";
@@ -818,23 +816,18 @@ export const InappAdvanced = (props) => {
818
816
  const payload = createPayload(latestHtmlValues);
819
817
 
820
818
  // Validate the INAPP content
821
- const isLiquidFlow = hasLiquidSupportFeature();
822
819
  // Skip validation if no tags are available (e.g., in tests or when tags haven't loaded)
823
820
  const hasTags = tags && tags.length > 0;
824
- if (isLiquidFlow && hasTags) {
825
- validateInAppContent(payload, {
821
+
822
+ if (!isFullMode || hasTags) {
823
+ await validateInAppContent(payload, {
826
824
  currentTab: panes === ANDROID ? 1 : 2, // Convert ANDROID/IOS to tab numbers
827
825
  onError,
828
826
  onSuccess,
829
827
  getLiquidTags: (content, callback) => globalActions.getLiquidTags(content, callback),
830
828
  formatMessage,
831
829
  messages: formBuilderMessages,
832
- tagLookupMap: metaEntities?.tagLookupMap || {},
833
- eventContextTags: metaEntities?.eventContextTags || [],
834
- isLiquidFlow,
835
- forwardedTags: {},
836
830
  skipTags: (tag) => {
837
- // Skip certain tags if needed
838
831
  const skipRegexes = [
839
832
  /dynamic_expiry_date_after_\d+_days\.FORMAT_\d/,
840
833
  /unsubscribe\(#[a-zA-Z\d]{6}\)/,
@@ -842,96 +835,12 @@ export const InappAdvanced = (props) => {
842
835
  /SURVEY.*\.TOKEN/,
843
836
  /^[A-Za-z].*\([a-zA-Z\d]*\)/,
844
837
  ];
845
-
846
838
  return skipRegexes.some((regex) => regex.test(tag));
847
839
  },
848
840
  singleTab: getSingleTab(accountData),
849
841
  });
850
- } else if (hasTags) {
851
- // For non-liquid flow, validate tags using validateTags (only if tags are available)
852
- const androidContent = latestHtmlValues?.android || (androidBeeHtml?.value || (typeof androidBeeHtml === 'string' ? androidBeeHtml : ''));
853
- const iosContent = latestHtmlValues?.ios || (iosBeeHtml?.value || (typeof iosBeeHtml === 'string' ? iosBeeHtml : ''));
854
-
855
- const androidSupported = get(accountData, 'selectedWeChatAccount.configs.android') === DEVICE_SUPPORTED || get(editContent, 'ANDROID.deviceType') === ANDROID;
856
- const iosSupported = get(accountData, 'selectedWeChatAccount.configs.ios') === DEVICE_SUPPORTED || get(editContent, 'IOS.deviceType') === IOS_CAPITAL;
857
-
858
- let hasErrors = false;
859
- const newErrors = {
860
- STANDARD_ERROR_MSG: {
861
- ANDROID: [],
862
- IOS: [],
863
- GENERIC: [],
864
- },
865
- LIQUID_ERROR_MSG: {
866
- ANDROID: [],
867
- IOS: [],
868
- GENERIC: [],
869
- },
870
- };
871
-
872
- // Validate Android content
873
- if (androidSupported && androidContent && androidContent?.trim() !== '') {
874
- const validationResponse = validateTags({
875
- content: androidContent,
876
- tagsParam: tags,
877
- injectedTagsParams: injectedTags || {},
878
- location,
879
- tagModule: getDefaultTags,
880
- eventContextTags: metaEntities?.eventContextTags || [],
881
- }) || {};
882
-
883
- if (validationResponse?.unsupportedTags?.length > 0) {
884
- hasErrors = true;
885
- newErrors.LIQUID_ERROR_MSG.ANDROID.push(
886
- formatMessage(globalMessages.unsupportedTagsValidationError, {
887
- unsupportedTags: validationResponse.unsupportedTags.join(", "),
888
- })
889
- );
890
- }
891
- if (validationResponse?.isBraceError) {
892
- hasErrors = true;
893
- newErrors.LIQUID_ERROR_MSG.ANDROID.push(
894
- formatMessage(globalMessages.unbalanacedCurlyBraces)
895
- );
896
- }
897
- }
898
-
899
- // Validate iOS content
900
- if (iosSupported && iosContent && iosContent?.trim() !== '') {
901
- const validationResponse = validateTags({
902
- content: iosContent,
903
- tagsParam: tags,
904
- injectedTagsParams: injectedTags || {},
905
- location,
906
- tagModule: getDefaultTags,
907
- eventContextTags: metaEntities?.eventContextTags || [],
908
- }) || {};
909
-
910
- if (validationResponse?.unsupportedTags?.length > 0) {
911
- hasErrors = true;
912
- newErrors.LIQUID_ERROR_MSG.IOS.push(
913
- formatMessage(globalMessages.unsupportedTagsValidationError, {
914
- unsupportedTags: validationResponse.unsupportedTags.join(", "),
915
- })
916
- );
917
- }
918
- if (validationResponse?.isBraceError) {
919
- hasErrors = true;
920
- newErrors.LIQUID_ERROR_MSG.IOS.push(
921
- formatMessage(globalMessages.unbalanacedCurlyBraces)
922
- );
923
- }
924
- }
925
-
926
- if (hasErrors) {
927
- setErrorMessage(newErrors);
928
- } else {
929
- // No errors, proceed with submission
930
- onSuccess();
931
- }
932
842
  } else {
933
- // No tags available, skip validation and proceed directly
934
- onSuccess();
843
+ await onSuccess();
935
844
  }
936
845
  };
937
846
 
@@ -1036,15 +945,7 @@ export const InappAdvanced = (props) => {
1036
945
  )}
1037
946
  <CapButton
1038
947
  onClick={async () => {
1039
- const isLiquidFlow = hasLiquidSupportFeature();
1040
- const hasTags = tags && tags?.length > 0;
1041
- if (isLiquidFlow || hasTags) {
1042
- // Use validation middleware for tag validation
1043
- await liquidMiddleWare();
1044
- } else {
1045
- // No validation needed, proceed directly
1046
- await onDoneCallback();
1047
- }
948
+ await liquidMiddleWare();
1048
949
  }}
1049
950
  disabled={isDisableDone()}
1050
951
  className="inapp-create-btn"
@@ -61,6 +61,7 @@ describe('InappAdvanced Component', () => {
61
61
 
62
62
  const mockGlobalActions = {
63
63
  fetchSchemaForEntity: jest.fn(),
64
+ getLiquidTags: jest.fn((content, callback) => callback({ askAiraResponse: { data: [] }, isError: false })),
64
65
  };
65
66
 
66
67
  defaultProps = {
@@ -409,6 +410,7 @@ describe('InappAdvanced Component', () => {
409
410
  actions: mockActions,
410
411
  globalActions: {
411
412
  fetchSchemaForEntity: jest.fn(),
413
+ getLiquidTags: jest.fn((content, callback) => callback({ askAiraResponse: { data: [] }, isError: false })),
412
414
  },
413
415
  location: {
414
416
  pathname: '/inapp/create',
@@ -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,7 +137,6 @@ export const LineText = ({
137
137
  const { valid, isBraceError } = validateTags({
138
138
  content: value,
139
139
  tagsParam: tags,
140
- injectedTagsParams: injectedTags,
141
140
  location,
142
141
  tagModule: 'outbound',
143
142
  isFullMode,
@@ -38,6 +38,8 @@ 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, validateMobilePushContent } from '../../../utils/commonUtils';
42
+ import formBuilderMessages from '../../../v2Components/FormBuilder/messages';
41
43
 
42
44
  const PrefixWrapper = styled.div`
43
45
  margin-right: 16px;
@@ -63,6 +65,8 @@ export class Create extends React.Component { // eslint-disable-line react/prefe
63
65
  injectedTags: {},
64
66
  };
65
67
  }
68
+ this.hasFetchedInitialTagsRef = false;
69
+ this.lastFetchedTagContextRef = null;
66
70
  }
67
71
  componentWillMount = () => {
68
72
  if (this.props.route.name === 'view') {
@@ -91,8 +95,56 @@ export class Create extends React.Component { // eslint-disable-line react/prefe
91
95
  this.props.globalActions.fetchSchemaForEntity(query);
92
96
  };
93
97
  componentWillReceiveProps = (nextProps) => {
94
- if (nextProps.isGetFormData && !this.props.isFullMode) {
95
- nextProps.getFormLibraryData(this.getFormData());
98
+ // Library mode: on Done click (transition to isGetFormData), run extractTags only when no existing validation errors (braces, personalization, etc.)
99
+ if (nextProps.isGetFormData && !this.props.isGetFormData && !nextProps.isFullMode) {
100
+ // If form already has validation errors (braces, personalization tags, etc.), do not call extractTags or return payload; always return early
101
+ if (!this.state.isFormValid) {
102
+ if (typeof nextProps.onValidationFail === 'function') {
103
+ nextProps.onValidationFail();
104
+ }
105
+ return;
106
+ }
107
+ const hasAllValidationCallbacks =
108
+ typeof nextProps.getLiquidTags === 'function' &&
109
+ typeof nextProps.showLiquidErrorInFooter === 'function' &&
110
+ typeof nextProps.onValidationFail === 'function';
111
+
112
+ if (hasAllValidationCallbacks) {
113
+ const formDataArr = [this.state.formData?.[0], this.state.formData?.[1]];
114
+ validateMobilePushContent(formDataArr, {
115
+ currentTab: this.state.currentTab,
116
+ getLiquidTags: nextProps.getLiquidTags,
117
+ formatMessage: this.props.intl.formatMessage,
118
+ messages: formBuilderMessages,
119
+ onError: (err) => {
120
+ const { standardErrors = [], liquidErrors = [] } = err;
121
+ // _validatePlatformSpecificContent passes { standardErrors: { ANDROID, IOS, generic }, liquidErrors: { ... } }; footer expects arrays
122
+ const toArray = (v) => (Array.isArray(v) ? v : (v && typeof v === 'object' ? [].concat(...Object.values(v)) : []));
123
+ const STANDARD_ERROR_MSG = toArray(standardErrors);
124
+ const LIQUID_ERROR_MSG = toArray(liquidErrors);
125
+ if (typeof nextProps.showLiquidErrorInFooter === 'function') {
126
+ nextProps.showLiquidErrorInFooter(
127
+ { STANDARD_ERROR_MSG, LIQUID_ERROR_MSG },
128
+ this.state.currentTab
129
+ );
130
+ }
131
+ // Only trigger onValidationFail when there are actual errors; skip when helper called onError with empty arrays (reset case)
132
+ if ((STANDARD_ERROR_MSG.length > 0 || LIQUID_ERROR_MSG.length > 0) && typeof nextProps.onValidationFail === 'function') {
133
+ nextProps.onValidationFail();
134
+ }
135
+ },
136
+ onSuccess: () => {
137
+ if (this.state.isFormValid && typeof nextProps.getFormLibraryData === 'function') {
138
+ nextProps.getFormLibraryData(this.getFormData());
139
+ }
140
+ },
141
+ });
142
+ } else {
143
+ // Fail closed: require full validation callback set; treat any missing callback as validation failure
144
+ if (typeof nextProps.onValidationFail === 'function') {
145
+ nextProps.onValidationFail();
146
+ }
147
+ }
96
148
  } else if (nextProps.isGetFormData && this.props.isGetFormData !== nextProps.isGetFormData && this.props.isFullMode && !this.props.Create.createTemplateInProgress) {
97
149
  this.startValidation();
98
150
  }
@@ -132,16 +184,19 @@ export class Create extends React.Component { // eslint-disable-line react/prefe
132
184
  }
133
185
  schema.standalone.sections.splice(1, 1);
134
186
  this.injectEvents(schema);
135
- const query = {
136
- layout: 'mobilepush',
137
- type: 'TAG',
138
- context: this.props.location.query.type === 'embedded' ? this.props.location.query.module : 'default',
139
- embedded: this.props.location.query.type === 'embedded' ? this.props.location.query.type : 'full',
140
- };
141
- if (this.props.getDefaultTags) {
142
- query.context = this.props.getDefaultTags;
187
+ if (!this.hasFetchedInitialTagsRef) {
188
+ this.hasFetchedInitialTagsRef = true;
189
+ const context = this.props.getDefaultTags
190
+ || (this.props.location.query.type === 'embedded' ? this.props.location.query.module : 'default');
191
+ this.lastFetchedTagContextRef = typeof context === 'string' ? context.toLowerCase() : context;
192
+ const query = {
193
+ layout: 'mobilepush',
194
+ type: 'TAG',
195
+ context: this.lastFetchedTagContextRef,
196
+ embedded: this.props.location.query.type === 'embedded' ? this.props.location.query.type : 'full',
197
+ };
198
+ this.props.globalActions.fetchSchemaForEntity(query);
143
199
  }
144
- this.props.globalActions.fetchSchemaForEntity(query);
145
200
  }
146
201
  };
147
202
  componentWillUnmount = () => {
@@ -156,6 +211,15 @@ export class Create extends React.Component { // eslint-disable-line react/prefe
156
211
  const newFormData = cloneDeep(formData);
157
212
  const {templateCta} = this.state;
158
213
  const { defaultData = {}, isFullMode, showTemplateName} = this.props;
214
+
215
+ // Check for personalization tokens if restriction is enabled and notify parent
216
+ if (this.props.restrictPersonalization) {
217
+ const hasTokens = checkForPersonalizationTokens(newFormData);
218
+ if (this.props.onPersonalizationTokensChange) {
219
+ this.props.onPersonalizationTokensChange(hasTokens);
220
+ }
221
+ }
222
+
159
223
  if (!isEmpty(templateCta)) {
160
224
  newFormData[this.state.currentTab - 1][`secondary-cta-${this.state.currentTab - 1}-label`] = get(templateCta, 'name');
161
225
  newFormData[this.state.currentTab - 1][`secondary-cta-${this.state.currentTab - 1}-action`] = get(templateCta, 'ctaTemplateDetails[0].buttonText');
@@ -663,31 +727,21 @@ export class Create extends React.Component { // eslint-disable-line react/prefe
663
727
  }
664
728
  showError = () => {
665
729
  const {intl} = this.props;
666
- const {errorData} = this.state;
730
+ const {errorData, schema} = this.state;
667
731
  const errorMessage = {key: 'validation-error', message: intl.formatMessage(messages.validationError)};
668
732
  if (!isEmpty(this.state.formData) && !this.state.isFormValid) {
669
733
  let tab = this.state.currentTab;
670
- const isAndroidInvalid = Object.values(errorData[0]).includes(true);
671
- const isIosInvalid = Object.values(errorData[1]).includes(true);
672
- let isTagErrorExist = false;
734
+ const isAndroidInvalid = Object.values(errorData[0] || {}).includes(true);
735
+ const isIosInvalid = Object.values(errorData[1] || {}).includes(true);
736
+ const isIosTabVisible = get(schema, 'containers[0].panes[1].isSupported', true) !== false;
673
737
  if (isAndroidInvalid) {
674
738
  tab = 1;
675
739
  errorMessage.description = intl.formatMessage(messages.invalidAndroidMessage);
676
- const invalidTags = errorData[0]['invalid-tags'];
677
- if (!isEmpty(invalidTags)) {
678
- isTagErrorExist = true;
679
- errorMessage.description = `${intl.formatMessage(messages.invalidAndroidMessage)} ${intl.formatMessage(messages.invalidTags)}: ${invalidTags.join(',')} `;
680
- }
681
- } else if (isIosInvalid) {
740
+ } else if (isIosInvalid && isIosTabVisible) {
682
741
  tab = 2;
683
742
  errorMessage.description = intl.formatMessage(messages.invalidIosMessage);
684
- const invalidTags = errorData[1]['invalid-tags'];
685
- if (!isEmpty(invalidTags)) {
686
- isTagErrorExist = true;
687
- errorMessage.description = `${intl.formatMessage(messages.invalidIosMessage)} ${intl.formatMessage(messages.invalidTags)}: ${invalidTags.join(',')} `;
688
- }
689
743
  }
690
- if (tab !== this.state.currentTab || isTagErrorExist) {
744
+ if (tab !== this.state.currentTab) {
691
745
  CapNotification.error(errorMessage);
692
746
  }
693
747
  }
@@ -1499,6 +1553,17 @@ export class Create extends React.Component { // eslint-disable-line react/prefe
1499
1553
 
1500
1554
  saveFormData = (formData) => {
1501
1555
  //this function gets called from form bulder only when the form data is valid
1556
+
1557
+ // Check for personalization tokens if restriction is enabled
1558
+ if (this.props.restrictPersonalization) {
1559
+ const hasTokens = checkForPersonalizationTokens(formData);
1560
+ if (hasTokens) {
1561
+ const message = this.props.intl.formatMessage(messages.personalizationTokensErrorMessage);
1562
+ CapNotification.error({message, key: 'personalizationTokensError'});
1563
+ return;
1564
+ }
1565
+ }
1566
+
1502
1567
  const obj = this.getTransformedData(formData);
1503
1568
  const content = getContent(obj);
1504
1569
  const {
@@ -1771,10 +1836,15 @@ export class Create extends React.Component { // eslint-disable-line react/prefe
1771
1836
  this.injectEvents(schema);
1772
1837
  };
1773
1838
  handleOnTagsContextChange = (data) => {
1839
+ const context = (data || '').toLowerCase() === 'all' ? 'default' : (data || '').toLowerCase();
1840
+ if (this.lastFetchedTagContextRef === context) {
1841
+ return;
1842
+ }
1843
+ this.lastFetchedTagContextRef = context;
1774
1844
  const query = {
1775
1845
  layout: 'mobilepush',
1776
1846
  type: 'TAG',
1777
- context: (data || '').toLowerCase() === 'all' ? 'default' : (data || '').toLowerCase(),
1847
+ context,
1778
1848
  embedded: this.props.location.query.type === 'embedded' ? this.props.location.query.type : 'full',
1779
1849
  };
1780
1850
  this.props.globalActions.fetchSchemaForEntity(query);
@@ -1896,7 +1966,9 @@ export class Create extends React.Component { // eslint-disable-line react/prefe
1896
1966
  hideTestAndPreviewBtn={this.props.hideTestAndPreviewBtn}
1897
1967
  isFullMode={this.props.isFullMode}
1898
1968
  eventContextTags={this.props?.eventContextTags}
1969
+ waitEventContextTags={this.props?.waitEventContextTags}
1899
1970
  messageDetails={this.props?.messageDetails}
1971
+ restrictPersonalization={this.props.restrictPersonalization}
1900
1972
  />
1901
1973
  </CapColumn>
1902
1974
  {this.props.iosCtasData && this.state.showIosCtaTable &&
@@ -1997,10 +2069,15 @@ Create.propTypes = {
1997
2069
  onPreviewContentClicked: PropTypes.func,
1998
2070
  onTestContentClicked: PropTypes.func,
1999
2071
  eventContextTags: PropTypes.array,
2072
+ waitEventContextTags: PropTypes.object,
2073
+ getLiquidTags: PropTypes.func,
2000
2074
  showLiquidErrorInFooter: PropTypes.func,
2001
2075
  showTestAndPreviewSlidebox: PropTypes.bool,
2002
2076
  handleTestAndPreview: PropTypes.func,
2003
2077
  handleCloseTestAndPreview: PropTypes.func,
2078
+ restrictPersonalization: PropTypes.bool,
2079
+ isAnonymousType: PropTypes.bool,
2080
+ onPersonalizationTokensChange: PropTypes.func,
2004
2081
  };
2005
2082
 
2006
2083
  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
  });