@capillarytech/creatives-library 8.0.242-alpha.10 → 8.0.242-alpha.11

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 (256) hide show
  1. package/assets/Android.png +0 -0
  2. package/assets/iOS.png +0 -0
  3. package/config/app.js +1 -1
  4. package/constants/unified.js +2 -2
  5. package/initialReducer.js +0 -2
  6. package/package.json +1 -1
  7. package/services/api.js +5 -10
  8. package/services/tests/api.test.js +0 -18
  9. package/translations/en.json +4 -3
  10. package/utils/common.js +6 -5
  11. package/utils/commonUtils.js +1 -14
  12. package/utils/imageUrlUpload.js +141 -0
  13. package/utils/tests/commonUtil.test.js +0 -224
  14. package/utils/transformTemplateConfig.js +10 -0
  15. package/v2Components/CapDeviceContent/index.js +56 -61
  16. package/v2Components/CapImageUpload/constants.js +2 -0
  17. package/v2Components/CapImageUpload/index.js +65 -16
  18. package/v2Components/CapImageUpload/index.scss +4 -1
  19. package/v2Components/CapImageUpload/messages.js +5 -1
  20. package/v2Components/CapImageUrlUpload/constants.js +26 -0
  21. package/v2Components/CapImageUrlUpload/index.js +365 -0
  22. package/v2Components/CapImageUrlUpload/index.scss +35 -0
  23. package/v2Components/CapImageUrlUpload/messages.js +47 -0
  24. package/v2Components/CapTagList/index.js +1 -6
  25. package/v2Components/CapTagListWithInput/index.js +1 -5
  26. package/v2Components/CapTagListWithInput/messages.js +1 -1
  27. package/v2Components/CapWhatsappCTA/tests/index.test.js +0 -5
  28. package/v2Components/ErrorInfoNote/index.js +72 -412
  29. package/v2Components/ErrorInfoNote/messages.js +0 -22
  30. package/v2Components/ErrorInfoNote/style.scss +2 -279
  31. package/v2Components/HtmlEditor/HTMLEditor.js +91 -220
  32. package/v2Components/HtmlEditor/__tests__/HTMLEditor.test.js +133 -1132
  33. package/v2Components/HtmlEditor/__tests__/index.lazy.test.js +12 -17
  34. package/v2Components/HtmlEditor/_htmlEditor.scss +45 -107
  35. package/v2Components/HtmlEditor/_index.lazy.scss +1 -1
  36. package/v2Components/HtmlEditor/components/CodeEditorPane/_codeEditorPane.scss +101 -13
  37. package/v2Components/HtmlEditor/components/CodeEditorPane/index.js +139 -148
  38. package/v2Components/HtmlEditor/components/DeviceToggle/_deviceToggle.scss +1 -2
  39. package/v2Components/HtmlEditor/components/DeviceToggle/index.js +3 -3
  40. package/v2Components/HtmlEditor/components/EditorToolbar/_editorToolbar.scss +0 -9
  41. package/v2Components/HtmlEditor/components/EditorToolbar/index.js +1 -1
  42. package/v2Components/HtmlEditor/components/FullscreenModal/_fullscreenModal.scss +0 -22
  43. package/v2Components/HtmlEditor/components/InAppPreviewPane/DeviceFrame.js +7 -4
  44. package/v2Components/HtmlEditor/components/InAppPreviewPane/__tests__/DeviceFrame.test.js +45 -35
  45. package/v2Components/HtmlEditor/components/InAppPreviewPane/_inAppPreviewPane.scss +3 -1
  46. package/v2Components/HtmlEditor/components/InAppPreviewPane/constants.js +33 -33
  47. package/v2Components/HtmlEditor/components/InAppPreviewPane/index.js +6 -7
  48. package/v2Components/HtmlEditor/components/PreviewPane/_previewPane.scss +6 -3
  49. package/v2Components/HtmlEditor/components/PreviewPane/index.js +11 -10
  50. package/v2Components/HtmlEditor/components/SplitContainer/_splitContainer.scss +1 -1
  51. package/v2Components/HtmlEditor/components/ValidationErrorDisplay/__tests__/index.test.js +72 -70
  52. package/v2Components/HtmlEditor/components/ValidationErrorDisplay/index.js +31 -49
  53. package/v2Components/HtmlEditor/constants.js +20 -29
  54. package/v2Components/HtmlEditor/hooks/__tests__/useInAppContent.test.js +16 -373
  55. package/v2Components/HtmlEditor/hooks/useEditorContent.js +2 -5
  56. package/v2Components/HtmlEditor/hooks/useInAppContent.js +146 -88
  57. package/v2Components/HtmlEditor/index.js +1 -1
  58. package/v2Components/HtmlEditor/messages.js +85 -95
  59. package/v2Components/HtmlEditor/utils/liquidTemplateSupport.js +101 -99
  60. package/v2Components/HtmlEditor/utils/properSyntaxHighlighting.js +25 -23
  61. package/v2Components/HtmlEditor/utils/validationAdapter.js +41 -34
  62. package/v2Components/MobilePushPreviewV2/index.js +7 -32
  63. package/v2Components/TemplatePreview/_templatePreview.scss +24 -44
  64. package/v2Components/TemplatePreview/index.js +32 -47
  65. package/v2Components/TemplatePreview/messages.js +0 -4
  66. package/v2Components/TestAndPreviewSlidebox/index.js +25 -31
  67. package/v2Containers/App/constants.js +5 -0
  68. package/v2Containers/BeeEditor/index.js +80 -82
  69. package/v2Containers/Cap/tests/__snapshots__/index.test.js.snap +4 -3
  70. package/v2Containers/CreativesContainer/SlideBoxContent.js +118 -148
  71. package/v2Containers/CreativesContainer/SlideBoxFooter.js +3 -9
  72. package/v2Containers/CreativesContainer/SlideBoxHeader.js +2 -2
  73. package/v2Containers/CreativesContainer/constants.js +2 -1
  74. package/v2Containers/CreativesContainer/index.js +41 -173
  75. package/v2Containers/CreativesContainer/messages.js +4 -4
  76. package/v2Containers/CreativesContainer/tests/SlideBoxContent.test.js +210 -0
  77. package/v2Containers/CreativesContainer/tests/__snapshots__/SlideBoxContent.test.js.snap +354 -38
  78. package/v2Containers/CreativesContainer/tests/__snapshots__/index.test.js.snap +0 -36
  79. package/v2Containers/Email/actions.js +0 -7
  80. package/v2Containers/Email/constants.js +1 -5
  81. package/v2Containers/Email/index.js +0 -13
  82. package/v2Containers/Email/messages.js +0 -32
  83. package/v2Containers/Email/reducer.js +1 -12
  84. package/v2Containers/Email/sagas.js +6 -41
  85. package/v2Containers/Email/tests/__snapshots__/reducer.test.js.snap +0 -2
  86. package/v2Containers/EmailWrapper/components/EmailWrapperView.js +7 -193
  87. package/v2Containers/EmailWrapper/components/HTMLEditorTesting.js +74 -40
  88. package/v2Containers/EmailWrapper/components/__tests__/HTMLEditorTesting.test.js +67 -2
  89. package/v2Containers/EmailWrapper/constants.js +0 -2
  90. package/v2Containers/EmailWrapper/hooks/useEmailWrapper.js +67 -436
  91. package/v2Containers/EmailWrapper/index.js +23 -99
  92. package/v2Containers/EmailWrapper/messages.js +1 -61
  93. package/v2Containers/EmailWrapper/tests/EmailWrapperView.test.js +214 -0
  94. package/v2Containers/EmailWrapper/tests/useEmailWrapper.test.js +77 -111
  95. package/v2Containers/InApp/actions.js +0 -7
  96. package/v2Containers/InApp/constants.js +4 -20
  97. package/v2Containers/InApp/index.js +357 -801
  98. package/v2Containers/InApp/index.scss +3 -4
  99. package/v2Containers/InApp/messages.js +3 -7
  100. package/v2Containers/InApp/reducer.js +3 -21
  101. package/v2Containers/InApp/sagas.js +9 -29
  102. package/v2Containers/InApp/selectors.js +5 -25
  103. package/v2Containers/InApp/tests/index.test.js +50 -154
  104. package/v2Containers/InApp/tests/reducer.test.js +0 -34
  105. package/v2Containers/InApp/tests/sagas.test.js +9 -61
  106. package/v2Containers/Line/Container/ImageCarousel/tests/__snapshots__/content.test.js.snap +12 -12
  107. package/v2Containers/Line/Container/ImageCarousel/tests/__snapshots__/index.test.js.snap +8 -8
  108. package/v2Containers/Line/Container/Wrapper/tests/__snapshots__/index.test.js.snap +100 -77
  109. package/v2Containers/Line/Container/tests/__snapshots__/index.test.js.snap +72 -63
  110. package/v2Containers/Rcs/tests/__snapshots__/index.test.js.snap +184 -150
  111. package/v2Containers/SmsTrai/Create/tests/__snapshots__/index.test.js.snap +16 -12
  112. package/v2Containers/SmsTrai/Edit/tests/__snapshots__/index.test.js.snap +32 -28
  113. package/v2Containers/TagList/index.js +1 -67
  114. package/v2Containers/Templates/ChannelTypeIllustration.js +13 -1
  115. package/v2Containers/Templates/_templates.scss +202 -56
  116. package/v2Containers/Templates/actions.js +2 -1
  117. package/v2Containers/Templates/constants.js +1 -0
  118. package/v2Containers/Templates/index.js +278 -128
  119. package/v2Containers/Templates/messages.js +24 -4
  120. package/v2Containers/Templates/reducer.js +2 -0
  121. package/v2Containers/Templates/tests/index.test.js +10 -0
  122. package/v2Containers/TemplatesV2/index.js +8 -1
  123. package/v2Containers/TemplatesV2/messages.js +4 -0
  124. package/v2Containers/WebPush/Create/components/BrandIconSection.js +108 -0
  125. package/v2Containers/WebPush/Create/components/ButtonForm.js +172 -0
  126. package/v2Containers/WebPush/Create/components/ButtonItem.js +101 -0
  127. package/v2Containers/WebPush/Create/components/ButtonList.js +145 -0
  128. package/v2Containers/WebPush/Create/components/ButtonsLinksSection.js +164 -0
  129. package/v2Containers/WebPush/Create/components/ButtonsLinksSection.test.js +463 -0
  130. package/v2Containers/WebPush/Create/components/FormActions.js +54 -0
  131. package/v2Containers/WebPush/Create/components/FormActions.test.js +163 -0
  132. package/v2Containers/WebPush/Create/components/MediaSection.js +142 -0
  133. package/v2Containers/WebPush/Create/components/MediaSection.test.js +341 -0
  134. package/v2Containers/WebPush/Create/components/MessageSection.js +103 -0
  135. package/v2Containers/WebPush/Create/components/MessageSection.test.js +268 -0
  136. package/v2Containers/WebPush/Create/components/NotificationTitleSection.js +87 -0
  137. package/v2Containers/WebPush/Create/components/NotificationTitleSection.test.js +210 -0
  138. package/v2Containers/WebPush/Create/components/TemplateNameSection.js +54 -0
  139. package/v2Containers/WebPush/Create/components/TemplateNameSection.test.js +143 -0
  140. package/v2Containers/WebPush/Create/components/__snapshots__/ButtonsLinksSection.test.js.snap +86 -0
  141. package/v2Containers/WebPush/Create/components/__snapshots__/FormActions.test.js.snap +16 -0
  142. package/v2Containers/WebPush/Create/components/__snapshots__/MediaSection.test.js.snap +41 -0
  143. package/v2Containers/WebPush/Create/components/__snapshots__/MessageSection.test.js.snap +54 -0
  144. package/v2Containers/WebPush/Create/components/__snapshots__/NotificationTitleSection.test.js.snap +37 -0
  145. package/v2Containers/WebPush/Create/components/__snapshots__/TemplateNameSection.test.js.snap +21 -0
  146. package/v2Containers/WebPush/Create/components/_buttons.scss +246 -0
  147. package/v2Containers/WebPush/Create/components/tests/ButtonForm.test.js +554 -0
  148. package/v2Containers/WebPush/Create/components/tests/ButtonItem.test.js +607 -0
  149. package/v2Containers/WebPush/Create/components/tests/ButtonList.test.js +633 -0
  150. package/v2Containers/WebPush/Create/components/tests/__snapshots__/ButtonForm.test.js.snap +666 -0
  151. package/v2Containers/WebPush/Create/components/tests/__snapshots__/ButtonItem.test.js.snap +74 -0
  152. package/v2Containers/WebPush/Create/components/tests/__snapshots__/ButtonList.test.js.snap +78 -0
  153. package/v2Containers/WebPush/Create/hooks/useButtonManagement.js +138 -0
  154. package/v2Containers/WebPush/Create/hooks/useButtonManagement.test.js +406 -0
  155. package/v2Containers/WebPush/Create/hooks/useCharacterCount.js +30 -0
  156. package/v2Containers/WebPush/Create/hooks/useCharacterCount.test.js +151 -0
  157. package/v2Containers/WebPush/Create/hooks/useImageUpload.js +104 -0
  158. package/v2Containers/WebPush/Create/hooks/useImageUpload.test.js +538 -0
  159. package/v2Containers/WebPush/Create/hooks/useTagManagement.js +122 -0
  160. package/v2Containers/WebPush/Create/hooks/useTagManagement.test.js +633 -0
  161. package/v2Containers/WebPush/Create/index.js +1056 -0
  162. package/v2Containers/WebPush/Create/index.scss +134 -0
  163. package/v2Containers/WebPush/Create/messages.js +203 -0
  164. package/v2Containers/WebPush/Create/preview/DevicePreviewContent.js +228 -0
  165. package/v2Containers/WebPush/Create/preview/NotificationContainer.js +294 -0
  166. package/v2Containers/WebPush/Create/preview/PreviewContent.js +90 -0
  167. package/v2Containers/WebPush/Create/preview/PreviewControls.js +305 -0
  168. package/v2Containers/WebPush/Create/preview/PreviewDisclaimer.js +23 -0
  169. package/v2Containers/WebPush/Create/preview/WebPushPreview.js +150 -0
  170. package/v2Containers/WebPush/Create/preview/assets/Light.svg +53 -0
  171. package/v2Containers/WebPush/Create/preview/assets/Top.svg +5 -0
  172. package/v2Containers/WebPush/Create/preview/assets/android-arrow-down.svg +9 -0
  173. package/v2Containers/WebPush/Create/preview/assets/android-arrow-up.svg +9 -0
  174. package/v2Containers/WebPush/Create/preview/assets/chrome-icon.png +0 -0
  175. package/v2Containers/WebPush/Create/preview/assets/edge-icon.png +0 -0
  176. package/v2Containers/WebPush/Create/preview/assets/firefox-icon.svg +106 -0
  177. package/v2Containers/WebPush/Create/preview/assets/iOS.svg +26 -0
  178. package/v2Containers/WebPush/Create/preview/assets/macos-arrow-down-icon.svg +9 -0
  179. package/v2Containers/WebPush/Create/preview/assets/macos-triple-dot-icon.svg +9 -0
  180. package/v2Containers/WebPush/Create/preview/assets/opera-icon.svg +18 -0
  181. package/v2Containers/WebPush/Create/preview/assets/safari-icon.svg +29 -0
  182. package/v2Containers/WebPush/Create/preview/assets/windows-close-icon.svg +9 -0
  183. package/v2Containers/WebPush/Create/preview/assets/windows-triple-dot-icon.svg +9 -0
  184. package/v2Containers/WebPush/Create/preview/components/AndroidMobileChromeHeader.js +47 -0
  185. package/v2Containers/WebPush/Create/preview/components/AndroidMobileExpanded.js +141 -0
  186. package/v2Containers/WebPush/Create/preview/components/IOSHeader.js +45 -0
  187. package/v2Containers/WebPush/Create/preview/components/NotificationExpandedContent.js +68 -0
  188. package/v2Containers/WebPush/Create/preview/components/NotificationHeader.js +61 -0
  189. package/v2Containers/WebPush/Create/preview/components/WindowsChromeExpanded.js +99 -0
  190. package/v2Containers/WebPush/Create/preview/components/tests/AndroidMobileExpanded.test.js +733 -0
  191. package/v2Containers/WebPush/Create/preview/components/tests/WindowsChromeExpanded.test.js +571 -0
  192. package/v2Containers/WebPush/Create/preview/components/tests/__snapshots__/AndroidMobileExpanded.test.js.snap +81 -0
  193. package/v2Containers/WebPush/Create/preview/components/tests/__snapshots__/WindowsChromeExpanded.test.js.snap +81 -0
  194. package/v2Containers/WebPush/Create/preview/config/notificationMappings.js +50 -0
  195. package/v2Containers/WebPush/Create/preview/constants.js +637 -0
  196. package/v2Containers/WebPush/Create/preview/notification-container.scss +79 -0
  197. package/v2Containers/WebPush/Create/preview/preview.scss +351 -0
  198. package/v2Containers/WebPush/Create/preview/styles/_android-mobile-chrome.scss +370 -0
  199. package/v2Containers/WebPush/Create/preview/styles/_android-mobile-edge.scss +12 -0
  200. package/v2Containers/WebPush/Create/preview/styles/_android-mobile-firefox.scss +12 -0
  201. package/v2Containers/WebPush/Create/preview/styles/_android-mobile-opera.scss +12 -0
  202. package/v2Containers/WebPush/Create/preview/styles/_android-tablet-chrome.scss +47 -0
  203. package/v2Containers/WebPush/Create/preview/styles/_android-tablet-edge.scss +11 -0
  204. package/v2Containers/WebPush/Create/preview/styles/_android-tablet-firefox.scss +11 -0
  205. package/v2Containers/WebPush/Create/preview/styles/_android-tablet-opera.scss +11 -0
  206. package/v2Containers/WebPush/Create/preview/styles/_base.scss +207 -0
  207. package/v2Containers/WebPush/Create/preview/styles/_ios.scss +153 -0
  208. package/v2Containers/WebPush/Create/preview/styles/_ipados.scss +107 -0
  209. package/v2Containers/WebPush/Create/preview/styles/_macos-chrome.scss +101 -0
  210. package/v2Containers/WebPush/Create/preview/styles/_windows-chrome.scss +229 -0
  211. package/v2Containers/WebPush/Create/preview/tests/DevicePreviewContent.test.js +909 -0
  212. package/v2Containers/WebPush/Create/preview/tests/NotificationContainer.test.js +1081 -0
  213. package/v2Containers/WebPush/Create/preview/tests/PreviewControls.test.js +723 -0
  214. package/v2Containers/WebPush/Create/preview/tests/WebPushPreview.test.js +943 -0
  215. package/v2Containers/WebPush/Create/preview/tests/__snapshots__/DevicePreviewContent.test.js.snap +131 -0
  216. package/v2Containers/WebPush/Create/preview/tests/__snapshots__/NotificationContainer.test.js.snap +112 -0
  217. package/v2Containers/WebPush/Create/preview/tests/__snapshots__/PreviewControls.test.js.snap +144 -0
  218. package/v2Containers/WebPush/Create/preview/tests/__snapshots__/WebPushPreview.test.js.snap +129 -0
  219. package/v2Containers/WebPush/Create/utils/payloadBuilder.js +94 -0
  220. package/v2Containers/WebPush/Create/utils/payloadBuilder.test.js +390 -0
  221. package/v2Containers/WebPush/Create/utils/previewUtils.js +89 -0
  222. package/v2Containers/WebPush/Create/utils/urlValidation.js +115 -0
  223. package/v2Containers/WebPush/Create/utils/urlValidation.test.js +449 -0
  224. package/v2Containers/WebPush/Create/utils/validation.js +75 -0
  225. package/v2Containers/WebPush/Create/utils/validation.test.js +283 -0
  226. package/v2Containers/WebPush/actions.js +60 -0
  227. package/v2Containers/WebPush/constants.js +128 -0
  228. package/v2Containers/WebPush/index.js +2 -0
  229. package/v2Containers/WebPush/reducer.js +104 -0
  230. package/v2Containers/WebPush/sagas.js +119 -0
  231. package/v2Containers/WebPush/selectors.js +65 -0
  232. package/v2Containers/WebPush/tests/reducer.test.js +863 -0
  233. package/v2Containers/WebPush/tests/sagas.test.js +566 -0
  234. package/v2Containers/WebPush/tests/selectors.test.js +843 -0
  235. package/v2Containers/Whatsapp/tests/__snapshots__/index.test.js.snap +528 -431
  236. package/v2Components/HtmlEditor/components/ValidationTabs/_validationTabs.scss +0 -254
  237. package/v2Components/HtmlEditor/components/ValidationTabs/index.js +0 -362
  238. package/v2Components/HtmlEditor/components/ValidationTabs/messages.js +0 -51
  239. package/v2Containers/BeePopupEditor/constants.js +0 -10
  240. package/v2Containers/BeePopupEditor/index.js +0 -193
  241. package/v2Containers/BeePopupEditor/tests/index.test.js +0 -627
  242. package/v2Containers/EmailWrapper/components/EmailHTMLEditor.js +0 -1046
  243. package/v2Containers/InApp/__tests__/InAppHTMLEditor.test.js +0 -376
  244. package/v2Containers/InApp/__tests__/sagas.test.js +0 -363
  245. package/v2Containers/InApp/tests/selectors.test.js +0 -612
  246. package/v2Containers/InAppWrapper/components/InAppWrapperView.js +0 -162
  247. package/v2Containers/InAppWrapper/components/__tests__/InAppWrapperView.test.js +0 -267
  248. package/v2Containers/InAppWrapper/components/inAppWrapperView.scss +0 -9
  249. package/v2Containers/InAppWrapper/constants.js +0 -16
  250. package/v2Containers/InAppWrapper/hooks/__tests__/useInAppWrapper.test.js +0 -473
  251. package/v2Containers/InAppWrapper/hooks/useInAppWrapper.js +0 -198
  252. package/v2Containers/InAppWrapper/index.js +0 -148
  253. package/v2Containers/InAppWrapper/messages.js +0 -49
  254. package/v2Containers/InappAdvance/index.js +0 -1099
  255. package/v2Containers/InappAdvance/index.scss +0 -10
  256. package/v2Containers/InappAdvance/tests/index.test.js +0 -448
@@ -46,6 +46,10 @@ export default defineMessages({
46
46
  id: `${scope}.mobilepushHeader`,
47
47
  defaultMessage: `Mobile Push`,
48
48
  },
49
+ "webpushHeader": {
50
+ id: `${scope}.webpushHeader`,
51
+ defaultMessage: `Web Push`,
52
+ },
49
53
  "ebillHeader": {
50
54
  id: `${scope}.ebillHeader`,
51
55
  defaultMessage: `Ebill`,
@@ -342,6 +346,10 @@ export default defineMessages({
342
346
  id: `${scope}.newWhatsappTemplate`,
343
347
  defaultMessage: 'Add new Whatsapp {template}',
344
348
  },
349
+ "newWebPushTemplate": {
350
+ id: `${scope}.newWebPushTemplate`,
351
+ defaultMessage: 'Add new Web push {template}',
352
+ },
345
353
  "newInAppMessageTemplate": {
346
354
  id: `${scope}.newInAppMessageTemplate`,
347
355
  defaultMessage: 'Add new In app message {template}',
@@ -378,6 +386,14 @@ export default defineMessages({
378
386
  id: `${scope}.whatsappDescIllustration`,
379
387
  defaultMessage: 'These templates can be reused when creating a\nnew message content.',
380
388
  },
389
+ "webPushTitleIllustration": {
390
+ id: `${scope}.webPushTitleIllustration`,
391
+ defaultMessage: 'Add a new Web push creative {template}',
392
+ },
393
+ "webPushDescIllustration": {
394
+ id: `${scope}.webPushDescIllustration`,
395
+ defaultMessage: 'These templates can be reused when creating a new message content.',
396
+ },
381
397
  "whatsappAccountNotConfiguredTitle": {
382
398
  id: `${scope}.whatsappAccountNotConfiguredTitle`,
383
399
  defaultMessage: 'Whatsapp account is not configured',
@@ -462,6 +478,10 @@ export default defineMessages({
462
478
  id: `${scope}.zaloAccount`,
463
479
  defaultMessage: 'Zalo account',
464
480
  },
481
+ "webpushAccount": {
482
+ id: `${scope}.webpushAccount`,
483
+ defaultMessage: 'Web push account',
484
+ },
465
485
  "rcsAccount": {
466
486
  id: `${scope}.rcsAccount`,
467
487
  defaultMessage: 'RCS account',
@@ -498,6 +518,10 @@ export default defineMessages({
498
518
  id: `${scope}.noAccountsPresentZalo`,
499
519
  defaultMessage: "Zalo accounts are not setup for your brand",
500
520
  },
521
+ "noAccountsPresentWebpush": {
522
+ id: `${scope}.noAccountsPresentWebpush`,
523
+ defaultMessage: "Web push accounts are not setup for your brand",
524
+ },
501
525
  "noAccountsPresentRcs": {
502
526
  id: `${scope}.noAccountsPresentRcs`,
503
527
  defaultMessage: "RCS accounts are not setup for your brand",
@@ -534,10 +558,6 @@ export default defineMessages({
534
558
  id: `${scope}.rcsOnlyApprovedTemplates`,
535
559
  defaultMessage: 'Only "Approved" templates are available here, as you can use those templates to create a message.',
536
560
  },
537
- "layout": {
538
- id: `${scope}.layout`,
539
- defaultMessage: `Layout`,
540
- },
541
561
  "status": {
542
562
  id: `${scope}.status`,
543
563
  defaultMessage: 'Status',
@@ -124,6 +124,8 @@ function templatesReducer(state = initialState, action) {
124
124
  return state
125
125
  .set('selectedFacebookAccount', fromJS(action.faceBookAccount))
126
126
  .set('templates', []);
127
+ case types.SET_WEBPUSH_ACCOUNT:
128
+ return state.set('selectedWebPushAccount', fromJS(action.account));
127
129
  case types.RESET_ACCOUNT:
128
130
  return state
129
131
  .remove('selectedWeChatAccount')
@@ -22,6 +22,7 @@ describe('Test Templates container', () => {
22
22
  const getAllTemplates = jest.fn();
23
23
  const getUserList = jest.fn();
24
24
  const getSenderDetails = jest.fn();
25
+ const resetTemplate = jest.fn();
25
26
  let renderedComponent;
26
27
 
27
28
  beforeEach(() => {
@@ -54,6 +55,7 @@ describe('Test Templates container', () => {
54
55
  getAllTemplates,
55
56
  getUserList,
56
57
  getSenderDetails,
58
+ resetTemplate,
57
59
  }}
58
60
  location={{
59
61
  pathname: `/${channel}`,
@@ -79,6 +81,8 @@ describe('Test Templates container', () => {
79
81
  channel: 'WHATSAPP',
80
82
  orgUnitId: -1,
81
83
  });
84
+ // resetTemplate should be called when entering account selection mode
85
+ expect(resetTemplate).toHaveBeenCalled();
82
86
  });
83
87
 
84
88
  it('Should render temlates when whatsapp templates are passed', () => {
@@ -103,6 +107,8 @@ describe('Test Templates container', () => {
103
107
  Templates: {},
104
108
  });
105
109
  expect(renderedComponent).toMatchSnapshot();
110
+ // SMS doesn't enter account selection mode, so resetTemplate shouldn't be called on mount
111
+ expect(resetTemplate).not.toHaveBeenCalled();
106
112
  });
107
113
 
108
114
  it('Should render temlates when whatsapp templates are passed in full mode', () => {
@@ -123,6 +129,8 @@ describe('Test Templates container', () => {
123
129
  it('Should render correct component for zalo channel', () => {
124
130
  RenderFunctionFor('zalo');
125
131
  expect(renderedComponent).toMatchSnapshot();
132
+ // resetTemplate should be called when entering account selection mode
133
+ expect(resetTemplate).toHaveBeenCalled();
126
134
  });
127
135
  it('Should render temlates when zalo templates are passed', () => {
128
136
  RenderFunctionFor('zalo');
@@ -201,6 +209,8 @@ describe('Test Templates container', () => {
201
209
  channel: 'RCS',
202
210
  orgUnitId: -1,
203
211
  });
212
+ // resetTemplate should be called when entering account selection mode
213
+ expect(resetTemplate).toHaveBeenCalled();
204
214
  });
205
215
 
206
216
  it('Should render templates when RCS templates are passed', () => {
@@ -30,7 +30,7 @@ import FTP from '../FTP';
30
30
  import Gallery from '../Assets/Gallery';
31
31
  import withStyles from '../../hoc/withStyles';
32
32
  import styles, { CapTabStyle } from './TemplatesV2.style';
33
- import { CREATIVES_UI_VIEW, LOYALTY, WHATSAPP, RCS, LINE, EMAIL, ASSETS, JP_LOCALE_HIDE_FEATURE, ZALO, INAPP } from '../App/constants';
33
+ import { CREATIVES_UI_VIEW, LOYALTY, WHATSAPP, RCS, LINE, EMAIL, ASSETS, JP_LOCALE_HIDE_FEATURE, ZALO, INAPP, WEBPUSH } from '../App/constants';
34
34
  import AccessForbidden from '../../v2Components/AccessForbidden';
35
35
  import { getObjFromQueryParams } from '../../utils/v2common';
36
36
  import { makeSelectAuthenticated, selectCurrentOrgDetails } from "../../v2Containers/Cap/selectors";
@@ -65,6 +65,13 @@ export class TemplatesV2 extends React.Component { // eslint-disable-line react/
65
65
  email: {content: <></>, tab: intl.formatMessage(messages.email), key: 'email'},
66
66
  //'wechat': {content: this.getTemplatesComponent('wechat'), tab: 'Wechat', key: 'wechat'},
67
67
  mPush: {content: <></>, tab: intl.formatMessage(messages.pushNotification), key: 'mobilepush'},
68
+ ...(commonUtil.hasWebPushFeatureEnabled() ? {
69
+ webPush: {
70
+ content: <div></div>,
71
+ tab: intl.formatMessage(messages.webPush),
72
+ key: WEBPUSH,
73
+ }
74
+ } : {}),
68
75
  viber: {content: <></>, tab: intl.formatMessage(messages.viber), key: 'viber'},
69
76
  whatsapp: { content: <></>, tab: intl.formatMessage(messages.whatsapp), key: WHATSAPP },
70
77
  zalo: { content: <div></div>, tab: intl.formatMessage(messages.zalo), key: ZALO },
@@ -86,4 +86,8 @@ export default defineMessages({
86
86
  id: `creatives.containersV2.TemplatesV2.inapp`,
87
87
  defaultMessage: 'In app message',
88
88
  },
89
+ webPush: {
90
+ id: `creatives.containersV2.TemplatesV2.webPush`,
91
+ defaultMessage: 'Web Push',
92
+ },
89
93
  });
@@ -0,0 +1,108 @@
1
+ import React from 'react';
2
+ import PropTypes from 'prop-types';
3
+ import { FormattedMessage } from 'react-intl';
4
+ import CapRow from '@capillarytech/cap-ui-library/CapRow';
5
+ import CapHeading from '@capillarytech/cap-ui-library/CapHeading';
6
+ import CapRadioGroup from '@capillarytech/cap-ui-library/CapRadioGroup';
7
+ import CapDivider from '@capillarytech/cap-ui-library/CapDivider';
8
+ import CapImageUpload from '../../../../v2Components/CapImageUpload';
9
+ import { WEBPUSH_BRAND_ICON } from '../../../CreativesContainer/constants';
10
+ import {
11
+ BRAND_ICON_OPTIONS,
12
+ ALLOWED_IMAGE_EXTENSIONS_REGEX,
13
+ WEBPUSH_BRAND_ICON_SIZE,
14
+ WEBPUSH_BRAND_ICON_RECOMMENDED_DIMENSIONS,
15
+ } from '../../constants';
16
+
17
+ /**
18
+ * BrandIconSection component - Brand icon/logo upload options
19
+ */
20
+ export const BrandIconSection = ({
21
+ brandIconOption,
22
+ onBrandIconChange,
23
+ brandIconUpload,
24
+ isLocked,
25
+ isAnyUploadActive,
26
+ formatMessage,
27
+ messages,
28
+ webPush,
29
+ isFullMode,
30
+ }) => {
31
+ const {
32
+ imageSrc: brandIconSrc,
33
+ uploadAsset: uploadBrandIconAsset,
34
+ setUpdateImageSrc: setUpdateBrandIconSrc,
35
+ updateOnReUpload: updateOnBrandIconReUpload,
36
+ } = brandIconUpload;
37
+
38
+ const brandIconOptions = [
39
+ { value: BRAND_ICON_OPTIONS.DONT_SHOW, label: formatMessage(messages.dontShow) },
40
+ { value: BRAND_ICON_OPTIONS.UPLOAD_IMAGE, label: formatMessage(messages.uploadImage) },
41
+ // NOTE: Commented out due to technical blocker - "Add image URL" option for Brand icon/logo
42
+ // { value: BRAND_ICON_OPTIONS.ADD_IMAGE_URL, label: formatMessage(messages.addImageUrl) },
43
+ ];
44
+
45
+ return (
46
+ <>
47
+ <CapRow className="creatives-webpush-brand-icon">
48
+ <CapHeading type="h4" className="webpush-brand-icon">
49
+ <FormattedMessage {...messages.brandIconLogo} />
50
+ </CapHeading>
51
+ <CapRadioGroup
52
+ options={brandIconOptions}
53
+ value={brandIconOption}
54
+ onChange={onBrandIconChange}
55
+ disabled={isAnyUploadActive}
56
+ />
57
+ </CapRow>
58
+ {brandIconOption === BRAND_ICON_OPTIONS.UPLOAD_IMAGE && (
59
+ <CapRow
60
+ className="webpush-brand-icon-upload-section"
61
+ style={isLocked ? { pointerEvents: 'none', opacity: 0.5 } : undefined}
62
+ aria-disabled={isLocked}
63
+ >
64
+ <CapImageUpload
65
+ allowedExtensionsRegex={ALLOWED_IMAGE_EXTENSIONS_REGEX}
66
+ imgSize={WEBPUSH_BRAND_ICON_SIZE}
67
+ uploadAsset={uploadBrandIconAsset}
68
+ isFullMode={isFullMode}
69
+ imageSrc={brandIconSrc}
70
+ updateImageSrc={setUpdateBrandIconSrc}
71
+ updateOnReUpload={updateOnBrandIconReUpload}
72
+ index={1}
73
+ className="cap-custom-image-upload"
74
+ key="webpush-brand-icon-uploaded-image"
75
+ imageData={webPush}
76
+ channel={WEBPUSH_BRAND_ICON}
77
+ showReUploadButton
78
+ recommendedDimensions={WEBPUSH_BRAND_ICON_RECOMMENDED_DIMENSIONS}
79
+ disabled={isLocked}
80
+ />
81
+ </CapRow>
82
+ )}
83
+ <CapDivider />
84
+ </>
85
+ );
86
+ };
87
+
88
+ BrandIconSection.propTypes = {
89
+ brandIconOption: PropTypes.string.isRequired,
90
+ onBrandIconChange: PropTypes.func.isRequired,
91
+ brandIconUpload: PropTypes.object.isRequired,
92
+ isLocked: PropTypes.bool,
93
+ isAnyUploadActive: PropTypes.bool,
94
+ formatMessage: PropTypes.func.isRequired,
95
+ messages: PropTypes.object.isRequired,
96
+ webPush: PropTypes.object,
97
+ isFullMode: PropTypes.bool,
98
+ };
99
+
100
+ BrandIconSection.defaultProps = {
101
+ isLocked: false,
102
+ isAnyUploadActive: false,
103
+ webPush: {},
104
+ isFullMode: true,
105
+ };
106
+
107
+ export default BrandIconSection;
108
+
@@ -0,0 +1,172 @@
1
+ import React, { useState, useCallback } from 'react';
2
+ import PropTypes from 'prop-types';
3
+ import { FormattedMessage } from 'react-intl';
4
+ import CapRow from '@capillarytech/cap-ui-library/CapRow';
5
+ import CapInput from '@capillarytech/cap-ui-library/CapInput';
6
+ import CapButton from '@capillarytech/cap-ui-library/CapButton';
7
+ import CapHeading from '@capillarytech/cap-ui-library/CapHeading';
8
+ import messages from '../messages';
9
+ import { isValidHttpUrl } from '../utils/urlValidation';
10
+ import { WEBPUSH_BUTTON_TYPES, BUTTON_TEXT_MAX_LENGTH } from '../../constants';
11
+
12
+ const ButtonForm = ({
13
+ buttonType, // 'primary' or 'secondary'
14
+ formatMessage,
15
+ onSave,
16
+ onCancel,
17
+ initialData,
18
+ isEditMode,
19
+ }) => {
20
+ const [buttonText, setButtonText] = useState(initialData?.text || '');
21
+ const [buttonUrl, setButtonUrl] = useState(initialData?.url || '');
22
+ const [buttonTextError, setButtonTextError] = useState('');
23
+ const [buttonUrlError, setButtonUrlError] = useState('');
24
+
25
+ const validateButtonText = useCallback((value) => {
26
+ if (!value || value.trim() === '') {
27
+ return formatMessage(messages.buttonTextRequired);
28
+ }
29
+ return '';
30
+ }, [formatMessage]);
31
+
32
+ const validateButtonUrl = useCallback((value) => {
33
+ if (!value || value.trim() === '') {
34
+ return formatMessage(messages.buttonUrlRequired);
35
+ }
36
+
37
+ if (!isValidHttpUrl(value)) {
38
+ return formatMessage(messages.buttonUrlInvalid);
39
+ }
40
+
41
+ return '';
42
+ }, [formatMessage]);
43
+
44
+ const handleButtonTextChange = useCallback((e) => {
45
+ const { value } = e.target;
46
+ setButtonText(value);
47
+ const nextError = validateButtonText(value);
48
+ setButtonTextError((prev) => (prev === nextError ? prev : nextError));
49
+ }, [validateButtonText]);
50
+
51
+ const handleButtonUrlChange = useCallback((e) => {
52
+ const { value } = e.target;
53
+ setButtonUrl(value);
54
+ const nextError = validateButtonUrl(value);
55
+ setButtonUrlError((prev) => (prev === nextError ? prev : nextError));
56
+ }, [validateButtonUrl]);
57
+
58
+ const handleSave = useCallback(() => {
59
+ const textError = validateButtonText(buttonText);
60
+ const urlError = validateButtonUrl(buttonUrl);
61
+
62
+ if (textError || urlError) {
63
+ setButtonTextError(textError);
64
+ setButtonUrlError(urlError);
65
+ return;
66
+ }
67
+
68
+ onSave({
69
+ text: buttonText.trim(),
70
+ url: buttonUrl.trim(),
71
+ type: buttonType,
72
+ });
73
+ }, [buttonText, buttonUrl, buttonType, onSave, validateButtonText, validateButtonUrl]);
74
+
75
+ const handleCancel = useCallback(() => {
76
+ onCancel();
77
+ }, [onCancel]);
78
+
79
+ const isSaveDisabled = !buttonText.trim() || !buttonUrl.trim() || buttonTextError || buttonUrlError;
80
+
81
+ const renderCharacterCountSuffix = () => {
82
+ const currentLength = buttonText.length;
83
+ const maxLength = BUTTON_TEXT_MAX_LENGTH;
84
+
85
+ return (
86
+ <span className="button-character-count-suffix">
87
+ {`${currentLength}/${maxLength}`}
88
+ </span>
89
+ );
90
+ };
91
+
92
+ const handleKeyDown = useCallback((e) => {
93
+ if (e.key === 'Enter' && !isSaveDisabled) {
94
+ e.preventDefault();
95
+ handleSave();
96
+ }
97
+ }, [handleSave, isSaveDisabled]);
98
+
99
+ return (
100
+ <div className="webpush-button-form" onKeyDown={handleKeyDown}>
101
+ <CapRow className="button-form-row">
102
+ <CapHeading type="h4" className="button-form-heading">
103
+ <FormattedMessage {...messages.buttonText} />
104
+ </CapHeading>
105
+ <div className="button-form-field">
106
+ <CapInput
107
+ id={`webpush-button-text-input-${buttonType}`}
108
+ placeholder={formatMessage(messages.buttonTextPlaceholder)}
109
+ value={buttonText}
110
+ onChange={handleButtonTextChange}
111
+ maxLength={BUTTON_TEXT_MAX_LENGTH}
112
+ size="default"
113
+ status={buttonTextError ? 'error' : ''}
114
+ help={buttonTextError || ''}
115
+ suffix={renderCharacterCountSuffix()}
116
+ />
117
+ </div>
118
+ </CapRow>
119
+ <CapRow className="button-form-row">
120
+ <CapHeading type="h4" className="button-form-heading">
121
+ <FormattedMessage {...messages.buttonUrlLabel} />
122
+ </CapHeading>
123
+ <CapInput
124
+ id={`webpush-button-url-input-${buttonType}`}
125
+ placeholder={formatMessage(messages.buttonUrlPlaceholder)}
126
+ value={buttonUrl}
127
+ onChange={handleButtonUrlChange}
128
+ size="default"
129
+ status={buttonUrlError ? 'error' : ''}
130
+ help={buttonUrlError || ''}
131
+ />
132
+ </CapRow>
133
+ <CapRow className="button-form-actions">
134
+ <CapButton
135
+ type="primary"
136
+ onClick={handleSave}
137
+ disabled={isSaveDisabled}
138
+ className="button-form-save"
139
+ >
140
+ <FormattedMessage {...messages.saveButton} />
141
+ </CapButton>
142
+ <CapButton
143
+ type="secondary"
144
+ onClick={handleCancel}
145
+ className="button-form-cancel"
146
+ >
147
+ <FormattedMessage {...(isEditMode ? messages.cancelButton : messages.deleteButton)} />
148
+ </CapButton>
149
+ </CapRow>
150
+ </div>
151
+ );
152
+ };
153
+
154
+ ButtonForm.propTypes = {
155
+ buttonType: PropTypes.oneOf([WEBPUSH_BUTTON_TYPES.PRIMARY, WEBPUSH_BUTTON_TYPES.SECONDARY]).isRequired,
156
+ formatMessage: PropTypes.func.isRequired,
157
+ onSave: PropTypes.func.isRequired,
158
+ onCancel: PropTypes.func.isRequired,
159
+ initialData: PropTypes.shape({
160
+ text: PropTypes.string,
161
+ url: PropTypes.string,
162
+ }),
163
+ isEditMode: PropTypes.bool,
164
+ };
165
+
166
+ ButtonForm.defaultProps = {
167
+ initialData: null,
168
+ isEditMode: false,
169
+ };
170
+
171
+ export default ButtonForm;
172
+
@@ -0,0 +1,101 @@
1
+ import React from 'react';
2
+ import PropTypes from 'prop-types';
3
+ import CapRow from '@capillarytech/cap-ui-library/CapRow';
4
+ import CapColumn from '@capillarytech/cap-ui-library/CapColumn';
5
+ import CapIcon from '@capillarytech/cap-ui-library/CapIcon';
6
+
7
+ const ButtonItem = ({
8
+ button,
9
+ index,
10
+ onEdit,
11
+ onDelete,
12
+ onDragStart,
13
+ onDragOver,
14
+ onDrop,
15
+ onDragEnd,
16
+ disabled,
17
+ }) => {
18
+ const handleDragStart = (e) => {
19
+ if (disabled) return;
20
+ e.dataTransfer.effectAllowed = 'move';
21
+ e.dataTransfer.setData('text/html', e.currentTarget);
22
+ onDragStart(index);
23
+ };
24
+
25
+ const handleDragOver = (e) => {
26
+ if (disabled) return;
27
+ e.preventDefault();
28
+ e.dataTransfer.dropEffect = 'move';
29
+ onDragOver(index);
30
+ };
31
+
32
+ const handleDrop = (e) => {
33
+ if (disabled) return;
34
+ e.preventDefault();
35
+ e.stopPropagation();
36
+ onDrop(index);
37
+ };
38
+
39
+ return (
40
+ <div
41
+ className={`webpush-button-item ${disabled ? 'disabled' : ''}`}
42
+ draggable={!disabled}
43
+ onDragStart={handleDragStart}
44
+ onDragOver={handleDragOver}
45
+ onDrop={handleDrop}
46
+ onDragEnd={onDragEnd}
47
+ >
48
+ <CapRow align="middle" className="button-item-content">
49
+ <CapColumn span={1} className="button-item-drag-handle">
50
+ <CapIcon type="drag" className="drag-icon" />
51
+ </CapColumn>
52
+ <CapColumn span={1} className="button-item-icon">
53
+ <CapIcon type="link" className="link-icon" />
54
+ </CapColumn>
55
+ <CapColumn span={14} className="button-item-info">
56
+ <div className="button-item-text-row">
57
+ <span className="button-item-text">{button.text}</span>
58
+ </div>
59
+ </CapColumn>
60
+ <CapColumn span={8} className="button-item-actions">
61
+ <div className="button-item-url">{button.url}</div>
62
+ <div className="action-icons">
63
+ <CapIcon
64
+ type="edit"
65
+ className="action-icon"
66
+ onClick={() => !disabled && onEdit(index)}
67
+ />
68
+ <CapIcon
69
+ type="delete"
70
+ className="action-icon delete-icon"
71
+ onClick={() => !disabled && onDelete(index)}
72
+ />
73
+ </div>
74
+ </CapColumn>
75
+ </CapRow>
76
+ </div>
77
+ );
78
+ };
79
+
80
+ ButtonItem.propTypes = {
81
+ button: PropTypes.shape({
82
+ text: PropTypes.string.isRequired,
83
+ url: PropTypes.string.isRequired,
84
+ type: PropTypes.string.isRequired,
85
+ }).isRequired,
86
+ index: PropTypes.number.isRequired,
87
+ onEdit: PropTypes.func.isRequired,
88
+ onDelete: PropTypes.func.isRequired,
89
+ onDragStart: PropTypes.func.isRequired,
90
+ onDragOver: PropTypes.func.isRequired,
91
+ onDrop: PropTypes.func.isRequired,
92
+ onDragEnd: PropTypes.func.isRequired,
93
+ disabled: PropTypes.bool,
94
+ };
95
+
96
+ ButtonItem.defaultProps = {
97
+ disabled: false,
98
+ };
99
+
100
+ export default ButtonItem;
101
+
@@ -0,0 +1,145 @@
1
+ import React, { useState } from 'react';
2
+ import PropTypes from 'prop-types';
3
+ import { FormattedMessage } from 'react-intl';
4
+ import CapRow from '@capillarytech/cap-ui-library/CapRow';
5
+ import CapButton from '@capillarytech/cap-ui-library/CapButton';
6
+ import ButtonItem from './ButtonItem';
7
+ import messages from '../messages';
8
+
9
+ const ButtonList = ({
10
+ buttons,
11
+ onEdit,
12
+ onDelete,
13
+ onReorder,
14
+ onAddPrimary,
15
+ onAddSecondary,
16
+ showAddPrimary,
17
+ showAddSecondary,
18
+ disabled,
19
+ disableSecondaryButton,
20
+ isInlineFormVisible,
21
+ inlineFormIndex,
22
+ renderInlineForm,
23
+ }) => {
24
+ const [draggedIndex, setDraggedIndex] = useState(null);
25
+
26
+ const handleDragStart = (index) => {
27
+ if (disabled) return;
28
+ setDraggedIndex(index);
29
+ };
30
+
31
+ const handleDragOver = (index) => {
32
+ if (disabled) return;
33
+ if (draggedIndex === null || draggedIndex === index) return;
34
+
35
+ // Reorder buttons
36
+ onReorder(draggedIndex, index);
37
+ setDraggedIndex(index);
38
+ };
39
+
40
+ const handleDrop = () => {
41
+ if (disabled) return;
42
+ };
43
+
44
+ const handleDragEnd = () => {
45
+ if (disabled) return;
46
+ setDraggedIndex(null);
47
+ };
48
+
49
+ const shouldRenderInlineForm = isInlineFormVisible
50
+ && typeof inlineFormIndex === 'number'
51
+ && inlineFormIndex >= 0;
52
+
53
+ // Don't render the container if there are no buttons
54
+ if (buttons.length === 0) {
55
+ return null;
56
+ }
57
+
58
+ return (
59
+ <div className="webpush-button-list">
60
+ {buttons.map((button, index) => {
61
+ if (shouldRenderInlineForm && inlineFormIndex === index && typeof renderInlineForm === 'function') {
62
+ return (
63
+ <div key={`button-inline-form-${button.id}`} className="button-inline-form">
64
+ {renderInlineForm()}
65
+ </div>
66
+ );
67
+ }
68
+ // Only disable items that are not being edited
69
+ const isItemDisabled = disabled || (isInlineFormVisible && inlineFormIndex !== null && inlineFormIndex !== index);
70
+ return (
71
+ <ButtonItem
72
+ key={button.id}
73
+ button={button}
74
+ index={index}
75
+ onEdit={onEdit}
76
+ onDelete={onDelete}
77
+ onDragStart={handleDragStart}
78
+ onDragOver={handleDragOver}
79
+ onDrop={handleDrop}
80
+ onDragEnd={handleDragEnd}
81
+ disabled={isItemDisabled}
82
+ />
83
+ );
84
+ })}
85
+ {showAddPrimary && (
86
+ <CapRow className="button-list-add-button">
87
+ <CapButton
88
+ type="flat"
89
+ onClick={onAddPrimary}
90
+ className="add-primary-button button-add-trigger"
91
+ icon="plus"
92
+ disabled={disabled}
93
+ >
94
+ <FormattedMessage {...messages.addPrimaryButton} />
95
+ </CapButton>
96
+ </CapRow>
97
+ )}
98
+ {showAddSecondary && (
99
+ <CapRow className="button-list-add-button">
100
+ <CapButton
101
+ type="flat"
102
+ onClick={onAddSecondary}
103
+ className="add-secondary-button button-add-trigger"
104
+ icon="plus"
105
+ disabled={disableSecondaryButton || disabled}
106
+ >
107
+ <FormattedMessage {...messages.addSecondaryButton} />
108
+ </CapButton>
109
+ </CapRow>
110
+ )}
111
+ </div>
112
+ );
113
+ };
114
+
115
+ ButtonList.propTypes = {
116
+ buttons: PropTypes.arrayOf(PropTypes.shape({
117
+ id: PropTypes.string.isRequired,
118
+ text: PropTypes.string.isRequired,
119
+ url: PropTypes.string.isRequired,
120
+ type: PropTypes.string.isRequired,
121
+ })).isRequired,
122
+ onEdit: PropTypes.func.isRequired,
123
+ onDelete: PropTypes.func.isRequired,
124
+ onReorder: PropTypes.func.isRequired,
125
+ onAddPrimary: PropTypes.func.isRequired,
126
+ onAddSecondary: PropTypes.func.isRequired,
127
+ showAddPrimary: PropTypes.bool.isRequired,
128
+ showAddSecondary: PropTypes.bool.isRequired,
129
+ disabled: PropTypes.bool,
130
+ disableSecondaryButton: PropTypes.bool,
131
+ isInlineFormVisible: PropTypes.bool,
132
+ inlineFormIndex: PropTypes.number,
133
+ renderInlineForm: PropTypes.func,
134
+ };
135
+
136
+ ButtonList.defaultProps = {
137
+ disabled: false,
138
+ disableSecondaryButton: false,
139
+ isInlineFormVisible: false,
140
+ inlineFormIndex: null,
141
+ renderInlineForm: null,
142
+ };
143
+
144
+ export default ButtonList;
145
+