@capillarytech/creatives-library 8.0.316 → 8.0.317-alpha.0

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 (172) hide show
  1. package/constants/unified.js +15 -0
  2. package/package.json +1 -1
  3. package/services/api.js +6 -0
  4. package/services/tests/api.test.js +7 -0
  5. package/utils/common.js +6 -1
  6. package/utils/templateVarUtils.js +172 -0
  7. package/utils/tests/tagValidations.test.js +34 -0
  8. package/utils/tests/templateVarUtils.test.js +160 -0
  9. package/v2Components/CapTagList/index.js +25 -22
  10. package/v2Components/CapTagList/style.scss +48 -0
  11. package/v2Components/CapTagListWithInput/__tests__/CapTagListWithInput.test.js +63 -0
  12. package/v2Components/CapTagListWithInput/index.js +4 -0
  13. package/v2Components/CapWhatsappCTA/index.js +2 -0
  14. package/v2Components/CommonTestAndPreview/CustomValuesEditor.js +70 -49
  15. package/v2Components/CommonTestAndPreview/DeliverySettings/DeliverySettings.scss +8 -2
  16. package/v2Components/CommonTestAndPreview/DeliverySettings/ModifyDeliverySettings.js +207 -21
  17. package/v2Components/CommonTestAndPreview/DeliverySettings/constants.js +16 -0
  18. package/v2Components/CommonTestAndPreview/DeliverySettings/index.js +85 -10
  19. package/v2Components/CommonTestAndPreview/DeliverySettings/messages.js +30 -0
  20. package/v2Components/CommonTestAndPreview/DeliverySettings/utils/parseSenderDetailsResponse.js +79 -11
  21. package/v2Components/CommonTestAndPreview/SendTestMessage.js +11 -5
  22. package/v2Components/CommonTestAndPreview/UnifiedPreview/_unifiedPreview.scss +20 -1
  23. package/v2Components/CommonTestAndPreview/UnifiedPreview/index.js +133 -4
  24. package/v2Components/CommonTestAndPreview/_commonTestAndPreview.scss +12 -0
  25. package/v2Components/CommonTestAndPreview/constants.js +38 -0
  26. package/v2Components/CommonTestAndPreview/index.js +693 -155
  27. package/v2Components/CommonTestAndPreview/messages.js +41 -3
  28. package/v2Components/CommonTestAndPreview/previewApiUtils.js +59 -0
  29. package/v2Components/CommonTestAndPreview/sagas.js +15 -6
  30. package/v2Components/CommonTestAndPreview/tests/CustomValuesEditor.test.js +352 -0
  31. package/v2Components/CommonTestAndPreview/tests/DeliverySettings/ModifyDeliverySettings.test.js +269 -1
  32. package/v2Components/CommonTestAndPreview/tests/DeliverySettings/index.test.js +118 -5
  33. package/v2Components/CommonTestAndPreview/tests/DeliverySettings/utils/parseSenderDetailsResponse.test.js +341 -0
  34. package/v2Components/CommonTestAndPreview/tests/SendTestMessage.test.js +25 -4
  35. package/v2Components/CommonTestAndPreview/tests/UnifiedPreview/index.test.js +199 -1
  36. package/v2Components/CommonTestAndPreview/tests/index.test.js +132 -4
  37. package/v2Components/CommonTestAndPreview/tests/previewApiUtils.test.js +67 -0
  38. package/v2Components/CommonTestAndPreview/tests/sagas.test.js +2 -2
  39. package/v2Components/FormBuilder/index.js +14 -1
  40. package/v2Components/HtmlEditor/HTMLEditor.js +6 -1
  41. package/v2Components/HtmlEditor/__tests__/HTMLEditor.apiErrors.test.js +1 -0
  42. package/v2Components/HtmlEditor/__tests__/HTMLEditor.test.js +927 -2
  43. package/v2Components/HtmlEditor/components/CodeEditorPane/index.js +3 -0
  44. package/v2Components/SmsFallback/SmsFallbackLocalSelector.js +87 -0
  45. package/v2Components/SmsFallback/constants.js +73 -0
  46. package/v2Components/SmsFallback/index.js +956 -0
  47. package/v2Components/SmsFallback/index.scss +265 -0
  48. package/v2Components/SmsFallback/messages.js +78 -0
  49. package/v2Components/SmsFallback/smsFallbackUtils.js +107 -0
  50. package/v2Components/SmsFallback/tests/SmsFallbackLocalSelector.test.js +50 -0
  51. package/v2Components/SmsFallback/tests/rcsSmsFallback.acceptance.test.js +147 -0
  52. package/v2Components/SmsFallback/tests/smsFallbackHandlers.test.js +304 -0
  53. package/v2Components/SmsFallback/tests/smsFallbackUi.test.js +197 -0
  54. package/v2Components/SmsFallback/tests/smsFallbackUtils.test.js +261 -0
  55. package/v2Components/SmsFallback/tests/useLocalTemplateList.test.js +422 -0
  56. package/v2Components/SmsFallback/useLocalTemplateList.js +92 -0
  57. package/v2Components/TestAndPreviewSlidebox/index.js +8 -1
  58. package/v2Components/TestAndPreviewSlidebox/sagas.js +11 -4
  59. package/v2Components/TestAndPreviewSlidebox/tests/saga.test.js +3 -1
  60. package/v2Components/VarSegmentMessageEditor/constants.js +2 -0
  61. package/v2Components/VarSegmentMessageEditor/index.js +125 -0
  62. package/v2Components/VarSegmentMessageEditor/index.scss +46 -0
  63. package/v2Containers/BeeEditor/index.js +3 -0
  64. package/v2Containers/CommunicationFlow/CommunicationFlow.js +291 -0
  65. package/v2Containers/CommunicationFlow/CommunicationFlow.scss +25 -0
  66. package/v2Containers/CommunicationFlow/Tests/CommunicationFlow.test.js +255 -0
  67. package/v2Containers/CommunicationFlow/constants.js +200 -0
  68. package/v2Containers/CommunicationFlow/index.js +102 -0
  69. package/v2Containers/CommunicationFlow/messages.js +346 -0
  70. package/v2Containers/CommunicationFlow/steps/ChannelSelectionStep/ChannelSelectionStep.js +522 -0
  71. package/v2Containers/CommunicationFlow/steps/ChannelSelectionStep/ChannelSelectionStep.scss +170 -0
  72. package/v2Containers/CommunicationFlow/steps/ChannelSelectionStep/Tests/ChannelSelectionStep.test.js +796 -0
  73. package/v2Containers/CommunicationFlow/steps/ChannelSelectionStep/index.js +5 -0
  74. package/v2Containers/CommunicationFlow/steps/CommunicationStrategyStep/CommunicationStrategyStep.js +95 -0
  75. package/v2Containers/CommunicationFlow/steps/CommunicationStrategyStep/Tests/CommunicationStrategyStep.test.js +133 -0
  76. package/v2Containers/CommunicationFlow/steps/CommunicationStrategyStep/index.js +5 -0
  77. package/v2Containers/CommunicationFlow/steps/DeliverySettingsStep/DeliverySettingsSection.js +289 -0
  78. package/v2Containers/CommunicationFlow/steps/DeliverySettingsStep/DeliverySettingsSection.scss +70 -0
  79. package/v2Containers/CommunicationFlow/steps/DeliverySettingsStep/SenderDetails.js +319 -0
  80. package/v2Containers/CommunicationFlow/steps/DeliverySettingsStep/SenderDetails.scss +69 -0
  81. package/v2Containers/CommunicationFlow/steps/DeliverySettingsStep/Tests/DeliverySettingsSection.test.js +616 -0
  82. package/v2Containers/CommunicationFlow/steps/DeliverySettingsStep/Tests/SenderDetails.test.js +577 -0
  83. package/v2Containers/CommunicationFlow/steps/DeliverySettingsStep/Tests/deliverySettingsConfig.test.js +1111 -0
  84. package/v2Containers/CommunicationFlow/steps/DeliverySettingsStep/deliverySettingsConfig.js +696 -0
  85. package/v2Containers/CommunicationFlow/steps/DeliverySettingsStep/index.js +7 -0
  86. package/v2Containers/CommunicationFlow/steps/DynamicControlsStep/DynamicControlsStep.js +102 -0
  87. package/v2Containers/CommunicationFlow/steps/DynamicControlsStep/DynamicControlsStep.scss +36 -0
  88. package/v2Containers/CommunicationFlow/steps/DynamicControlsStep/Tests/DynamicControlsStep.test.js +91 -0
  89. package/v2Containers/CommunicationFlow/steps/DynamicControlsStep/index.js +5 -0
  90. package/v2Containers/CommunicationFlow/steps/MessageTypeStep/MessageTypeStep.js +86 -0
  91. package/v2Containers/CommunicationFlow/steps/MessageTypeStep/Tests/MessageTypeStep.test.js +100 -0
  92. package/v2Containers/CommunicationFlow/steps/MessageTypeStep/index.js +5 -0
  93. package/v2Containers/CommunicationFlow/utils/getEnabledSteps.js +30 -0
  94. package/v2Containers/CreativesContainer/CreativesSlideBoxWrapper.js +43 -0
  95. package/v2Containers/CreativesContainer/SlideBoxContent.js +64 -5
  96. package/v2Containers/CreativesContainer/SlideBoxFooter.js +10 -1
  97. package/v2Containers/CreativesContainer/SlideBoxHeader.js +29 -4
  98. package/v2Containers/CreativesContainer/constants.js +12 -0
  99. package/v2Containers/CreativesContainer/embeddedSlideboxUtils.js +67 -0
  100. package/v2Containers/CreativesContainer/index.js +289 -93
  101. package/v2Containers/CreativesContainer/index.scss +51 -1
  102. package/v2Containers/CreativesContainer/tests/SlideBoxContent.localTemplates.test.js +90 -0
  103. package/v2Containers/CreativesContainer/tests/SlideBoxFooter.test.js +104 -0
  104. package/v2Containers/CreativesContainer/tests/SlideBoxHeader.test.js +110 -0
  105. package/v2Containers/CreativesContainer/tests/__snapshots__/SlideBoxContent.test.js.snap +8 -0
  106. package/v2Containers/CreativesContainer/tests/__snapshots__/SlideBoxHeader.test.js.snap +363 -0
  107. package/v2Containers/CreativesContainer/tests/__snapshots__/index.test.js.snap +20 -10
  108. package/v2Containers/CreativesContainer/tests/embeddedSlideboxUtils.test.js +258 -0
  109. package/v2Containers/CreativesContainer/tests/index.test.js +71 -9
  110. package/v2Containers/CreativesContainer/tests/useLocalTemplatesProp.test.js +125 -0
  111. package/v2Containers/Email/index.js +1 -0
  112. package/v2Containers/EmailWrapper/components/EmailHTMLEditor.js +7 -1
  113. package/v2Containers/EmailWrapper/components/EmailWrapperView.js +3 -0
  114. package/v2Containers/EmailWrapper/components/__tests__/EmailHTMLEditor.test.js +20 -2
  115. package/v2Containers/EmailWrapper/components/__tests__/EmailWrapperView.test.js +16 -1
  116. package/v2Containers/EmailWrapper/hooks/useEmailWrapper.js +3 -0
  117. package/v2Containers/EmailWrapper/index.js +4 -0
  118. package/v2Containers/EmailWrapper/tests/useEmailWrapper.edgeCases.test.js +1 -0
  119. package/v2Containers/EmailWrapper/tests/useEmailWrapper.test.js +9 -0
  120. package/v2Containers/InAppWrapper/hooks/__tests__/useInAppWrapper.test.js +19 -0
  121. package/v2Containers/InAppWrapper/hooks/useInAppWrapper.js +3 -0
  122. package/v2Containers/InAppWrapper/index.js +3 -0
  123. package/v2Containers/MobilePush/Create/index.js +2 -0
  124. package/v2Containers/MobilePush/Edit/index.js +2 -0
  125. package/v2Containers/MobilepushWrapper/index.js +3 -1
  126. package/v2Containers/Rcs/constants.js +32 -1
  127. package/v2Containers/Rcs/index.js +951 -873
  128. package/v2Containers/Rcs/index.scss +85 -6
  129. package/v2Containers/Rcs/messages.js +10 -1
  130. package/v2Containers/Rcs/rcsLibraryHydrationUtils.js +205 -0
  131. package/v2Containers/Rcs/tests/__snapshots__/index.test.js.snap +40834 -1963
  132. package/v2Containers/Rcs/tests/__snapshots__/utils.test.js.snap +0 -5
  133. package/v2Containers/Rcs/tests/index.test.js +41 -38
  134. package/v2Containers/Rcs/tests/mockData.js +38 -0
  135. package/v2Containers/Rcs/tests/rcsLibraryHydrationUtils.test.js +251 -0
  136. package/v2Containers/Rcs/tests/utils.test.js +379 -1
  137. package/v2Containers/Rcs/utils.js +358 -10
  138. package/v2Containers/Sms/Create/index.js +83 -36
  139. package/v2Containers/Sms/Edit/index.js +2 -0
  140. package/v2Containers/Sms/smsFormDataHelpers.js +67 -0
  141. package/v2Containers/Sms/tests/smsFormDataHelpers.test.js +253 -0
  142. package/v2Containers/SmsTrai/Create/index.js +9 -4
  143. package/v2Containers/SmsTrai/Edit/constants.js +2 -0
  144. package/v2Containers/SmsTrai/Edit/index.js +611 -128
  145. package/v2Containers/SmsTrai/Edit/index.scss +121 -0
  146. package/v2Containers/SmsTrai/Edit/messages.js +9 -4
  147. package/v2Containers/SmsTrai/Edit/tests/__snapshots__/index.test.js.snap +4327 -2374
  148. package/v2Containers/SmsWrapper/index.js +39 -8
  149. package/v2Containers/TagList/index.js +47 -2
  150. package/v2Containers/TagList/messages.js +4 -0
  151. package/v2Containers/TagList/tests/TagList.test.js +122 -20
  152. package/v2Containers/TagList/tests/mockdata.js +17 -0
  153. package/v2Containers/Templates/TemplatesActionBar.js +101 -0
  154. package/v2Containers/Templates/_templates.scss +61 -2
  155. package/v2Containers/Templates/actions.js +11 -0
  156. package/v2Containers/Templates/constants.js +2 -0
  157. package/v2Containers/Templates/index.js +90 -40
  158. package/v2Containers/Templates/sagas.js +57 -12
  159. package/v2Containers/Templates/tests/TemplatesActionBar.test.js +120 -0
  160. package/v2Containers/Templates/tests/__snapshots__/index.test.js.snap +1043 -1079
  161. package/v2Containers/Templates/tests/sagas.test.js +193 -12
  162. package/v2Containers/Templates/tests/smsTemplatesListApi.test.js +180 -0
  163. package/v2Containers/Templates/utils/smsTemplatesListApi.js +79 -0
  164. package/v2Containers/TemplatesV2/TemplatesV2.style.js +72 -1
  165. package/v2Containers/TemplatesV2/index.js +86 -23
  166. package/v2Containers/TemplatesV2/tests/TemplatesV2.localTemplates.test.js +131 -0
  167. package/v2Containers/Viber/index.js +5 -0
  168. package/v2Containers/WebPush/Create/hooks/useTagManagement.js +0 -2
  169. package/v2Containers/WebPush/Create/index.js +9 -1
  170. package/v2Containers/Whatsapp/index.js +8 -20
  171. package/v2Containers/Whatsapp/tests/__snapshots__/index.test.js.snap +598 -34
  172. package/v2Containers/Zalo/index.js +2 -0
@@ -0,0 +1,319 @@
1
+ /**
2
+ * SenderDetails - Config-driven sender details slidebox for all channels
3
+ *
4
+ * Renders fields from deliverySettingsConfig. Add new channels/fields in config.
5
+ * Supports theme via BEM classes (sender-details__*).
6
+ */
7
+
8
+ import React, {
9
+ useState, useEffect, useCallback, useMemo,
10
+ } from 'react';
11
+ import PropTypes from 'prop-types';
12
+ import { injectIntl } from 'react-intl';
13
+ import CapSlideBox from '@capillarytech/cap-ui-library/CapSlideBox';
14
+ import CapRow from '@capillarytech/cap-ui-library/CapRow';
15
+ import CapHeading from '@capillarytech/cap-ui-library/CapHeading';
16
+ import CapIcon from '@capillarytech/cap-ui-library/CapIcon';
17
+ import CapButton from '@capillarytech/cap-ui-library/CapButton';
18
+ import CapSelect from '@capillarytech/cap-ui-library/CapSelect';
19
+ import CapLabel from '@capillarytech/cap-ui-library/CapLabel';
20
+ import CapLink from '@capillarytech/cap-ui-library/CapLink';
21
+ import CapSpin from '@capillarytech/cap-ui-library/CapSpin';
22
+ import CapTooltip from '@capillarytech/cap-ui-library/CapTooltip';
23
+ import CapError from '@capillarytech/cap-ui-library/CapError';
24
+ import {
25
+ getFieldsForChannels,
26
+ FIELD_TYPE,
27
+ parseEntityForDisplay,
28
+ getDefaultValueForField,
29
+ getEmailDefaultsForDomainId,
30
+ getSmsDefaultsForDomainId,
31
+ getRcsAccountName,
32
+ } from './deliverySettingsConfig';
33
+ import messages from '../../messages';
34
+ import './SenderDetails.scss';
35
+
36
+ /** Re-export for DeliverySettingsSection - uses config's parseEntityForDisplay */
37
+ export const parseSenderDetailsFromEntity = parseEntityForDisplay;
38
+
39
+ const SenderDetails = ({
40
+ show,
41
+ onClose,
42
+ channels = [],
43
+ preloadedDomainProperties,
44
+ savedFieldValues,
45
+ onSave,
46
+ whatsappSourceAccountId,
47
+ whatsappAccountName,
48
+ intl,
49
+ }) => {
50
+ const { formatMessage } = intl || {};
51
+
52
+ const [entity, setEntity] = useState(null);
53
+ const [loading, setLoading] = useState(false);
54
+ const [error, setError] = useState(null);
55
+ const [fieldValues, setFieldValues] = useState({});
56
+ const [initialFieldValues, setInitialFieldValues] = useState({});
57
+
58
+ const channelKey = (channels || []).join(',');
59
+ const fieldConfigs = useMemo(() => getFieldsForChannels(channels), [channelKey]);
60
+
61
+ // Context for WABA-bound fields (WhatsApp sender number filtered by sourceAccountIdentifier)
62
+ const wabaContext = useMemo(() => ({
63
+ whatsappSourceAccountId: whatsappSourceAccountId || '',
64
+ }), [whatsappSourceAccountId]);
65
+
66
+ // Only use preloaded data from parent (DeliverySettingsSection) - no fetch here to avoid duplicate API calls
67
+ // When reopening, use savedFieldValues to restore user's last saved selections
68
+ useEffect(() => {
69
+ if (!show || !channels?.length) return;
70
+ if (preloadedDomainProperties) {
71
+ setEntity(preloadedDomainProperties);
72
+ const initial = {};
73
+ fieldConfigs.forEach((config) => {
74
+ const fromEntity = config.getValue(preloadedDomainProperties, wabaContext) || '';
75
+ const fromSaved = savedFieldValues?.[config.fieldKey];
76
+ initial[config.fieldKey] = (fromSaved != null && fromSaved !== '') ? fromSaved : fromEntity;
77
+ });
78
+ // Set WhatsApp account name (disabled field, driven by template)
79
+ if (whatsappAccountName) {
80
+ initial.whatsappAccount = whatsappAccountName;
81
+ }
82
+ // Set RCS account name (disabled field)
83
+ const rcsAccName = getRcsAccountName(preloadedDomainProperties);
84
+ if (rcsAccName) {
85
+ initial.rcsAccount = rcsAccName;
86
+ }
87
+ setFieldValues(initial);
88
+ setInitialFieldValues(initial);
89
+ setLoading(false);
90
+ setError(null);
91
+ } else {
92
+ // preloadedDomainProperties is not yet available (or the parent's fetch failed).
93
+ // Show nothing rather than an eternal spinner — the parent controls data availability.
94
+ setLoading(false);
95
+ setEntity(null);
96
+ setFieldValues({});
97
+ setInitialFieldValues({});
98
+ }
99
+ }, [show, channels, preloadedDomainProperties, savedFieldValues, fieldConfigs, whatsappAccountName, wabaContext]);
100
+
101
+ const handleFieldChange = useCallback((fieldKey, value) => {
102
+ setFieldValues((prev) => {
103
+ const next = { ...prev, [fieldKey]: value };
104
+ if (fieldKey === 'smsDomain' && entity) {
105
+ const defs = getSmsDefaultsForDomainId(entity, value);
106
+ next.smsSenderId = defs.senderId;
107
+ }
108
+ if (fieldKey === 'emailDomain' && entity) {
109
+ const defs = getEmailDefaultsForDomainId(entity, value);
110
+ next.emailSenderId = defs.senderId;
111
+ next.emailSenderName = defs.senderName;
112
+ next.emailReplyToId = defs.replyToId;
113
+ }
114
+ return next;
115
+ });
116
+ }, [entity]);
117
+
118
+ const handleReset = useCallback((fieldKey) => {
119
+ setFieldValues((prev) => {
120
+ const next = { ...prev };
121
+ if (fieldKey === 'smsDomain') {
122
+ const defaultDomain = getDefaultValueForField('smsDomain', entity, { fieldValues: prev });
123
+ const defs = getSmsDefaultsForDomainId(entity, defaultDomain);
124
+ next.smsDomain = defaultDomain;
125
+ next.smsSenderId = defs.senderId;
126
+ } else if (fieldKey === 'emailDomain') {
127
+ const defaultDomain = getDefaultValueForField('emailDomain', entity, { fieldValues: prev });
128
+ const defs = getEmailDefaultsForDomainId(entity, defaultDomain);
129
+ next.emailDomain = defaultDomain;
130
+ next.emailSenderId = defs.senderId;
131
+ next.emailSenderName = defs.senderName;
132
+ next.emailReplyToId = defs.replyToId;
133
+ } else {
134
+ next[fieldKey] = getDefaultValueForField(fieldKey, entity, { fieldValues: prev });
135
+ }
136
+ return next;
137
+ });
138
+ }, [entity]);
139
+
140
+ const handleSave = () => {
141
+ if (onSave) {
142
+ const saveValues = { ...fieldValues };
143
+ // Include WhatsApp domainId derived from sourceAccountIdentifier for persistence
144
+ if (whatsappSourceAccountId && entity) {
145
+ const whatsappDomains = entity?.WHATSAPP || [];
146
+ const matchedDomain = (Array.isArray(whatsappDomains) ? whatsappDomains : [whatsappDomains]).find((domain) => {
147
+ const connectionProperties = domain?.domainProperties?.connectionProperties || {};
148
+ return (connectionProperties.sourceAccountIdentifier || connectionProperties.wabaId || connectionProperties.userid) === whatsappSourceAccountId;
149
+ });
150
+ if (matchedDomain) {
151
+ saveValues.whatsappDomainId = matchedDomain?.domainProperties?.id ?? matchedDomain?.domainId ?? matchedDomain?.id;
152
+ }
153
+ }
154
+ onSave(saveValues);
155
+ }
156
+ onClose();
157
+ };
158
+
159
+ const hasChanges = useMemo(() => {
160
+ const editableKeys = new Set(
161
+ fieldConfigs.filter((fieldConfig) => fieldConfig.type !== FIELD_TYPE.DISPLAY && !fieldConfig.disabled).map((fieldConfig) => fieldConfig.fieldKey),
162
+ );
163
+ return [...editableKeys].some((fieldKey) => (fieldValues[fieldKey] ?? '') !== (initialFieldValues[fieldKey] ?? ''));
164
+ }, [fieldValues, initialFieldValues, fieldConfigs]);
165
+
166
+ const hasAllValues = useMemo(
167
+ () => fieldConfigs
168
+ .filter((config) => config.type !== FIELD_TYPE.DISPLAY && !config.disabled)
169
+ .every((config) => (fieldValues[config.fieldKey] ?? '').toString().trim() !== ''),
170
+ [fieldValues, fieldConfigs],
171
+ );
172
+
173
+ const header = (
174
+ <CapRow type="flex" align="middle" justify="space-between" className="sender-details__header">
175
+ <CapRow type="flex" align="middle" className="sender-details__header-left">
176
+ <CapIcon type="arrow-left" size="s" onClick={onClose} className="sender-details__back-icon" aria-label="Back" />
177
+ <CapHeading type="h1">{formatMessage(messages.senderDetails)}</CapHeading>
178
+ </CapRow>
179
+ </CapRow>
180
+ );
181
+
182
+ const footer = (
183
+ <CapRow className="sender-details__footer">
184
+ <CapButton type="primary" onClick={handleSave} disabled={!hasChanges || !hasAllValues}>
185
+ {formatMessage(messages.saveChanges)}
186
+ </CapButton>
187
+ </CapRow>
188
+ );
189
+
190
+ const renderField = (config) => {
191
+ const {
192
+ fieldKey, messageKey, type, getOptions, disabled: isDisabled,
193
+ } = config;
194
+ const value = fieldValues[fieldKey] ?? '';
195
+ const optionContext = { fieldValues, ...wabaContext };
196
+ const options = entity && getOptions ? (getOptions(entity, optionContext) || []) : [];
197
+
198
+ // WhatsApp/RCS account: disabled field showing account name, build options from value
199
+ if (isDisabled && (fieldKey === 'whatsappAccount' || fieldKey === 'rcsAccount') && value) {
200
+ const accountOptions = [{ label: value, value }];
201
+ const selectNode = (
202
+ <CapSelect
203
+ value={value}
204
+ placeholder={formatMessage(messages.select)}
205
+ className="sender-details__select"
206
+ options={accountOptions}
207
+ style={{ width: '20.375rem' }}
208
+ disabled
209
+ />
210
+ );
211
+ return (
212
+ <CapRow key={fieldKey} className="sender-details__field">
213
+ <CapHeading type="h4">{formatMessage(messages[messageKey] || { defaultMessage: messageKey })}</CapHeading>
214
+ <CapRow type="flex" align="middle" className="sender-details__field-row">
215
+ {fieldKey === 'whatsappAccount' ? (
216
+ <CapTooltip title={formatMessage(messages.whatsappAccountTooltip)} overlayClassName="sender-details__account-name-tooltip">
217
+ {selectNode}
218
+ </CapTooltip>
219
+ ) : selectNode}
220
+ </CapRow>
221
+ </CapRow>
222
+ );
223
+ }
224
+
225
+ if (type === FIELD_TYPE.DISPLAY) {
226
+ return (
227
+ <CapHeading type="h4">{formatMessage(messages[messageKey] || { defaultMessage: messageKey }, { domain: value })}</CapHeading>
228
+ );
229
+ }
230
+
231
+ if (type === FIELD_TYPE.SELECT) {
232
+ const isSingleOption = options.length <= 1;
233
+ const isDomainField = fieldKey === 'smsDomain' || fieldKey === 'emailDomain';
234
+ const showEmptyOptionsError = !isDisabled && entity && options?.length === 0;
235
+ const emptyOptionsErrorMsg = isDomainField
236
+ ? formatMessage(messages.domainGatewayError)
237
+ : formatMessage(messages.senderNotConfiguredError);
238
+ return (
239
+ <CapRow key={fieldKey} className="sender-details__field">
240
+ <CapHeading type="h4">{formatMessage(messages[messageKey] || { defaultMessage: messageKey })}</CapHeading>
241
+ <CapRow type="flex" align="middle" className="sender-details__field-row">
242
+ <CapSelect
243
+ value={value}
244
+ onChange={(val) => handleFieldChange(fieldKey, val)}
245
+ placeholder={formatMessage(messages.select)}
246
+ className="sender-details__select"
247
+ options={options}
248
+ style={{ width: '20.375rem' }}
249
+ disabled={isDisabled}
250
+ />
251
+ {!isDisabled && (
252
+ <CapLink
253
+ type="false"
254
+ fontWeight="m"
255
+ className="sender-details__reset-link"
256
+ title={formatMessage(messages.reset)}
257
+ onClick={() => { if (!isSingleOption) handleReset(fieldKey); }}
258
+ />
259
+ )}
260
+ </CapRow>
261
+ {showEmptyOptionsError && (
262
+ <CapError type="error" className="sender-details__field-error">
263
+ {emptyOptionsErrorMsg}
264
+ </CapError>
265
+ )}
266
+ </CapRow>
267
+ );
268
+ }
269
+ return null;
270
+ };
271
+
272
+ const content = (
273
+ <CapSpin spinning={loading}>
274
+ <CapRow className="sender-details__content">
275
+ {error && <CapLabel type="label2" className="sender-details__error">{error}</CapLabel>}
276
+ {!loading && !error && entity && fieldConfigs.length > 0 && (
277
+ <>
278
+ {fieldConfigs?.map((config) => renderField(config))}
279
+ </>
280
+ )}
281
+ </CapRow>
282
+ </CapSpin>
283
+ );
284
+
285
+ return (
286
+ <CapSlideBox
287
+ show={show}
288
+ handleClose={onClose}
289
+ header={header}
290
+ footer={footer}
291
+ content={content}
292
+ className="sender-details"
293
+ closeIconPosition="right"
294
+ />
295
+ );
296
+ };
297
+
298
+ SenderDetails.propTypes = {
299
+ show: PropTypes.bool.isRequired,
300
+ onClose: PropTypes.func.isRequired,
301
+ channels: PropTypes.arrayOf(PropTypes.string),
302
+ preloadedDomainProperties: PropTypes.object,
303
+ savedFieldValues: PropTypes.object,
304
+ onSave: PropTypes.func,
305
+ whatsappSourceAccountId: PropTypes.string,
306
+ whatsappAccountName: PropTypes.string,
307
+ intl: PropTypes.object.isRequired,
308
+ };
309
+
310
+ SenderDetails.defaultProps = {
311
+ channels: [],
312
+ preloadedDomainProperties: null,
313
+ savedFieldValues: null,
314
+ onSave: null,
315
+ whatsappSourceAccountId: '',
316
+ whatsappAccountName: '',
317
+ };
318
+
319
+ export default injectIntl(SenderDetails);
@@ -0,0 +1,69 @@
1
+ @import '~@capillarytech/cap-ui-library/styles/_variables.scss';
2
+
3
+ .sender-details {
4
+ --sd-padding: #{$CAP_SPACE_48}; // 48px - same as other slideboxes
5
+ --sd-content-gap: #{$CAP_SPACE_16};
6
+ --sd-error-color: #ff4d4f;
7
+ --sd-select-width: 20.375rem; // 326px
8
+
9
+ padding: 0 var(--sd-padding);
10
+
11
+ &__back-icon {
12
+ cursor: pointer;
13
+ margin-right: $CAP_SPACE_16;
14
+ }
15
+
16
+ &__content {
17
+ flex-direction: column;
18
+ gap: var(--sd-content-gap);
19
+ }
20
+
21
+ &__field {
22
+ flex-direction: column;
23
+ margin-bottom: $CAP_SPACE_08;
24
+ }
25
+
26
+ &__display-value {
27
+ margin-top: $CAP_SPACE_04;
28
+ }
29
+
30
+ &__select {
31
+ margin-bottom: $CAP_SPACE_16;
32
+ width: var(--sd-select-width);
33
+ min-width: var(--sd-select-width);
34
+ }
35
+
36
+ &__reset-link {
37
+ padding: $CAP_SPACE_08 $CAP_SPACE_16;
38
+ margin: -0.8rem 0 0 0;
39
+ background: none;
40
+ border: none;
41
+ color: $FONT_COLOR_05;
42
+ font-size: $FONT_SIZE_M;
43
+ font-weight: $FONT_WEIGHT_MEDIUM;
44
+ line-height: $CAP_SPACE_20;
45
+ cursor: pointer;
46
+ }
47
+
48
+ &__error {
49
+ color: var(--sd-error-color);
50
+ }
51
+
52
+ &__field-error {
53
+ margin-top: -$CAP_SPACE_08;
54
+ width: var(--sd-select-width);
55
+ min-width: var(--sd-select-width);
56
+ max-width: var(--sd-select-width);
57
+ display: block;
58
+ box-sizing: border-box;
59
+ }
60
+
61
+ &__footer {
62
+ justify-content: flex-end;
63
+ }
64
+ &__account-name-tooltip {
65
+ .ant-tooltip-content {
66
+ width: 21.3rem;
67
+ }
68
+ }
69
+ }