@capillarytech/creatives-library 7.18.0-beta.0 → 8.0.1

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 (334) hide show
  1. package/app.js +27 -54
  2. package/assets/Line_Preview_English.svg +24 -0
  3. package/assets/Line_Preview_Japanese.svg +24 -0
  4. package/components/CapTagList/index.js +2 -2
  5. package/components/CapTagList/messages.js +8 -0
  6. package/components/Ckeditor/index.js +4 -2
  7. package/components/Ckeditor/style.scss +3 -0
  8. package/components/FormBuilder/_formBuilder.scss +4 -16
  9. package/components/FormBuilder/index.js +4 -3
  10. package/components/FormBuilder/messages.js +4 -0
  11. package/components/Sidebar/index.js +4 -4
  12. package/config/path.js +1 -1
  13. package/containers/App/constants.js +95 -0
  14. package/containers/App/index.js +52 -0
  15. package/containers/App/sagas.js +8 -3
  16. package/containers/Assets/Gallery/index.js +17 -3
  17. package/containers/Assets/Gallery/messages.js +4 -0
  18. package/containers/Assets/Gallery/sagas.js +14 -14
  19. package/containers/Cap/index.js +84 -50
  20. package/containers/Cap/sagas.js +20 -12
  21. package/containers/Cap/selectors.js +13 -13
  22. package/containers/Cap/tests/__snapshots__/index.test.js.snap +1 -1
  23. package/containers/Cap/tests/saga.test.js +81 -1
  24. package/containers/Dashboard/index.js +34 -17
  25. package/containers/Dashboard/sagas.js +7 -1
  26. package/containers/Ebill/index.js +16 -3
  27. package/containers/Ebill/sagas.js +18 -11
  28. package/containers/Email/index.js +20 -3
  29. package/containers/Email/sagas.js +34 -23
  30. package/containers/LanguageProvider/index.js +49 -31
  31. package/containers/LanguageProvider/tests/index.test.js +5 -3
  32. package/containers/Line/Create/index.js +15 -2
  33. package/containers/Line/Create/sagas.js +26 -17
  34. package/containers/Line/Edit/sagas.js +12 -13
  35. package/containers/Login/index.js +36 -11
  36. package/containers/MobilePush/Create/index.js +17 -2
  37. package/containers/MobilePush/Create/sagas.js +18 -12
  38. package/containers/MobilePush/Edit/index.js +20 -3
  39. package/containers/MobilePush/Edit/sagas.js +30 -20
  40. package/containers/Sms/Create/index.js +15 -2
  41. package/containers/Sms/Create/sagas.js +8 -6
  42. package/containers/Sms/Edit/index.js +15 -3
  43. package/containers/Sms/Edit/sagas.js +14 -8
  44. package/containers/TagList/constants.js +23 -0
  45. package/containers/Templates/actions.js +0 -5
  46. package/containers/Templates/index.js +47 -14
  47. package/containers/Templates/sagas.js +20 -23
  48. package/containers/WeChat/MapTemplates/index.js +19 -2
  49. package/containers/WeChat/MapTemplates/sagas.js +17 -17
  50. package/containers/WeChat/RichmediaTemplates/Create/index.js +18 -2
  51. package/containers/WeChat/RichmediaTemplates/Create/sagas.js +11 -8
  52. package/containers/WeChat/RichmediaTemplates/Edit/index.js +21 -2
  53. package/containers/WeChat/RichmediaTemplates/Edit/sagas.js +9 -5
  54. package/entry.js +2 -0
  55. package/global-styles.js +2 -2
  56. package/gtm/eventDefinitionsMap.js +1 -1
  57. package/helpers/intl-enzym-test-helpers.js +1 -1
  58. package/hoc/withReactRouterV3Compatibility.js +66 -0
  59. package/index.js +12 -0
  60. package/initialReducer.js +32 -0
  61. package/initialState.js +1 -0
  62. package/mfe-exposed-components.js +8 -0
  63. package/package.json +16 -11
  64. package/routes.js +206 -749
  65. package/services/api.js +62 -17
  66. package/services/tests/api.test.js +248 -1
  67. package/styles/components/navigation/_leftnav.scss +13 -0
  68. package/styles/containers/layout/_layoutPage.scss +14 -0
  69. package/tests/integration/TemplateCreation/TemplateCreation.integration.test.js +21 -16
  70. package/tests/store.test.js +5 -3
  71. package/translations/en.json +1 -9
  72. package/translations/ja-JP.json +0 -8
  73. package/translations/zh.json +0 -8
  74. package/utils/authWrapper.js +43 -17
  75. package/utils/cdnTransformation.js +73 -44
  76. package/utils/checkStore.js +21 -0
  77. package/utils/common.js +198 -8
  78. package/utils/commonUtils.js +17 -1
  79. package/utils/customAuthWrapper.js +62 -0
  80. package/utils/customConnectedAuthWrapper.js +26 -0
  81. package/utils/history.js +8 -0
  82. package/utils/injectReducer.js +2 -0
  83. package/utils/injectSaga.js +2 -0
  84. package/utils/tagValidations.js +2 -2
  85. package/utils/tests/cdnTransformation.test.js +6 -4
  86. package/utils/tests/common.mockdata.js +623 -0
  87. package/utils/tests/common.test.js +273 -0
  88. package/utils/tests/commonUtil.test.js +79 -0
  89. package/v2Components/CapDeviceContent/index.js +330 -0
  90. package/v2Components/CapDeviceContent/index.scss +115 -0
  91. package/v2Components/CapDeviceContent/messages.js +94 -0
  92. package/v2Components/CapDeviceContent/tests/index.test.js +89 -0
  93. package/v2Components/CapImageUpload/constants.js +6 -0
  94. package/v2Components/CapImageUpload/index.js +23 -15
  95. package/v2Components/CapImageUpload/index.scss +6 -0
  96. package/v2Components/CapImageUpload/messages.js +7 -7
  97. package/v2Components/CapInAppCTA/constants.js +25 -0
  98. package/v2Components/CapInAppCTA/index.js +279 -0
  99. package/v2Components/CapInAppCTA/index.scss +99 -0
  100. package/v2Components/CapInAppCTA/messages.js +85 -0
  101. package/v2Components/CapTagList/index.js +149 -26
  102. package/v2Components/CapTagList/messages.js +12 -0
  103. package/v2Components/CapTagList/style.scss +26 -0
  104. package/v2Components/CapVideoUpload/constants.js +6 -0
  105. package/v2Components/CapVideoUpload/index.js +48 -22
  106. package/v2Components/CapVideoUpload/index.scss +4 -2
  107. package/v2Components/CapVideoUpload/messages.js +10 -6
  108. package/v2Components/CapWhatsappQuickReply/index.js +255 -0
  109. package/v2Components/CapWhatsappQuickReply/index.scss +54 -0
  110. package/v2Components/CapWhatsappQuickReply/messages.js +32 -0
  111. package/v2Components/Ckeditor/index.js +56 -22
  112. package/v2Components/Ckeditor/style.scss +3 -0
  113. package/v2Components/Ckeditor/tests/index.test.js +44 -0
  114. package/v2Components/CmsTemplatesComponent/index.js +1 -0
  115. package/v2Components/CmsTemplatesComponent/messages.js +4 -0
  116. package/v2Components/EmailMobilePreview/index.js +4 -2
  117. package/v2Components/EmailPreviewV2/index.js +6 -4
  118. package/v2Components/EmailPreviewV2/tests/__snapshots__/index.test.js.snap +0 -3
  119. package/v2Components/FormBuilder/_formBuilder.scss +1 -0
  120. package/v2Components/FormBuilder/constants.js +1 -1
  121. package/v2Components/FormBuilder/index.js +111 -29
  122. package/v2Components/FormBuilder/messages.js +4 -0
  123. package/v2Components/FormBuilder/tests/index.test.js +5 -2
  124. package/v2Components/MobilePushPreviewV2/index.js +57 -22
  125. package/v2Components/NavigationBar/constants.js +1 -0
  126. package/v2Components/NavigationBar/index.js +84 -113
  127. package/v2Components/NavigationBar/messages.js +8 -0
  128. package/v2Components/NavigationBar/style.js +9 -0
  129. package/v2Components/NavigationBar/tests/index.test.js +32 -9
  130. package/v2Components/NavigationBar/tests/mockData.js +1 -0
  131. package/v2Components/NewCallTask/tests/index.test.js +5 -3
  132. package/v2Components/Pagination/index.js +2 -1
  133. package/v2Components/RenderRoute/RenderRoute.js +11 -0
  134. package/v2Components/RenderRoute/index.js +1 -0
  135. package/v2Components/TemplatePreview/_templatePreview.scss +535 -0
  136. package/v2Components/TemplatePreview/assets/images/inapp_mobile_android_bottom.svg +11 -0
  137. package/v2Components/TemplatePreview/assets/images/inapp_mobile_android_full.svg +11 -0
  138. package/v2Components/TemplatePreview/assets/images/inapp_mobile_android_modal.svg +11 -0
  139. package/v2Components/TemplatePreview/assets/images/inapp_mobile_android_top.svg +11 -0
  140. package/v2Components/TemplatePreview/assets/images/inapp_mobile_ios_bottom.svg +6 -0
  141. package/v2Components/TemplatePreview/assets/images/inapp_mobile_ios_full.svg +18 -0
  142. package/v2Components/TemplatePreview/assets/images/inapp_mobile_ios_modal.svg +7 -0
  143. package/v2Components/TemplatePreview/assets/images/inapp_mobile_ios_top.svg +13 -0
  144. package/v2Components/TemplatePreview/index.js +745 -362
  145. package/v2Components/TemplatePreview/messages.js +8 -0
  146. package/v2Components/TemplatePreview/tests/__snapshots__/index.test.js.snap +47 -14
  147. package/v2Components/TemplatePreview/tests/index.test.js +9 -0
  148. package/v2Components/WhatsappStatusContainer/_whatsappStatusContainer.scss +8 -1
  149. package/v2Containers/App/constants.js +12 -6
  150. package/v2Containers/App/sagas.js +0 -1
  151. package/v2Containers/Assets/Gallery/index.js +1 -0
  152. package/v2Containers/Assets/Gallery/sagas.js +15 -14
  153. package/v2Containers/BeeEditor/index.js +3 -1
  154. package/v2Containers/BeeEditor/sagas.js +8 -5
  155. package/v2Containers/CallTask/sagas.js +7 -1
  156. package/v2Containers/Cap/actions.js +4 -0
  157. package/v2Containers/Cap/constants.js +20 -1
  158. package/v2Containers/Cap/index.js +116 -17
  159. package/v2Containers/Cap/messages.js +8 -0
  160. package/v2Containers/Cap/reducer.js +18 -3
  161. package/v2Containers/Cap/sagas.js +64 -9
  162. package/v2Containers/Cap/selectors.js +27 -13
  163. package/v2Containers/Cap/tests/Cap.test.js +164 -0
  164. package/v2Containers/Cap/tests/__snapshots__/index.test.js.snap +2 -1
  165. package/v2Containers/Cap/tests/actions.test.js +11 -0
  166. package/v2Containers/Cap/tests/reducer.test.js +59 -0
  167. package/v2Containers/Cap/tests/saga.test.js +181 -2
  168. package/v2Containers/Cap/tests/selectors.test.js +42 -18
  169. package/v2Containers/CapFacebookPreview/sagas.js +7 -5
  170. package/v2Containers/CreativesContainer/SlideBoxContent.js +86 -4
  171. package/v2Containers/CreativesContainer/SlideBoxFooter.js +4 -3
  172. package/v2Containers/CreativesContainer/SlideBoxHeader.js +30 -14
  173. package/v2Containers/CreativesContainer/constants.js +5 -0
  174. package/v2Containers/CreativesContainer/index.js +157 -38
  175. package/v2Containers/CreativesContainer/index.scss +12 -0
  176. package/v2Containers/CreativesContainer/messages.js +33 -1
  177. package/v2Containers/CreativesContainer/tests/SlideBoxContent.test.js +11 -0
  178. package/v2Containers/CreativesContainer/tests/SlideBoxFooter.test.js +5 -2
  179. package/v2Containers/CreativesContainer/tests/SlideBoxHeader.test.js +7 -1
  180. package/v2Containers/CreativesContainer/tests/__snapshots__/SlideBoxContent.test.js.snap +227 -0
  181. package/v2Containers/CreativesContainer/tests/__snapshots__/SlideBoxHeader.test.js.snap +73 -0
  182. package/v2Containers/CreativesContainer/tests/__snapshots__/index.test.js.snap +80 -0
  183. package/v2Containers/CreativesContainer/tests/index.test.js +16 -0
  184. package/v2Containers/Ebill/sagas.js +3 -10
  185. package/v2Containers/Email/index.js +38 -19
  186. package/v2Containers/Email/initialSchema.js +1 -1
  187. package/v2Containers/Email/sagas.js +22 -26
  188. package/v2Containers/EmailWrapper/index.js +18 -8
  189. package/v2Containers/FTP/index.js +2 -2
  190. package/v2Containers/FTP/sagas.js +3 -4
  191. package/v2Containers/Facebook/sagas.js +26 -17
  192. package/v2Containers/InApp/actions.js +64 -0
  193. package/v2Containers/InApp/constants.js +160 -0
  194. package/v2Containers/InApp/index.js +792 -0
  195. package/v2Containers/InApp/index.scss +50 -0
  196. package/v2Containers/InApp/messages.js +114 -0
  197. package/v2Containers/InApp/reducer.js +109 -0
  198. package/v2Containers/InApp/sagas.js +151 -0
  199. package/v2Containers/InApp/selectors.js +12 -0
  200. package/v2Containers/InApp/tests/action.test.js +53 -0
  201. package/v2Containers/InApp/tests/index.test.js +165 -0
  202. package/v2Containers/InApp/tests/mockData.js +898 -0
  203. package/v2Containers/InApp/tests/reducer.test.js +177 -0
  204. package/v2Containers/InApp/tests/sagas.test.js +391 -0
  205. package/v2Containers/InApp/utils.js +12 -0
  206. package/v2Containers/LanguageProvider/index.js +17 -5
  207. package/v2Containers/LanguageProvider/reducer.js +3 -2
  208. package/v2Containers/LanguageProvider/sagas.js +7 -8
  209. package/v2Containers/LanguageProvider/selectors.js +2 -1
  210. package/v2Containers/LanguageProvider/tests/index.test.js +5 -2
  211. package/v2Containers/LanguageProvider/tests/reducer.test.js +6 -3
  212. package/v2Containers/Line/Container/ImageCarousel/tests/__snapshots__/content.test.js.snap +28 -16
  213. package/v2Containers/Line/Container/ImageCarousel/tests/__snapshots__/index.test.js.snap +2 -2
  214. package/v2Containers/Line/Container/ImageCarousel/tests/content.test.js +5 -3
  215. package/v2Containers/Line/Container/ImageCarousel/tests/index.test.js +5 -3
  216. package/v2Containers/Line/Container/ImageMap/index.js +1 -1
  217. package/v2Containers/Line/Container/Text/index.js +16 -1
  218. package/v2Containers/Line/Container/Video/index.js +2 -1
  219. package/v2Containers/Line/Container/Wrapper/tests/__snapshots__/index.test.js.snap +18134 -107
  220. package/v2Containers/Line/Container/Wrapper/tests/index.test.js +5 -3
  221. package/v2Containers/Line/Container/Wrapper/utils.js +1 -1
  222. package/v2Containers/Line/Container/index.js +4 -0
  223. package/v2Containers/Line/Container/sagas.js +30 -20
  224. package/v2Containers/Line/Container/tests/__snapshots__/index.test.js.snap +123 -81
  225. package/v2Containers/Line/Container/tests/index.test.js +5 -2
  226. package/v2Containers/Login/index.js +1 -2
  227. package/v2Containers/MobilePush/Create/index.js +40 -17
  228. package/v2Containers/MobilePush/Create/sagas.js +18 -12
  229. package/v2Containers/MobilePush/Edit/index.js +16 -7
  230. package/v2Containers/MobilePush/Edit/sagas.js +30 -20
  231. package/v2Containers/MobilepushWrapper/index.js +3 -0
  232. package/v2Containers/Rcs/sagas.js +14 -14
  233. package/v2Containers/Rcs/tests/__snapshots__/index.test.js.snap +123 -87
  234. package/v2Containers/Rcs/tests/index.test.js +5 -3
  235. package/v2Containers/Sms/Create/sagas.js +10 -6
  236. package/v2Containers/Sms/Edit/sagas.js +14 -8
  237. package/v2Containers/SmsTrai/Create/sagas.js +9 -10
  238. package/v2Containers/SmsTrai/Create/tests/__snapshots__/index.test.js.snap +4 -4
  239. package/v2Containers/SmsTrai/Edit/tests/__snapshots__/index.test.js.snap +12 -8
  240. package/v2Containers/SmsTrai/Edit/tests/index.test.js +5 -3
  241. package/v2Containers/TagList/_tagList.scss +18 -0
  242. package/v2Containers/TagList/index.js +81 -42
  243. package/v2Containers/TagList/tests/TagList.test.js +6 -7
  244. package/v2Containers/TagList/tests/mockdata.js +10 -166
  245. package/v2Containers/TagList/tests/utils.test.js +17 -0
  246. package/v2Containers/TagList/utils.js +15 -0
  247. package/v2Containers/Templates/_templates.scss +60 -5
  248. package/v2Containers/Templates/actions.js +6 -5
  249. package/v2Containers/Templates/constants.js +2 -1
  250. package/v2Containers/Templates/index.js +576 -181
  251. package/v2Containers/Templates/messages.js +52 -8
  252. package/v2Containers/Templates/reducer.js +3 -1
  253. package/v2Containers/Templates/sagas.js +54 -38
  254. package/v2Containers/Templates/tests/__snapshots__/index.test.js.snap +669 -43
  255. package/v2Containers/Templates/tests/actions.test.js +19 -0
  256. package/v2Containers/Templates/tests/index.test.js +53 -1
  257. package/v2Containers/Templates/tests/mockData.js +45 -1
  258. package/v2Containers/Templates/tests/reducer.test.js +50 -0
  259. package/v2Containers/Templates/tests/sagas.test.js +116 -3
  260. package/v2Containers/Templates/tests/selector.test.js +17 -0
  261. package/v2Containers/TemplatesV2/index.js +180 -8
  262. package/v2Containers/TemplatesV2/messages.js +8 -0
  263. package/v2Containers/TemplatesV2/tests/index.test.js +104 -0
  264. package/v2Containers/TemplatesV2/tests/mockData.js +685 -0
  265. package/v2Containers/Viber/constants.js +58 -0
  266. package/v2Containers/Viber/index.js +404 -421
  267. package/v2Containers/Viber/index.scss +107 -0
  268. package/v2Containers/Viber/messages.js +70 -2
  269. package/v2Containers/Viber/sagas.js +22 -14
  270. package/v2Containers/Viber/style.js +20 -0
  271. package/v2Containers/Viber/tests/index.test.js +299 -0
  272. package/v2Containers/Viber/tests/mockData.js +134 -0
  273. package/v2Containers/WeChat/MapTemplates/sagas.js +22 -14
  274. package/v2Containers/WeChat/RichmediaTemplates/Create/sagas.js +12 -11
  275. package/v2Containers/WeChat/RichmediaTemplates/Edit/sagas.js +9 -5
  276. package/v2Containers/Whatsapp/actions.js +16 -0
  277. package/v2Containers/Whatsapp/constants.js +24 -0
  278. package/v2Containers/Whatsapp/index.js +892 -222
  279. package/v2Containers/Whatsapp/index.scss +91 -1
  280. package/v2Containers/Whatsapp/messages.js +98 -1
  281. package/v2Containers/Whatsapp/reducer.js +19 -0
  282. package/v2Containers/Whatsapp/sagas.js +67 -12
  283. package/v2Containers/Whatsapp/styles.scss +35 -0
  284. package/v2Containers/Whatsapp/tests/__snapshots__/index.test.js.snap +34983 -24886
  285. package/v2Containers/Whatsapp/tests/__snapshots__/utils.test.js.snap +12 -0
  286. package/v2Containers/Whatsapp/tests/actions.test.js +21 -0
  287. package/v2Containers/Whatsapp/tests/index.test.js +17 -4
  288. package/v2Containers/Whatsapp/tests/mockData.js +77 -0
  289. package/v2Containers/Whatsapp/tests/reducer.test.js +67 -0
  290. package/v2Containers/Whatsapp/tests/saga.test.js +201 -0
  291. package/v2Containers/Whatsapp/tests/utils.test.js +18 -0
  292. package/v2Containers/Whatsapp/utils.js +65 -4
  293. package/v2Containers/Zalo/actions.js +24 -0
  294. package/v2Containers/Zalo/constants.js +59 -0
  295. package/v2Containers/Zalo/index.js +548 -0
  296. package/v2Containers/Zalo/index.scss +75 -0
  297. package/v2Containers/Zalo/messages.js +86 -0
  298. package/v2Containers/Zalo/reducer.js +63 -0
  299. package/v2Containers/Zalo/saga.js +45 -0
  300. package/v2Containers/Zalo/selectors.js +19 -0
  301. package/v2Containers/Zalo/tests/actions.test.js +26 -0
  302. package/v2Containers/Zalo/tests/index.test.js +149 -0
  303. package/v2Containers/Zalo/tests/mockData.js +11527 -0
  304. package/v2Containers/Zalo/tests/reducer.test.js +96 -0
  305. package/v2Containers/Zalo/tests/saga.test.js +118 -0
  306. package/v2Containers/Zalo/tests/selector.test.js +51 -0
  307. package/v2Containers/mockdata.js +1531 -680
  308. package/containers/TestPage/constants.js +0 -7
  309. package/containers/TestPage/index.js +0 -31
  310. package/containers/TestPage/messages.js +0 -13
  311. package/containers/TestPage/reducer.js +0 -21
  312. package/containers/TestPage/sagas.js +0 -11
  313. package/containers/Testv2/actions.js +0 -15
  314. package/containers/Testv2/constants.js +0 -7
  315. package/containers/Testv2/index.js +0 -47
  316. package/containers/Testv2/messages.js +0 -21
  317. package/containers/Testv2/reducer.js +0 -23
  318. package/containers/Testv2/sagas.js +0 -11
  319. package/containers/Testv2/selectors.js +0 -25
  320. package/reducers.js +0 -73
  321. package/store.js +0 -61
  322. package/utils/tests/asyncInjectors.test.js +0 -173
  323. package/v2Containers/TestPage/constants.js +0 -7
  324. package/v2Containers/TestPage/index.js +0 -31
  325. package/v2Containers/TestPage/messages.js +0 -13
  326. package/v2Containers/TestPage/reducer.js +0 -21
  327. package/v2Containers/TestPage/sagas.js +0 -11
  328. package/v2Containers/Testv2/actions.js +0 -15
  329. package/v2Containers/Testv2/constants.js +0 -7
  330. package/v2Containers/Testv2/index.js +0 -47
  331. package/v2Containers/Testv2/messages.js +0 -21
  332. package/v2Containers/Testv2/reducer.js +0 -23
  333. package/v2Containers/Testv2/sagas.js +0 -11
  334. package/v2Containers/Testv2/selectors.js +0 -25
@@ -5,10 +5,11 @@ import React, { useState, useEffect, useCallback } from 'react';
5
5
  import { bindActionCreators } from 'redux';
6
6
  import { createStructuredSelector } from 'reselect';
7
7
  import { injectIntl, FormattedMessage } from 'react-intl';
8
- import { get, isEmpty, cloneDeep } from 'lodash';
8
+ import { get, isEmpty, cloneDeep, isEqual } from 'lodash';
9
9
  import styled from 'styled-components';
10
10
  import CapSpin from '@capillarytech/cap-ui-library/CapSpin';
11
11
  import CapRow from '@capillarytech/cap-ui-library/CapRow';
12
+ import CapIcon from '@capillarytech/cap-ui-library/CapIcon';
12
13
  import CapColumn from '@capillarytech/cap-ui-library/CapColumn';
13
14
  import CapHeader from '@capillarytech/cap-ui-library/CapHeader';
14
15
  import CapTooltipWithInfo from '@capillarytech/cap-ui-library/CapTooltipWithInfo';
@@ -25,6 +26,7 @@ import CapAlert from '@capillarytech/cap-ui-library/CapAlert';
25
26
  import CapCheckbox from '@capillarytech/cap-ui-library/CapCheckbox';
26
27
  import CapLink from '@capillarytech/cap-ui-library/CapLink';
27
28
  import moment from 'moment';
29
+
28
30
  import {
29
31
  CAP_SPACE_04,
30
32
  CAP_SPACE_16,
@@ -57,6 +59,7 @@ import {
57
59
  WHATSAPP_MEDIA_TYPES,
58
60
  WHATSAPP_BUTTON_TYPES,
59
61
  INITIAL_CTA_DATA,
62
+ INITIAL_QUICK_REPLY_DATA,
60
63
  ALLOWED_IMAGE_EXTENSIONS_REGEX,
61
64
  WHATSAPP_IMG_SIZE,
62
65
  HOST_TWILIO,
@@ -68,6 +71,14 @@ import {
68
71
  WHATSAPP_VIDEO_SIZE,
69
72
  DOCUMENT_FORMAT,
70
73
  DOCUMENT_SIZE,
74
+ TEMPLATE_HEADER_MAX_LENGTH,
75
+ QUICK_REPLY_BUTTON_TEXT_MAX_LENGTH,
76
+ HEADER_TEXT,
77
+ FOOTER_TEXT,
78
+ MESSAGE_TEXT,
79
+ BUTTON_TEXT,
80
+ OTP_CONFIG_URI,
81
+ WHATSAPP_CATEGORIES,
71
82
  } from './constants';
72
83
  import { DATE_DISPLAY_FORMAT, TIME_DISPLAY_FORMAT } from '../App/constants';
73
84
  import messages from './messages';
@@ -87,10 +98,12 @@ import { getCdnUrl } from '../../utils/cdnTransformation';
87
98
  import CapVideoUpload from '../../v2Components/CapVideoUpload';
88
99
  import CapDocumentUpload from '../../v2Components/CapDocumentUpload';
89
100
  import { getWhatsappDocPreview } from './utils';
101
+ import CapWhatsappQuickReply from '../../v2Components/CapWhatsappQuickReply';
90
102
 
91
103
  let varMap = {};
92
104
  let editContent = {};
93
105
  let tagValidationResponse = {};
106
+ let headerTagValidationResponse = {};
94
107
 
95
108
  export const Whatsapp = (props) => {
96
109
  const {
@@ -128,6 +141,10 @@ export const Whatsapp = (props) => {
128
141
  );
129
142
  const [templateMessage, setTemplateMessage] = useState('');
130
143
  const [templateMessageError, setTemplateMessageError] = useState(false);
144
+ const [templateHeader, setTemplateHeader] = useState('');
145
+ const [templateHeaderError, setTemplateHeaderError] = useState(false);
146
+ const [templateFooter, setTemplateFooter] = useState('');
147
+ const [templateFooterError, setTemplateFooterError] = useState(false);
131
148
  const [addedVarCount, setAddedVarCount] = useState(0);
132
149
  const [accountId, setAccountId] = useState('');
133
150
  const [accessToken, setAccessToken] = useState('');
@@ -135,6 +152,8 @@ export const Whatsapp = (props) => {
135
152
  const [host, setHost] = useState('');
136
153
  const [spin, setSpin] = useState(false);
137
154
  const [unsubscribeRequired, setUnsubscribeRequired] = useState(false);
155
+ const [securityWarningReqd, setSecurityWarningReqd] = useState(false);
156
+ const [expiryMinutes, setExpiryMinutes] = useState(0);
138
157
  const [whatsappImageSrc, setWhatsappImageSrc] = useState('');
139
158
  const [whatsappVideoSrcAndPreview, setWhatsappVideoSrcAndPreview] = useState({
140
159
  whatsappVideoSrc: '',
@@ -159,14 +178,29 @@ export const Whatsapp = (props) => {
159
178
  //buttons
160
179
  const [buttonType, setButtonType] = useState(WHATSAPP_BUTTON_TYPES.NONE);
161
180
  const [ctaData, setCtadata] = useState(INITIAL_CTA_DATA);
181
+ const [quickReplyData, setQuickReplyData] = useState(
182
+ INITIAL_QUICK_REPLY_DATA
183
+ );
184
+ const [tempHeaderData, setTempHeaderData] = useState([]);
185
+ const [headerVarMappedData, setHeaderVarMappedData] = useState({});
186
+ const [updatedHeaderData, setUpdatedHeaderData] = useState([]);
187
+ const [headerTextAreaId, setHeaderTextAreaId] = useState('');
188
+ const [isHeaderTagValidationError, updateIsHeaderTagValidationError] =
189
+ useState(false);
190
+ const [showUrlPreview, setShowUrlPreview] = useState(false);
191
+ const [previewUrl, setPreviewUrl] = useState('');
162
192
 
163
193
  const validVarRegex = /{{([1-9]|1[0-9])}}/g;
194
+ const headerValidVarRegex = /{{(1)}}/g;
195
+ const previewUrlMatchingRegex = /(http|ftp|https):\/\/([\w_-]+(?:(?:\.[\w_-]+)+))([\w.,@?^=%&:\/~+#-]*[\w@?^=%&\/~+#-])/g;
164
196
 
165
197
  const isBtnTypeCta = buttonType === WHATSAPP_BUTTON_TYPES.CTA;
198
+ const isBtnTypeQuickReply = buttonType === WHATSAPP_BUTTON_TYPES.QUICK_REPLY;
166
199
  const isMediaTypeText = templateMediaType === WHATSAPP_MEDIA_TYPES.TEXT;
167
200
  const isMediaTypeImage = templateMediaType === WHATSAPP_MEDIA_TYPES.IMAGE;
168
201
  const isMediaTypeVideo = templateMediaType === WHATSAPP_MEDIA_TYPES.VIDEO;
169
202
  const isMediaTypeDoc = templateMediaType === WHATSAPP_MEDIA_TYPES.DOCUMENT;
203
+ const isHostIsNotTwilio = host !== HOST_TWILIO;
170
204
  const WhatsappFooter = styled.div`
171
205
  background-color: ${CAP_WHITE};
172
206
  position: fixed;
@@ -213,6 +247,7 @@ export const Whatsapp = (props) => {
213
247
  return () => {
214
248
  actions.resetEditTemplate();
215
249
  varMap = {};
250
+ setHeaderVarMappedData({});
216
251
  };
217
252
  }, [paramObj.id]);
218
253
 
@@ -241,6 +276,8 @@ export const Whatsapp = (props) => {
241
276
  buttons = [],
242
277
  videoPreviewImg = '',
243
278
  whatsappDocParams = {},
279
+ whatsappMedia: { header = '', footer = '' } = {},
280
+ isPreviewUrl = false,
244
281
  } = editContent;
245
282
  setTemplateCategory(category);
246
283
  setTemplateStatus(status);
@@ -262,6 +299,9 @@ export const Whatsapp = (props) => {
262
299
  });
263
300
  setKarixFileHandle(karixFileHandle);
264
301
  setButtonType(btnType);
302
+ setTemplateFooter(footer);
303
+ setTemplateHeader(header);
304
+ setShowUrlPreview(isPreviewUrl);
265
305
  if (btnType === WHATSAPP_BUTTON_TYPES.CTA && buttons.length > 0) {
266
306
  setCtadata(
267
307
  buttons.map((cta) => {
@@ -288,16 +328,70 @@ export const Whatsapp = (props) => {
288
328
  }),
289
329
  );
290
330
  }
331
+ if (btnType === WHATSAPP_BUTTON_TYPES.QUICK_REPLY && buttons?.length > 0) {
332
+ setQuickReplyData(buttons);
333
+ }
291
334
  computeTempMsgArray();
335
+ if (header && (mediaType === WHATSAPP_MEDIA_TYPES.TEXT && isHostIsNotTwilio)) {
336
+ computeHeaderMsgArray();
337
+ }
292
338
  }
293
339
  }, [editData.templateDetails || templateData]);
294
340
 
341
+ const converStringToVarArr = (validVarArr, content) => {
342
+ const templateVarArray = [];
343
+ while (content?.length !== 0) {
344
+ //converting content string to an array split at var
345
+ const index = content.indexOf(validVarArr?.[0]);
346
+ if (index !== -1) {
347
+ templateVarArray.push(content.substring(0, index)); //push string before var
348
+ templateVarArray.push(validVarArr?.[0]); //push var
349
+ content = content.substring(index + validVarArr?.[0]?.length, content?.length); //remaining str
350
+ validVarArr?.shift(); //remove considered var
351
+ } else {
352
+ templateVarArray.push(content); //remaining str
353
+ break;
354
+ }
355
+ }
356
+ return templateVarArray;
357
+ }
358
+
359
+ const computeHeaderMsgArray = () => {
360
+ let msg = get(editContent, `whatsappMedia.header`, '');
361
+ const validVarArr = msg?.match(headerValidVarRegex) || [];
362
+ //conerting msg string to variable arr
363
+ const templateHeaderArray = converStringToVarArr(validVarArr, msg);
364
+ setTempHeaderData(templateHeaderArray);
365
+ if (templateHeaderArray?.length !== 0) {
366
+ let headerVarMap = {};
367
+ const {
368
+ whatsappMedia: { headerVarMapped = {} },
369
+ } = editContent;
370
+ if (!isEmpty(headerVarMapped)) {
371
+ headerVarMap = cloneDeep(headerVarMapped);
372
+ } else {
373
+ templateHeaderArray?.forEach((headerValue, i) => {
374
+ if (headerValue?.match(headerValidVarRegex)?.length > 0) {
375
+ headerVarMap[`${headerValue}_${i}`] = '';
376
+ }
377
+ })
378
+ }
379
+ const arr = [...templateHeaderArray];
380
+ for (const key in headerVarMap) {
381
+ if (headerVarMap[key] !== '') {
382
+ arr[key.slice(key.indexOf('_') + 1)] = headerVarMap[key];
383
+ }
384
+ }
385
+ setHeaderVarMappedData(headerVarMap);
386
+ setUpdatedHeaderData(arr);
387
+ }
388
+ };
389
+
295
390
  const computeTempMsgArray = () => {
296
391
  let msg = get(editContent, `languages[0].content`, '');
297
392
  const validVarArr = msg.match(validVarRegex) || [];
298
393
  const unsubscribeRegex1 = /Click {{([1-9]|1[0-9])}} to unsubscribe/g;
299
394
  const unsubscribeRegex2 = /Click {{unsubscribe}} to unsubscribe/g;
300
- const templateMessageArray = [];
301
395
  //removing $'' which was added for twilio enter handling
302
396
  // msg = msg.slice(2, -1);
303
397
  if (
@@ -317,19 +411,11 @@ export const Whatsapp = (props) => {
317
411
  }
318
412
  setUnsubscribeRequired(true);
319
413
  }
320
- while (msg.length !== 0) {
321
- //converting content string to an array split at var
322
- const index = msg.indexOf(validVarArr[0]);
323
- if (index !== -1) {
324
- templateMessageArray.push(msg.substring(0, index)); //push string before var
325
- templateMessageArray.push(validVarArr[0]); //push var
326
- msg = msg.substring(index + validVarArr[0].length, msg.length); //remaining str
327
- validVarArr.shift(); //remove considered var
328
- } else {
329
- templateMessageArray.push(msg); //remaining str
330
- break;
331
- }
414
+ if(msg?.includes(formatMessage(messages.securitySuffix))){
415
+ setUnsubscribeRequired(true);
332
416
  }
417
+ //converting msg string to variable arr
418
+ const templateMessageArray = converStringToVarArr(validVarArr, msg);
333
419
  updateTempMsgArray(templateMessageArray.filter((i) => i === 0 || i));
334
420
  };
335
421
 
@@ -353,15 +439,20 @@ export const Whatsapp = (props) => {
353
439
  arr[key.slice(key.indexOf('_') + 1)] = varMap[key];
354
440
  }
355
441
  }
442
+ // extract preview url from message
443
+ if (arr?.length) {
444
+ const validUrls = arr.join("").match(previewUrlMatchingRegex) || [];
445
+ setPreviewUrl(validUrls?.[0] || '')
446
+ }
356
447
  setUpdatedSmsEditor(arr);
357
448
  }
358
449
  }, [tempMsgArray]);
359
450
 
360
451
  useEffect(() => {
361
- if (tempMsgArray?.length && !loadingTags) {
452
+ if ((tempMsgArray?.length || tempHeaderData?.length) && !loadingTags) {
362
453
  setSpin(false);
363
454
  }
364
- }, [tempMsgArray, loadingTags]);
455
+ }, [tempMsgArray, loadingTags, tempHeaderData]);
365
456
 
366
457
  // tag Code start from here
367
458
  useEffect(() => {
@@ -393,27 +484,72 @@ export const Whatsapp = (props) => {
393
484
  }
394
485
  }, [metaEntities, isEditFlow]);
395
486
 
396
- //performs tag validation
397
- useEffect(() => {
398
- if (
399
- !isFullMode &&
400
- updatedSmsEditor?.length > 0 &&
401
- !updatedSmsEditor.join('').match(validVarRegex)
402
- ) {
403
- tagValidationResponse =
487
+ const tagValidation = (contentData, regex, type) => {
488
+ if (contentData?.length > 0 && !contentData.join("").match(regex)) {
489
+ const validationResponse =
404
490
  validateTags({
405
- content: updatedSmsEditor.join(''),
491
+ content: contentData.join(""),
406
492
  tagsParam: tags,
407
493
  injectedTagsParams: injectedTags,
408
494
  location,
409
495
  tagModule: getDefaultTags,
410
496
  }) || {};
411
- updateIsTagValidationError(
412
- tagValidationResponse.unsupportedTags.length > 0,
413
- );
497
+ const unsupportedTagsLengthCheck =
498
+ validationResponse?.unsupportedTags?.length > 0;
499
+ if (type === HEADER_TEXT) {
500
+ headerTagValidationResponse = validationResponse;
501
+ updateIsHeaderTagValidationError(unsupportedTagsLengthCheck);
502
+ } else {
503
+ tagValidationResponse = validationResponse;
504
+ updateIsTagValidationError(unsupportedTagsLengthCheck);
505
+ }
414
506
  }
507
+ };
508
+
509
+ // as per change in message body we filter out url using regex
510
+ // preview URL is not supported by the Gateway (Karix/Gupshup), show hiding it for now. once the Gateway support is available, previewUrl option would be shown.
511
+ // useEffect(() => {
512
+ // if (updatedSmsEditor?.length > 0) {
513
+ // const previewUrlArr = updatedSmsEditor.join("").match(previewUrlMatchingRegex) || [];
514
+ // if (previewUrlArr?.length > 0) {
515
+ // setPreviewUrl(previewUrlArr[0]);
516
+ // } else {
517
+ // setPreviewUrl('');
518
+ // }
519
+ // }
520
+ // }, [updatedSmsEditor])
521
+
522
+ // const debounceFn = useCallback(
523
+ // debounce(url => {
524
+ // actions.getMetaTags({
525
+ // previewUrl: url,
526
+ // callBack: actionCallback,
527
+ // })
528
+ // }, 500),
529
+ // [],
530
+ // );
531
+
532
+ // as per change in url and preview checkbox we call api and extract the meta information of url
533
+ // we will open once preview url support
534
+ // useEffect(() => {
535
+ // if (!isEmpty(previewUrl) && showUrlPreview) {
536
+ // debounceFn(previewUrl);
537
+ // } else {
538
+ // actions.resetMetaTags();
539
+ // }
540
+ // }, [previewUrl, showUrlPreview])
541
+
542
+ //performs tag validation
543
+ useEffect(() => {
544
+ if (!isFullMode)
545
+ tagValidation(updatedSmsEditor, validVarRegex, MESSAGE_TEXT);
415
546
  }, [updatedSmsEditor, tags]);
416
547
 
548
+ useEffect(() => {
549
+ if (!isFullMode)
550
+ tagValidation(updatedHeaderData, headerValidVarRegex, HEADER_TEXT);
551
+ }, [updatedHeaderData, tags]);
552
+
417
553
  const handleOnTagsContextChange = (data) => {
418
554
  const { type } = location.query || {};
419
555
  const isEmbedded = type === EMBEDDED;
@@ -429,26 +565,68 @@ export const Whatsapp = (props) => {
429
565
  globalActions.fetchSchemaForEntity(query);
430
566
  };
431
567
 
432
- const onTagSelect = (data) => {
433
- if (varMap && updatedSmsEditor) {
434
- const numId = Number(textAreaId?.slice(textAreaId?.indexOf('_') + 1));
435
- if (numId != NaN) {
436
- const arr = [...updatedSmsEditor];
568
+ const onTagSelect = (tagSelectData) => {
569
+ const {
570
+ data = "",
571
+ type = MESSAGE_TEXT,
572
+ mapData = {},
573
+ updatedData = [],
574
+ areaId = "",
575
+ regex,
576
+ } = tagSelectData;
577
+ if (mapData && updatedData) {
578
+ const numId = Number(areaId?.slice(areaId?.indexOf("_") + 1));
579
+ if (!isNaN(numId)) {
580
+ const arr = [...updatedData];
437
581
  //when trying to insert tag in empty textarea,{#var#} is replaced with "" and then tag is added
438
- if (arr[numId]?.match(validVarRegex)?.length > 0) {
439
- arr[numId] = '';
582
+ if (arr?.[numId]?.match(regex)?.length > 0) {
583
+ arr[numId] = "";
440
584
  }
441
585
  const messageData = `${arr[numId]}{{${data}}}`;
442
586
  arr[numId] = messageData;
443
- varMap[textAreaId] = messageData;
444
- setUpdatedSmsEditor(arr);
587
+ if (type === HEADER_TEXT) {
588
+ setHeaderVarMappedData((prevState) => ({
589
+ ...prevState,
590
+ [areaId]: messageData,
591
+ }));
592
+ setUpdatedHeaderData(arr);
593
+ } else {
594
+ varMap[areaId] = messageData;
595
+ setUpdatedSmsEditor(arr);
596
+ }
445
597
  }
446
598
  }
447
599
  };
448
600
 
601
+ const onMessageTagSelect = (data) => {
602
+ onTagSelect({
603
+ data,
604
+ type: MESSAGE_TEXT,
605
+ mapData: varMap,
606
+ updatedData: updatedSmsEditor,
607
+ areaId: textAreaId,
608
+ regex: validVarRegex,
609
+ });
610
+ };
611
+
612
+ const onHeaderTagSelect = (data) => {
613
+ onTagSelect({
614
+ data,
615
+ type: HEADER_TEXT,
616
+ mapData: headerVarMappedData,
617
+ updatedData: updatedHeaderData,
618
+ areaId: headerTextAreaId,
619
+ regex: headerValidVarRegex,
620
+ });
621
+ };
622
+
449
623
  //setting the id of currently selected text area, is used onTagSelect
450
- const setTextAreaId = ({ target: { id } }) => {
451
- updateTextAreaId(id);
624
+ const setTextAreaId = ({ target: { id } }, type) => {
625
+ if (type === HEADER_TEXT) {
626
+ setHeaderTextAreaId(id);
627
+ } else {
628
+ updateTextAreaId(id);
629
+ }
452
630
  };
453
631
  // tag Code end
454
632
 
@@ -528,10 +706,11 @@ export const Whatsapp = (props) => {
528
706
  disabled: host === HOST_TWILIO,
529
707
  },
530
708
  ];
531
-
709
+ const isAuthenticationTemplate = isEqual(templateCategory, WHATSAPP_CATEGORIES.authentication);
532
710
  const onChangeButtonType = ({ target: { value } }) => {
533
711
  setButtonType(value);
534
712
  setCtadata(INITIAL_CTA_DATA);
713
+ setQuickReplyData(INITIAL_QUICK_REPLY_DATA);
535
714
  };
536
715
 
537
716
  const updateHandler = (data, index, full) => {
@@ -557,6 +736,42 @@ export const Whatsapp = (props) => {
557
736
  });
558
737
  };
559
738
 
739
+ const computeTextLength = (type) => {
740
+ switch (type) {
741
+ case MESSAGE_TEXT:
742
+ let whatsappContentLen = 0;
743
+ whatsappContentLen = isEditFlow
744
+ ? updatedSmsEditor?.join("")?.length
745
+ : templateMessage?.length;
746
+ whatsappContentLen += unsubscribeRequired ? UNSUBSCRIBE_TEXT_LENGTH : 0;
747
+ return whatsappContentLen;
748
+ case HEADER_TEXT:
749
+ let headerContentLen = 0;
750
+ headerContentLen = isEditFlow
751
+ ? updatedHeaderData?.join("")?.length
752
+ : templateHeader?.length;
753
+ return headerContentLen || 0;
754
+ case FOOTER_TEXT:
755
+ return templateFooter?.length || 0;
756
+ default:
757
+ let overallLength =
758
+ computeTextLength(MESSAGE_TEXT) +
759
+ computeTextLength(HEADER_TEXT) +
760
+ computeTextLength(FOOTER_TEXT);
761
+ return overallLength;
762
+ }
763
+ };
764
+
765
+ //used by create and edit
766
+ const renderMessageLength = (type, currentLength) => (
767
+ <CapHeading type="label1" className="whatsapp-render-message-length">
768
+ {formatMessage(messages.templateMessageLength, {
769
+ currentLength: currentLength ? currentLength : computeTextLength(type),
770
+ maxLength: maxLengthByType(type),
771
+ })}
772
+ </CapHeading>
773
+ );
774
+
560
775
  const buttonRadioOptions = [
561
776
  {
562
777
  value: WHATSAPP_BUTTON_TYPES.NONE,
@@ -591,25 +806,26 @@ export const Whatsapp = (props) => {
591
806
  {
592
807
  value: WHATSAPP_BUTTON_TYPES.QUICK_REPLY,
593
808
  label: (
594
- <CapTooltip
595
- placement="bottom"
596
- title={!isEditFlow && formatMessage(messages.disabledFeatureTooltip)}
597
- >
809
+ <>
598
810
  <div
599
811
  className="whatsapp-button-quick-reply"
600
- style={{
601
- marginTop: isBtnTypeCta ? '0px' : '24px',
602
- opacity: isEditFlow ? '' : '0.4',
603
- }}
604
812
  >
605
813
  <CapHeading type="h4">
606
814
  {formatMessage(messages.btnTypeQuickReply)}
607
815
  </CapHeading>
608
816
  <CapLabel>{formatMessage(messages.quickReplyDesc)}</CapLabel>
609
817
  </div>
610
- </CapTooltip>
818
+ {isBtnTypeQuickReply && (
819
+ <CapWhatsappQuickReply
820
+ quickReplyData={quickReplyData}
821
+ isEditFlow={isEditFlow}
822
+ renderMessageLength={renderMessageLength}
823
+ setQuickReplyData={setQuickReplyData}
824
+ />
825
+ )}
826
+ </>
611
827
  ),
612
- disabled: true,
828
+ disabled: host === HOST_TWILIO
613
829
  },
614
830
  ];
615
831
 
@@ -621,15 +837,45 @@ export const Whatsapp = (props) => {
621
837
 
622
838
  const unsubscribeHandler = ({ target: { checked } }) => {
623
839
  setUnsubscribeRequired(checked);
840
+ if (isAuthenticationTemplate) {
841
+ if (checked && !templateMessage?.includes(formatMessage(messages.securitySuffix))) {
842
+ setTemplateMessage(`${templateMessage} ${formatMessage(messages.securitySuffix)}`);
843
+ } else {
844
+ setTemplateMessage(formatMessage(messages.authenticationMsg));
845
+ }
846
+ }
847
+ const error = templateMessageErrorHandler(templateMessage);
848
+ setTemplateMessageError(error);
849
+ };
850
+
851
+ const extraSecurityFooter = ({ target: { checked = false } } = {}) => {
852
+ setSecurityWarningReqd(checked);
853
+ setExpiryMinutes(0);
854
+ if (checked) {
855
+ setTemplateFooter(formatMessage(messages.codeExpiryNumMinutes).replace(formatMessage(messages.numMinutes), ''));
856
+ } else {
857
+ setTemplateFooter("");
858
+ }
624
859
  const error = templateMessageErrorHandler(templateMessage);
625
860
  setTemplateMessageError(error);
626
861
  };
627
862
 
863
+ const changeExpiryMinutes =(event) => {
864
+ setExpiryMinutes(event);
865
+ const footerContent =`${formatMessage(
866
+ messages.codeExpiryNumMinutes,
867
+ )}` ;
868
+ setTemplateFooter(footerContent.replace(formatMessage(messages.numMinutes), event));
869
+ }
870
+
628
871
  const renderUnsubscribeText = () => {
629
872
  const isDisabled =
630
873
  isEditFlow ||
631
- templateMessage.length + UNSUBSCRIBE_TEXT_LENGTH >
874
+ templateMessage?.length + UNSUBSCRIBE_TEXT_LENGTH >
632
875
  TEMPLATE_MESSAGE_MAX_LENGTH;
876
+ const messageFooter = isAuthenticationTemplate ?
877
+ formatMessage(messages.templateSecurityDisclaimer):
878
+ formatMessage(messages.templateMessageUnsubscribeText, { unsubscribe: '{{unsubscribe}}' });
633
879
  return (
634
880
  <>
635
881
  <CapColumn span={12}>
@@ -654,35 +900,27 @@ export const Whatsapp = (props) => {
654
900
  }
655
901
  >
656
902
  <span className="whatsapp-render-unsubscribe-text">
657
- {formatMessage(messages.templateMessageUnsubscribeText, { unsubscribe: '{{unsubscribe}}'})}
903
+ {messageFooter}
658
904
  </span>
659
905
  </CapTooltip>
660
906
  </CapCheckbox>
661
907
  </CapColumn>
662
- <CapColumn span={12}></CapColumn>
663
908
  </>
664
909
  );
665
910
  };
666
911
 
667
- const computeTextLength = () => {
668
- let whatsappContentLen = 0;
669
- whatsappContentLen = isEditFlow
670
- ? updatedSmsEditor.join('').length
671
- : templateMessage.length;
672
- whatsappContentLen += unsubscribeRequired ? UNSUBSCRIBE_TEXT_LENGTH : 0;
673
- return whatsappContentLen;
912
+ const maxLengthByType = (type) => {
913
+ switch (type) {
914
+ case MESSAGE_TEXT:
915
+ return TEMPLATE_MESSAGE_MAX_LENGTH;
916
+ case HEADER_TEXT:
917
+ case FOOTER_TEXT:
918
+ return TEMPLATE_HEADER_MAX_LENGTH;
919
+ case BUTTON_TEXT:
920
+ return QUICK_REPLY_BUTTON_TEXT_MAX_LENGTH;
921
+ }
674
922
  };
675
923
 
676
- //used by create and edit
677
- const renderMessageLength = () => (
678
- <CapHeading type="label1" className="whatsapp-render-message-length">
679
- {formatMessage(messages.templateMessageLength, {
680
- currentLength: computeTextLength(),
681
- maxLength: TEMPLATE_MESSAGE_MAX_LENGTH,
682
- })}
683
- </CapHeading>
684
- );
685
-
686
924
  const renderButtonsSection = () => (
687
925
  <>
688
926
  <CapHeader
@@ -692,21 +930,25 @@ export const Whatsapp = (props) => {
692
930
  <CapHeading type="h4">
693
931
  {formatMessage(messages.btnLabel)}
694
932
  </CapHeading>
695
- <CapHeading className="whatsapp-optional-label">
933
+ {!isAuthenticationTemplate && <CapHeading className="whatsapp-optional-label">
696
934
  {formatMessage(messages.optional)}
697
- </CapHeading>
935
+ </CapHeading>}
698
936
  </CapRow>
699
937
  }
700
938
  description={
701
939
  <CapLabel type="label3">{formatMessage(messages.btnDesc)}</CapLabel>
702
940
  }
703
941
  />
704
- <CapRadioGroup
705
- options={buttonRadioOptions}
706
- value={buttonType}
707
- onChange={onChangeButtonType}
708
- className="whatsapp-btn-radio-group"
709
- />
942
+ {isAuthenticationTemplate ?
943
+ <CapWhatsappQuickReply
944
+ authenticationFlow={true}
945
+ /> :
946
+ <CapRadioGroup
947
+ options={buttonRadioOptions}
948
+ value={buttonType}
949
+ onChange={onChangeButtonType}
950
+ className="whatsapp-btn-radio-group"
951
+ />}
710
952
  </>
711
953
  );
712
954
 
@@ -838,13 +1080,33 @@ export const Whatsapp = (props) => {
838
1080
  errorMessage = formatMessage(
839
1081
  globalMessages.emptyTemplateNameErrorMessage,
840
1082
  );
1083
+ } else if (value.length < 3 && host === HOST_GUPSHUP) {
1084
+ errorMessage = formatMessage(messages.templateNameMinCharacters);
841
1085
  } else if (!templateNameRegex.test(value)) {
842
1086
  errorMessage = formatMessage(messages.templateNameRegexErrorMessage);
843
1087
  }
844
1088
  setTemplateNameError(errorMessage);
845
1089
  };
846
1090
 
1091
+ const resetCategoryRelatedStates = () => {
1092
+ setTemplateHeader('');
1093
+ setTemplateFooter('');
1094
+ setExpiryMinutes(0);
1095
+ setUnsubscribeRequired(false);
1096
+ setCtadata({});
1097
+ setQuickReplyData({});
1098
+ setTemplateMediaType(WHATSAPP_MEDIA_TYPES.TEXT)
1099
+ setGupshupMediaFile();
1100
+ setKarixFileHandle('');
1101
+ };
1102
+
847
1103
  const onTemplateCategoryChange = (value) => {
1104
+ if (value === WHATSAPP_CATEGORIES.authentication) {
1105
+ resetCategoryRelatedStates();
1106
+ setTemplateMessage(formatMessage(messages.authenticationMsg));
1107
+ } else {
1108
+ setTemplateMessage('');
1109
+ }
848
1110
  setTemplateCategory(value);
849
1111
  };
850
1112
 
@@ -856,18 +1118,56 @@ export const Whatsapp = (props) => {
856
1118
  setTemplateMediaType(value);
857
1119
  };
858
1120
 
859
- const onAddVar = () => {
860
- const validVarArr = templateMessage.match(validVarRegex) || [];
861
- const tempMsg = `${templateMessage}{{${validVarArr.length + 1}}}`;
862
- const error = templateMessageErrorHandler(tempMsg);
863
- setTemplateMessage(tempMsg);
864
- setTemplateMessageError(error);
1121
+ const onMessageAddVar = () => {
1122
+ onAddVar(MESSAGE_TEXT, templateMessage, validVarRegex);
865
1123
  };
866
1124
 
867
- const onTemplateMessageChange = ({ target: { value } }) => {
868
- const error = templateMessageErrorHandler(value);
869
- setTemplateMessage(value);
870
- setTemplateMessageError(error);
1125
+ const onHeaderAddVar = () => {
1126
+ onAddVar(HEADER_TEXT, templateHeader, headerValidVarRegex);
1127
+ };
1128
+
1129
+ const onAddVar = (type, messageContent, regex) => {
1130
+ const validVarArr = messageContent.match(regex) || [];
1131
+ const tempMsg = `${messageContent}{{${validVarArr.length + 1}}}`;
1132
+ const error = type === HEADER_TEXT ? templateHeaderErrorHandler(tempMsg) : templateMessageErrorHandler(tempMsg);
1133
+ if (type === HEADER_TEXT) {
1134
+ setTemplateHeader(tempMsg);
1135
+ setTemplateHeaderError(error);
1136
+ } else {
1137
+ setTemplateMessage(tempMsg);
1138
+ setTemplateMessageError(error);
1139
+ }
1140
+ }
1141
+
1142
+ const onTemplateValueChange = ({ target: { value } }, type) => {
1143
+ if (type === HEADER_TEXT) {
1144
+ const error = templateHeaderErrorHandler(value);
1145
+ setTemplateHeader(value);
1146
+ setTemplateHeaderError(error);
1147
+ } else {
1148
+ const error = templateMessageErrorHandler(value);
1149
+ setTemplateMessage(value);
1150
+ setTemplateMessageError(error);
1151
+ }
1152
+ }
1153
+
1154
+ const onTemplateFooterChanges = ({ target: { value } }) => {
1155
+ let error = false;
1156
+ if (value?.length > TEMPLATE_HEADER_MAX_LENGTH) {
1157
+ error = formatMessage(messages.templateFooterLengthError);
1158
+ }
1159
+ setTemplateFooter(value);
1160
+ setTemplateFooterError(error);
1161
+ };
1162
+
1163
+ const templateHeaderErrorHandler = (value) => {
1164
+ let errorMessage = false;
1165
+ if (value?.length > TEMPLATE_HEADER_MAX_LENGTH) {
1166
+ errorMessage = formatMessage(messages.templateHeaderLengthError);
1167
+ } else {
1168
+ errorMessage = variableErrorHandling(value, HEADER_TEXT);
1169
+ }
1170
+ return errorMessage;
871
1171
  };
872
1172
 
873
1173
  const templateMessageErrorHandler = (value) => {
@@ -880,41 +1180,58 @@ export const Whatsapp = (props) => {
880
1180
  ) {
881
1181
  errorMessage = formatMessage(messages.templateMessageLengthError);
882
1182
  } else {
883
- const validVarArr = value.match(validVarRegex) || [];
884
- const validVarSet = [...new Set(validVarArr)];
885
-
886
- const invalidVarRegex = /{{(.*?)}}/g;
887
- const invalidVarArr = value.match(invalidVarRegex) || [];
888
- const invalidVarSet = [...new Set(invalidVarArr)];
889
-
890
- const noContentBetweenVars = /}}\s*{{/g;
891
- const moreThanTwoBrackets = /{{3,}([1-9]|1[0-9])}{3,}/g;
892
- const consecutiveNewLines = /\n\s*\n\s*\n/;
893
- if (value.match(consecutiveNewLines)) {
894
- errorMessage = formatMessage(messages.removeMultinewlineChars);
895
- } else if (validVarArr?.length > 0 || invalidVarArr?.length > 0) {
896
- if (validVarArr?.length !== validVarSet?.length) {
897
- //checks for repetations like Hi {{1}}, offer for you {{1}}
898
- errorMessage = formatMessage(messages.repetativeVars);
899
- } else if (invalidVarSet?.length !== validVarSet?.length) {
900
- //checks for invalid vars like Hi {{abcd}}, offer for you {{^_^}}
901
- errorMessage = formatMessage(messages.unknownVars, {one: '{{1}}', nineteen: '{{19}}'});
902
- } else if (value.match(noContentBetweenVars)?.length > 0) {
903
- //checks for text between vars like Hi {{1}}{{2}}
904
- errorMessage = formatMessage(messages.noContentBetweenVars);
905
- } else if (value.match(moreThanTwoBrackets)?.length > 0) {
906
- //checks for >2 brackets {{{1}}}
907
- errorMessage = formatMessage(messages.useTwoBracketsOnly);
1183
+ errorMessage = variableErrorHandling(value, MESSAGE_TEXT);
1184
+ }
1185
+ //we are not allowing user input incase of authentication flow
1186
+ if(isAuthenticationTemplate){
1187
+ errorMessage = false;
1188
+ }
1189
+ return errorMessage;
1190
+ };
1191
+
1192
+ const variableErrorHandling = (value, type) => {
1193
+ let errorMessage = false;
1194
+ const validVarArr = value.match(type === HEADER_TEXT ? headerValidVarRegex : validVarRegex) || [];
1195
+ const validVarSet = [...new Set(validVarArr)];
1196
+
1197
+ const invalidVarRegex = /{{(.*?)}}/g;
1198
+ const invalidVarArr = value.match(invalidVarRegex) || [];
1199
+ const invalidVarSet = [...new Set(invalidVarArr)];
1200
+
1201
+ const noContentBetweenVars = /}}\s*{{/g;
1202
+ const moreThanTwoBrackets = /{{3,}([1-9]|1[0-9])}{3,}/g;
1203
+ const consecutiveNewLines = /\n\s*\n\s*\n/;
1204
+ if (value.match(consecutiveNewLines)) {
1205
+ errorMessage = formatMessage(messages.removeMultinewlineChars);
1206
+ } else if (validVarArr?.length > 0 || invalidVarArr?.length > 0) {
1207
+ if (validVarArr?.length !== validVarSet?.length) {
1208
+ //checks for repetations like Hi {{1}}, offer for you {{1}}
1209
+ errorMessage = formatMessage(messages.repetativeVars);
1210
+ } else if (invalidVarSet?.length !== validVarSet?.length) {
1211
+ //checks for invalid vars like Hi {{abcd}}, offer for you {{^_^}}
1212
+ if (type === HEADER_TEXT) {
1213
+ errorMessage = formatMessage(messages.headerUnknownVars);
908
1214
  } else {
909
- //checks if vars are added sequentially like, Hi {{1}}, offer for you {{2}} today {{3}}
910
- const checkSequence = [...validVarSet].filter(
911
- (validVar, index) => `{{${index + 1}}}` !== validVar,
912
- );
913
- if (checkSequence?.length > 0) {
914
- errorMessage = formatMessage(messages.sequenceVars, {one: '{{1}}'});
915
- } else {
916
- setAddedVarCount(validVarSet?.length || 0);
917
- }
1215
+ errorMessage = formatMessage(messages.unknownVars, {
1216
+ one: "{{1}}",
1217
+ nineteen: "{{19}}",
1218
+ });
1219
+ }
1220
+ } else if (value.match(noContentBetweenVars)?.length > 0) {
1221
+ //checks for text between vars like Hi {{1}}{{2}}
1222
+ errorMessage = formatMessage(messages.noContentBetweenVars);
1223
+ } else if (value.match(moreThanTwoBrackets)?.length > 0) {
1224
+ //checks for >2 brackets {{{1}}}
1225
+ errorMessage = formatMessage(messages.useTwoBracketsOnly);
1226
+ } else {
1227
+ //checks if vars are added sequentially like, Hi {{1}}, offer for you {{2}} today {{3}}
1228
+ const checkSequence = [...validVarSet].filter(
1229
+ (validVar, index) => `{{${index + 1}}}` !== validVar
1230
+ );
1231
+ if (checkSequence?.length > 0) {
1232
+ errorMessage = formatMessage(messages.sequenceVars, { one: "{{1}}" });
1233
+ } else {
1234
+ if (type === MESSAGE_TEXT) setAddedVarCount(validVarSet?.length || 0);
918
1235
  }
919
1236
  }
920
1237
  }
@@ -927,11 +1244,12 @@ export const Whatsapp = (props) => {
927
1244
  if (unsubscribeRequired) {
928
1245
  return `${updatedSmsEditor.join('')}\n${formatMessage(
929
1246
  messages.templateMessageUnsubscribeText,
1247
+ { unsubscribe: "{{unsubscribe}}" }
930
1248
  )}`;
931
1249
  }
932
1250
  //campaigns edit flow + unsubscribeNotRequired
933
1251
  return updatedSmsEditor.join('');
934
- } else if (unsubscribeRequired) {
1252
+ } else if (unsubscribeRequired && !isAuthenticationTemplate) {
935
1253
  //creatives create and edit flow + unsubscribeRequired
936
1254
  return `${templateMessage}\n${formatMessage(
937
1255
  messages.modifiedUnsubscribeText,
@@ -963,13 +1281,23 @@ export const Whatsapp = (props) => {
963
1281
  };
964
1282
  });
965
1283
 
1284
+ const getQuickReplyData = () =>
1285
+ quickReplyData.map((quickReply) => {
1286
+ const { index, text, type } = quickReply;
1287
+ return {
1288
+ index,
1289
+ text,
1290
+ type,
1291
+ };
1292
+ });
1293
+
966
1294
  const createPayload = () => {
967
1295
  let mediaParams = {};
968
1296
  const { whatsappVideoSrc = '', whatsappVideoPreviewImg = '' } = whatsappVideoSrcAndPreview;
969
1297
  switch (templateMediaType) {
970
1298
  case WHATSAPP_MEDIA_TYPES.IMAGE:
971
1299
  mediaParams = {
972
- imageUrl: getCdnUrl({url: whatsappImageSrc, channelName: WHATSAPP }),
1300
+ imageUrl: getCdnUrl({ url: whatsappImageSrc, channelName: WHATSAPP }),
973
1301
  karixFileHandle,
974
1302
  };
975
1303
  break;
@@ -990,7 +1318,7 @@ export const Whatsapp = (props) => {
990
1318
  default:
991
1319
  break;
992
1320
  }
993
- return ({
1321
+ return {
994
1322
  name: templateName,
995
1323
  versions: {
996
1324
  base: {
@@ -1010,16 +1338,35 @@ export const Whatsapp = (props) => {
1010
1338
  mediaType: templateMediaType,
1011
1339
  ...mediaParams,
1012
1340
  varMapped: !isFullMode ? varMap : {},
1013
- templateEditor: !isFullMode && tempMsgArray.join(''),
1341
+ templateEditor: !isFullMode && tempMsgArray.join(""),
1014
1342
  accountId,
1015
1343
  accessToken,
1016
1344
  hostName: host,
1345
+ ...(isBtnTypeQuickReply && {
1346
+ buttonType,
1347
+ buttons: getQuickReplyData(),
1348
+ }),
1349
+ whatsappMedia: {
1350
+ ...(isMediaTypeText && isHostIsNotTwilio && {
1351
+ header: isEditFlow && !isFullMode ? updatedHeaderData.join("") : templateHeader,
1352
+ headerVarMapped: !isFullMode ? headerVarMappedData : {},
1353
+ headerTemplate: !isFullMode && tempHeaderData.join(""),
1354
+ }),
1355
+ ...(isHostIsNotTwilio && {
1356
+ footer: templateFooter || ""
1357
+ }),
1358
+ },
1359
+ ...(isEditFlow && !isFullMode && {
1360
+ isPreviewUrl: showUrlPreview
1361
+ }),
1362
+ securityRecommendation: unsubscribeRequired,
1363
+ codeExpiryMinutes: expiryMinutes,
1017
1364
  },
1018
1365
  },
1019
1366
  },
1020
1367
  },
1021
1368
  type: WHATSAPP,
1022
- });
1369
+ };
1023
1370
  };
1024
1371
 
1025
1372
  const actionCallback = ({ errorMessage }) => {
@@ -1063,7 +1410,8 @@ export const Whatsapp = (props) => {
1063
1410
  type: WHATSAPP,
1064
1411
  });
1065
1412
  };
1066
-
1413
+ const isMediatypeValid =()=> ((isMediaTypeImage && whatsappImageSrc === "") || (isMediaTypeVideo && whatsappVideoSrcAndPreview?.whatsappVideoSrc === "") || (isMediaTypeDoc && whatsappDocSource === ""));
1414
+
1067
1415
  const isDisableDone = () => {
1068
1416
  //if template name is not entered
1069
1417
  if (templateName.trim() === '' || templateNameError) {
@@ -1078,11 +1426,15 @@ export const Whatsapp = (props) => {
1078
1426
  return true;
1079
1427
  }
1080
1428
  //if template message is not entered
1081
- if (templateMessage.trim() === '' || templateMessageError) {
1429
+ if (templateMessage?.trim() === '' || templateMessageError) {
1082
1430
  return true;
1083
1431
  }
1084
1432
  //if media type is image, video or document and the mediaType file is not uploaded
1085
- if (!isMediaTypeText && host === HOST_KARIX && karixFileHandle === '') {
1433
+
1434
+ if (!isMediaTypeText && isMediatypeValid() ) {
1435
+ return true;
1436
+ }
1437
+ if (templateHeaderError || templateFooterError) {
1086
1438
  return true;
1087
1439
  }
1088
1440
  //cta
@@ -1101,19 +1453,27 @@ export const Whatsapp = (props) => {
1101
1453
  //if button type is cta and there are no buttons saved
1102
1454
  return true;
1103
1455
  }
1456
+
1457
+ if(isAuthenticationTemplate && securityWarningReqd && !expiryMinutes){
1458
+ return true;
1459
+ }
1460
+ if (isBtnTypeQuickReply) {
1461
+ return !quickReplyData.every((quickReply) => quickReply?.isSaved === true);
1462
+ }
1104
1463
  return false;
1105
1464
  };
1106
1465
 
1107
1466
  const renderMediaSection = () => (
1108
1467
  <>
1109
- {renderLabel('mediaLabel')}
1110
- <CapRadioGroup
1111
- id="whatsapp-media-radio"
1112
- options={mediaRadioOptions}
1113
- value={templateMediaType}
1114
- onChange={onTemplateMediaTypeChange}
1115
- className="whatsapp-media-radio"
1116
- />
1468
+ {!isAuthenticationTemplate && <>{renderLabel('mediaLabel')}
1469
+ <CapRadioGroup
1470
+ id="whatsapp-media-radio"
1471
+ options={mediaRadioOptions}
1472
+ value={templateMediaType}
1473
+ onChange={onTemplateMediaTypeChange}
1474
+ className="whatsapp-media-radio"
1475
+ />
1476
+ </>}
1117
1477
  </>
1118
1478
  );
1119
1479
 
@@ -1133,9 +1493,7 @@ export const Whatsapp = (props) => {
1133
1493
  <CapHeading type="h4">
1134
1494
  {formatMessage(globalMessages.templateNameLabel)}
1135
1495
  <CapTooltipWithInfo
1136
- infoIconProps={{
1137
- style: { marginLeft: CAP_SPACE_04 },
1138
- }}
1496
+ className="whatsapp-text-field_spacing"
1139
1497
  autoAdjustOverflow
1140
1498
  title={<FormattedMessage {...messages.templateNameTooltip} />}
1141
1499
  />
@@ -1152,22 +1510,24 @@ export const Whatsapp = (props) => {
1152
1510
  onChange={onTemplateNameChange}
1153
1511
  errorMessage={templateNameError}
1154
1512
  placeholder={formatMessage(globalMessages.templateNamePlaceholder)}
1155
- defaultValue={templateName || ''}
1156
- value={templateName || ''}
1513
+ defaultValue={templateName || ""}
1514
+ value={templateName || ""}
1157
1515
  size="default"
1158
1516
  />
1159
1517
  {/* template category */}
1160
- {renderLabel('templateCategoryLabel')}
1518
+ {renderLabel("templateCategoryLabel")}
1161
1519
  <CapSelect
1162
1520
  id="select-whatsapp-category"
1163
1521
  options={
1164
- host === HOST_TWILIO ? twilioCategoryOptions : karixGupshupCategoryOptions
1522
+ host === HOST_TWILIO
1523
+ ? twilioCategoryOptions
1524
+ : karixGupshupCategoryOptions
1165
1525
  }
1166
1526
  onChange={onTemplateCategoryChange}
1167
1527
  value={templateCategory}
1168
1528
  />
1169
1529
  {/* template language */}
1170
- {renderLabel('messageLanguageLabel')}
1530
+ {renderLabel("messageLanguageLabel")}
1171
1531
  <CapSelect
1172
1532
  id="select-whatsapp-language"
1173
1533
  options={LANGUAGE_OPTIONS || []}
@@ -1177,24 +1537,77 @@ export const Whatsapp = (props) => {
1177
1537
  {/* template media type */}
1178
1538
  {renderMediaSection()}
1179
1539
  {renderMediaComponent()}
1540
+ {/* this section is for header section in create mode */}
1541
+ {isMediaTypeText && isHostIsNotTwilio && !isAuthenticationTemplate && (
1542
+ <>
1543
+ <CapHeader
1544
+ title={
1545
+ <CapHeading type="h4" className="whatsapp-create-mode-heading">
1546
+ {formatMessage(messages.templateHeaderLabel)}
1547
+ <CapTooltipWithInfo
1548
+ placement="right"
1549
+ className="whatsapp-text-field_spacing"
1550
+ autoAdjustOverflow
1551
+ title={
1552
+ <FormattedMessage {...messages.templateHeaderTooltip} />
1553
+ }
1554
+ />
1555
+ <CapHeading className="whatsapp-optional-label1 align-item-center">
1556
+ {formatMessage(messages.optional)}
1557
+ </CapHeading>
1558
+ </CapHeading>
1559
+ }
1560
+ suffix={
1561
+ <CapButton
1562
+ type="flat"
1563
+ isAddBtn
1564
+ onClick={onHeaderAddVar}
1565
+ disabled={
1566
+ ((templateHeader.match(headerValidVarRegex) || []).length >
1567
+ 0 ||
1568
+ templateHeaderError) &&
1569
+ templateHeader
1570
+ }
1571
+ >
1572
+ {formatMessage(messages.addVar)}
1573
+ </CapButton>
1574
+ }
1575
+ />
1576
+ <CapRow className="whatsapp-create-template-message-input whatsapp-create-template-header-input">
1577
+ <TextArea
1578
+ id="whatsapp-create-template-message-input"
1579
+ autosize={{ minRows: 1, maxRows: 5 }}
1580
+ placeholder={formatMessage(messages.templateMessagePlaceholder)}
1581
+ onChange={(e) => onTemplateValueChange(e, HEADER_TEXT)}
1582
+ errorMessage={
1583
+ templateHeaderError && (
1584
+ <CapError className="whatsapp-template-message-error">
1585
+ {templateHeaderError}
1586
+ </CapError>
1587
+ )
1588
+ }
1589
+ value={templateHeader || ""}
1590
+ />
1591
+ </CapRow>
1592
+ {renderMessageLength(HEADER_TEXT)}
1593
+ </>
1594
+ )}
1180
1595
  {/* template message create flow */}
1181
1596
  <CapHeader
1182
- className={`${isMediaTypeImage ? 'whatsapp-heading-spacing' : ''}`}
1597
+ className={`${isMediaTypeImage ? "whatsapp-heading-spacing" : ""}`}
1183
1598
  title={
1184
1599
  <CapHeading type="h4" className="whatsapp-render-heading">
1185
1600
  {formatMessage(messages.templateMessageLabel)}
1186
1601
  <CapTooltipWithInfo
1187
1602
  placement="right"
1188
- infoIconProps={{
1189
- style: { marginLeft: CAP_SPACE_04 },
1190
- }}
1603
+ className="whatsapp-text-field_spacing"
1191
1604
  autoAdjustOverflow
1192
1605
  title={
1193
1606
  <FormattedMessage
1194
1607
  {...messages.templateMessageTooltip}
1195
1608
  values={{
1196
1609
  br: <br />,
1197
- var: '{{1}}',
1610
+ var: "{{1}}",
1198
1611
  }}
1199
1612
  />
1200
1613
  }
@@ -1202,16 +1615,22 @@ export const Whatsapp = (props) => {
1202
1615
  </CapHeading>
1203
1616
  }
1204
1617
  suffix={
1205
- <CapButton
1206
- type="flat"
1207
- isAddBtn
1208
- onClick={onAddVar}
1209
- disabled={
1210
- (addedVarCount >= 19 || templateMessageError) && templateMessage
1211
- }
1212
- >
1213
- {formatMessage(messages.addVar)}
1214
- </CapButton>
1618
+ <>
1619
+ {!isAuthenticationTemplate && (
1620
+ <CapButton
1621
+ data-testid="suffix-button"
1622
+ type="flat"
1623
+ isAddBtn
1624
+ onClick={onMessageAddVar}
1625
+ disabled={
1626
+ (addedVarCount >= 19 || templateMessageError) &&
1627
+ templateMessage
1628
+ }
1629
+ >
1630
+ {formatMessage(messages.addVar)}
1631
+ </CapButton>
1632
+ )}
1633
+ </>
1215
1634
  }
1216
1635
  />
1217
1636
  <CapRow className="whatsapp-create-template-message-input">
@@ -1219,7 +1638,7 @@ export const Whatsapp = (props) => {
1219
1638
  id="whatsapp-create-template-message-input"
1220
1639
  autosize={{ minRows: 3, maxRows: 5 }}
1221
1640
  placeholder={formatMessage(messages.templateMessagePlaceholder)}
1222
- onChange={onTemplateMessageChange}
1641
+ onChange={(e) => onTemplateValueChange(e, MESSAGE_TEXT)}
1223
1642
  errorMessage={
1224
1643
  templateMessageError && (
1225
1644
  <CapError className="whatsapp-template-message-error">
@@ -1227,11 +1646,120 @@ export const Whatsapp = (props) => {
1227
1646
  </CapError>
1228
1647
  )
1229
1648
  }
1230
- value={templateMessage || ''}
1649
+ value={templateMessage || ""}
1650
+ disabled={isAuthenticationTemplate}
1231
1651
  />
1232
1652
  {renderUnsubscribeText()}
1233
1653
  </CapRow>
1234
- {renderMessageLength()}
1654
+ {renderMessageLength(MESSAGE_TEXT)}
1655
+ {/* this section if for footer in create mode */}
1656
+ {isHostIsNotTwilio && (
1657
+ <>
1658
+ <CapHeader
1659
+ className={`${isMediaTypeImage ? "whatsapp-heading-spacing" : ""}`}
1660
+ title={
1661
+ <CapHeading type="h4" className="whatsapp-create-mode-heading">
1662
+ {formatMessage(messages.templateFooterLabel)}
1663
+ <CapTooltipWithInfo
1664
+ placement="right"
1665
+ className="whatsapp-text-field_spacing"
1666
+ autoAdjustOverflow
1667
+ title={
1668
+ <FormattedMessage {...messages.templateFooterTooltip} />
1669
+ }
1670
+ />
1671
+ <CapHeading className="whatsapp-optional-label1 align-item-center">
1672
+ {formatMessage(messages.optional)}
1673
+ </CapHeading>
1674
+ </CapHeading>
1675
+ }
1676
+ />
1677
+ <CapRow className="whatsapp-create-template-message-input whatsapp-create-template-header-input">
1678
+ {isAuthenticationTemplate ? (
1679
+ <CapRow className="whatsapp-extra-security-footer">
1680
+ <CapCheckbox
1681
+ onChange={extraSecurityFooter}
1682
+ checked={securityWarningReqd}
1683
+ disabled={isEditFlow}
1684
+ autoFocus={true}
1685
+ className="whatsapp-unsubscribe-checkbox"
1686
+ >
1687
+ <CapLabel.CapLabelInline
1688
+ type="label2"
1689
+ className="whatsapp-render-unsubscribe-text"
1690
+ >
1691
+ {formatMessage(messages.expirationWarning)}
1692
+ </CapLabel.CapLabelInline>
1693
+ </CapCheckbox>
1694
+ {securityWarningReqd && (
1695
+ <>
1696
+ <CapRow className="whatsapp-extra-security-footer-input">
1697
+ {formatMessage(messages.codeExpiresIn)}
1698
+ <CapInput.Number
1699
+ min={0}
1700
+ max={90}
1701
+ placeholder={formatMessage(messages.enterExpiryTime)}
1702
+ onChange={(event) => changeExpiryMinutes(event)}
1703
+ />
1704
+ {formatMessage(messages.minutes)}
1705
+ </CapRow>
1706
+ <CapRow className="whatsapp-extra-security-footer-note">
1707
+ {formatMessage(messages.expiryCodeNote)}
1708
+ <CapTooltip
1709
+ title={
1710
+ <CapHeader
1711
+ titleClass="whatsapp-tooltip-header"
1712
+ descriptionClass="whatsapp-tooltip-header"
1713
+ size="regular"
1714
+ title={formatMessage(
1715
+ messages.checkExpiryTooltipHeader
1716
+ )}
1717
+ description={formatMessage(
1718
+ messages.checkExpiryTooltipDesc
1719
+ )}
1720
+ />
1721
+ }
1722
+ >
1723
+
1724
+ <CapButton
1725
+ type="flat"
1726
+ className="add-btn"
1727
+ onClick={() =>
1728
+ window.open(
1729
+ `${window.location.origin}${OTP_CONFIG_URI}`,
1730
+ "_blank"
1731
+ )
1732
+ }
1733
+ >
1734
+ {formatMessage(messages.checkExpiryCode)}
1735
+ <CapIcon size="s" type="launch"/>
1736
+ </CapButton>
1737
+ </CapTooltip>
1738
+ </CapRow>
1739
+ </>
1740
+ )}
1741
+ </CapRow>
1742
+ ) : (
1743
+ <TextArea
1744
+ id="whatsapp-create-template-message-input"
1745
+ autosize={{ minRows: 1, maxRows: 5 }}
1746
+ placeholder={formatMessage(messages.templateMessagePlaceholder)}
1747
+ onChange={onTemplateFooterChanges}
1748
+ errorMessage={
1749
+ templateFooterError && (
1750
+ <CapError className="whatsapp-template-message-error">
1751
+ {templateFooterError}
1752
+ </CapError>
1753
+ )
1754
+ }
1755
+ value={templateFooter || ""}
1756
+ disabled={isAuthenticationTemplate}
1757
+ />
1758
+ )}
1759
+ </CapRow>
1760
+ {renderMessageLength(FOOTER_TEXT)}
1761
+ </>
1762
+ )}
1235
1763
  {renderButtonsSection()}
1236
1764
  </>
1237
1765
  );
@@ -1315,39 +1843,55 @@ export const Whatsapp = (props) => {
1315
1843
  };
1316
1844
 
1317
1845
  // on change event of Text Area
1318
- const textAreaValueChange = ({ target: { value, id } }) => {
1319
- const numId = Number(id.slice(id.indexOf('_') + 1));
1320
- const arr = [...updatedSmsEditor];
1321
-
1846
+ const textAreaValueChange = ({ target: { value, id } }, type) => {
1847
+ const numId = Number(id.slice(id.indexOf("_") + 1));
1322
1848
  //assign entered value to varMap
1323
- varMap[id] = value;
1324
- //based on entered value update updatedSmsEditor
1325
- if (value === '') {
1326
- arr[numId] = id.slice(0, id.indexOf('_'));
1849
+ if (type === HEADER_TEXT) {
1850
+ const arr = [...updatedHeaderData];
1851
+ setHeaderVarMappedData((prevState) => ({
1852
+ ...prevState,
1853
+ [id]: value,
1854
+ }));
1855
+ if (value === "") {
1856
+ arr[numId] = id.slice(0, id.indexOf("_"));
1857
+ } else {
1858
+ arr[numId] = value;
1859
+ }
1860
+ setUpdatedHeaderData(arr);
1327
1861
  } else {
1328
- arr[numId] = value;
1862
+ const arr = [...updatedSmsEditor];
1863
+ varMap[id] = value;
1864
+ //based on entered value update updatedSmsEditor
1865
+ if (value === "") {
1866
+ arr[numId] = id.slice(0, id.indexOf("_"));
1867
+ } else {
1868
+ arr[numId] = value;
1869
+ }
1870
+ setUpdatedSmsEditor(arr);
1329
1871
  }
1330
- setUpdatedSmsEditor(arr);
1331
1872
  };
1332
1873
 
1333
- const textAreaValue = (idValue) => {
1334
- if (idValue >= 0 && updatedSmsEditor) {
1335
- const value = updatedSmsEditor[idValue];
1874
+ const textAreaValue = (idValue, type) => {
1875
+ if (idValue >= 0) {
1876
+ const value =
1877
+ type === HEADER_TEXT
1878
+ ? updatedHeaderData[idValue]
1879
+ : updatedSmsEditor[idValue];
1336
1880
  //if value is there and it is not a variable return it
1337
- if (value && (value.match(validVarRegex) || []).length === 0) {
1881
+ if (value && (value.match(type === HEADER_TEXT ? headerValidVarRegex : validVarRegex) || []).length === 0) {
1338
1882
  return value;
1339
1883
  }
1340
1884
  }
1341
- return '';
1885
+ return "";
1342
1886
  };
1343
1887
 
1344
- const renderedEditMessage = () => {
1888
+ const renderedEditMessage = (messageData, type) => {
1345
1889
  const renderArray = [];
1346
- if (tempMsgArray?.length !== 0) {
1890
+ if (messageData?.length !== 0) {
1347
1891
  let varCount = 0;
1348
- tempMsgArray.forEach((elem, index) => {
1892
+ messageData.forEach((elem, index) => {
1349
1893
  // if var return textarea else return text
1350
- if (elem.match(validVarRegex)?.length > 0) {
1894
+ if (elem.match(type === HEADER_TEXT ? headerValidVarRegex : validVarRegex)?.length > 0) {
1351
1895
  varCount += 1;
1352
1896
  renderArray.push(
1353
1897
  <TextArea
@@ -1357,11 +1901,11 @@ export const Whatsapp = (props) => {
1357
1901
  value: `{{${varCount}}}`,
1358
1902
  })}
1359
1903
  autosize={{ minRows: 1, maxRows: 3 }}
1360
- onChange={textAreaValueChange}
1361
- value={textAreaValue(index)}
1362
- onFocus={setTextAreaId}
1904
+ onChange={(e) => textAreaValueChange(e, type)}
1905
+ value={textAreaValue(index, type)}
1906
+ onFocus={(e) => setTextAreaId(e, type)}
1363
1907
  disabled={templateStatus !== WHATSAPP_STATUSES.approved}
1364
- />,
1908
+ />
1365
1909
  );
1366
1910
  } else {
1367
1911
  renderArray.push(
@@ -1371,19 +1915,21 @@ export const Whatsapp = (props) => {
1371
1915
  className="whatsapp-edit-template-message-heading"
1372
1916
  >
1373
1917
  {elem}
1374
- </CapHeading>,
1918
+ </CapHeading>
1375
1919
  );
1376
1920
  }
1377
1921
  });
1378
1922
  }
1379
- renderArray.push(renderUnsubscribeText());
1923
+ if (type !== HEADER_TEXT) {
1924
+ renderArray.push(renderUnsubscribeText());
1925
+ }
1380
1926
  return renderArray;
1381
1927
  };
1382
1928
 
1383
1929
  const disabledEditTooltipRender = () => {
1384
1930
  switch (templateStatus) {
1385
1931
  case WHATSAPP_STATUSES.approved:
1386
- return '';
1932
+ return "";
1387
1933
  case WHATSAPP_STATUSES.rejected:
1388
1934
  return formatMessage(messages.disabledEditTooltip, {
1389
1935
  status: templateStatus,
@@ -1395,9 +1941,10 @@ export const Whatsapp = (props) => {
1395
1941
  }
1396
1942
  };
1397
1943
 
1398
- const tagValidationErrorMessage = () => {
1399
- const { unsupportedTags = [], isBraceError} = tagValidationResponse;
1400
- let tagError = '';
1944
+ const tagValidationErrorMessage = (type) => {
1945
+ const { unsupportedTags = [], isBraceError } =
1946
+ type === HEADER_TEXT ? headerTagValidationResponse : tagValidationResponse;
1947
+ let tagError = "";
1401
1948
  if (unsupportedTags.length > 0) {
1402
1949
  tagError = formatMessage(globalMessages.unsupportedTagsValidationError, {
1403
1950
  unsupportedTags,
@@ -1418,9 +1965,53 @@ export const Whatsapp = (props) => {
1418
1965
  />
1419
1966
  )}
1420
1967
  {/* template media type */}
1421
- {renderLabel('mediaLabel')}
1968
+ {renderLabel("mediaLabel")}
1422
1969
  <CapLabel type="label15">{capitalizeString(templateMediaType)}</CapLabel>
1423
1970
  {renderMediaComponent()}
1971
+ {/* this section is for render header section */}
1972
+ {(templateHeader && isMediaTypeText && isHostIsNotTwilio) && (
1973
+ <>
1974
+ <CapRow className="whatsapp-render-heading">
1975
+ <CapHeader
1976
+ title={
1977
+ <CapHeading type="h4">
1978
+ {formatMessage(messages.templateHeaderLabel)}
1979
+ </CapHeading>
1980
+ }
1981
+ suffix={
1982
+ templateStatus === WHATSAPP_STATUSES.approved && !isAuthenticationTemplate && (
1983
+ <TagList
1984
+ label={formatMessage(globalMessages.addLabels)}
1985
+ onTagSelect={onHeaderTagSelect}
1986
+ location={location}
1987
+ tags={tags || []}
1988
+ onContextChange={handleOnTagsContextChange}
1989
+ injectedTags={injectedTags || {}}
1990
+ selectedOfferDetails={selectedOfferDetails}
1991
+ />
1992
+ )
1993
+ }
1994
+ />
1995
+ </CapRow>
1996
+ <CapTooltip placement="bottom" title={disabledEditTooltipRender()}>
1997
+ <CapRow
1998
+ className={`whatsapp-edit-template-message-input ${
1999
+ templateStatus !== WHATSAPP_STATUSES.approved &&
2000
+ "whatsapp-edit-disabled"
2001
+ }`}
2002
+ >
2003
+ {renderedEditMessage(tempHeaderData, HEADER_TEXT)}
2004
+ </CapRow>
2005
+ </CapTooltip>
2006
+ {renderMessageLength(HEADER_TEXT)}
2007
+ {isHeaderTagValidationError && tagValidationErrorMessage(HEADER_TEXT)}
2008
+ {computeTextLength(HEADER_TEXT) > TEMPLATE_HEADER_MAX_LENGTH && (
2009
+ <CapError>
2010
+ {formatMessage(messages.templateHeaderLengthError)}
2011
+ </CapError>
2012
+ )}
2013
+ </>
2014
+ )}
1424
2015
  <CapRow className="whatsapp-render-heading">
1425
2016
  <CapHeader
1426
2017
  title={
@@ -1429,10 +2020,10 @@ export const Whatsapp = (props) => {
1429
2020
  </CapHeading>
1430
2021
  }
1431
2022
  suffix={
1432
- templateStatus === WHATSAPP_STATUSES.approved && (
2023
+ templateStatus === WHATSAPP_STATUSES.approved && !isAuthenticationTemplate && (
1433
2024
  <TagList
1434
2025
  label={formatMessage(globalMessages.addLabels)}
1435
- onTagSelect={onTagSelect}
2026
+ onTagSelect={onMessageTagSelect}
1436
2027
  location={location}
1437
2028
  tags={tags || []}
1438
2029
  onContextChange={handleOnTagsContextChange}
@@ -1450,29 +2041,76 @@ export const Whatsapp = (props) => {
1450
2041
  'whatsapp-edit-disabled'
1451
2042
  }`}
1452
2043
  >
1453
- {renderedEditMessage()}
2044
+ {renderedEditMessage(tempMsgArray)}
1454
2045
  </CapRow>
1455
2046
  </CapTooltip>
1456
2047
 
1457
- {renderMessageLength()}
1458
- {isTagValidationError && tagValidationErrorMessage()}
1459
- {computeTextLength() > TEMPLATE_MESSAGE_MAX_LENGTH ? (
2048
+ {renderMessageLength(MESSAGE_TEXT)}
2049
+ {isTagValidationError && tagValidationErrorMessage(MESSAGE_TEXT)}
2050
+ {computeTextLength(MESSAGE_TEXT) > TEMPLATE_MESSAGE_MAX_LENGTH ? (
1460
2051
  <CapError>
1461
2052
  {formatMessage(messages.templateMessageLengthError)}
1462
2053
  </CapError>
1463
2054
  ) : (
1464
- ''
2055
+ ""
2056
+ )}
2057
+ {/* preview URL is not supported by the Gateway (Karix/Gupshup), show hiding it for now. once the Gateway support is available, previewUrl option would be shown.
2058
+ <CapRow>
2059
+ <CapCheckbox
2060
+ className={`whatsapp-unsubscribe-checkbox ${'whatsapp-create-unsubscribe-checkbox'}`}
2061
+ onChange={previewUrlHandler}
2062
+ checked={showUrlPreview}
2063
+ disabled={!isMediaTypeText}
2064
+ autoFocus={true}
2065
+ >
2066
+ <span className="whatsapp-render-url-preview-text">
2067
+ {formatMessage(messages.showUrlPreview)}
2068
+ </span>
2069
+ </CapCheckbox>
2070
+ </CapRow> */}
2071
+ {templateFooter && isHostIsNotTwilio && (
2072
+ <>
2073
+ <CapHeader
2074
+ className={`${isMediaTypeImage ? "whatsapp-heading-spacing" : ""}`}
2075
+ title={
2076
+ <CapHeading type="h4" className="whatsapp-render-heading">
2077
+ {formatMessage(messages.templateFooterLabel)}
2078
+ </CapHeading>
2079
+ }
2080
+ />
2081
+ <CapRow className="whatsapp-footer-edit-container">
2082
+ <CapHeading type="h4" className="whatsapp-footer-edit-text">
2083
+ {templateFooter}
2084
+ </CapHeading>
2085
+ </CapRow>
2086
+ {renderMessageLength(FOOTER_TEXT)}
2087
+ </>
1465
2088
  )}
1466
2089
  {/* button section view in edit mode*/}
1467
2090
  <CapRow>
1468
- <CapHeading type="h4" className="whatsapp-render-heading">
1469
- {formatMessage(messages.btnLabel)}
1470
- </CapHeading>
1471
- <CapLabel type="label15">
1472
- {isBtnTypeCta
1473
- ? formatMessage(messages.btnTypeCTA)
1474
- : formatMessage(messages.btnTypeNone)}
1475
- </CapLabel>
2091
+ {isBtnTypeQuickReply ? (
2092
+ <CapHeading type="h4" className="whatsapp-render-heading">
2093
+ {formatMessage(messages.quickReplyButtons)}
2094
+ </CapHeading>
2095
+ ) : (
2096
+ <>
2097
+ <CapHeading type="h4" className="whatsapp-render-heading">
2098
+ {formatMessage(messages.btnLabel)}
2099
+ </CapHeading>
2100
+ <CapLabel type="label15">
2101
+ {isBtnTypeCta
2102
+ ? formatMessage(messages.btnTypeCTA)
2103
+ : !isAuthenticationTemplate && formatMessage(messages.btnTypeNone)}
2104
+ </CapLabel>
2105
+ </>
2106
+ )}
2107
+ {isAuthenticationTemplate && (
2108
+ <CapLabel type="label15">
2109
+ <CapWhatsappQuickReply
2110
+ authenticationFlow={true}
2111
+ />
2112
+ </CapLabel>
2113
+ )}
1476
2114
  {isBtnTypeCta && (
1477
2115
  <CapWhatsappCTA
1478
2116
  ctaData={ctaData}
@@ -1485,6 +2123,14 @@ export const Whatsapp = (props) => {
1485
2123
  selectedOfferDetails={selectedOfferDetails}
1486
2124
  />
1487
2125
  )}
2126
+ {isBtnTypeQuickReply && (
2127
+ <CapWhatsappQuickReply
2128
+ quickReplyData={quickReplyData}
2129
+ isEditFlow={isEditFlow}
2130
+ renderMessageLength={renderMessageLength}
2131
+ setQuickReplyData={setQuickReplyData}
2132
+ />
2133
+ )}
1488
2134
  </CapRow>
1489
2135
  </>
1490
2136
  );
@@ -1492,25 +2138,37 @@ export const Whatsapp = (props) => {
1492
2138
 
1493
2139
  //used by create and edit
1494
2140
  const getPreviewSection = () => {
2141
+ const { metaTagsDetails = {} } = editData || {};
1495
2142
  const templateMsg = (
1496
2143
  <>
1497
2144
  <CapLabel type="label5">
1498
- {isEditFlow ? updatedSmsEditor.join('') : templateMessage}
2145
+ {isEditFlow ? updatedSmsEditor.join("") : templateMessage}
1499
2146
  </CapLabel>
1500
- {unsubscribeRequired && (
2147
+ {unsubscribeRequired && !isAuthenticationTemplate && (
1501
2148
  <CapLabel type="label5">
1502
2149
  {formatMessage(messages.templateMessageUnsubscribeText)}
1503
2150
  </CapLabel>
1504
2151
  )}
1505
2152
  </>
1506
2153
  );
2154
+ const templateHeaderPreview = (
2155
+ <CapLabel className="whatsapp-template-header-preview">
2156
+ {isEditFlow ? updatedHeaderData.join("") : templateHeader}
2157
+ </CapLabel>
2158
+ );
2159
+ const templateFooterPreview = (
2160
+ <CapLabel className="whatsapp-template-footer-preview">
2161
+ {templateFooter}
2162
+ </CapLabel>
2163
+ );
1507
2164
  const mediaPreview = {};
1508
2165
  switch (templateMediaType) {
1509
2166
  case WHATSAPP_MEDIA_TYPES.IMAGE:
1510
2167
  mediaPreview.whatsappImageSrc = whatsappImageSrc;
1511
2168
  break;
1512
2169
  case WHATSAPP_MEDIA_TYPES.VIDEO:
1513
- mediaPreview.whatsappVideoPreviewImg = whatsappVideoSrcAndPreview?.whatsappVideoPreviewImg;
2170
+ mediaPreview.whatsappVideoPreviewImg =
2171
+ whatsappVideoSrcAndPreview?.whatsappVideoPreviewImg;
1514
2172
  break;
1515
2173
  case WHATSAPP_MEDIA_TYPES.DOCUMENT:
1516
2174
  mediaPreview.docPreview = docPreview;
@@ -1524,9 +2182,21 @@ export const Whatsapp = (props) => {
1524
2182
  content={{
1525
2183
  ...mediaPreview,
1526
2184
  templateMsg,
2185
+ templateHeaderPreview,
2186
+ templateFooterPreview,
1527
2187
  ...(isBtnTypeCta && {
1528
2188
  ctaData,
1529
2189
  }),
2190
+ ...(isAuthenticationTemplate && {
2191
+ ctaData : [{text: formatMessage(globalMessages.autofill), type: WHATSAPP_CATEGORIES.authentication}]
2192
+ }),
2193
+ ...(isBtnTypeQuickReply && {
2194
+ quickReplyData,
2195
+ }),
2196
+ ...(isMediaTypeText && showUrlPreview && {
2197
+ showUrlPreview,
2198
+ metaTagsDetails,
2199
+ }),
1530
2200
  }}
1531
2201
  whatsappContentLen={computeTextLength()}
1532
2202
  whatsappAccountName={accountName}
@@ -1536,12 +2206,12 @@ export const Whatsapp = (props) => {
1536
2206
 
1537
2207
  const isEditDoneDisabled = () =>
1538
2208
  isTagValidationError ||
1539
- Object.values(varMap).some((inputValue) => inputValue === '') ||
1540
- computeTextLength() > TEMPLATE_MESSAGE_MAX_LENGTH ||
1541
- (isBtnTypeCta && ctaData.some((btn) => btn?.url?.includes('{{1}}'))) ||
1542
- (isMediaTypeImage && whatsappImageSrc === '') ||
1543
- (isMediaTypeVideo && whatsappVideoSrcAndPreview?.whatsappVideoSrc === '') ||
1544
- (isMediaTypeDoc && whatsappDocSource === '');
2209
+ isHeaderTagValidationError ||
2210
+ Object.values(varMap).some((inputValue) => inputValue === "") ||
2211
+ Object.values(headerVarMappedData).some((inputValue) => inputValue === "") ||
2212
+ computeTextLength(MESSAGE_TEXT) > TEMPLATE_MESSAGE_MAX_LENGTH ||
2213
+ computeTextLength(HEADER_TEXT) > TEMPLATE_HEADER_MAX_LENGTH ||
2214
+ (isBtnTypeCta && ctaData.some((btn) => btn?.url?.includes("{{1}}"))) || isMediatypeValid();
1545
2215
 
1546
2216
  return (
1547
2217
  <CapSpin spinning={spin}>
@@ -1561,9 +2231,9 @@ export const Whatsapp = (props) => {
1561
2231
  title={
1562
2232
  isDisableDone()
1563
2233
  ? formatMessage(messages.btnDisabledTooltip)
1564
- : ''
2234
+ : ""
1565
2235
  }
1566
- placement={'right'}
2236
+ placement={"right"}
1567
2237
  >
1568
2238
  <div className="button-disabled-tooltip-wrapper">
1569
2239
  <CapButton
@@ -1589,9 +2259,9 @@ export const Whatsapp = (props) => {
1589
2259
  title={
1590
2260
  isEditDoneDisabled()
1591
2261
  ? formatMessage(messages.btnDisabledTooltip)
1592
- : ''
2262
+ : ""
1593
2263
  }
1594
- placement={'right'}
2264
+ placement={"right"}
1595
2265
  >
1596
2266
  <div className="button-disabled-tooltip-wrapper">
1597
2267
  <CapButton