cap-creatives-ui 8.0.280 → 8.0.321

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (247) hide show
  1. package/.github/workflows/pr-title-check.yml +88 -0
  2. package/app/constants/unified.js +21 -1
  3. package/app/containers/App/constants.js +0 -1
  4. package/app/containers/Login/test/index.test.js +123 -0
  5. package/app/containers/Login/test/selectors.test.js +165 -0
  6. package/app/initialState.js +0 -2
  7. package/app/services/api.js +6 -0
  8. package/app/services/tests/api.test.js +7 -0
  9. package/app/services/tests/getSchema.test.js +95 -0
  10. package/app/utils/common.js +23 -9
  11. package/app/utils/commonUtils.js +64 -93
  12. package/app/utils/tagValidations.js +83 -219
  13. package/app/utils/templateVarUtils.js +172 -0
  14. package/app/utils/tests/common.test.js +265 -323
  15. package/app/utils/tests/commonUtil.test.js +461 -118
  16. package/app/utils/tests/commonUtils.test.js +581 -0
  17. package/app/utils/tests/messageUtils.test.js +95 -0
  18. package/app/utils/tests/smsCharCount.test.js +304 -0
  19. package/app/utils/tests/smsCharCountV2.test.js +213 -10
  20. package/app/utils/tests/tagValidations.test.js +474 -357
  21. package/app/utils/tests/templateVarUtils.test.js +160 -0
  22. package/app/v2Components/CapDeviceContent/index.js +10 -7
  23. package/app/v2Components/CapTagList/index.js +32 -24
  24. package/app/v2Components/CapTagList/style.scss +48 -0
  25. package/app/v2Components/CapTagListWithInput/__tests__/CapTagListWithInput.test.js +63 -0
  26. package/app/v2Components/CapTagListWithInput/index.js +8 -0
  27. package/app/v2Components/CapWhatsappCTA/index.js +2 -0
  28. package/app/v2Components/CapWhatsappCarouselButton/index.js +32 -14
  29. package/app/v2Components/CapWhatsappCarouselButton/tests/index.test.js +120 -2
  30. package/app/v2Components/CommonTestAndPreview/CustomValuesEditor.js +70 -49
  31. package/app/v2Components/CommonTestAndPreview/DeliverySettings/DeliverySettings.scss +39 -0
  32. package/app/v2Components/CommonTestAndPreview/DeliverySettings/ModifyDeliverySettings.js +606 -0
  33. package/app/v2Components/CommonTestAndPreview/DeliverySettings/ModifyDeliverySettings.scss +36 -0
  34. package/app/v2Components/CommonTestAndPreview/DeliverySettings/constants.js +79 -0
  35. package/app/v2Components/CommonTestAndPreview/DeliverySettings/index.js +314 -0
  36. package/app/v2Components/CommonTestAndPreview/DeliverySettings/messages.js +141 -0
  37. package/app/v2Components/CommonTestAndPreview/DeliverySettings/utils/parseSenderDetailsResponse.js +156 -0
  38. package/app/v2Components/CommonTestAndPreview/SendTestMessage.js +57 -1
  39. package/app/v2Components/CommonTestAndPreview/UnifiedPreview/_unifiedPreview.scss +20 -1
  40. package/app/v2Components/CommonTestAndPreview/UnifiedPreview/index.js +133 -4
  41. package/app/v2Components/CommonTestAndPreview/_commonTestAndPreview.scss +210 -4
  42. package/app/v2Components/CommonTestAndPreview/actions.js +20 -0
  43. package/app/v2Components/CommonTestAndPreview/constants.js +57 -1
  44. package/app/v2Components/CommonTestAndPreview/index.js +878 -156
  45. package/app/v2Components/CommonTestAndPreview/messages.js +41 -3
  46. package/app/v2Components/CommonTestAndPreview/previewApiUtils.js +59 -0
  47. package/app/v2Components/CommonTestAndPreview/reducer.js +47 -0
  48. package/app/v2Components/CommonTestAndPreview/sagas.js +75 -5
  49. package/app/v2Components/CommonTestAndPreview/selectors.js +51 -0
  50. package/app/v2Components/CommonTestAndPreview/tests/CustomValuesEditor.test.js +352 -0
  51. package/app/v2Components/CommonTestAndPreview/tests/DeliverySettings/ModifyDeliverySettings.test.js +1156 -0
  52. package/app/v2Components/CommonTestAndPreview/tests/DeliverySettings/index.test.js +334 -0
  53. package/app/v2Components/CommonTestAndPreview/tests/DeliverySettings/utils/parseSenderDetailsResponse.test.js +576 -0
  54. package/app/v2Components/CommonTestAndPreview/tests/SendTestMessage.test.js +156 -0
  55. package/app/v2Components/CommonTestAndPreview/tests/UnifiedPreview/index.test.js +199 -1
  56. package/app/v2Components/CommonTestAndPreview/tests/actions.test.js +50 -0
  57. package/app/v2Components/CommonTestAndPreview/tests/constants.test.js +18 -7
  58. package/app/v2Components/CommonTestAndPreview/tests/index.test.js +914 -5
  59. package/app/v2Components/CommonTestAndPreview/tests/previewApiUtils.test.js +67 -0
  60. package/app/v2Components/CommonTestAndPreview/tests/reducer.test.js +118 -0
  61. package/app/v2Components/CommonTestAndPreview/tests/sagas.test.js +146 -378
  62. package/app/v2Components/CommonTestAndPreview/tests/selectors.test.js +146 -0
  63. package/app/v2Components/ErrorInfoNote/index.js +24 -26
  64. package/app/v2Components/FormBuilder/index.js +182 -204
  65. package/app/v2Components/FormBuilder/messages.js +4 -8
  66. package/app/v2Components/HtmlEditor/HTMLEditor.js +7 -6
  67. package/app/v2Components/HtmlEditor/__tests__/HTMLEditor.apiErrors.test.js +1 -1
  68. package/app/v2Components/HtmlEditor/__tests__/HTMLEditor.test.js +928 -17
  69. package/app/v2Components/HtmlEditor/components/CodeEditorPane/index.js +4 -2
  70. package/app/v2Components/HtmlEditor/hooks/__tests__/useValidation.test.js +452 -3
  71. package/app/v2Components/HtmlEditor/hooks/useValidation.js +12 -9
  72. package/app/v2Components/HtmlEditor/utils/__tests__/htmlValidator.enhanced.test.js +132 -0
  73. package/app/v2Components/HtmlEditor/utils/htmlValidator.js +4 -2
  74. package/app/v2Components/SmsFallback/SmsFallbackLocalSelector.js +87 -0
  75. package/app/v2Components/SmsFallback/constants.js +73 -0
  76. package/app/v2Components/SmsFallback/index.js +956 -0
  77. package/app/v2Components/SmsFallback/index.scss +265 -0
  78. package/app/v2Components/SmsFallback/messages.js +78 -0
  79. package/app/v2Components/SmsFallback/smsFallbackUtils.js +107 -0
  80. package/app/v2Components/SmsFallback/tests/SmsFallbackLocalSelector.test.js +50 -0
  81. package/app/v2Components/SmsFallback/tests/rcsSmsFallback.acceptance.test.js +147 -0
  82. package/app/v2Components/SmsFallback/tests/smsFallbackHandlers.test.js +304 -0
  83. package/app/v2Components/SmsFallback/tests/smsFallbackUi.test.js +197 -0
  84. package/app/v2Components/SmsFallback/tests/smsFallbackUtils.test.js +261 -0
  85. package/app/v2Components/SmsFallback/tests/useLocalTemplateList.test.js +422 -0
  86. package/app/v2Components/SmsFallback/useLocalTemplateList.js +92 -0
  87. package/app/v2Components/TestAndPreviewSlidebox/index.js +22 -1
  88. package/app/v2Components/TestAndPreviewSlidebox/sagas.js +11 -4
  89. package/app/v2Components/TestAndPreviewSlidebox/tests/saga.test.js +3 -1
  90. package/app/v2Components/VarSegmentMessageEditor/constants.js +2 -0
  91. package/app/v2Components/VarSegmentMessageEditor/index.js +125 -0
  92. package/app/v2Components/VarSegmentMessageEditor/index.scss +46 -0
  93. package/app/v2Containers/BeeEditor/index.js +3 -0
  94. package/app/v2Containers/BeePopupEditor/index.js +9 -2
  95. package/app/v2Containers/Cap/mockData.js +0 -14
  96. package/app/v2Containers/Cap/reducer.js +3 -55
  97. package/app/v2Containers/Cap/tests/reducer.test.js +0 -102
  98. package/app/v2Containers/CommunicationFlow/CommunicationFlow.js +291 -0
  99. package/app/v2Containers/CommunicationFlow/CommunicationFlow.scss +25 -0
  100. package/app/v2Containers/CommunicationFlow/Tests/CommunicationFlow.test.js +255 -0
  101. package/app/v2Containers/CommunicationFlow/constants.js +200 -0
  102. package/app/v2Containers/CommunicationFlow/index.js +102 -0
  103. package/app/v2Containers/CommunicationFlow/messages.js +346 -0
  104. package/app/v2Containers/CommunicationFlow/steps/ChannelSelectionStep/ChannelSelectionStep.js +522 -0
  105. package/app/v2Containers/CommunicationFlow/steps/ChannelSelectionStep/ChannelSelectionStep.scss +170 -0
  106. package/app/v2Containers/CommunicationFlow/steps/ChannelSelectionStep/Tests/ChannelSelectionStep.test.js +796 -0
  107. package/app/v2Containers/CommunicationFlow/steps/ChannelSelectionStep/index.js +5 -0
  108. package/app/v2Containers/CommunicationFlow/steps/CommunicationStrategyStep/CommunicationStrategyStep.js +95 -0
  109. package/app/v2Containers/CommunicationFlow/steps/CommunicationStrategyStep/Tests/CommunicationStrategyStep.test.js +133 -0
  110. package/app/v2Containers/CommunicationFlow/steps/CommunicationStrategyStep/index.js +5 -0
  111. package/app/v2Containers/CommunicationFlow/steps/DeliverySettingsStep/DeliverySettingsSection.js +289 -0
  112. package/app/v2Containers/CommunicationFlow/steps/DeliverySettingsStep/DeliverySettingsSection.scss +70 -0
  113. package/app/v2Containers/CommunicationFlow/steps/DeliverySettingsStep/SenderDetails.js +319 -0
  114. package/app/v2Containers/CommunicationFlow/steps/DeliverySettingsStep/SenderDetails.scss +69 -0
  115. package/app/v2Containers/CommunicationFlow/steps/DeliverySettingsStep/Tests/DeliverySettingsSection.test.js +616 -0
  116. package/app/v2Containers/CommunicationFlow/steps/DeliverySettingsStep/Tests/SenderDetails.test.js +577 -0
  117. package/app/v2Containers/CommunicationFlow/steps/DeliverySettingsStep/Tests/deliverySettingsConfig.test.js +1111 -0
  118. package/app/v2Containers/CommunicationFlow/steps/DeliverySettingsStep/deliverySettingsConfig.js +696 -0
  119. package/app/v2Containers/CommunicationFlow/steps/DeliverySettingsStep/index.js +7 -0
  120. package/app/v2Containers/CommunicationFlow/steps/DynamicControlsStep/DynamicControlsStep.js +102 -0
  121. package/app/v2Containers/CommunicationFlow/steps/DynamicControlsStep/DynamicControlsStep.scss +36 -0
  122. package/app/v2Containers/CommunicationFlow/steps/DynamicControlsStep/Tests/DynamicControlsStep.test.js +91 -0
  123. package/app/v2Containers/CommunicationFlow/steps/DynamicControlsStep/index.js +5 -0
  124. package/app/v2Containers/CommunicationFlow/steps/MessageTypeStep/MessageTypeStep.js +86 -0
  125. package/app/v2Containers/CommunicationFlow/steps/MessageTypeStep/Tests/MessageTypeStep.test.js +100 -0
  126. package/app/v2Containers/CommunicationFlow/steps/MessageTypeStep/index.js +5 -0
  127. package/app/v2Containers/CommunicationFlow/utils/getEnabledSteps.js +30 -0
  128. package/app/v2Containers/CreativesContainer/CreativesSlideBoxWrapper.js +43 -0
  129. package/app/v2Containers/CreativesContainer/SlideBoxContent.js +127 -11
  130. package/app/v2Containers/CreativesContainer/SlideBoxFooter.js +62 -9
  131. package/app/v2Containers/CreativesContainer/SlideBoxHeader.js +29 -4
  132. package/app/v2Containers/CreativesContainer/constants.js +24 -0
  133. package/app/v2Containers/CreativesContainer/embeddedSlideboxUtils.js +67 -0
  134. package/app/v2Containers/CreativesContainer/index.js +346 -71
  135. package/app/v2Containers/CreativesContainer/index.scss +51 -1
  136. package/app/v2Containers/CreativesContainer/messages.js +12 -0
  137. package/app/v2Containers/CreativesContainer/tests/SlideBoxContent.localTemplates.test.js +90 -0
  138. package/app/v2Containers/CreativesContainer/tests/SlideBoxContent.test.js +69 -1
  139. package/app/v2Containers/CreativesContainer/tests/SlideBoxFooter.test.js +443 -0
  140. package/app/v2Containers/CreativesContainer/tests/SlideBoxHeader.test.js +110 -0
  141. package/app/v2Containers/CreativesContainer/tests/__snapshots__/SlideBoxContent.test.js.snap +147 -4
  142. package/app/v2Containers/CreativesContainer/tests/__snapshots__/SlideBoxHeader.test.js.snap +363 -0
  143. package/app/v2Containers/CreativesContainer/tests/__snapshots__/index.test.js.snap +57 -10
  144. package/app/v2Containers/CreativesContainer/tests/embeddedSlideboxUtils.test.js +258 -0
  145. package/app/v2Containers/CreativesContainer/tests/index.test.js +71 -9
  146. package/app/v2Containers/CreativesContainer/tests/useLocalTemplatesProp.test.js +125 -0
  147. package/app/v2Containers/Email/index.js +2 -5
  148. package/app/v2Containers/EmailWrapper/components/EmailHTMLEditor.js +58 -77
  149. package/app/v2Containers/EmailWrapper/components/EmailWrapperView.js +3 -0
  150. package/app/v2Containers/EmailWrapper/components/__tests__/EmailHTMLEditor.test.js +158 -89
  151. package/app/v2Containers/EmailWrapper/components/__tests__/EmailWrapperView.test.js +16 -1
  152. package/app/v2Containers/EmailWrapper/hooks/useEmailWrapper.js +17 -12
  153. package/app/v2Containers/EmailWrapper/index.js +4 -0
  154. package/app/v2Containers/EmailWrapper/tests/useEmailWrapper.edgeCases.test.js +1 -0
  155. package/app/v2Containers/EmailWrapper/tests/useEmailWrapper.test.js +133 -0
  156. package/app/v2Containers/FTP/index.js +2 -51
  157. package/app/v2Containers/FTP/messages.js +0 -4
  158. package/app/v2Containers/InApp/__tests__/InAppHTMLEditor.test.js +110 -155
  159. package/app/v2Containers/InApp/index.js +297 -118
  160. package/app/v2Containers/InApp/tests/index.test.js +17 -6
  161. package/app/v2Containers/InApp/tests/mockData.js +1 -1
  162. package/app/v2Containers/InAppWrapper/hooks/__tests__/useInAppWrapper.test.js +19 -0
  163. package/app/v2Containers/InAppWrapper/hooks/useInAppWrapper.js +3 -0
  164. package/app/v2Containers/InAppWrapper/index.js +3 -0
  165. package/app/v2Containers/InappAdvance/index.js +5 -104
  166. package/app/v2Containers/InappAdvance/tests/index.test.js +2 -0
  167. package/app/v2Containers/Line/Container/ImageCarousel/tests/__snapshots__/content.test.js.snap +24 -3
  168. package/app/v2Containers/Line/Container/Text/index.js +0 -1
  169. package/app/v2Containers/MobilePush/Create/index.js +105 -28
  170. package/app/v2Containers/MobilePush/Create/messages.js +4 -0
  171. package/app/v2Containers/MobilePush/Edit/index.js +250 -68
  172. package/app/v2Containers/MobilePush/Edit/messages.js +4 -0
  173. package/app/v2Containers/MobilePushNew/components/PlatformContentFields.js +36 -12
  174. package/app/v2Containers/MobilePushNew/components/tests/PlatformContentFields.test.js +68 -27
  175. package/app/v2Containers/MobilePushNew/index.js +78 -35
  176. package/app/v2Containers/MobilePushNew/messages.js +8 -0
  177. package/app/v2Containers/MobilepushWrapper/index.js +11 -1
  178. package/app/v2Containers/Rcs/constants.js +32 -1
  179. package/app/v2Containers/Rcs/index.js +963 -916
  180. package/app/v2Containers/Rcs/index.scss +85 -6
  181. package/app/v2Containers/Rcs/messages.js +10 -1
  182. package/app/v2Containers/Rcs/rcsLibraryHydrationUtils.js +205 -0
  183. package/app/v2Containers/Rcs/tests/__snapshots__/index.test.js.snap +41136 -1566
  184. package/app/v2Containers/Rcs/tests/__snapshots__/utils.test.js.snap +0 -5
  185. package/app/v2Containers/Rcs/tests/index.test.js +41 -38
  186. package/app/v2Containers/Rcs/tests/mockData.js +38 -0
  187. package/app/v2Containers/Rcs/tests/rcsLibraryHydrationUtils.test.js +251 -0
  188. package/app/v2Containers/Rcs/tests/utils.test.js +379 -1
  189. package/app/v2Containers/Rcs/utils.js +358 -10
  190. package/app/v2Containers/Sms/Create/index.js +122 -39
  191. package/app/v2Containers/Sms/Create/messages.js +4 -0
  192. package/app/v2Containers/Sms/Edit/index.js +37 -3
  193. package/app/v2Containers/Sms/commonMethods.js +3 -6
  194. package/app/v2Containers/Sms/smsFormDataHelpers.js +67 -0
  195. package/app/v2Containers/Sms/tests/commonMethods.test.js +122 -0
  196. package/app/v2Containers/Sms/tests/smsFormDataHelpers.test.js +253 -0
  197. package/app/v2Containers/SmsTrai/Create/index.js +9 -4
  198. package/app/v2Containers/SmsTrai/Create/index.scss +1 -1
  199. package/app/v2Containers/SmsTrai/Edit/constants.js +2 -0
  200. package/app/v2Containers/SmsTrai/Edit/index.js +667 -160
  201. package/app/v2Containers/SmsTrai/Edit/index.scss +121 -0
  202. package/app/v2Containers/SmsTrai/Edit/messages.js +9 -4
  203. package/app/v2Containers/SmsTrai/Edit/tests/__snapshots__/index.test.js.snap +4590 -2436
  204. package/app/v2Containers/SmsWrapper/index.js +41 -8
  205. package/app/v2Containers/TagList/index.js +63 -2
  206. package/app/v2Containers/TagList/messages.js +8 -0
  207. package/app/v2Containers/TagList/tests/TagList.test.js +122 -20
  208. package/app/v2Containers/TagList/tests/mockdata.js +17 -0
  209. package/app/v2Containers/Templates/TemplatesActionBar.js +101 -0
  210. package/app/v2Containers/Templates/_templates.scss +61 -2
  211. package/app/v2Containers/Templates/actions.js +11 -0
  212. package/app/v2Containers/Templates/constants.js +2 -0
  213. package/app/v2Containers/Templates/index.js +90 -40
  214. package/app/v2Containers/Templates/reducer.js +3 -1
  215. package/app/v2Containers/Templates/sagas.js +57 -12
  216. package/app/v2Containers/Templates/tests/TemplatesActionBar.test.js +120 -0
  217. package/app/v2Containers/Templates/tests/__snapshots__/index.test.js.snap +1043 -1079
  218. package/app/v2Containers/Templates/tests/reducer.test.js +12 -0
  219. package/app/v2Containers/Templates/tests/sagas.test.js +193 -12
  220. package/app/v2Containers/Templates/tests/smsTemplatesListApi.test.js +180 -0
  221. package/app/v2Containers/Templates/utils/smsTemplatesListApi.js +79 -0
  222. package/app/v2Containers/TemplatesV2/TemplatesV2.style.js +72 -1
  223. package/app/v2Containers/TemplatesV2/index.js +147 -49
  224. package/app/v2Containers/TemplatesV2/tests/TemplatesV2.localTemplates.test.js +131 -0
  225. package/app/v2Containers/Viber/index.js +9 -10
  226. package/app/v2Containers/Viber/index.scss +1 -1
  227. package/app/v2Containers/WebPush/Create/components/BrandIconSection.test.js +264 -0
  228. package/app/v2Containers/WebPush/Create/components/MessageSection.js +78 -19
  229. package/app/v2Containers/WebPush/Create/components/MessageSection.test.js +82 -0
  230. package/app/v2Containers/WebPush/Create/components/__snapshots__/BrandIconSection.test.js.snap +187 -0
  231. package/app/v2Containers/WebPush/Create/components/__snapshots__/MessageSection.test.js.snap +25 -17
  232. package/app/v2Containers/WebPush/Create/hooks/useAiraTriggerPosition.js +80 -0
  233. package/app/v2Containers/WebPush/Create/hooks/useAiraTriggerPosition.test.js +210 -0
  234. package/app/v2Containers/WebPush/Create/hooks/useTagManagement.js +1 -5
  235. package/app/v2Containers/WebPush/Create/hooks/useTagManagement.test.js +0 -7
  236. package/app/v2Containers/WebPush/Create/index.js +36 -6
  237. package/app/v2Containers/WebPush/Create/index.scss +5 -0
  238. package/app/v2Containers/WebPush/Create/messages.js +8 -1
  239. package/app/v2Containers/WebPush/Create/preview/tests/NotificationContainer.test.js +269 -0
  240. package/app/v2Containers/WebPush/Create/utils/validation.js +31 -15
  241. package/app/v2Containers/WebPush/Create/utils/validation.test.js +72 -24
  242. package/app/v2Containers/Whatsapp/index.js +28 -53
  243. package/app/v2Containers/Whatsapp/tests/__snapshots__/index.test.js.snap +26939 -3982
  244. package/app/v2Containers/Whatsapp/tests/index.test.js +172 -0
  245. package/app/v2Containers/Zalo/index.js +5 -11
  246. package/package.json +2 -2
  247. package/version +9 -0
@@ -0,0 +1,7 @@
1
+ /**
2
+ * DeliverySettingsStep - Entry point
3
+ * Exports: DeliverySettingsSection (integrated in ChannelSelectionStep), SenderDetails
4
+ */
5
+
6
+ export { default as SenderDetails, parseSenderDetailsFromEntity } from './SenderDetails';
7
+ export { default as DeliverySettingsSection } from './DeliverySettingsSection';
@@ -0,0 +1,102 @@
1
+ /**
2
+ * DynamicControlsStep Component
3
+ */
4
+
5
+ import React from 'react';
6
+ import PropTypes from 'prop-types';
7
+ import { injectIntl } from 'react-intl';
8
+ import CapRow from '@capillarytech/cap-ui-library/CapRow';
9
+ import CapHeading from '@capillarytech/cap-ui-library/CapHeading';
10
+ import CapSwitch from '@capillarytech/cap-ui-library/CapSwitch';
11
+ import messages from '../../messages';
12
+ import './DynamicControlsStep.scss';
13
+
14
+ const DynamicControlsStep = ({
15
+ value,
16
+ onChange,
17
+ controls,
18
+ error,
19
+ intl,
20
+ }) => {
21
+ const { formatMessage } = intl || {};
22
+ // formatMessage used for section title only
23
+ const dynamicControls = value?.dynamicControls || {};
24
+
25
+ const handleToggle = (key, checked) => {
26
+ onChange({
27
+ ...value,
28
+ dynamicControls: { ...dynamicControls, [key]: checked },
29
+ });
30
+ };
31
+
32
+ if (!controls?.length) return null;
33
+
34
+ return (
35
+ <CapRow className="dynamic-controls-step">
36
+ <CapHeading type="h3" className="heading-style">
37
+ {formatMessage(messages.dynamicControlsTitle)}
38
+ </CapHeading>
39
+
40
+ {controls.map(({ key, label, description }) => {
41
+ const checked = !!dynamicControls[key];
42
+ const displayLabel = label || key;
43
+
44
+ return (
45
+ <CapRow
46
+ key={key}
47
+ type="flex"
48
+ align="top"
49
+ justify="space-between"
50
+ className="dynamic-controls-step__row"
51
+ >
52
+ <CapRow className="dynamic-controls-step__label-wrap">
53
+ <CapHeading type="h4" className="dynamic-controls-step__label">
54
+ {displayLabel}
55
+ </CapHeading>
56
+ {description && (
57
+ <CapHeading type="label4" className="dynamic-controls-step__desc">
58
+ {description}
59
+ </CapHeading>
60
+ )}
61
+ </CapRow>
62
+ <CapSwitch
63
+ checked={checked}
64
+ onChange={(val) => handleToggle(key, val)}
65
+ className="dynamic-controls-step__switch"
66
+ />
67
+ </CapRow>
68
+ );
69
+ })}
70
+
71
+ {error && (
72
+ <CapRow className="validation-error dynamic-controls-step__error">
73
+ {error}
74
+ </CapRow>
75
+ )}
76
+ </CapRow>
77
+ );
78
+ };
79
+
80
+ DynamicControlsStep.propTypes = {
81
+ value: PropTypes.shape({
82
+ dynamicControls: PropTypes.object,
83
+ }),
84
+ onChange: PropTypes.func.isRequired,
85
+ controls: PropTypes.arrayOf(
86
+ PropTypes.shape({
87
+ key: PropTypes.string.isRequired,
88
+ label: PropTypes.oneOfType([PropTypes.string, PropTypes.node]),
89
+ description: PropTypes.oneOfType([PropTypes.string, PropTypes.node]),
90
+ }),
91
+ ),
92
+ error: PropTypes.string,
93
+ intl: PropTypes.object.isRequired,
94
+ };
95
+
96
+ DynamicControlsStep.defaultProps = {
97
+ value: {},
98
+ controls: [],
99
+ error: null,
100
+ };
101
+
102
+ export default injectIntl(DynamicControlsStep);
@@ -0,0 +1,36 @@
1
+ @import '~@capillarytech/cap-ui-library/styles/_variables.scss';
2
+
3
+ .dynamic-controls-step {
4
+ flex-direction: column;
5
+
6
+ &__row {
7
+ padding: $CAP_SPACE_16 0;
8
+ align-items: flex-start;
9
+ }
10
+
11
+ &__label-wrap {
12
+ flex-direction: column;
13
+ align-items: flex-start;
14
+ flex: 1;
15
+ padding-right: $CAP_SPACE_24;
16
+ }
17
+
18
+ &__label {
19
+ line-height: $CAP_SPACE_20;
20
+ }
21
+
22
+ &__desc {
23
+ margin-top: $CAP_SPACE_04;
24
+ color: $FONT_COLOR_03;
25
+ }
26
+
27
+ &__switch {
28
+ flex-shrink: 0;
29
+ margin-top: 0.125rem;
30
+ }
31
+
32
+ &__error {
33
+ margin-top: $CAP_SPACE_08;
34
+ color: $CAP_RED;
35
+ }
36
+ }
@@ -0,0 +1,91 @@
1
+ import React, { useState } from 'react';
2
+ import {
3
+ render, screen,
4
+ } from '@testing-library/react';
5
+ import userEvent from '@testing-library/user-event';
6
+ import '@testing-library/jest-dom';
7
+ import { IntlProvider } from 'react-intl';
8
+ import DynamicControlsStep from '../DynamicControlsStep';
9
+
10
+ const SAMPLE_CONTROLS = [
11
+ { key: 'alpha', label: 'Alpha', description: 'Alpha help' },
12
+ { key: 'beta', label: 'Beta', description: 'Beta help' },
13
+ ];
14
+
15
+ function renderWithIntl(ui) {
16
+ return render(
17
+ <IntlProvider locale="en" messages={{}} defaultLocale="en">
18
+ {ui}
19
+ </IntlProvider>,
20
+ );
21
+ }
22
+
23
+ function DynamicControlsHarness({ initialDynamicControls = {} }) {
24
+ const [value, setValue] = useState({ dynamicControls: initialDynamicControls });
25
+ return (
26
+ <DynamicControlsStep
27
+ value={value}
28
+ onChange={setValue}
29
+ controls={SAMPLE_CONTROLS}
30
+ />
31
+ );
32
+ }
33
+
34
+ describe('DynamicControlsStep', () => {
35
+ it('renders nothing when there are no controls', () => {
36
+ const { container } = renderWithIntl(
37
+ <DynamicControlsStep
38
+ value={{}}
39
+ onChange={jest.fn()}
40
+ controls={[]}
41
+ />,
42
+ );
43
+ expect(container.firstChild).toBeNull();
44
+ });
45
+
46
+ it('shows each switch on (true) or off (false) from dynamicControls for every field', () => {
47
+ renderWithIntl(
48
+ <DynamicControlsHarness initialDynamicControls={{ alpha: true, beta: false }} />,
49
+ );
50
+
51
+ expect(screen.getByText('Other controls')).toBeInTheDocument();
52
+ expect(screen.getByText('Alpha')).toBeInTheDocument();
53
+ expect(screen.getByText('Beta')).toBeInTheDocument();
54
+
55
+ const switches = screen.getAllByRole('switch');
56
+ expect(switches).toHaveLength(2);
57
+ expect(switches[0]).toBeChecked();
58
+ expect(switches[1]).not.toBeChecked();
59
+ });
60
+
61
+ it('toggles every control through false and true via onChange', async () => {
62
+ renderWithIntl(
63
+ <DynamicControlsHarness initialDynamicControls={{ alpha: true, beta: false }} />,
64
+ );
65
+ const switches = screen.getAllByRole('switch');
66
+
67
+ await userEvent.click(switches[0]);
68
+ expect(switches[0]).not.toBeChecked();
69
+
70
+ await userEvent.click(switches[1]);
71
+ expect(switches[1]).toBeChecked();
72
+
73
+ await userEvent.click(switches[0]);
74
+ expect(switches[0]).toBeChecked();
75
+
76
+ await userEvent.click(switches[1]);
77
+ expect(switches[1]).not.toBeChecked();
78
+ });
79
+
80
+ it('renders validation error when error is set', () => {
81
+ renderWithIntl(
82
+ <DynamicControlsStep
83
+ value={{ dynamicControls: { alpha: false } }}
84
+ onChange={jest.fn()}
85
+ controls={[SAMPLE_CONTROLS[0]]}
86
+ error="Dynamic controls validation failed"
87
+ />,
88
+ );
89
+ expect(screen.getByText('Dynamic controls validation failed')).toBeInTheDocument();
90
+ });
91
+ });
@@ -0,0 +1,5 @@
1
+ /**
2
+ * DynamicControlsStep - Entry point
3
+ */
4
+
5
+ export { default } from './DynamicControlsStep';
@@ -0,0 +1,86 @@
1
+ /**
2
+ * MessageTypeStep Component
3
+ *
4
+ * Radio group for selecting Message Type: Promotional | Transactional
5
+ */
6
+
7
+ import React from 'react';
8
+ import PropTypes from 'prop-types';
9
+ import { injectIntl } from 'react-intl';
10
+ import CapRadio from '@capillarytech/cap-ui-library/CapRadio';
11
+ import CapRow from '@capillarytech/cap-ui-library/CapRow';
12
+ import CapHeading from '@capillarytech/cap-ui-library/CapHeading';
13
+ import { CAP_SPACE_24 } from '@capillarytech/cap-ui-library/styled/variables';
14
+ import { MESSAGE_TYPES_OPTIONS } from '../../constants';
15
+ import messages from '../../messages';
16
+ import '../../CommunicationFlow.scss';
17
+
18
+ const MessageTypeStep = ({
19
+ value,
20
+ defaultOption,
21
+ options: optionsProp,
22
+ onChange,
23
+ error,
24
+ intl,
25
+ }) => {
26
+ const { formatMessage } = intl || {};
27
+ const options = optionsProp || MESSAGE_TYPES_OPTIONS;
28
+
29
+ // Use defaultOption value if value is null/undefined
30
+ const selectedValue = value || defaultOption?.value;
31
+
32
+ const handleChange = (messageType) => {
33
+ onChange(messageType);
34
+ };
35
+
36
+ return (
37
+ <CapRow className="message-type-step">
38
+ <CapHeading type="h3" className="heading-style">
39
+ {formatMessage(messages.messageTypeHeading)}
40
+ </CapHeading>
41
+
42
+ <CapRow align="middle" type="flex" gap={CAP_SPACE_24}>
43
+ {options?.map((option) => (
44
+ <CapRadio
45
+ key={option?.value}
46
+ checked={selectedValue === option?.value}
47
+ onChange={() => handleChange(option?.value)}
48
+ disabled={option?.disabled}
49
+ >
50
+ {option?.label}
51
+ </CapRadio>
52
+ ))}
53
+ </CapRow>
54
+
55
+ {error && (
56
+ <CapRow className="validation-error">
57
+ {error}
58
+ </CapRow>
59
+ )}
60
+ </CapRow>
61
+ );
62
+ };
63
+
64
+ MessageTypeStep.propTypes = {
65
+ value: PropTypes.oneOf(['promotional', 'transactional']),
66
+ defaultOption: PropTypes.shape({
67
+ value: PropTypes.string.isRequired,
68
+ label: PropTypes.node.isRequired,
69
+ }),
70
+ options: PropTypes.arrayOf(PropTypes.shape({
71
+ value: PropTypes.string.isRequired,
72
+ label: PropTypes.node.isRequired,
73
+ })),
74
+ onChange: PropTypes.func.isRequired,
75
+ error: PropTypes.string,
76
+ intl: PropTypes.object.isRequired,
77
+ };
78
+
79
+ MessageTypeStep.defaultProps = {
80
+ value: null,
81
+ defaultOption: null,
82
+ options: null,
83
+ error: null,
84
+ };
85
+
86
+ export default injectIntl(MessageTypeStep);
@@ -0,0 +1,100 @@
1
+ import React from 'react';
2
+ import { render, screen } from '@testing-library/react';
3
+ import userEvent from '@testing-library/user-event';
4
+ import '@testing-library/jest-dom';
5
+ import { IntlProvider } from 'react-intl';
6
+ import MessageTypeStep from '../MessageTypeStep';
7
+
8
+ const OPTIONS = [
9
+ { value: 'promotional', label: 'Promotional', disabled: false },
10
+ { value: 'transactional', label: 'Transactional', disabled: false },
11
+ ];
12
+
13
+ function renderWithIntl(ui) {
14
+ return render(
15
+ <IntlProvider locale="en" messages={{}} defaultLocale="en">
16
+ {ui}
17
+ </IntlProvider>,
18
+ );
19
+ }
20
+
21
+ describe('MessageTypeStep', () => {
22
+ it('shows the step heading and one radio per option', () => {
23
+ const onChange = jest.fn();
24
+ renderWithIntl(
25
+ <MessageTypeStep
26
+ value="promotional"
27
+ options={OPTIONS}
28
+ defaultOption={{ value: 'promotional', label: 'Promotional' }}
29
+ onChange={onChange}
30
+ />,
31
+ );
32
+
33
+ expect(screen.getByText(/message type/i)).toBeInTheDocument();
34
+ expect(screen.getByRole('radio', { name: /promotional/i })).toBeInTheDocument();
35
+ expect(screen.getByRole('radio', { name: /transactional/i })).toBeInTheDocument();
36
+ expect(screen.getByRole('radio', { name: /promotional/i })).toBeChecked();
37
+ });
38
+
39
+ it('uses defaultOption when value is null so the default appears selected', () => {
40
+ const onChange = jest.fn();
41
+ renderWithIntl(
42
+ <MessageTypeStep
43
+ value={null}
44
+ options={OPTIONS}
45
+ defaultOption={{ value: 'transactional', label: 'Transactional' }}
46
+ onChange={onChange}
47
+ />,
48
+ );
49
+
50
+ expect(screen.getByRole('radio', { name: /transactional/i })).toBeChecked();
51
+ expect(screen.getByRole('radio', { name: /promotional/i })).not.toBeChecked();
52
+ });
53
+
54
+ it('calls onChange with the chosen message type when the user switches radios', async () => {
55
+ const onChange = jest.fn();
56
+ renderWithIntl(
57
+ <MessageTypeStep
58
+ value="promotional"
59
+ options={OPTIONS}
60
+ defaultOption={{ value: 'promotional', label: 'Promotional' }}
61
+ onChange={onChange}
62
+ />,
63
+ );
64
+
65
+ await userEvent.click(screen.getByRole('radio', { name: /transactional/i }));
66
+ expect(onChange).toHaveBeenCalledWith('transactional');
67
+ });
68
+
69
+ it('disables individual options when configured', () => {
70
+ const onChange = jest.fn();
71
+ const withDisabled = [
72
+ { value: 'promotional', label: 'Promotional', disabled: true },
73
+ { value: 'transactional', label: 'Transactional', disabled: false },
74
+ ];
75
+ renderWithIntl(
76
+ <MessageTypeStep
77
+ value="transactional"
78
+ options={withDisabled}
79
+ onChange={onChange}
80
+ />,
81
+ );
82
+
83
+ expect(screen.getByRole('radio', { name: /promotional/i })).toBeDisabled();
84
+ expect(screen.getByRole('radio', { name: /transactional/i })).not.toBeDisabled();
85
+ });
86
+
87
+ it('shows validation error text below the radios', () => {
88
+ const onChange = jest.fn();
89
+ renderWithIntl(
90
+ <MessageTypeStep
91
+ value="promotional"
92
+ options={OPTIONS}
93
+ onChange={onChange}
94
+ error="Please choose a message type"
95
+ />,
96
+ );
97
+
98
+ expect(screen.getByText('Please choose a message type')).toBeInTheDocument();
99
+ });
100
+ });
@@ -0,0 +1,5 @@
1
+ /**
2
+ * MessageTypeStep - Entry point
3
+ */
4
+
5
+ export { default } from './MessageTypeStep';
@@ -0,0 +1,30 @@
1
+ import { STEPS } from '../constants';
2
+
3
+ /**
4
+ * Enabled steps in order from config.features.*.required flags.
5
+ * Channel selection, incentives, delivery, and dynamic controls are toggled independently.
6
+ */
7
+ export const getEnabledSteps = (config) => {
8
+ const { features = {} } = config;
9
+ const steps = [];
10
+
11
+ if (features.messageTypeData?.required) {
12
+ steps.push(STEPS.MESSAGE_TYPE);
13
+ }
14
+ if (features.communicationStrategyData?.required) {
15
+ steps.push(STEPS.COMMUNICATION_STRATEGY);
16
+ }
17
+ if (features.contentTemplateData?.required) {
18
+ steps.push(STEPS.CHANNEL_SELECTION);
19
+ }
20
+ if (features.incentivesData?.required) {
21
+ steps.push(STEPS.INCENTIVES);
22
+ }
23
+ if (features.deliverySettingsData?.required) {
24
+ steps.push(STEPS.DELIVERY_SETTINGS);
25
+ }
26
+ if (features.dynamicControlsData?.required) {
27
+ steps.push(STEPS.DYNAMIC_CONTROLS);
28
+ }
29
+ return steps;
30
+ };
@@ -0,0 +1,43 @@
1
+ /**
2
+ * Styled wrapper for CapSlideBox used by CreativesContainer and RCS SMS fallback
3
+ * so header/content/footer margins match.
4
+ */
5
+ import styled from 'styled-components';
6
+ import { CAP_SPACE_16 } from '@capillarytech/cap-ui-library/styled/variables';
7
+
8
+ const CreativesSlideBoxWrapper = styled.div`
9
+ .cap-slide-box-v2-container {
10
+ /*
11
+ * Liquid-error spacing must stay *inside* the content column. margin-bottom on
12
+ * .slidebox-content-container added to the in-flow height past 100vh, so the outer
13
+ * .cap-slide-box-v2-container (overflow-y: auto in cap-ui) gained a second scrollbar.
14
+ */
15
+ .slidebox-header {
16
+ margin-bottom: ${({ slideBoxWrapperMargin }) => `${slideBoxWrapperMargin}`};
17
+ padding: 0 rem;
18
+ &.has-footer {
19
+ overflow-x: hidden;
20
+ }
21
+ }
22
+ .slidebox-content-container {
23
+ margin-bottom: 0;
24
+ padding: 0 rem;
25
+ padding-bottom: ${({ slideBoxWrapperMargin }) => `${slideBoxWrapperMargin}`};
26
+ box-sizing: border-box;
27
+ &.has-footer {
28
+ overflow-x: hidden;
29
+ }
30
+ }
31
+ .slidebox-footer {
32
+ /* Only apply margin-bottom to footer when ErrorInfoNote is shown in footer (BEE editor) */
33
+ /* For HTML Editor, errors are shown in ValidationErrorDisplay (inside content area), so no footer margin needed */
34
+ margin-bottom: ${({ shouldApplyFooterMargin }) => (shouldApplyFooterMargin ? `${CAP_SPACE_16}` : '0')};
35
+ padding: 0 rem;
36
+ &.has-footer {
37
+ overflow-x: hidden;
38
+ }
39
+ }
40
+ }
41
+ `;
42
+
43
+ export default CreativesSlideBoxWrapper;