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
@@ -14,6 +14,8 @@ import CapRow from "@capillarytech/cap-ui-library/CapRow";
14
14
  import CapColumn from "@capillarytech/cap-ui-library/CapColumn";
15
15
  import CapButton from "@capillarytech/cap-ui-library/CapButton";
16
16
  import CapNotification from "@capillarytech/cap-ui-library/CapNotification";
17
+ import CapTab from "@capillarytech/cap-ui-library/CapTab";
18
+ import CapInput from "@capillarytech/cap-ui-library/CapInput";
17
19
  import { makeSelectInApp, makeSelectAccount, makeSelectGetTemplateDetailsInProgress } from "./selectors";
18
20
  import * as globalActions from '../Cap/actions';
19
21
  import {
@@ -31,7 +33,6 @@ import creativesMessages from '../CreativesContainer/messages';
31
33
  import withCreatives from "../../hoc/withCreatives";
32
34
  import UnifiedPreview from "../../v2Components/CommonTestAndPreview/UnifiedPreview";
33
35
  import TestAndPreviewSlidebox from '../../v2Components/TestAndPreviewSlidebox';
34
- import { validateTags } from "../../utils/tagValidations";
35
36
  import injectReducer from '../../utils/injectReducer';
36
37
  import v2InAppReducer from './reducer';
37
38
  import { v2InAppSagas } from './sagas';
@@ -51,19 +52,22 @@ import {
51
52
  LAYOUT_RADIO_OPTIONS,
52
53
  IOS_CAPITAL,
53
54
  } from "./constants";
54
- import { INAPP, SMS } from "../CreativesContainer/constants";
55
+ import { GENERIC, INAPP, SMS } from "../CreativesContainer/constants";
55
56
  import {
56
57
  ALL, TAG, EMBEDDED, DEFAULT, FULL, LIBRARY,
57
58
  } from "../Whatsapp/constants";
58
59
  import { getCdnUrl } from "../../utils/cdnTransformation";
59
60
  import { getCtaObject, hasAnyErrors, getSingleTab } from "./utils";
60
61
  import { validateInAppContent } from "../../utils/commonUtils";
61
- import { hasLiquidSupportFeature } from "../../utils/common";
62
+ import { validateTags } from "../../utils/tagValidations";
63
+ import { hasNewEditorFlowInAppEnabled, isAiContentBotDisabled } from "../../utils/common";
62
64
  import formBuilderMessages from "../../v2Components/FormBuilder/messages";
63
65
  import HTMLEditor from "../../v2Components/HtmlEditor";
64
66
  import { HTML_EDITOR_VARIANTS } from "../../v2Components/HtmlEditor/constants";
65
67
  import { INAPP_EDITOR_TYPES } from "../InAppWrapper/constants";
66
68
  import InappAdvanced from "../InappAdvance/index";
69
+ import CapDeviceContent from "../../v2Components/CapDeviceContent";
70
+ import capDeviceContentMessages from "../../v2Components/CapDeviceContent/messages";
67
71
  import { ErrorInfoNote } from "../../v2Components/ErrorInfoNote";
68
72
 
69
73
  let editContent = {};
@@ -74,6 +78,7 @@ export const InApp = (props) => {
74
78
  actions,
75
79
  globalActions,
76
80
  isFullMode,
81
+ isLoyaltyModule,
77
82
  onCreateComplete,
78
83
  params,
79
84
  templateData = {},
@@ -878,7 +883,7 @@ export const InApp = (props) => {
878
883
  // Use 'html editor template' as title for HTML editor to differentiate from BEE editor
879
884
  title: isHTMLTemplate ? 'html editor template' : titleAndroid,
880
885
  message: androidMessage,
881
- bodyType: templateLayoutType,
886
+ bodyType: bodyTypeForBackend,
882
887
  expandableDetails: {
883
888
  style: androidExpandableStyle,
884
889
  message: androidMessage,
@@ -1079,39 +1084,55 @@ export const InApp = (props) => {
1079
1084
  };
1080
1085
 
1081
1086
  // Validation middleware for tag validation (both liquid and non-liquid flow)
1087
+ // Liquid validation (extractTags) runs only in library mode
1082
1088
  const validationMiddleWare = async () => {
1083
- // Set up callbacks for validation results
1089
+ // Normalize validator bucket keys to component state keys (ANDROID, IOS_CAPITAL, GENERIC)
1090
+ // so we don't merge e.g. 'android'/'ios'/'generic' with ANDROID/IOS/GENERIC and get duplicate/stale keys
1091
+ const normalizeErrorBuckets = (errors) => {
1092
+ const normalized = {
1093
+ [ANDROID]: [],
1094
+ [IOS_CAPITAL]: [],
1095
+ [GENERIC]: [],
1096
+ };
1097
+ if (!errors || typeof errors !== 'object') return normalized;
1098
+ const keyMap = {
1099
+ ANDROID,
1100
+ android: ANDROID,
1101
+ [IOS_CAPITAL]: IOS_CAPITAL,
1102
+ [IOS]: IOS_CAPITAL,
1103
+ ios: IOS_CAPITAL,
1104
+ GENERIC,
1105
+ generic: GENERIC,
1106
+ };
1107
+ for (const [key, value] of Object.entries(errors)) {
1108
+ const targetKey = keyMap[key];
1109
+ if (targetKey != null && Array.isArray(value)) {
1110
+ normalized[targetKey] = value;
1111
+ }
1112
+ }
1113
+ return normalized;
1114
+ };
1084
1115
  const onError = ({ standardErrors, liquidErrors }) => {
1085
1116
  setErrorMessage((prev) => ({
1086
- STANDARD_ERROR_MSG: { ...prev.STANDARD_ERROR_MSG, ...standardErrors },
1087
- LIQUID_ERROR_MSG: { ...prev.LIQUID_ERROR_MSG, ...liquidErrors },
1117
+ STANDARD_ERROR_MSG: { ...prev.STANDARD_ERROR_MSG, ...normalizeErrorBuckets(standardErrors) },
1118
+ LIQUID_ERROR_MSG: { ...prev.LIQUID_ERROR_MSG, ...normalizeErrorBuckets(liquidErrors) },
1088
1119
  }));
1089
1120
  };
1090
1121
  const onSuccess = () => {
1091
- // Proceed with submission when validation is successful
1092
1122
  onDoneCallback();
1093
1123
  };
1094
1124
 
1095
- // Skip validation if no tags are available (e.g., in tests or when tags haven't loaded)
1096
- const hasTags = tags && tags.length > 0;
1097
-
1098
- // For liquid flow, use validateInAppContent
1099
- if (isLiquidFlow && hasTags) {
1100
- // Validate the INAPP content
1125
+ // Library mode: run extractTags validation (always, so we catch liquid errors even when tags not loaded)
1126
+ if (!isFullMode) {
1101
1127
  const payload = createPayload();
1102
1128
  validateInAppContent(payload, {
1103
- currentTab: panes === ANDROID ? 1 : 2, // Convert ANDROID/IOS to tab numbers
1129
+ currentTab: panes === ANDROID ? 1 : 2,
1104
1130
  onError,
1105
1131
  onSuccess,
1106
1132
  getLiquidTags: (content, callback) => globalActions.getLiquidTags(content, callback),
1107
1133
  formatMessage,
1108
1134
  messages: formBuilderMessages,
1109
- tagLookupMap: metaEntities?.tagLookupMap || {},
1110
- eventContextTags: metaEntities?.eventContextTags || [],
1111
- isLiquidFlow,
1112
- forwardedTags: {},
1113
1135
  skipTags: (tag) => {
1114
- // Skip certain tags if needed
1115
1136
  const skipRegexes = [
1116
1137
  /dynamic_expiry_date_after_\d+_days\.FORMAT_\d/,
1117
1138
  /unsubscribe\(#[a-zA-Z\d]{6}\)/,
@@ -1119,101 +1140,15 @@ export const InApp = (props) => {
1119
1140
  /SURVEY.*\.TOKEN/,
1120
1141
  /^[A-Za-z].*\([a-zA-Z\d]*\)/,
1121
1142
  ];
1122
-
1123
1143
  return skipRegexes.some((regex) => regex.test(tag));
1124
1144
  },
1125
1145
  singleTab: getSingleTab(accountData),
1126
1146
  });
1127
- } else if (hasTags) {
1128
- // For non-liquid flow, validate tags using validateTags (only if tags are available)
1129
- const androidContent = htmlContentAndroid || '';
1130
- const iosContent = htmlContentIos || '';
1131
-
1132
- const androidSupported = get(accountData, 'selectedWeChatAccount.configs.android') === DEVICE_SUPPORTED || get(editContent, 'ANDROID.deviceType') === ANDROID;
1133
- const iosSupported = get(accountData, 'selectedWeChatAccount.configs.ios') === DEVICE_SUPPORTED || get(editContent, 'IOS.deviceType') === IOS_CAPITAL;
1134
-
1135
- let hasErrors = false;
1136
- const newErrors = {
1137
- STANDARD_ERROR_MSG: {
1138
- ANDROID: [],
1139
- IOS: [],
1140
- GENERIC: [],
1141
- },
1142
- LIQUID_ERROR_MSG: {
1143
- ANDROID: [],
1144
- IOS: [],
1145
- GENERIC: [],
1146
- },
1147
- };
1148
-
1149
- // Validate Android content
1150
- if (androidSupported && androidContent && androidContent?.trim() !== '') {
1151
- const validationResponse = validateTags({
1152
- content: androidContent,
1153
- tagsParam: tags,
1154
- injectedTagsParams: injectedTags || {},
1155
- location,
1156
- tagModule: getDefaultTags,
1157
- eventContextTags: metaEntities?.eventContextTags || [],
1158
- }) || {};
1159
-
1160
- if (validationResponse?.unsupportedTags?.length > 0) {
1161
- hasErrors = true;
1162
- newErrors.LIQUID_ERROR_MSG.ANDROID.push(
1163
- formatMessage(globalMessages.unsupportedTagsValidationError, {
1164
- unsupportedTags: validationResponse.unsupportedTags.join(", "),
1165
- })
1166
- );
1167
- }
1168
- if (validationResponse?.isBraceError) {
1169
- hasErrors = true;
1170
- newErrors.LIQUID_ERROR_MSG.ANDROID.push(
1171
- formatMessage(globalMessages.unbalanacedCurlyBraces)
1172
- );
1173
- }
1174
- }
1175
-
1176
- // Validate iOS content
1177
- if (iosSupported && iosContent && iosContent?.trim() !== '') {
1178
- const validationResponse = validateTags({
1179
- content: iosContent,
1180
- tagsParam: tags,
1181
- injectedTagsParams: injectedTags || {},
1182
- location,
1183
- tagModule: getDefaultTags,
1184
- eventContextTags: metaEntities?.eventContextTags || [],
1185
- }) || {};
1186
-
1187
- if (validationResponse?.unsupportedTags?.length > 0) {
1188
- hasErrors = true;
1189
- newErrors.LIQUID_ERROR_MSG.IOS.push(
1190
- formatMessage(globalMessages.unsupportedTagsValidationError, {
1191
- unsupportedTags: validationResponse.unsupportedTags.join(", "),
1192
- })
1193
- );
1194
- }
1195
- if (validationResponse?.isBraceError) {
1196
- hasErrors = true;
1197
- newErrors.LIQUID_ERROR_MSG.IOS.push(
1198
- formatMessage(globalMessages.unbalanacedCurlyBraces)
1199
- );
1200
- }
1201
- }
1202
-
1203
- if (hasErrors) {
1204
- setErrorMessage(newErrors);
1205
- } else {
1206
- // No errors, proceed with submission
1207
- onSuccess();
1208
- }
1209
1147
  } else {
1210
- // No tags available, skip validation and proceed directly
1211
1148
  onSuccess();
1212
1149
  }
1213
1150
  };
1214
1151
 
1215
- const isLiquidFlow = hasLiquidSupportFeature();
1216
-
1217
1152
  // Check template data to determine editor type (for render decision)
1218
1153
  const templateDetails = isFullMode ? editData?.templateDetails : templateData;
1219
1154
  const versions = templateDetails?.versions || {};
@@ -1238,11 +1173,13 @@ export const InApp = (props) => {
1238
1173
  && !isBEEeditor
1239
1174
  && !isBeeFreeTemplate;
1240
1175
 
1176
+ const isNewEditorFlowEnabled = !isLoyaltyModule && hasNewEditorFlowInAppEnabled();
1177
+
1241
1178
  // Use state if available, otherwise fall back to direct data check
1242
- const shouldUseHTMLEditor = isHTMLTemplate || isHTMLTemplateFromData;
1179
+ const shouldUseHTMLEditor = isNewEditorFlowEnabled && (isHTMLTemplate || isHTMLTemplateFromData);
1243
1180
 
1244
1181
  // Only route to Bee editor if it's explicitly a Bee editor AND not an HTML template
1245
- const shouldUseBeeEditor = (isBEEeditor || isBeeFreeTemplate) && !shouldUseHTMLEditor;
1182
+ const shouldUseBeeEditor = isNewEditorFlowEnabled && (isBEEeditor || isBeeFreeTemplate) && !shouldUseHTMLEditor;
1246
1183
 
1247
1184
  // Early returns to avoid nested ternary
1248
1185
  if (isEditInApp && getTemplateDetailsInProgress) {
@@ -1278,10 +1215,222 @@ export const InApp = (props) => {
1278
1215
  );
1279
1216
  }
1280
1217
 
1218
+ // ── Old-flow helpers (used by CapDeviceContent when flag is disabled) ──────
1219
+ const aiContentBotDisabled = isAiContentBotDisabled();
1220
+
1221
+ /**
1222
+ * Clears stored API/liquid errors for a specific device (and GENERIC) so
1223
+ * hasAnyErrors() goes false and Done can be re-clicked after editing.
1224
+ * Does NOT clear errors that belong only to the *other* device.
1225
+ */
1226
+ const clearDeviceErrors = useCallback((platform) => {
1227
+ const key = platform === IOS ? IOS_CAPITAL : ANDROID;
1228
+ setErrorMessage((prev) => ({
1229
+ STANDARD_ERROR_MSG: {
1230
+ ...prev.STANDARD_ERROR_MSG,
1231
+ [key]: [],
1232
+ GENERIC: [],
1233
+ },
1234
+ LIQUID_ERROR_MSG: {
1235
+ ...prev.LIQUID_ERROR_MSG,
1236
+ [key]: [],
1237
+ GENERIC: [],
1238
+ },
1239
+ }));
1240
+ }, [IOS_CAPITAL, ANDROID]);
1241
+
1242
+ const setTitleAndroidWithClear = useCallback((value) => {
1243
+ clearDeviceErrors(ANDROID);
1244
+ setTitleAndroid(value);
1245
+ }, [clearDeviceErrors]);
1246
+
1247
+ const setTitleIosWithClear = useCallback((value) => {
1248
+ clearDeviceErrors(IOS);
1249
+ setTitleIos(value);
1250
+ }, [clearDeviceErrors]);
1251
+
1252
+ const setTemplateMessageAndroidWithClear = useCallback((value) => {
1253
+ clearDeviceErrors(ANDROID);
1254
+ setTemplateMessageAndroid(value);
1255
+ }, [clearDeviceErrors]);
1256
+
1257
+ const setTemplateMessageIosWithClear = useCallback((value) => {
1258
+ clearDeviceErrors(IOS);
1259
+ setTemplateMessageIos(value);
1260
+ }, [clearDeviceErrors]);
1261
+
1262
+ const templateDescErrorHandler = (value) => {
1263
+ const { unsupportedTags, isBraceError } = validateTags({
1264
+ content: value,
1265
+ tagsParam: tags,
1266
+ injectedTagsParams: injectedTags,
1267
+ location,
1268
+ tagModule: getDefaultTags,
1269
+ isFullMode,
1270
+ }) || {};
1271
+ if (unsupportedTags?.length > 0) {
1272
+ return formatMessage(globalMessages.unsupportedTagsValidationError, { unsupportedTags });
1273
+ }
1274
+ if (isBraceError) {
1275
+ return formatMessage(globalMessages.unbalanacedCurlyBraces);
1276
+ }
1277
+ return '';
1278
+ };
1279
+
1280
+ /** Same rules as CapDeviceContent onTitleChange / onTemplateMessageChange */
1281
+ const computeInAppTemplateFieldError = (value) => {
1282
+ let error = templateDescErrorHandler(value);
1283
+ if (value === '') {
1284
+ error = formatMessage(capDeviceContentMessages.emptyTemplateMessageErrorMessage);
1285
+ }
1286
+ return error;
1287
+ };
1288
+
1289
+ const onCopyTitleAndContent = () => {
1290
+ if (panes === ANDROID) {
1291
+ clearDeviceErrors(ANDROID);
1292
+ setTitleAndroid(titleIos);
1293
+ setTemplateMessageAndroid(templateMessageIos);
1294
+ setTemplateTitleErrorAndroid(computeInAppTemplateFieldError(titleIos));
1295
+ setTemplateMessageErrorAndroid(computeInAppTemplateFieldError(templateMessageIos));
1296
+ setInAppImageSrcAndroid(inAppImageSrcIos);
1297
+ } else {
1298
+ clearDeviceErrors(IOS);
1299
+ setTitleIos(titleAndroid);
1300
+ setTemplateMessageIos(templateMessageAndroid);
1301
+ setTemplateTitleErrorIos(computeInAppTemplateFieldError(titleAndroid));
1302
+ setTemplateMessageErrorIos(computeInAppTemplateFieldError(templateMessageAndroid));
1303
+ setInAppImageSrcIos(inAppImageSrcAndroid);
1304
+ }
1305
+ };
1306
+
1307
+ const onTagSelect = (value, index) => {
1308
+ const tag = `{{${value}}}`;
1309
+ if (panes === ANDROID) {
1310
+ clearDeviceErrors(ANDROID);
1311
+ const nextTitle = index === 0 ? titleAndroid + tag : titleAndroid;
1312
+ const nextMessage = index === 0 ? templateMessageAndroid : templateMessageAndroid + tag;
1313
+ if (index === 0) setTitleAndroid(nextTitle);
1314
+ else setTemplateMessageAndroid(nextMessage);
1315
+ setTemplateTitleErrorAndroid(computeInAppTemplateFieldError(nextTitle));
1316
+ setTemplateMessageErrorAndroid(computeInAppTemplateFieldError(nextMessage));
1317
+ } else {
1318
+ clearDeviceErrors(IOS);
1319
+ const nextTitle = index === 0 ? titleIos + tag : titleIos;
1320
+ const nextMessage = index === 0 ? templateMessageIos : templateMessageIos + tag;
1321
+ if (index === 0) setTitleIos(nextTitle);
1322
+ else setTemplateMessageIos(nextMessage);
1323
+ setTemplateTitleErrorIos(computeInAppTemplateFieldError(nextTitle));
1324
+ setTemplateMessageErrorIos(computeInAppTemplateFieldError(nextMessage));
1325
+ }
1326
+ };
1327
+
1328
+ // Device support flags (same derivation as InappAdvance)
1329
+ const isAndroidSupported = get(accountData, 'selectedWeChatAccount.configs.android') === DEVICE_SUPPORTED || get(editContent, 'ANDROID.deviceType') === ANDROID;
1330
+ const isIosSupported = get(accountData, 'selectedWeChatAccount.configs.ios') === DEVICE_SUPPORTED || get(editContent, 'IOS.deviceType') === IOS_CAPITAL;
1331
+
1332
+ // CapDeviceContent tab panes (old flow)
1333
+ const DEVICE_PANES = [
1334
+ {
1335
+ content: (
1336
+ <CapDeviceContent
1337
+ panes={ANDROID}
1338
+ actions={actions}
1339
+ editData={editData}
1340
+ isFullMode={isFullMode}
1341
+ inAppImageSrc={inAppImageSrcAndroid}
1342
+ setInAppImageSrc={setInAppImageSrcAndroid}
1343
+ isEditFlow={isEditFlow}
1344
+ ctaData={ctaDataAndroid}
1345
+ setCtaData={setCtaDataAndroid}
1346
+ buttonType={buttonTypeAndroid}
1347
+ setButtonType={setButtonTypeAndroid}
1348
+ templateMediaType={templateMediaType}
1349
+ setTemplateMediaType={setTemplateMediaType}
1350
+ title={titleAndroid}
1351
+ setTitle={setTitleAndroidWithClear}
1352
+ templateMessageError={templateMessageErrorAndroid}
1353
+ templateMessage={templateMessageAndroid}
1354
+ setTemplateMessage={setTemplateMessageAndroidWithClear}
1355
+ setTemplateMessageError={setTemplateMessageErrorAndroid}
1356
+ addActionLink={addActionLinkAndroid}
1357
+ setAddActionLink={setAddActionLinkAndroid}
1358
+ deepLink={deepLink}
1359
+ deepLinkValue={deepLinkValueAndroid}
1360
+ setDeepLinkValue={setDeepLinkValueAndroid}
1361
+ onCopyTitleAndContent={onCopyTitleAndContent}
1362
+ isOtherDeviceSupported={isIosSupported}
1363
+ tags={tags}
1364
+ onTagSelect={onTagSelect}
1365
+ handleOnTagsContextChange={handleOnTagsContextChange}
1366
+ templateDescErrorHandler={templateDescErrorHandler}
1367
+ templateTitleError={templateTitleErrorAndroid}
1368
+ setTemplateTitleError={setTemplateTitleErrorAndroid}
1369
+ isAiContentBotDisabled={aiContentBotDisabled}
1370
+ injectedTags={injectedTags}
1371
+ selectedOfferDetails={selectedOfferDetails}
1372
+ location={location}
1373
+ />
1374
+ ),
1375
+ tab: <FormattedMessage {...messages.Android} />,
1376
+ key: ANDROID,
1377
+ isSupported: isAndroidSupported,
1378
+ },
1379
+ {
1380
+ content: (
1381
+ <CapDeviceContent
1382
+ panes={IOS}
1383
+ actions={actions}
1384
+ editData={editData}
1385
+ isFullMode={isFullMode}
1386
+ inAppImageSrc={inAppImageSrcIos}
1387
+ setInAppImageSrc={setInAppImageSrcIos}
1388
+ isEditFlow={isEditFlow}
1389
+ ctaData={ctaDataIos}
1390
+ setCtaData={setCtaDataIos}
1391
+ buttonType={buttonTypeIos}
1392
+ setButtonType={setButtonTypeIos}
1393
+ templateMediaType={templateMediaType}
1394
+ setTemplateMediaType={setTemplateMediaType}
1395
+ title={titleIos}
1396
+ setTitle={setTitleIosWithClear}
1397
+ templateMessageError={templateMessageErrorIos}
1398
+ templateMessage={templateMessageIos}
1399
+ setTemplateMessage={setTemplateMessageIosWithClear}
1400
+ setTemplateMessageError={setTemplateMessageErrorIos}
1401
+ addActionLink={addActionLinkIos}
1402
+ setAddActionLink={setAddActionLinkIos}
1403
+ deepLink={deepLink}
1404
+ deepLinkValue={deepLinkValueIos}
1405
+ setDeepLinkValue={setDeepLinkValueIos}
1406
+ onCopyTitleAndContent={onCopyTitleAndContent}
1407
+ isOtherDeviceSupported={isAndroidSupported}
1408
+ tags={tags}
1409
+ onTagSelect={onTagSelect}
1410
+ handleOnTagsContextChange={handleOnTagsContextChange}
1411
+ templateDescErrorHandler={templateDescErrorHandler}
1412
+ templateTitleError={templateTitleErrorIos}
1413
+ setTemplateTitleError={setTemplateTitleErrorIos}
1414
+ isAiContentBotDisabled={aiContentBotDisabled}
1415
+ injectedTags={injectedTags}
1416
+ selectedOfferDetails={selectedOfferDetails}
1417
+ location={location}
1418
+ />
1419
+ ),
1420
+ tab: <FormattedMessage {...messages.Ios} />,
1421
+ key: IOS,
1422
+ isSupported: isIosSupported,
1423
+ },
1424
+ ];
1425
+ // ─────────────────────────────────────────────────────────────────────────
1426
+
1427
+ // Calculate column span: HTML editor = 18, everything else = 24
1428
+ const editorColumnSpan = shouldUseHTMLEditor ? 18 : 24;
1429
+
1281
1430
  return (
1282
1431
  <CapSpin spinning={spin || fetchingLiquidValidation} tip={fetchingLiquidValidation ? <FormattedMessage {...formBuilderMessages.liquidSpinText} /> : ""}>
1283
1432
  <CapRow className="cap-inapp-creatives">
1284
- <CapColumn span={shouldUseHTMLEditor ? 18 : 24}>
1433
+ <CapColumn span={editorColumnSpan}>
1285
1434
  {/* Creative layout type */}
1286
1435
  {shouldUseHTMLEditor && (
1287
1436
  <>
@@ -1302,7 +1451,7 @@ export const InApp = (props) => {
1302
1451
  />
1303
1452
  </>
1304
1453
  )}
1305
- {shouldUseHTMLEditor ? (
1454
+ {shouldUseHTMLEditor && (
1306
1455
  <HTMLEditor
1307
1456
  key={`inapp-html-editor-v${htmlEditorContentVersion}`}
1308
1457
  variant={HTML_EDITOR_VARIANTS.INAPP}
@@ -1318,19 +1467,16 @@ export const InApp = (props) => {
1318
1467
  location={location}
1319
1468
  selectedOfferDetails={selectedOfferDetails}
1320
1469
  onTagSelect={() => {
1321
- // Tag insertion is handled by HTMLEditor's CodeEditorPane at cursor position
1322
- // Content updates will be propagated via onContentChange callback
1470
+ // Tag insertion handled by HTMLEditor's CodeEditorPane at cursor position
1323
1471
  }}
1324
- // Don't pass globalActions to prevent duplicate API calls
1325
- // HTMLEditor will use onContextChange instead
1326
1472
  onContextChange={handleOnTagsContextChange}
1327
- // Pass validation errors to HTMLEditor for display
1328
1473
  errors={errorMessage}
1329
1474
  isFullMode={isFullMode}
1330
1475
  data-test="inapp-html-editor"
1331
1476
  style={{ width: '138%' }}
1332
1477
  />
1333
- ) : (
1478
+ )}
1479
+ {!shouldUseHTMLEditor && isNewEditorFlowEnabled && (
1334
1480
  <InappAdvanced
1335
1481
  getFormData={getFormData}
1336
1482
  setIsLoadingContent={setIsLoadingContent}
@@ -1355,11 +1501,44 @@ export const InApp = (props) => {
1355
1501
  onCreateComplete={onCreateComplete}
1356
1502
  />
1357
1503
  )}
1504
+ {!shouldUseHTMLEditor && !isNewEditorFlowEnabled && (
1505
+ <>
1506
+ <CapInput
1507
+ label={<FormattedMessage {...messages.creativeName} />}
1508
+ onChange={({ target: { value } }) => setTempName(value)}
1509
+ value={tempName}
1510
+ labelPosition="top"
1511
+ size="default"
1512
+ />
1513
+ <CapRow>
1514
+ <CapHeading type="h4">
1515
+ <FormattedMessage {...messages.creativeLayout} />
1516
+ </CapHeading>
1517
+ <CapHeading type="h6" className="inapp-creative-layout-desc">
1518
+ <FormattedMessage {...messages.creativeLayoutDesc} />
1519
+ </CapHeading>
1520
+ </CapRow>
1521
+ <CapRadioGroup
1522
+ id="inapp-layout-radio"
1523
+ options={LAYOUT_RADIO_OPTIONS}
1524
+ value={templateLayoutType}
1525
+ onChange={onTemplateLayoutTypeChange}
1526
+ className="inapp-layout-radio"
1527
+ />
1528
+ <CapTab
1529
+ panes={DEVICE_PANES.filter((devicePane) => devicePane?.isSupported === true)}
1530
+ onChange={(value) => setPanes(value)}
1531
+ activeKey={panes}
1532
+ defaultActiveKey={panes}
1533
+ className="inapp-template-device-tab"
1534
+ />
1535
+ </>
1536
+ )}
1358
1537
  </CapColumn>
1359
1538
  </CapRow>
1360
- {/* Footer with Done/Update button - Only show for HTML editor, bee editor has its own footer */}
1539
+ {/* Footer with Done/Update button - show for HTML editor and old CapDeviceContent flow */}
1361
1540
  {
1362
- shouldUseHTMLEditor && (
1541
+ (shouldUseHTMLEditor || !isNewEditorFlowEnabled) && (
1363
1542
  <>
1364
1543
  {hasAnyErrors(errorMessage) && (
1365
1544
  <ErrorInfoNote
@@ -21,18 +21,16 @@ import { getCtaObject } from '../utils';
21
21
  jest.mock('redux-auth-wrapper/history4/redirect', () => ({
22
22
  connectedRouterRedirect: jest.fn((config) => (Component) => Component),
23
23
  }));
24
+ import * as commonUtils from '../../../utils/commonUtils';
24
25
 
25
26
  const mockActions = {
26
27
  getTemplateInfoById: jest.fn(),
27
28
  resetEditTemplate: jest.fn(),
28
- getTemplateDetails: jest.fn((id, callback) => {
29
+ getTemplateDetails: jest.fn((id, setSpin) => {
29
30
  // Simulate successful template details fetch to prevent loading state
30
31
  // The callback is setSpin function, call it with false to stop spinner
31
- if (callback && typeof callback === 'function') {
32
- // Use setTimeout to ensure it's called after render
33
- setTimeout(() => {
34
- callback(false);
35
- }, 0);
32
+ if (setSpin && typeof setSpin === 'function') {
33
+ setTimeout(() => setSpin(false), 0);
36
34
  }
37
35
  }),
38
36
  editTemplate: jest.fn(),
@@ -41,6 +39,9 @@ const mockActions = {
41
39
  };
42
40
  const mockGlobalActions = {
43
41
  fetchSchemaForEntity: jest.fn(),
42
+ getLiquidTags: jest.fn((content, callback) =>
43
+ callback({ askAiraResponse: { data: [], errors: [] }, isError: false }),
44
+ ),
44
45
  };
45
46
 
46
47
  jest.mock('../../../v2Containers/TagList/index.js', () => ({
@@ -66,7 +67,17 @@ const renderComponent = (props) =>
66
67
  );
67
68
 
68
69
  describe('Test activity inApp container', () => {
70
+ afterEach(() => {
71
+ jest.restoreAllMocks();
72
+ });
73
+
69
74
  it('test case for inApp template update flow', async () => {
75
+ jest
76
+ .spyOn(commonUtils, 'validateInAppContent')
77
+ .mockImplementation((payload, options) => {
78
+ options.onSuccess();
79
+ return Promise.resolve(true);
80
+ });
70
81
  renderComponent({
71
82
  actions: mockActions,
72
83
  globalActions: mockGlobalActions,
@@ -894,5 +894,5 @@ export const deviceContentProps = {
894
894
  },
895
895
  ],
896
896
  tags: [],
897
+ isOtherDeviceSupported: true,
897
898
  };
898
-
@@ -78,6 +78,7 @@ describe('useInAppWrapper', () => {
78
78
  onPreviewContentClicked: jest.fn(),
79
79
  onTestContentClicked: jest.fn(),
80
80
  eventContextTags: {},
81
+ waitEventContextTags: {},
81
82
  onCreateComplete: jest.fn(),
82
83
  handleClose: jest.fn(),
83
84
  templateData: null,
@@ -424,6 +425,24 @@ describe('useInAppWrapper', () => {
424
425
 
425
426
  expect(capturedState.inAppProps.getDefaultTags).toBe('defaultTags');
426
427
  });
428
+
429
+ it('passes waitEventContextTags through to inAppProps', () => {
430
+ const waitMap = { block1: { eventName: 'E', blockName: 'B', tags: [] } };
431
+ let capturedState = null;
432
+ render(
433
+ <TestComponent
434
+ hookProps={{
435
+ ...defaultHookProps,
436
+ waitEventContextTags: waitMap,
437
+ }}
438
+ onStateChange={(state) => {
439
+ capturedState = state;
440
+ }}
441
+ />
442
+ );
443
+
444
+ expect(capturedState.inAppProps.waitEventContextTags).toEqual(waitMap);
445
+ });
427
446
  });
428
447
 
429
448
  describe('isShowInAppCreate', () => {
@@ -33,6 +33,7 @@ const useInAppWrapper = ({
33
33
  onPreviewContentClicked,
34
34
  onTestContentClicked,
35
35
  eventContextTags,
36
+ waitEventContextTags,
36
37
  onCreateComplete,
37
38
  handleClose,
38
39
  templateData,
@@ -149,6 +150,7 @@ const useInAppWrapper = ({
149
150
  onPreviewContentClicked,
150
151
  onTestContentClicked,
151
152
  eventContextTags,
153
+ waitEventContextTags,
152
154
  onCreateComplete,
153
155
  handleClose,
154
156
  };
@@ -173,6 +175,7 @@ const useInAppWrapper = ({
173
175
  onPreviewContentClicked,
174
176
  onTestContentClicked,
175
177
  eventContextTags,
178
+ waitEventContextTags,
176
179
  onCreateComplete,
177
180
  handleClose,
178
181
  ]);
@@ -36,6 +36,7 @@ const InAppWrapper = (props) => {
36
36
  onPreviewContentClicked,
37
37
  onTestContentClicked,
38
38
  eventContextTags,
39
+ waitEventContextTags,
39
40
  onCreateComplete,
40
41
  handleClose,
41
42
  templateData,
@@ -78,6 +79,7 @@ const InAppWrapper = (props) => {
78
79
  onPreviewContentClicked,
79
80
  onTestContentClicked,
80
81
  eventContextTags,
82
+ waitEventContextTags,
81
83
  onCreateComplete,
82
84
  handleClose,
83
85
  templateData,
@@ -124,6 +126,7 @@ InAppWrapper.propTypes = {
124
126
  onPreviewContentClicked: PropTypes.func,
125
127
  onTestContentClicked: PropTypes.func,
126
128
  eventContextTags: PropTypes.array,
129
+ waitEventContextTags: PropTypes.object,
127
130
  onCreateComplete: PropTypes.func,
128
131
  handleClose: PropTypes.func,
129
132
  templateData: PropTypes.object,