@capillarytech/creatives-library 8.0.295 → 8.0.297

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 (39) hide show
  1. package/package.json +1 -1
  2. package/v2Components/CommonTestAndPreview/DeliverySettings/DeliverySettings.scss +33 -0
  3. package/v2Components/CommonTestAndPreview/DeliverySettings/ModifyDeliverySettings.js +420 -0
  4. package/v2Components/CommonTestAndPreview/DeliverySettings/ModifyDeliverySettings.scss +36 -0
  5. package/v2Components/CommonTestAndPreview/DeliverySettings/constants.js +63 -0
  6. package/v2Components/CommonTestAndPreview/DeliverySettings/index.js +239 -0
  7. package/v2Components/CommonTestAndPreview/DeliverySettings/messages.js +111 -0
  8. package/v2Components/CommonTestAndPreview/DeliverySettings/utils/parseSenderDetailsResponse.js +88 -0
  9. package/v2Components/CommonTestAndPreview/SendTestMessage.js +51 -1
  10. package/v2Components/CommonTestAndPreview/actions.js +20 -0
  11. package/v2Components/CommonTestAndPreview/constants.js +15 -0
  12. package/v2Components/CommonTestAndPreview/index.js +200 -16
  13. package/v2Components/CommonTestAndPreview/reducer.js +47 -0
  14. package/v2Components/CommonTestAndPreview/sagas.js +61 -0
  15. package/v2Components/CommonTestAndPreview/selectors.js +51 -0
  16. package/v2Components/CommonTestAndPreview/tests/DeliverySettings/ModifyDeliverySettings.test.js +889 -0
  17. package/v2Components/CommonTestAndPreview/tests/DeliverySettings/index.test.js +221 -0
  18. package/v2Components/CommonTestAndPreview/tests/DeliverySettings/utils/parseSenderDetailsResponse.test.js +235 -0
  19. package/v2Components/CommonTestAndPreview/tests/SendTestMessage.test.js +135 -0
  20. package/v2Components/CommonTestAndPreview/tests/actions.test.js +50 -0
  21. package/v2Components/CommonTestAndPreview/tests/constants.test.js +18 -0
  22. package/v2Components/CommonTestAndPreview/tests/index.test.js +783 -2
  23. package/v2Components/CommonTestAndPreview/tests/reducer.test.js +118 -0
  24. package/v2Components/CommonTestAndPreview/tests/sagas.test.js +145 -0
  25. package/v2Components/CommonTestAndPreview/tests/selectors.test.js +146 -0
  26. package/v2Components/FormBuilder/index.js +1 -1
  27. package/v2Components/HtmlEditor/HTMLEditor.js +0 -1
  28. package/v2Components/HtmlEditor/__tests__/HTMLEditor.test.js +0 -1
  29. package/v2Components/HtmlEditor/hooks/__tests__/useValidation.test.js +3 -132
  30. package/v2Components/HtmlEditor/hooks/useValidation.js +9 -12
  31. package/v2Components/HtmlEditor/utils/htmlValidator.js +2 -4
  32. package/v2Components/TestAndPreviewSlidebox/index.js +14 -0
  33. package/v2Containers/EmailWrapper/components/EmailHTMLEditor.js +2 -2
  34. package/v2Containers/EmailWrapper/components/__tests__/EmailHTMLEditor.test.js +18 -110
  35. package/v2Containers/Rcs/tests/__snapshots__/index.test.js.snap +697 -12
  36. package/v2Containers/SmsTrai/Edit/index.js +5 -1
  37. package/v2Containers/SmsTrai/Edit/tests/__snapshots__/index.test.js.snap +201 -0
  38. package/v2Containers/Whatsapp/index.js +1 -1
  39. package/v2Containers/Whatsapp/tests/__snapshots__/index.test.js.snap +26242 -4225
@@ -0,0 +1,239 @@
1
+ /**
2
+ * DeliverySettings — summary row + CapSlideBox trigger for Test and Preview.
3
+ * Rendered only for SMS, Email, WhatsApp. Uses cap-ui-library only.
4
+ *
5
+ * Reference: cap-campaigns-v2 DeliverySettingsV2 (summary + modify panel).
6
+ */
7
+
8
+ import React, { useState, useCallback } from "react";
9
+ import PropTypes from "prop-types";
10
+ import CapRow from "@capillarytech/cap-ui-library/CapRow";
11
+ import CapHeading from "@capillarytech/cap-ui-library/CapHeading";
12
+ import CapIcon from "@capillarytech/cap-ui-library/CapIcon";
13
+ import CapLabel from "@capillarytech/cap-ui-library/CapLabel";
14
+ import CapSlideBox from "@capillarytech/cap-ui-library/CapSlideBox";
15
+ import { FormattedMessage } from "react-intl";
16
+ import get from "lodash/get";
17
+ import messages from "./messages";
18
+ import ModifyDeliverySettings from "./ModifyDeliverySettings";
19
+ import {
20
+ CHANNELS,
21
+ CHANNELS_WITH_DELIVERY_SETTINGS,
22
+ SUMMARY_EMPTY_PLACEHOLDER,
23
+ DELIVERY_SETTING_KEY_DOMAIN_ID,
24
+ DELIVERY_SETTING_KEY_GSM_SENDER_ID,
25
+ DELIVERY_SETTING_KEY_SENDER_EMAIL,
26
+ DELIVERY_SETTING_KEY_SENDER_LABEL,
27
+ DELIVERY_SETTING_KEY_SENDER_REPLY_TO,
28
+ DELIVERY_SETTING_KEY_SOURCE_ACCOUNT_IDENTIFIER,
29
+ DELIVERY_SETTING_KEY_SENDER_MOB_NUM,
30
+ TEST_ID_DELIVERY_SETTINGS_EDIT,
31
+ } from "./constants";
32
+ import "./DeliverySettings.scss";
33
+
34
+ const DeliverySettings = (props) => {
35
+ const {
36
+ channel,
37
+ deliverySettings = {},
38
+ senderDetailsOptions = [],
39
+ wecrmAccounts = [],
40
+ onSaveDeliverySettings,
41
+ isLoadingSenderDetails,
42
+ formatMessage,
43
+ smsTraiDltEnabled,
44
+ registeredSenderIds,
45
+ whatsappAccountFromForm,
46
+ } = props;
47
+
48
+ const [isSlideBoxOpen, setSlideBoxOpen] = useState(false);
49
+
50
+ const openSlideBox = useCallback(() => setSlideBoxOpen(true), []);
51
+ const closeSlideBox = useCallback(() => setSlideBoxOpen(false), []);
52
+
53
+ const handleSave = useCallback(
54
+ (values) => {
55
+ onSaveDeliverySettings(values);
56
+ closeSlideBox();
57
+ },
58
+ [onSaveDeliverySettings, closeSlideBox]
59
+ );
60
+
61
+ if (!CHANNELS_WITH_DELIVERY_SETTINGS.includes(channel)) {
62
+ return null;
63
+ }
64
+
65
+ const notConfiguredLabel = formatMessage(messages.notConfigured);
66
+
67
+ const getSummaryText = () => {
68
+ const empty = SUMMARY_EMPTY_PLACEHOLDER;
69
+ if (channel === CHANNELS.SMS) {
70
+ const domain = (senderDetailsOptions || []).find(
71
+ (d) => d.domainId === get(deliverySettings, DELIVERY_SETTING_KEY_DOMAIN_ID),
72
+ );
73
+ const domainName = domain?.domainName || empty;
74
+ const senderId = get(deliverySettings, DELIVERY_SETTING_KEY_GSM_SENDER_ID) || empty;
75
+ return { senderDomain: domainName, senderId };
76
+ }
77
+ if (channel === CHANNELS.EMAIL) {
78
+ const domain = (senderDetailsOptions || []).find(
79
+ (d) => d.domainId === get(deliverySettings, DELIVERY_SETTING_KEY_DOMAIN_ID),
80
+ );
81
+ const emailDomain = domain?.domainName || empty;
82
+ const senderEmail = get(deliverySettings, DELIVERY_SETTING_KEY_SENDER_EMAIL) || empty;
83
+ const senderLabel = get(deliverySettings, DELIVERY_SETTING_KEY_SENDER_LABEL) || empty;
84
+ const replyToId = get(deliverySettings, DELIVERY_SETTING_KEY_SENDER_REPLY_TO) || empty;
85
+ return {
86
+ emailDomain,
87
+ senderEmail,
88
+ senderLabel,
89
+ replyToId,
90
+ };
91
+ }
92
+ if (channel === CHANNELS.WHATSAPP) {
93
+ const account = (wecrmAccounts || []).find(
94
+ (a) => a.sourceAccountIdentifier
95
+ === get(deliverySettings, DELIVERY_SETTING_KEY_SOURCE_ACCOUNT_IDENTIFIER),
96
+ );
97
+ const accountName = account?.name || empty;
98
+ const senderNumber = get(deliverySettings, DELIVERY_SETTING_KEY_SENDER_MOB_NUM) || empty;
99
+ return { account: accountName, senderNumber };
100
+ }
101
+ return { account: empty, sender: empty };
102
+ };
103
+
104
+ const summary = getSummaryText();
105
+ let hasValues = false;
106
+ if (channel === CHANNELS.SMS) {
107
+ hasValues = summary.senderDomain !== SUMMARY_EMPTY_PLACEHOLDER
108
+ || summary.senderId !== SUMMARY_EMPTY_PLACEHOLDER;
109
+ } else if (channel === CHANNELS.EMAIL) {
110
+ hasValues = summary.emailDomain !== SUMMARY_EMPTY_PLACEHOLDER
111
+ || summary.senderEmail !== SUMMARY_EMPTY_PLACEHOLDER
112
+ || summary.senderLabel !== SUMMARY_EMPTY_PLACEHOLDER
113
+ || summary.replyToId !== SUMMARY_EMPTY_PLACEHOLDER;
114
+ } else if (channel === CHANNELS.WHATSAPP) {
115
+ hasValues = summary.account !== SUMMARY_EMPTY_PLACEHOLDER
116
+ || summary.senderNumber !== SUMMARY_EMPTY_PLACEHOLDER;
117
+ } else {
118
+ hasValues = summary.account !== SUMMARY_EMPTY_PLACEHOLDER
119
+ || summary.sender !== SUMMARY_EMPTY_PLACEHOLDER;
120
+ }
121
+
122
+ const getSummaryObject = () => {
123
+ if (!hasValues) return null;
124
+ const label = (msg) => formatMessage(msg);
125
+ if (channel === CHANNELS.SMS) {
126
+ return {
127
+ [label(messages.senderDomainSummary)]: summary.senderDomain,
128
+ [label(messages.senderId)]: summary.senderId,
129
+ };
130
+ }
131
+ if (channel === CHANNELS.EMAIL) {
132
+ return {
133
+ [label(messages.emailDomain)]: summary.emailDomain,
134
+ [label(messages.senderId)]: summary.senderEmail,
135
+ [label(messages.senderName)]: summary.senderLabel,
136
+ [label(messages.replyToId)]: summary.replyToId,
137
+ };
138
+ }
139
+ if (channel === CHANNELS.WHATSAPP) {
140
+ return {
141
+ [label(messages.account)]: summary.account,
142
+ [label(messages.senderNumber)]: summary.senderNumber,
143
+ };
144
+ }
145
+ return {
146
+ [label(messages.account)]: summary.account,
147
+ [label(messages.senderNumber)]: summary.sender,
148
+ };
149
+ };
150
+
151
+ const summaryObject = getSummaryObject();
152
+
153
+ return (
154
+ <CapRow className="delivery-settings">
155
+ <CapRow className="delivery-settings__heading-row">
156
+ <CapHeading type="h10">
157
+ <FormattedMessage {...messages.deliverySettings} />
158
+ </CapHeading>
159
+ </CapRow>
160
+ <CapRow type="flex" className="delivery-settings__summary-row">
161
+ <CapRow type="flex" className="delivery-settings__summary-inner">
162
+ {summaryObject == null ? (
163
+ <CapLabel type="label2">{notConfiguredLabel}</CapLabel>
164
+ ) : (
165
+ Object.entries(summaryObject).map(([key, value]) => (
166
+ <CapRow type="flex" key={key} className="delivery-settings__summary-entry">
167
+ <CapLabel type="label1" className="delivery-settings__summary-key">{key}</CapLabel>
168
+ <CapLabel type="label9">
169
+ :
170
+ {' '}
171
+ {value}
172
+ </CapLabel>
173
+ </CapRow>
174
+ ))
175
+ )}
176
+ </CapRow>
177
+ <CapIcon
178
+ type="edit"
179
+ onClick={openSlideBox}
180
+ className="delivery-settings__edit-icon"
181
+ data-testid={TEST_ID_DELIVERY_SETTINGS_EDIT}
182
+ size="s"
183
+ />
184
+ </CapRow>
185
+
186
+ {isSlideBoxOpen && (
187
+ <CapSlideBox
188
+ show
189
+ size="size-l"
190
+ header={<FormattedMessage {...messages.deliverySettings} />}
191
+ handleClose={closeSlideBox}
192
+ content={(
193
+ <ModifyDeliverySettings
194
+ channel={channel}
195
+ deliverySettings={deliverySettings}
196
+ senderDetailsOptions={senderDetailsOptions}
197
+ wecrmAccounts={wecrmAccounts}
198
+ onSaveDeliverySettings={handleSave}
199
+ onClose={closeSlideBox}
200
+ isLoading={isLoadingSenderDetails}
201
+ formatMessage={formatMessage}
202
+ smsTraiDltEnabled={smsTraiDltEnabled}
203
+ registeredSenderIds={registeredSenderIds}
204
+ whatsappAccountFromForm={whatsappAccountFromForm}
205
+ />
206
+ )}
207
+ />
208
+ )}
209
+ </CapRow>
210
+ );
211
+ };
212
+
213
+ DeliverySettings.propTypes = {
214
+ channel: PropTypes.string.isRequired,
215
+ deliverySettings: PropTypes.object,
216
+ senderDetailsOptions: PropTypes.array,
217
+ wecrmAccounts: PropTypes.array,
218
+ onSaveDeliverySettings: PropTypes.func.isRequired,
219
+ isLoadingSenderDetails: PropTypes.bool,
220
+ formatMessage: PropTypes.func,
221
+ smsTraiDltEnabled: PropTypes.bool,
222
+ registeredSenderIds: PropTypes.array,
223
+ whatsappAccountFromForm: PropTypes.shape({
224
+ accountName: PropTypes.string,
225
+ }),
226
+ };
227
+
228
+ DeliverySettings.defaultProps = {
229
+ deliverySettings: {},
230
+ senderDetailsOptions: [],
231
+ wecrmAccounts: [],
232
+ isLoadingSenderDetails: false,
233
+ formatMessage: undefined,
234
+ smsTraiDltEnabled: false,
235
+ registeredSenderIds: [],
236
+ whatsappAccountFromForm: undefined,
237
+ };
238
+
239
+ export default DeliverySettings;
@@ -0,0 +1,111 @@
1
+ /**
2
+ * DeliverySettings messages for Test and Preview.
3
+ * Aligned with cap-campaigns-v2 DeliverySettingsV2 and ModifyDeliverySettings messages.
4
+ */
5
+
6
+ import { defineMessages } from 'react-intl';
7
+
8
+ const prefix = 'creatives.CommonTestAndPreview.DeliverySettings';
9
+
10
+ export default defineMessages({
11
+ deliverySettings: {
12
+ id: `${prefix}.deliverySettings`,
13
+ defaultMessage: 'Delivery settings',
14
+ },
15
+ notConfigured: {
16
+ id: `${prefix}.notConfigured`,
17
+ defaultMessage: 'Not configured',
18
+ },
19
+ account: {
20
+ id: `${prefix}.account`,
21
+ defaultMessage: 'Account',
22
+ },
23
+ senderNumber: {
24
+ id: `${prefix}.senderNumber`,
25
+ defaultMessage: 'Sender number',
26
+ },
27
+ senderDomain: {
28
+ id: `${prefix}.senderDomain`,
29
+ defaultMessage: 'Sender domain',
30
+ },
31
+ senderId: {
32
+ id: `${prefix}.senderId`,
33
+ defaultMessage: 'Sender ID',
34
+ },
35
+ senderName: {
36
+ id: `${prefix}.senderName`,
37
+ defaultMessage: 'Sender name',
38
+ },
39
+ replyToId: {
40
+ id: `${prefix}.replyToId`,
41
+ defaultMessage: 'Reply-to ID',
42
+ },
43
+ done: {
44
+ id: `${prefix}.done`,
45
+ defaultMessage: 'Done',
46
+ },
47
+ smsDomain: {
48
+ id: `${prefix}.smsDomain`,
49
+ defaultMessage: 'SMS Domain',
50
+ },
51
+ /** SMS summary & form: "Sender Domain" (capital D) for summary line */
52
+ senderDomainSummary: {
53
+ id: `${prefix}.senderDomainSummary`,
54
+ defaultMessage: 'Sender Domain',
55
+ },
56
+ /** SMS form label with colon: "Sender domain:" */
57
+ senderDomainLabel: {
58
+ id: `${prefix}.senderDomainLabel`,
59
+ defaultMessage: 'Sender domain:',
60
+ },
61
+ /** SMS form label with colon: "Sender ID:" */
62
+ senderIdLabel: {
63
+ id: `${prefix}.senderIdLabel`,
64
+ defaultMessage: 'Sender ID:',
65
+ },
66
+ emailDomain: {
67
+ id: `${prefix}.emailDomain`,
68
+ defaultMessage: 'Email Domain',
69
+ },
70
+ /** Email form/summary: "Email domain:" (with colon) */
71
+ emailDomainLabel: {
72
+ id: `${prefix}.emailDomainLabel`,
73
+ defaultMessage: 'Email domain:',
74
+ },
75
+ /** Email form: "Sender ID:" (with colon) */
76
+ senderNameLabelEmail: {
77
+ id: `${prefix}.senderIdLabelEmail`,
78
+ defaultMessage: 'Sender Name:',
79
+ },
80
+ /** Email form/summary: "Reply-to ID:" (with colon) */
81
+ replyToIdLabel: {
82
+ id: `${prefix}.replyToIdLabel`,
83
+ defaultMessage: 'Reply-to ID:',
84
+ },
85
+ whatsappBusinessAcc: {
86
+ id: `${prefix}.whatsappBusinessAcc`,
87
+ defaultMessage: 'WhatsApp business account',
88
+ },
89
+ whatsappSenderNum: {
90
+ id: `${prefix}.whatsappSenderNum`,
91
+ defaultMessage: 'WhatsApp sender number',
92
+ },
93
+ /** WhatsApp form/summary: "Account:" (with colon) */
94
+ accountLabel: {
95
+ id: `${prefix}.accountLabel`,
96
+ defaultMessage: 'Account:',
97
+ },
98
+ /** WhatsApp form/summary: "Sender number:" (with colon) */
99
+ senderNumberLabel: {
100
+ id: `${prefix}.senderNumberLabel`,
101
+ defaultMessage: 'Sender number:',
102
+ },
103
+ noOptions: {
104
+ id: `${prefix}.noOptions`,
105
+ defaultMessage: 'No options',
106
+ },
107
+ disabledMessage: {
108
+ id: `${prefix}.disabledMessage`,
109
+ defaultMessage: 'Message template selected belongs to this account',
110
+ },
111
+ });
@@ -0,0 +1,88 @@
1
+ /**
2
+ * Normalize getSenderDetails(channel, orgUnitId) API response for a single channel.
3
+ * Output shape matches cap-campaigns-v2 parseSenderDetails so UI can consume
4
+ * domains with domainId, domainName, gsmSenders, emailSenders, emailRepliers, etc.
5
+ *
6
+ * Reference: cap-campaigns-v2 app/utils/parseSenderDetails.js
7
+ * No cross-repo imports; logic aligned with campaigns domain structure.
8
+ */
9
+
10
+ import get from 'lodash/get';
11
+ import { CHANNELS } from '../../constants';
12
+
13
+ const getSenderOptions = (contactInfo, key) =>
14
+ (contactInfo || [])
15
+ .filter((contactInfoItem) => contactInfoItem.type === key && contactInfoItem.valid)
16
+ .sort((contact) => (contact.default ? -1 : 0));
17
+
18
+ /**
19
+ * Parse raw API response for one channel into { domains: [...] }
20
+ * @param {string} channel - SMS | EMAIL | WHATSAPP
21
+ * @param {Object} response - API response (e.g. { entity: { SMS: [...] } } or { entity: [...] })
22
+ * @returns {{ domains: Array }} - domains array compatible with campaigns DeliverySettingsV2
23
+ */
24
+ export function parseSenderDetailsResponse(channel, response) {
25
+ const entity = get(response, 'entity', response);
26
+ if (!entity) {
27
+ return { domains: [] };
28
+ }
29
+
30
+ // Single-channel API: entity may be { [channel]: [...] } or direct array
31
+ let channelSenderDetails = get(entity, channel, null);
32
+ if (channelSenderDetails == null && Array.isArray(entity)) {
33
+ channelSenderDetails = entity;
34
+ }
35
+ if (!Array.isArray(channelSenderDetails)) {
36
+ return { domains: [] };
37
+ }
38
+
39
+ const domains = [];
40
+
41
+ channelSenderDetails.forEach((element) => {
42
+ const { id: dgmId, priority, domainProperties = {} } = element;
43
+ const {
44
+ domainName,
45
+ id = -1,
46
+ contactInfo,
47
+ connectionProperties: {
48
+ sourceAccountIdentifier = '',
49
+ wabaId = '',
50
+ userid = '',
51
+ } = {},
52
+ } = domainProperties;
53
+
54
+ const domain = {
55
+ dgmId,
56
+ domainName,
57
+ domainId: id,
58
+ priority: priority != null ? priority : 0,
59
+ };
60
+
61
+ if ([CHANNELS.SMS, CHANNELS.WHATSAPP].includes(channel)) {
62
+ domain.cdmaSenders = getSenderOptions(contactInfo, 'cdma_sender_id');
63
+ domain.gsmSenders = getSenderOptions(contactInfo, 'gsm_sender_id');
64
+ domain.sourceAccountIdentifier =
65
+ sourceAccountIdentifier || wabaId || userid || '';
66
+ }
67
+
68
+ if (channel === CHANNELS.EMAIL) {
69
+ domain.emailSenders = getSenderOptions(contactInfo, 'sender_id');
70
+ domain.emailRepliers = getSenderOptions(contactInfo, 'reply_to_id');
71
+ }
72
+
73
+ domains.push(domain);
74
+ });
75
+
76
+ // Sort by priority and dedupe by domainName (match campaigns behaviour)
77
+ domains.sort((a, b) => (a.priority || 0) - (b.priority || 0));
78
+ const deduped = domains.reduce((acc, domain) => {
79
+ if (!acc.find((d) => d.domainName === domain.domainName)) {
80
+ acc.push(domain);
81
+ }
82
+ return acc;
83
+ }, []);
84
+
85
+ return { domains: deduped };
86
+ }
87
+
88
+ export default parseSenderDetailsResponse;
@@ -8,6 +8,10 @@ import CapStepsAccordian from '@capillarytech/cap-ui-library/CapStepsAccordian';
8
8
  import CapTreeSelect from '@capillarytech/cap-ui-library/CapTreeSelect';
9
9
  import isEmpty from 'lodash/isEmpty';
10
10
  import messages from './messages';
11
+ import DeliverySettings from './DeliverySettings';
12
+ import { CHANNELS } from './constants';
13
+
14
+ const CHANNELS_WITH_DELIVERY_SETTINGS = [CHANNELS.SMS, CHANNELS.EMAIL, CHANNELS.WHATSAPP];
11
15
 
12
16
  const SendTestMessage = ({
13
17
  isFetchingTestCustomers,
@@ -17,8 +21,16 @@ const SendTestMessage = ({
17
21
  selectedTestEntities,
18
22
  handleSendTestMessage,
19
23
  formData,
24
+ channel,
20
25
  isSendingTestMessage,
21
26
  formatMessage,
27
+ deliverySettings,
28
+ senderDetailsOptions,
29
+ wecrmAccounts,
30
+ onSaveDeliverySettings,
31
+ isLoadingSenderDetails,
32
+ smsTraiDltEnabled,
33
+ registeredSenderIds,
22
34
  }) => (
23
35
  <CapStepsAccordian
24
36
  showNumberSteps={false}
@@ -43,6 +55,24 @@ const SendTestMessage = ({
43
55
  multiple
44
56
  placeholder={formatMessage(messages.testCustomersPlaceholder)}
45
57
  />
58
+ {CHANNELS_WITH_DELIVERY_SETTINGS.includes(channel) && (
59
+ <DeliverySettings
60
+ channel={channel}
61
+ deliverySettings={deliverySettings || {}}
62
+ senderDetailsOptions={senderDetailsOptions || []}
63
+ wecrmAccounts={wecrmAccounts || []}
64
+ onSaveDeliverySettings={onSaveDeliverySettings}
65
+ isLoadingSenderDetails={isLoadingSenderDetails}
66
+ formatMessage={formatMessage}
67
+ smsTraiDltEnabled={smsTraiDltEnabled}
68
+ registeredSenderIds={registeredSenderIds}
69
+ whatsappAccountFromForm={
70
+ channel === CHANNELS.WHATSAPP && formData?.accountName
71
+ ? { accountName: formData.accountName }
72
+ : undefined
73
+ }
74
+ />
75
+ )}
46
76
  <CapButton onClick={handleSendTestMessage} disabled={isEmpty(selectedTestEntities) || isSendingTestMessage}>
47
77
  <FormattedMessage {...messages.sendTestButton} />
48
78
  </CapButton>
@@ -60,9 +90,29 @@ SendTestMessage.propTypes = {
60
90
  handleTestEntitiesChange: PropTypes.func.isRequired,
61
91
  selectedTestEntities: PropTypes.array.isRequired,
62
92
  handleSendTestMessage: PropTypes.func.isRequired,
63
- formData: PropTypes.object.isRequired,
93
+ formData: PropTypes.object,
94
+ channel: PropTypes.string,
64
95
  isSendingTestMessage: PropTypes.bool.isRequired,
65
96
  formatMessage: PropTypes.func.isRequired,
97
+ deliverySettings: PropTypes.object,
98
+ senderDetailsOptions: PropTypes.array,
99
+ wecrmAccounts: PropTypes.array,
100
+ onSaveDeliverySettings: PropTypes.func,
101
+ isLoadingSenderDetails: PropTypes.bool,
102
+ smsTraiDltEnabled: PropTypes.bool,
103
+ registeredSenderIds: PropTypes.array,
104
+ };
105
+
106
+ SendTestMessage.defaultProps = {
107
+ formData: undefined,
108
+ channel: undefined,
109
+ deliverySettings: {},
110
+ senderDetailsOptions: [],
111
+ wecrmAccounts: [],
112
+ onSaveDeliverySettings: undefined,
113
+ isLoadingSenderDetails: false,
114
+ smsTraiDltEnabled: false,
115
+ registeredSenderIds: [],
66
116
  };
67
117
 
68
118
  export default SendTestMessage;
@@ -18,6 +18,8 @@ import {
18
18
  GET_PREFILLED_VALUES_REQUESTED,
19
19
  CLEAR_PREFILLED_VALUES,
20
20
  CLEAR_PREVIEW_ERRORS,
21
+ GET_SENDER_DETAILS_REQUESTED,
22
+ GET_WECRM_ACCOUNTS_REQUESTED,
21
23
  } from './constants';
22
24
 
23
25
  // ============================================
@@ -125,3 +127,21 @@ export const clearPrefilledValues = () => ({
125
127
  export const clearPreviewErrors = () => ({
126
128
  type: CLEAR_PREVIEW_ERRORS,
127
129
  });
130
+
131
+ /**
132
+ * Request sender details for a channel (SMS, EMAIL, WHATSAPP) for delivery settings
133
+ * @param {Object} payload - { channel, orgUnitId }
134
+ */
135
+ export const getSenderDetailsRequested = (payload) => ({
136
+ type: GET_SENDER_DETAILS_REQUESTED,
137
+ payload,
138
+ });
139
+
140
+ /**
141
+ * Request WeCRM accounts (e.g. for WhatsApp account dropdown)
142
+ * @param {Object} payload - { sourceName } e.g. { sourceName: 'WHATSAPP' }
143
+ */
144
+ export const getWeCrmAccountsRequested = (payload) => ({
145
+ type: GET_WECRM_ACCOUNTS_REQUESTED,
146
+ payload,
147
+ });
@@ -55,6 +55,16 @@ export const CLEAR_SEARCH_RESULTS = 'app/CommonTestAndPreview/CLEAR_SEARCH_RESUL
55
55
  export const CLEAR_PREFILLED_VALUES = 'app/CommonTestAndPreview/CLEAR_PREFILLED_VALUES';
56
56
  export const CLEAR_PREVIEW_ERRORS = 'app/CommonTestAndPreview/CLEAR_PREVIEW_ERRORS';
57
57
 
58
+ // Get Sender Details (delivery settings for Test and Preview)
59
+ export const GET_SENDER_DETAILS_REQUESTED = 'app/CommonTestAndPreview/GET_SENDER_DETAILS_REQUESTED';
60
+ export const GET_SENDER_DETAILS_SUCCESS = 'app/CommonTestAndPreview/GET_SENDER_DETAILS_SUCCESS';
61
+ export const GET_SENDER_DETAILS_FAILURE = 'app/CommonTestAndPreview/GET_SENDER_DETAILS_FAILURE';
62
+
63
+ // Get WeCRM Accounts (WhatsApp account list)
64
+ export const GET_WECRM_ACCOUNTS_REQUESTED = 'app/CommonTestAndPreview/GET_WECRM_ACCOUNTS_REQUESTED';
65
+ export const GET_WECRM_ACCOUNTS_SUCCESS = 'app/CommonTestAndPreview/GET_WECRM_ACCOUNTS_SUCCESS';
66
+ export const GET_WECRM_ACCOUNTS_FAILURE = 'app/CommonTestAndPreview/GET_WECRM_ACCOUNTS_FAILURE';
67
+
58
68
  // ============================================
59
69
  // CHANNEL CONSTANTS
60
70
  // ============================================
@@ -169,6 +179,11 @@ export const UNSUBSCRIBE_TAG_NAME = 'unsubscribe';
169
179
  export const IN_APP_CHANNEL_NAME = 'in-app';
170
180
  export const MOBILE_PUSH_CHANNEL_NAME = 'mobile push';
171
181
  export const CHANNEL = 'channel';
182
+ export const PHONE_NUMBER = 'PHONE_NUMBER';
183
+ export const DYNAMIC_URL = 'DYNAMIC_URL';
184
+ export const IMAGE = 'IMAGE';
185
+ export const VIDEO = 'VIDEO';
186
+ export const URL = 'URL';
172
187
 
173
188
  // Initial Payload Template (for reference)
174
189
  export const INITIAL_PAYLOAD = {