@capillarytech/creatives-library 8.0.353-alpha.5 → 8.0.353-alpha.6

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 (136) hide show
  1. package/constants/unified.js +29 -0
  2. package/package.json +1 -1
  3. package/services/tests/api.test.js +35 -20
  4. package/utils/commonUtils.js +19 -1
  5. package/utils/rcsPayloadUtils.js +92 -0
  6. package/utils/templateVarUtils.js +201 -0
  7. package/utils/tests/rcsPayloadUtils.test.js +226 -0
  8. package/utils/tests/templateVarUtils.test.js +204 -0
  9. package/v2Components/CapActionButton/constants.js +7 -0
  10. package/v2Components/CapActionButton/index.js +166 -108
  11. package/v2Components/CapActionButton/index.scss +157 -6
  12. package/v2Components/CapActionButton/messages.js +19 -3
  13. package/v2Components/CapActionButton/tests/index.test.js +41 -17
  14. package/v2Components/CapTagList/index.js +10 -0
  15. package/v2Components/CommonTestAndPreview/CustomValuesEditor.js +72 -49
  16. package/v2Components/CommonTestAndPreview/DeliverySettings/DeliverySettings.scss +8 -2
  17. package/v2Components/CommonTestAndPreview/DeliverySettings/ModifyDeliverySettings.js +213 -21
  18. package/v2Components/CommonTestAndPreview/DeliverySettings/constants.js +16 -0
  19. package/v2Components/CommonTestAndPreview/DeliverySettings/index.js +85 -10
  20. package/v2Components/CommonTestAndPreview/DeliverySettings/messages.js +30 -0
  21. package/v2Components/CommonTestAndPreview/DeliverySettings/utils/parseSenderDetailsResponse.js +79 -11
  22. package/v2Components/CommonTestAndPreview/SendTestMessage.js +10 -5
  23. package/v2Components/CommonTestAndPreview/UnifiedPreview/PreviewHeader.js +0 -17
  24. package/v2Components/CommonTestAndPreview/UnifiedPreview/RcsPreviewContent.js +157 -15
  25. package/v2Components/CommonTestAndPreview/UnifiedPreview/_unifiedPreview.scss +346 -146
  26. package/v2Components/CommonTestAndPreview/UnifiedPreview/index.js +138 -48
  27. package/v2Components/CommonTestAndPreview/_commonTestAndPreview.scss +11 -0
  28. package/v2Components/CommonTestAndPreview/constants.js +38 -4
  29. package/v2Components/CommonTestAndPreview/index.js +691 -235
  30. package/v2Components/CommonTestAndPreview/messages.js +45 -3
  31. package/v2Components/CommonTestAndPreview/previewApiUtils.js +59 -0
  32. package/v2Components/CommonTestAndPreview/sagas.js +25 -6
  33. package/v2Components/CommonTestAndPreview/tests/CustomValuesEditor.test.js +308 -284
  34. package/v2Components/CommonTestAndPreview/tests/DeliverySettings/ModifyDeliverySettings.test.js +231 -65
  35. package/v2Components/CommonTestAndPreview/tests/DeliverySettings/index.test.js +118 -5
  36. package/v2Components/CommonTestAndPreview/tests/DeliverySettings/utils/parseSenderDetailsResponse.test.js +341 -0
  37. package/v2Components/CommonTestAndPreview/tests/PreviewSection.test.js +8 -1
  38. package/v2Components/CommonTestAndPreview/tests/SendTestMessage.test.js +34 -13
  39. package/v2Components/CommonTestAndPreview/tests/UnifiedPreview/PreviewHeader.test.js +0 -159
  40. package/v2Components/CommonTestAndPreview/tests/UnifiedPreview/RcsPreviewContent.test.js +281 -283
  41. package/v2Components/CommonTestAndPreview/tests/UnifiedPreview/index.test.js +199 -256
  42. package/v2Components/CommonTestAndPreview/tests/constants.test.js +1 -2
  43. package/v2Components/CommonTestAndPreview/tests/index.test.js +132 -198
  44. package/v2Components/CommonTestAndPreview/tests/previewApiUtils.test.js +67 -0
  45. package/v2Components/CommonTestAndPreview/tests/sagas.test.js +36 -26
  46. package/v2Components/FormBuilder/index.js +11 -6
  47. package/v2Components/SmsFallback/SmsFallbackLocalSelector.js +91 -0
  48. package/v2Components/SmsFallback/constants.js +73 -0
  49. package/v2Components/SmsFallback/index.js +956 -0
  50. package/v2Components/SmsFallback/index.scss +265 -0
  51. package/v2Components/SmsFallback/messages.js +78 -0
  52. package/v2Components/SmsFallback/smsFallbackUtils.js +119 -0
  53. package/v2Components/SmsFallback/tests/SmsFallbackLocalSelector.test.js +50 -0
  54. package/v2Components/SmsFallback/tests/rcsSmsFallback.acceptance.test.js +147 -0
  55. package/v2Components/SmsFallback/tests/smsFallbackHandlers.test.js +304 -0
  56. package/v2Components/SmsFallback/tests/smsFallbackUi.test.js +223 -0
  57. package/v2Components/SmsFallback/tests/smsFallbackUtils.test.js +309 -0
  58. package/v2Components/SmsFallback/tests/useLocalTemplateList.test.js +422 -0
  59. package/v2Components/SmsFallback/useLocalTemplateList.js +92 -0
  60. package/v2Components/TemplatePreview/_templatePreview.scss +38 -23
  61. package/v2Components/TemplatePreview/constants.js +2 -0
  62. package/v2Components/TemplatePreview/index.js +143 -31
  63. package/v2Components/TemplatePreview/tests/index.test.js +142 -0
  64. package/v2Components/TestAndPreviewSlidebox/index.js +15 -3
  65. package/v2Components/TestAndPreviewSlidebox/sagas.js +11 -4
  66. package/v2Components/TestAndPreviewSlidebox/tests/saga.test.js +3 -1
  67. package/v2Components/VarSegmentMessageEditor/constants.js +2 -0
  68. package/v2Components/VarSegmentMessageEditor/index.js +125 -0
  69. package/v2Components/VarSegmentMessageEditor/index.scss +46 -0
  70. package/v2Containers/App/constants.js +0 -3
  71. package/v2Containers/CreativesContainer/CreativesSlideBoxWrapper.js +43 -0
  72. package/v2Containers/CreativesContainer/SlideBoxContent.js +36 -4
  73. package/v2Containers/CreativesContainer/SlideBoxFooter.js +10 -1
  74. package/v2Containers/CreativesContainer/SlideBoxHeader.js +29 -4
  75. package/v2Containers/CreativesContainer/constants.js +9 -0
  76. package/v2Containers/CreativesContainer/embeddedSlideboxUtils.js +79 -0
  77. package/v2Containers/CreativesContainer/index.js +322 -103
  78. package/v2Containers/CreativesContainer/index.scss +51 -1
  79. package/v2Containers/CreativesContainer/tests/SlideBoxContent.localTemplates.test.js +90 -0
  80. package/v2Containers/CreativesContainer/tests/SlideBoxFooter.test.js +78 -34
  81. package/v2Containers/CreativesContainer/tests/SlideBoxHeader.test.js +79 -16
  82. package/v2Containers/CreativesContainer/tests/__snapshots__/SlideBoxContent.test.js.snap +8 -0
  83. package/v2Containers/CreativesContainer/tests/__snapshots__/SlideBoxHeader.test.js.snap +357 -98
  84. package/v2Containers/CreativesContainer/tests/__snapshots__/index.test.js.snap +20 -15
  85. package/v2Containers/CreativesContainer/tests/embeddedSlideboxUtils.test.js +258 -0
  86. package/v2Containers/CreativesContainer/tests/index.test.js +71 -9
  87. package/v2Containers/CreativesContainer/tests/useLocalTemplatesProp.test.js +125 -0
  88. package/v2Containers/MobilePush/Create/test/saga.test.js +2 -2
  89. package/v2Containers/Rcs/constants.js +119 -10
  90. package/v2Containers/Rcs/index.js +2445 -813
  91. package/v2Containers/Rcs/index.scss +280 -8
  92. package/v2Containers/Rcs/messages.js +34 -3
  93. package/v2Containers/Rcs/rcsLibraryHydrationUtils.js +225 -0
  94. package/v2Containers/Rcs/tests/__snapshots__/index.test.js.snap +98018 -70073
  95. package/v2Containers/Rcs/tests/__snapshots__/utils.test.js.snap +0 -5
  96. package/v2Containers/Rcs/tests/index.test.js +152 -121
  97. package/v2Containers/Rcs/tests/mockData.js +38 -0
  98. package/v2Containers/Rcs/tests/rcsLibraryHydrationUtils.test.js +318 -0
  99. package/v2Containers/Rcs/tests/utils.test.js +646 -30
  100. package/v2Containers/Rcs/utils.js +478 -11
  101. package/v2Containers/Sms/Create/index.js +106 -40
  102. package/v2Containers/Sms/smsFormDataHelpers.js +67 -0
  103. package/v2Containers/Sms/tests/smsFormDataHelpers.test.js +253 -0
  104. package/v2Containers/SmsTrai/Create/index.js +9 -4
  105. package/v2Containers/SmsTrai/Edit/constants.js +2 -0
  106. package/v2Containers/SmsTrai/Edit/index.js +640 -130
  107. package/v2Containers/SmsTrai/Edit/index.scss +121 -0
  108. package/v2Containers/SmsTrai/Edit/messages.js +14 -4
  109. package/v2Containers/SmsTrai/Edit/tests/__snapshots__/index.test.js.snap +4328 -2375
  110. package/v2Containers/SmsWrapper/index.js +37 -8
  111. package/v2Containers/TagList/index.js +6 -0
  112. package/v2Containers/Templates/TemplatesActionBar.js +101 -0
  113. package/v2Containers/Templates/_templates.scss +166 -9
  114. package/v2Containers/Templates/actions.js +11 -0
  115. package/v2Containers/Templates/constants.js +2 -0
  116. package/v2Containers/Templates/index.js +122 -120
  117. package/v2Containers/Templates/sagas.js +56 -12
  118. package/v2Containers/Templates/tests/TemplatesActionBar.test.js +120 -0
  119. package/v2Containers/Templates/tests/__snapshots__/index.test.js.snap +1062 -1017
  120. package/v2Containers/Templates/tests/sagas.test.js +199 -16
  121. package/v2Containers/Templates/tests/smsTemplatesListApi.test.js +180 -0
  122. package/v2Containers/Templates/utils/smsTemplatesListApi.js +79 -0
  123. package/v2Containers/TemplatesV2/TemplatesV2.style.js +72 -1
  124. package/v2Containers/TemplatesV2/index.js +86 -23
  125. package/v2Containers/TemplatesV2/tests/TemplatesV2.localTemplates.test.js +131 -0
  126. package/v2Containers/WeChat/MapTemplates/test/saga.test.js +9 -9
  127. package/v2Containers/WebPush/Create/index.js +8 -91
  128. package/v2Containers/WebPush/Create/index.scss +0 -7
  129. package/v2Containers/Whatsapp/index.js +3 -20
  130. package/v2Containers/Whatsapp/tests/__snapshots__/index.test.js.snap +578 -34
  131. package/v2Components/CommonTestAndPreview/UnifiedPreview/WebPushPreviewContent.js +0 -169
  132. package/v2Components/CommonTestAndPreview/tests/UnifiedPreview/WebPushPreviewContent.test.js +0 -522
  133. package/v2Containers/App/tests/constants.test.js +0 -61
  134. package/v2Containers/Templates/tests/webpush.test.js +0 -375
  135. package/v2Containers/WebPush/Create/tests/getTemplateContent.test.js +0 -338
  136. package/v2Containers/WebPush/Create/tests/testAndPreviewIntegration.test.js +0 -325
@@ -32,16 +32,37 @@ import {
32
32
  DELIVERY_SETTING_KEY_SENDER_REPLY_TO,
33
33
  DELIVERY_SETTING_KEY_SOURCE_ACCOUNT_IDENTIFIER,
34
34
  DELIVERY_SETTING_KEY_SENDER_MOB_NUM,
35
+ DELIVERY_SETTING_KEY_SMS_FALLBACK_DOMAIN_ID,
35
36
  } from './constants';
36
37
  import './ModifyDeliverySettings.scss';
37
38
 
38
39
  const findDefault = (array) => find(array, { default: true }) || (array && array[0]) || {};
39
40
 
41
+ /**
42
+ * Drop empty GSM rows. Optionally drop rows whose value equals domain name — some APIs duplicate
43
+ * domain label as a bogus sender row; RCS/DLT often legitimately use the same string (e.g. DetailsForGW1).
44
+ */
45
+ const filterUsableGsmSendersForDomain = (domain, gsmSenders, { skipDomainNameEchoFilter = false } = {}) => {
46
+ const normalizedDomainName =
47
+ domain?.domainName != null ? String(domain.domainName).trim().toLowerCase() : '';
48
+ return (gsmSenders || []).filter((gsmSenderRow) => {
49
+ const rawValue = gsmSenderRow?.value;
50
+ if (rawValue == null) return false;
51
+ const trimmedSenderValue = String(rawValue).trim();
52
+ if (!trimmedSenderValue) return false;
53
+ const senderMatchesDomainLabel =
54
+ normalizedDomainName && trimmedSenderValue.toLowerCase() === normalizedDomainName;
55
+ if (!skipDomainNameEchoFilter && senderMatchesDomainLabel) return false;
56
+ return true;
57
+ });
58
+ };
59
+
40
60
  const ModifyDeliverySettings = (props) => {
41
61
  const {
42
62
  channel,
43
63
  deliverySettings: initialSettings = {},
44
64
  senderDetailsOptions = [],
65
+ smsFallbackSenderDetailsOptions = [],
45
66
  wecrmAccounts = [],
46
67
  onSaveDeliverySettings,
47
68
  onClose,
@@ -102,17 +123,21 @@ const ModifyDeliverySettings = (props) => {
102
123
  if (!(channel === CHANNELS.SMS && smsTraiDltEnabled)) {
103
124
  return allDomainOptions;
104
125
  }
126
+ // Without template registered sender IDs, strict DLT filter removes every domain — keep full list.
127
+ if (!registeredSenderIds?.length) {
128
+ return allDomainOptions;
129
+ }
105
130
 
106
- return allDomainOptions.filter((domain) => (domain.gsmSenders || []).some(
107
- (gsmId) => registeredSenderIds.includes(gsmId.value),
131
+ return allDomainOptions.filter((domain) => (domain?.gsmSenders || []).some(
132
+ (gsmSenderOption) => registeredSenderIds?.includes(gsmSenderOption?.value),
108
133
  ));
109
134
  }, [allDomainOptions, channel, registeredSenderIds, smsTraiDltEnabled]);
110
135
 
111
136
  const selectedDomain = useMemo(
112
137
  () => (senderDetailsOptions || []).find(
113
- (d) => d.domainId === get(localSettings, DELIVERY_SETTING_KEY_DOMAIN_ID),
138
+ (senderDomain) => senderDomain.domainId === get(localSettings, DELIVERY_SETTING_KEY_DOMAIN_ID),
114
139
  ) || {},
115
- [senderDetailsOptions, localSettings.domainId],
140
+ [senderDetailsOptions, get(localSettings, DELIVERY_SETTING_KEY_DOMAIN_ID)],
116
141
  );
117
142
  const {
118
143
  gsmSenders: selectedDomainGsmSenders = [],
@@ -120,25 +145,103 @@ const ModifyDeliverySettings = (props) => {
120
145
  emailRepliers: selectedDomainEmailRepliers = [],
121
146
  } = selectedDomain;
122
147
 
148
+ const rcsSenderOptions = useMemo(
149
+ () => {
150
+ if (channel !== CHANNELS.RCS) return [];
151
+ const rcsDomainRows = senderDetailsOptions || [];
152
+ const selectedRcsDomainId = get(localSettings, DELIVERY_SETTING_KEY_DOMAIN_ID);
153
+ const rcsDomainsForDropdown =
154
+ selectedRcsDomainId != null && selectedRcsDomainId !== ''
155
+ ? rcsDomainRows.filter((senderDomain) => senderDomain?.domainId === selectedRcsDomainId)
156
+ : rcsDomainRows;
157
+ return rcsDomainsForDropdown.flatMap((senderDomain) =>
158
+ filterUsableGsmSendersForDomain(senderDomain, senderDomain?.gsmSenders, {
159
+ skipDomainNameEchoFilter: true,
160
+ }).map((gsmSenderRow) => ({
161
+ value: senderDomain?.domainId != null && gsmSenderRow?.value != null
162
+ ? `${senderDomain.domainId}|${gsmSenderRow.value}`
163
+ : gsmSenderRow?.value,
164
+ label: String(gsmSenderRow?.value ?? ''),
165
+ })));
166
+ },
167
+ [channel, senderDetailsOptions, localSettings],
168
+ );
169
+
170
+ const rcsGsmSenderIdForSelect = useMemo(() => {
171
+ const raw = get(localSettings, DELIVERY_SETTING_KEY_GSM_SENDER_ID);
172
+ if (raw == null || raw === '') return undefined;
173
+ const allowed = new Set((rcsSenderOptions || []).map((senderOption) => senderOption.value));
174
+ return allowed.has(raw) ? raw : undefined;
175
+ }, [localSettings, rcsSenderOptions]);
176
+
177
+ const smsFallbackDomainOptions = useMemo(
178
+ () => {
179
+ const raw = (smsFallbackSenderDetailsOptions || []).map((senderDetails) => ({
180
+ label: senderDetails.domainName || senderDetails.domainId,
181
+ value: senderDetails.domainId,
182
+ ...senderDetails,
183
+ }));
184
+ if (!(channel === CHANNELS.RCS && smsTraiDltEnabled && registeredSenderIds?.length)) {
185
+ return raw;
186
+ }
187
+ return raw.filter((domain) => (domain?.gsmSenders || []).some(
188
+ (gsmSenderOption) => registeredSenderIds?.includes(gsmSenderOption?.value),
189
+ ));
190
+ },
191
+ [channel, smsFallbackSenderDetailsOptions, smsTraiDltEnabled, registeredSenderIds],
192
+ );
193
+
194
+ const smsSenderOptions = useMemo(
195
+ () => {
196
+ if (channel !== CHANNELS.RCS) return [];
197
+ const smsFallbackDomainRows = smsFallbackSenderDetailsOptions || [];
198
+ const selectedSmsFallbackDomainId = get(localSettings, DELIVERY_SETTING_KEY_SMS_FALLBACK_DOMAIN_ID);
199
+ const smsFallbackDomainsForDropdown =
200
+ selectedSmsFallbackDomainId != null && selectedSmsFallbackDomainId !== ''
201
+ ? smsFallbackDomainRows.filter((senderDomain) => senderDomain?.domainId === selectedSmsFallbackDomainId)
202
+ : smsFallbackDomainRows;
203
+ const shouldFilterSmsSendersByDltRegistration = smsTraiDltEnabled && registeredSenderIds?.length;
204
+ return smsFallbackDomainsForDropdown.flatMap((senderDomain) =>
205
+ filterUsableGsmSendersForDomain(senderDomain, senderDomain?.gsmSenders)
206
+ .filter((smsGsmSenderRow) =>
207
+ !shouldFilterSmsSendersByDltRegistration || registeredSenderIds?.includes(smsGsmSenderRow?.value))
208
+ .map((gsmSenderRow) => ({
209
+ value: senderDomain?.domainId != null && gsmSenderRow?.value != null
210
+ ? `${senderDomain.domainId}|${gsmSenderRow.value}`
211
+ : gsmSenderRow?.value,
212
+ label: String(gsmSenderRow?.value ?? ''),
213
+ })));
214
+ },
215
+ [channel, smsFallbackSenderDetailsOptions, localSettings, smsTraiDltEnabled, registeredSenderIds],
216
+ );
217
+
218
+ const smsFallbackGsmIdForSelect = useMemo(() => {
219
+ const raw = get(localSettings, DELIVERY_SETTING_KEY_CDMA_SENDER_ID);
220
+ if (raw == null || raw === '') return undefined;
221
+ const allowed = new Set((smsSenderOptions || []).map((senderOption) => senderOption.value));
222
+ return allowed.has(raw) ? raw : undefined;
223
+ }, [localSettings, smsSenderOptions]);
224
+
123
225
  const gsmOptions = useMemo(
124
226
  () => {
125
- const smsGsmSenders = channel === CHANNELS.SMS && smsTraiDltEnabled
126
- ? selectedDomainGsmSenders.filter((gsmId) => registeredSenderIds.includes(gsmId.value))
227
+ const smsGsmSendersForSelect = channel === CHANNELS.SMS && smsTraiDltEnabled && registeredSenderIds?.length
228
+ ? selectedDomainGsmSenders.filter((gsmSenderOption) =>
229
+ registeredSenderIds?.includes(gsmSenderOption?.value))
127
230
  : selectedDomainGsmSenders;
128
231
 
129
- return smsGsmSenders.map((o) => ({
130
- label: o.value || o.label,
131
- value: o.value,
232
+ return smsGsmSendersForSelect.map((gsmSenderRow) => ({
233
+ label: gsmSenderRow?.value || gsmSenderRow?.label,
234
+ value: gsmSenderRow?.value,
132
235
  }));
133
236
  },
134
237
  [channel, registeredSenderIds, selectedDomainGsmSenders, smsTraiDltEnabled],
135
238
  );
136
239
 
137
240
  const emailSenderOptions = useMemo(
138
- () => selectedDomainEmailSenders.map((o) => ({
139
- label: o.value || o.label,
140
- value: o.value,
141
- senderLabel: o.label,
241
+ () => selectedDomainEmailSenders.map((emailSenderRow) => ({
242
+ label: emailSenderRow.value || emailSenderRow.label,
243
+ value: emailSenderRow.value,
244
+ senderLabel: emailSenderRow.label,
142
245
  })),
143
246
  [selectedDomainEmailSenders],
144
247
  );
@@ -204,13 +307,53 @@ const ModifyDeliverySettings = (props) => {
204
307
  });
205
308
  }, []);
206
309
 
310
+ const onSmsFallbackDomainChange = useCallback(
311
+ (value) => {
312
+ setLocalSettings((prev) => {
313
+ const next = cloneDeep(prev);
314
+ next[DELIVERY_SETTING_KEY_SMS_FALLBACK_DOMAIN_ID] = value;
315
+ const selectedSmsFallbackDomain = (smsFallbackSenderDetailsOptions || []).find(
316
+ (senderDomain) => senderDomain?.domainId === value,
317
+ );
318
+ const usableSmsFallbackGsmSenders = filterUsableGsmSendersForDomain(
319
+ selectedSmsFallbackDomain,
320
+ selectedSmsFallbackDomain?.gsmSenders,
321
+ );
322
+ const shouldFilterSmsFallbackSendersByDltRegistration =
323
+ channel === CHANNELS.RCS && smsTraiDltEnabled && registeredSenderIds?.length;
324
+ const smsFallbackGsmSenders = shouldFilterSmsFallbackSendersByDltRegistration
325
+ ? usableSmsFallbackGsmSenders.filter((smsGsmSenderRow) =>
326
+ registeredSenderIds?.includes(smsGsmSenderRow?.value))
327
+ : usableSmsFallbackGsmSenders;
328
+ const firstSmsFallbackGsmSender = smsFallbackGsmSenders[0];
329
+ const composite = selectedSmsFallbackDomain?.domainId != null && firstSmsFallbackGsmSender?.value != null
330
+ ? `${selectedSmsFallbackDomain.domainId}|${firstSmsFallbackGsmSender.value}`
331
+ : (firstSmsFallbackGsmSender?.value || '');
332
+ next[DELIVERY_SETTING_KEY_CDMA_SENDER_ID] = composite;
333
+ return next;
334
+ });
335
+ },
336
+ [channel, smsFallbackSenderDetailsOptions, smsTraiDltEnabled, registeredSenderIds],
337
+ );
338
+
207
339
  const onDomainChange = useCallback(
208
340
  (value) => {
209
- const domain = domainOptions.find((d) => d.value === value);
341
+ const domain = domainOptions.find((domainOption) => domainOption.value === value);
210
342
  updateSetting(DELIVERY_SETTING_KEY_DOMAIN_ID, value);
211
343
  if (domain?.dgmId != null) updateSetting(DELIVERY_SETTING_KEY_DOMAIN_GATEWAY_MAP_ID, domain.dgmId);
344
+ if (channel === CHANNELS.RCS && domain) {
345
+ const usableRcsGsmSenders = filterUsableGsmSendersForDomain(domain, domain?.gsmSenders, {
346
+ skipDomainNameEchoFilter: true,
347
+ });
348
+ const firstRcsGsmSender = usableRcsGsmSenders[0];
349
+ const composite = domain?.domainId != null && firstRcsGsmSender?.value != null
350
+ ? `${domain.domainId}|${firstRcsGsmSender.value}`
351
+ : (firstRcsGsmSender?.value || '');
352
+ updateSetting(DELIVERY_SETTING_KEY_GSM_SENDER_ID, composite);
353
+ return;
354
+ }
212
355
  if (channel === CHANNELS.SMS && domain) {
213
- const smsGsmSenders = smsTraiDltEnabled
356
+ const smsGsmSenders = smsTraiDltEnabled && registeredSenderIds?.length
214
357
  ? (domain.gsmSenders || []).filter((gsmId) => registeredSenderIds.includes(gsmId.value))
215
358
  : domain.gsmSenders;
216
359
  const def = findDefault(smsGsmSenders);
@@ -230,9 +373,20 @@ const ModifyDeliverySettings = (props) => {
230
373
  );
231
374
 
232
375
  const handleDone = useCallback(() => {
233
- onSaveDeliverySettings(localSettings);
376
+ const next = cloneDeep(localSettings);
377
+ if (channel === CHANNELS.RCS) {
378
+ const rawRcs = get(next, DELIVERY_SETTING_KEY_GSM_SENDER_ID);
379
+ if (rawRcs && !(rcsSenderOptions || []).some((senderOption) => senderOption.value === rawRcs)) {
380
+ next[DELIVERY_SETTING_KEY_GSM_SENDER_ID] = '';
381
+ }
382
+ const rawSms = get(next, DELIVERY_SETTING_KEY_CDMA_SENDER_ID);
383
+ if (rawSms && !(smsSenderOptions || []).some((senderOption) => senderOption.value === rawSms)) {
384
+ next[DELIVERY_SETTING_KEY_CDMA_SENDER_ID] = '';
385
+ }
386
+ }
387
+ onSaveDeliverySettings(next);
234
388
  if (onClose) onClose();
235
- }, [localSettings, onSaveDeliverySettings, onClose]);
389
+ }, [channel, localSettings, onSaveDeliverySettings, onClose, rcsSenderOptions, smsSenderOptions]);
236
390
 
237
391
  const renderSelectRow = useCallback(
238
392
  ({
@@ -286,7 +440,7 @@ const ModifyDeliverySettings = (props) => {
286
440
  value: get(localSettings, DELIVERY_SETTING_KEY_SENDER_EMAIL),
287
441
  onChange: (val) => {
288
442
  const sender = selectedDomainEmailSenders.find(
289
- (s) => s.value === val,
443
+ (emailSenderRow) => emailSenderRow.value === val,
290
444
  );
291
445
  updateSetting(DELIVERY_SETTING_KEY_SENDER_EMAIL, val);
292
446
  updateSetting(DELIVERY_SETTING_KEY_SENDER_LABEL, sender?.label || val);
@@ -298,7 +452,7 @@ const ModifyDeliverySettings = (props) => {
298
452
  value: get(localSettings, DELIVERY_SETTING_KEY_SENDER_LABEL) || '',
299
453
  onChange: (val) => {
300
454
  const sender = selectedDomainEmailSenders.find(
301
- (s) => (s.label || s.value) === val,
455
+ (emailSenderRow) => (emailSenderRow.label || emailSenderRow.value) === val,
302
456
  );
303
457
  if (sender) {
304
458
  updateSetting(DELIVERY_SETTING_KEY_SENDER_EMAIL, sender.value);
@@ -326,7 +480,7 @@ const ModifyDeliverySettings = (props) => {
326
480
  onChange: (val) => {
327
481
  updateSetting(DELIVERY_SETTING_KEY_SOURCE_ACCOUNT_IDENTIFIER, val);
328
482
  const domain = (senderDetailsOptions || []).find(
329
- (d) => d.sourceAccountIdentifier === val,
483
+ (whatsappAccountRow) => whatsappAccountRow.sourceAccountIdentifier === val,
330
484
  );
331
485
  const first = domain?.gsmSenders?.[0];
332
486
  updateSetting(DELIVERY_SETTING_KEY_SENDER_MOB_NUM, first?.value || '');
@@ -340,10 +494,39 @@ const ModifyDeliverySettings = (props) => {
340
494
  onChange: (val) => updateSetting(DELIVERY_SETTING_KEY_SENDER_MOB_NUM, val),
341
495
  },
342
496
  ];
497
+ const rcsFields = [
498
+ {
499
+ titleMessage: messages.rcsDomainLabel,
500
+ options: domainOptions,
501
+ value: get(localSettings, DELIVERY_SETTING_KEY_DOMAIN_ID),
502
+ onChange: (val) => onDomainChange(val),
503
+ },
504
+ {
505
+ titleMessage: messages.rcsSenderIdLabel,
506
+ options: rcsSenderOptions,
507
+ value: rcsGsmSenderIdForSelect,
508
+ onChange: (val) => updateSetting(DELIVERY_SETTING_KEY_GSM_SENDER_ID, val),
509
+ },
510
+ ...((smsFallbackSenderDetailsOptions || []).length > 0 ? [
511
+ {
512
+ titleMessage: messages.fallbackSmsDomainLabel,
513
+ options: smsFallbackDomainOptions,
514
+ value: get(localSettings, DELIVERY_SETTING_KEY_SMS_FALLBACK_DOMAIN_ID),
515
+ onChange: onSmsFallbackDomainChange,
516
+ },
517
+ {
518
+ titleMessage: messages.fallbackSmsSenderIdLabel,
519
+ options: smsSenderOptions,
520
+ value: smsFallbackGsmIdForSelect,
521
+ onChange: (val) => updateSetting(DELIVERY_SETTING_KEY_CDMA_SENDER_ID, val),
522
+ },
523
+ ] : []),
524
+ ];
343
525
  const byChannel = {
344
526
  [CHANNELS.SMS]: smsFields,
345
527
  [CHANNELS.EMAIL]: emailFields,
346
528
  [CHANNELS.WHATSAPP]: whatsappFields,
529
+ [CHANNELS.RCS]: rcsFields,
347
530
  };
348
531
  return byChannel[channel] || [];
349
532
  }, [
@@ -356,6 +539,13 @@ const ModifyDeliverySettings = (props) => {
356
539
  wecrmAccountOptions,
357
540
  whatsappAccountOptionsForDisplay,
358
541
  whatsappSenderOptions,
542
+ rcsSenderOptions,
543
+ rcsGsmSenderIdForSelect,
544
+ smsSenderOptions,
545
+ smsFallbackGsmIdForSelect,
546
+ smsFallbackDomainOptions,
547
+ smsFallbackSenderDetailsOptions,
548
+ onSmsFallbackDomainChange,
359
549
  localSettings,
360
550
  selectedDomainEmailSenders,
361
551
  senderDetailsOptions,
@@ -390,9 +580,10 @@ const ModifyDeliverySettings = (props) => {
390
580
  };
391
581
 
392
582
  ModifyDeliverySettings.propTypes = {
393
- channel: PropTypes.oneOf([CHANNELS.SMS, CHANNELS.EMAIL, CHANNELS.WHATSAPP]).isRequired,
583
+ channel: PropTypes.oneOf([CHANNELS.SMS, CHANNELS.EMAIL, CHANNELS.WHATSAPP, CHANNELS.RCS]).isRequired,
394
584
  deliverySettings: PropTypes.object,
395
585
  senderDetailsOptions: PropTypes.array,
586
+ smsFallbackSenderDetailsOptions: PropTypes.array,
396
587
  wecrmAccounts: PropTypes.array,
397
588
  onSaveDeliverySettings: PropTypes.func.isRequired,
398
589
  onClose: PropTypes.func,
@@ -408,6 +599,7 @@ ModifyDeliverySettings.propTypes = {
408
599
  ModifyDeliverySettings.defaultProps = {
409
600
  deliverySettings: {},
410
601
  senderDetailsOptions: [],
602
+ smsFallbackSenderDetailsOptions: [],
411
603
  wecrmAccounts: [],
412
604
  onClose: undefined,
413
605
  isLoading: false,
@@ -21,6 +21,8 @@ export const DELIVERY_SETTING_KEY_SENDER_LABEL = 'senderLabel';
21
21
  export const DELIVERY_SETTING_KEY_SENDER_REPLY_TO = 'senderReplyTo';
22
22
  export const DELIVERY_SETTING_KEY_SOURCE_ACCOUNT_IDENTIFIER = 'sourceAccountIdentifier';
23
23
  export const DELIVERY_SETTING_KEY_SENDER_MOB_NUM = 'senderMobNum';
24
+ /** RCS: SMS fallback domain (separate from primary RCS domainId) */
25
+ export const DELIVERY_SETTING_KEY_SMS_FALLBACK_DOMAIN_ID = 'smsFallbackDomainId';
24
26
 
25
27
  /** data-testid for delivery settings edit icon */
26
28
  export const TEST_ID_DELIVERY_SETTINGS_EDIT = 'delivery-settings-edit';
@@ -32,6 +34,7 @@ export const CHANNELS_WITH_DELIVERY_SETTINGS = [
32
34
  CHANNELS.SMS,
33
35
  CHANNELS.EMAIL,
34
36
  CHANNELS.WHATSAPP,
37
+ CHANNELS.RCS,
35
38
  ];
36
39
 
37
40
  /** Default empty delivery setting per channel (campaigns-style shape) */
@@ -56,8 +59,21 @@ export const DEFAULT_DELIVERY_SETTING_WHATSAPP = {
56
59
  sourceAccountIdentifier: '',
57
60
  };
58
61
 
62
+ /** RCS: gsmSenderId = RCS sender, cdmaSenderId = SMS fallback sender (reuse same keys) */
63
+ export const DEFAULT_DELIVERY_SETTING_RCS = {
64
+ domainId: null,
65
+ domainGatewayMapId: null,
66
+ gsmSenderId: '',
67
+ smsFallbackDomainId: null,
68
+ cdmaSenderId: '',
69
+ };
70
+
59
71
  export const DEFAULT_DELIVERY_SETTINGS_BY_CHANNEL = {
60
72
  [CHANNELS.SMS]: DEFAULT_DELIVERY_SETTING_SMS,
61
73
  [CHANNELS.EMAIL]: DEFAULT_DELIVERY_SETTING_EMAIL,
62
74
  [CHANNELS.WHATSAPP]: DEFAULT_DELIVERY_SETTING_WHATSAPP,
75
+ [CHANNELS.RCS]: DEFAULT_DELIVERY_SETTING_RCS,
63
76
  };
77
+
78
+ /** API `contactInfo.type` keys that map to RCS-style GSM sender rows (env-specific naming). */
79
+ export const RCS_CONTACT_INFO_GSM_TYPE_KEYS = ['gsm_sender_id', 'rcs_sender_id', 'rcs_sender'];
@@ -1,11 +1,11 @@
1
1
  /**
2
2
  * DeliverySettings — summary row + CapSlideBox trigger for Test and Preview.
3
- * Rendered only for SMS, Email, WhatsApp. Uses cap-ui-library only.
3
+ * Rendered for SMS, Email, WhatsApp, RCS (ModifyDeliverySettings). RCS uses gsmSenderId + cdmaSenderId (SMS fallback).
4
4
  *
5
5
  * Reference: cap-campaigns-v2 DeliverySettingsV2 (summary + modify panel).
6
6
  */
7
7
 
8
- import React, { useState, useCallback } from "react";
8
+ import React, { useState, useCallback, useMemo } from "react";
9
9
  import PropTypes from "prop-types";
10
10
  import CapRow from "@capillarytech/cap-ui-library/CapRow";
11
11
  import CapHeading from "@capillarytech/cap-ui-library/CapHeading";
@@ -22,6 +22,7 @@ import {
22
22
  SUMMARY_EMPTY_PLACEHOLDER,
23
23
  DELIVERY_SETTING_KEY_DOMAIN_ID,
24
24
  DELIVERY_SETTING_KEY_GSM_SENDER_ID,
25
+ DELIVERY_SETTING_KEY_CDMA_SENDER_ID,
25
26
  DELIVERY_SETTING_KEY_SENDER_EMAIL,
26
27
  DELIVERY_SETTING_KEY_SENDER_LABEL,
27
28
  DELIVERY_SETTING_KEY_SENDER_REPLY_TO,
@@ -35,7 +36,7 @@ const DeliverySettings = (props) => {
35
36
  const {
36
37
  channel,
37
38
  deliverySettings = {},
38
- senderDetailsOptions = [],
39
+ senderDetailsByChannel = {},
39
40
  wecrmAccounts = [],
40
41
  onSaveDeliverySettings,
41
42
  isLoadingSenderDetails,
@@ -43,6 +44,7 @@ const DeliverySettings = (props) => {
43
44
  smsTraiDltEnabled,
44
45
  registeredSenderIds,
45
46
  whatsappAccountFromForm,
47
+ isChannelSmsFallbackPreviewEnabled,
46
48
  } = props;
47
49
 
48
50
  const [isSlideBoxOpen, setSlideBoxOpen] = useState(false);
@@ -58,17 +60,68 @@ const DeliverySettings = (props) => {
58
60
  [onSaveDeliverySettings, closeSlideBox]
59
61
  );
60
62
 
63
+ const senderDetailsOptions = useMemo(
64
+ () => (senderDetailsByChannel[channel] || []),
65
+ [senderDetailsByChannel, channel],
66
+ );
67
+ const smsDomainsForRcs = useMemo(
68
+ () => (channel === CHANNELS.RCS ? (senderDetailsByChannel[CHANNELS.SMS] || []) : []),
69
+ [channel, senderDetailsByChannel],
70
+ );
71
+
61
72
  if (!CHANNELS_WITH_DELIVERY_SETTINGS.includes(channel)) {
62
73
  return null;
63
74
  }
64
75
 
65
76
  const notConfiguredLabel = formatMessage(messages.notConfigured);
66
77
 
78
+ const getDisplayFromDomains = (domains, compositeValue) => {
79
+ if (!compositeValue || !domains?.length) return compositeValue || SUMMARY_EMPTY_PLACEHOLDER;
80
+ for (const senderDomain of domains) {
81
+ for (const gsmSenderRow of senderDomain.gsmSenders || []) {
82
+ const value = senderDomain.domainId != null && gsmSenderRow.value != null
83
+ ? `${senderDomain.domainId}|${gsmSenderRow.value}`
84
+ : gsmSenderRow.value;
85
+ if (value === compositeValue && (senderDomain.domainName || gsmSenderRow.value)) {
86
+ return [senderDomain.domainName, gsmSenderRow.value].filter(Boolean).join(' · ');
87
+ }
88
+ }
89
+ }
90
+ return compositeValue || SUMMARY_EMPTY_PLACEHOLDER;
91
+ };
92
+
93
+ /** RCS summary: show sender ID only (no "domain · sender"). */
94
+ const getSenderIdOnlyFromComposite = (domains, compositeValue) => {
95
+ if (!compositeValue || !domains?.length) return compositeValue || SUMMARY_EMPTY_PLACEHOLDER;
96
+ for (const senderDomain of domains) {
97
+ for (const gsmSenderRow of senderDomain.gsmSenders || []) {
98
+ const value = senderDomain.domainId != null && gsmSenderRow.value != null
99
+ ? `${senderDomain.domainId}|${gsmSenderRow.value}`
100
+ : gsmSenderRow.value;
101
+ if (value === compositeValue && gsmSenderRow.value != null) {
102
+ return String(gsmSenderRow.value);
103
+ }
104
+ }
105
+ }
106
+ return compositeValue || SUMMARY_EMPTY_PLACEHOLDER;
107
+ };
108
+
67
109
  const getSummaryText = () => {
68
110
  const empty = SUMMARY_EMPTY_PLACEHOLDER;
111
+ if (channel === CHANNELS.RCS) {
112
+ const rcsVal = get(deliverySettings, DELIVERY_SETTING_KEY_GSM_SENDER_ID) || '';
113
+ const smsVal = get(deliverySettings, DELIVERY_SETTING_KEY_CDMA_SENDER_ID) || '';
114
+ const summaryRcs = {
115
+ rcsSenderId: getSenderIdOnlyFromComposite(senderDetailsOptions, rcsVal),
116
+ };
117
+ if (isChannelSmsFallbackPreviewEnabled) {
118
+ summaryRcs.smsFallbackSenderId = getSenderIdOnlyFromComposite(smsDomainsForRcs, smsVal);
119
+ }
120
+ return summaryRcs;
121
+ }
69
122
  if (channel === CHANNELS.SMS) {
70
123
  const domain = (senderDetailsOptions || []).find(
71
- (d) => d.domainId === get(deliverySettings, DELIVERY_SETTING_KEY_DOMAIN_ID),
124
+ (senderDomain) => senderDomain.domainId === get(deliverySettings, DELIVERY_SETTING_KEY_DOMAIN_ID),
72
125
  );
73
126
  const domainName = domain?.domainName || empty;
74
127
  const senderId = get(deliverySettings, DELIVERY_SETTING_KEY_GSM_SENDER_ID) || empty;
@@ -76,7 +129,7 @@ const DeliverySettings = (props) => {
76
129
  }
77
130
  if (channel === CHANNELS.EMAIL) {
78
131
  const domain = (senderDetailsOptions || []).find(
79
- (d) => d.domainId === get(deliverySettings, DELIVERY_SETTING_KEY_DOMAIN_ID),
132
+ (senderDomain) => senderDomain.domainId === get(deliverySettings, DELIVERY_SETTING_KEY_DOMAIN_ID),
80
133
  );
81
134
  const emailDomain = domain?.domainName || empty;
82
135
  const senderEmail = get(deliverySettings, DELIVERY_SETTING_KEY_SENDER_EMAIL) || empty;
@@ -103,7 +156,12 @@ const DeliverySettings = (props) => {
103
156
 
104
157
  const summary = getSummaryText();
105
158
  let hasValues = false;
106
- if (channel === CHANNELS.SMS) {
159
+ if (channel === CHANNELS.RCS) {
160
+ hasValues = (summary.rcsSenderId && summary.rcsSenderId !== SUMMARY_EMPTY_PLACEHOLDER)
161
+ || (isChannelSmsFallbackPreviewEnabled
162
+ && summary.smsFallbackSenderId
163
+ && summary.smsFallbackSenderId !== SUMMARY_EMPTY_PLACEHOLDER);
164
+ } else if (channel === CHANNELS.SMS) {
107
165
  hasValues = summary.senderDomain !== SUMMARY_EMPTY_PLACEHOLDER
108
166
  || summary.senderId !== SUMMARY_EMPTY_PLACEHOLDER;
109
167
  } else if (channel === CHANNELS.EMAIL) {
@@ -122,6 +180,15 @@ const DeliverySettings = (props) => {
122
180
  const getSummaryObject = () => {
123
181
  if (!hasValues) return null;
124
182
  const label = (msg) => formatMessage(msg);
183
+ if (channel === CHANNELS.RCS) {
184
+ const rcsSummary = {
185
+ [label(messages.rcsSenderIdLabel)]: summary.rcsSenderId,
186
+ };
187
+ if (isChannelSmsFallbackPreviewEnabled) {
188
+ rcsSummary[label(messages.fallbackSmsSenderIdLabel)] = summary.smsFallbackSenderId;
189
+ }
190
+ return rcsSummary;
191
+ }
125
192
  if (channel === CHANNELS.SMS) {
126
193
  return {
127
194
  [label(messages.senderDomainSummary)]: summary.senderDomain,
@@ -165,7 +232,7 @@ const DeliverySettings = (props) => {
165
232
  Object.entries(summaryObject).map(([key, value]) => (
166
233
  <CapRow type="flex" key={key} className="delivery-settings__summary-entry">
167
234
  <CapLabel type="label1" className="delivery-settings__summary-key">{key}</CapLabel>
168
- <CapLabel type="label9">
235
+ <CapLabel type="label9" className="delivery-settings__summary-value">
169
236
  :
170
237
  {' '}
171
238
  {value}
@@ -194,6 +261,11 @@ const DeliverySettings = (props) => {
194
261
  channel={channel}
195
262
  deliverySettings={deliverySettings}
196
263
  senderDetailsOptions={senderDetailsOptions}
264
+ smsFallbackSenderDetailsOptions={
265
+ channel === CHANNELS.RCS && isChannelSmsFallbackPreviewEnabled
266
+ ? smsDomainsForRcs
267
+ : undefined
268
+ }
197
269
  wecrmAccounts={wecrmAccounts}
198
270
  onSaveDeliverySettings={handleSave}
199
271
  onClose={closeSlideBox}
@@ -213,9 +285,9 @@ const DeliverySettings = (props) => {
213
285
  DeliverySettings.propTypes = {
214
286
  channel: PropTypes.string.isRequired,
215
287
  deliverySettings: PropTypes.object,
216
- senderDetailsOptions: PropTypes.array,
288
+ senderDetailsByChannel: PropTypes.object,
217
289
  wecrmAccounts: PropTypes.array,
218
- onSaveDeliverySettings: PropTypes.func.isRequired,
290
+ onSaveDeliverySettings: PropTypes.func,
219
291
  isLoadingSenderDetails: PropTypes.bool,
220
292
  formatMessage: PropTypes.func,
221
293
  smsTraiDltEnabled: PropTypes.bool,
@@ -223,17 +295,20 @@ DeliverySettings.propTypes = {
223
295
  whatsappAccountFromForm: PropTypes.shape({
224
296
  accountName: PropTypes.string,
225
297
  }),
298
+ isChannelSmsFallbackPreviewEnabled: PropTypes.bool,
226
299
  };
227
300
 
228
301
  DeliverySettings.defaultProps = {
229
302
  deliverySettings: {},
230
- senderDetailsOptions: [],
303
+ senderDetailsByChannel: {},
231
304
  wecrmAccounts: [],
305
+ onSaveDeliverySettings: () => {},
232
306
  isLoadingSenderDetails: false,
233
307
  formatMessage: undefined,
234
308
  smsTraiDltEnabled: false,
235
309
  registeredSenderIds: [],
236
310
  whatsappAccountFromForm: undefined,
311
+ isChannelSmsFallbackPreviewEnabled: false,
237
312
  };
238
313
 
239
314
  export default DeliverySettings;
@@ -108,4 +108,34 @@ export default defineMessages({
108
108
  id: `${prefix}.disabledMessage`,
109
109
  defaultMessage: 'Message template selected belongs to this account',
110
110
  },
111
+ /** RCS: primary domain (slidebox) */
112
+ rcsDomainLabel: {
113
+ id: `${prefix}.rcsDomainLabel`,
114
+ defaultMessage: 'RCS domain:',
115
+ },
116
+ /** RCS: SMS fallback domain (slidebox) */
117
+ fallbackSmsDomainLabel: {
118
+ id: `${prefix}.fallbackSmsDomainLabel`,
119
+ defaultMessage: 'Fallback SMS domain:',
120
+ },
121
+ /** RCS: "RCS sender ID" */
122
+ rcsSenderIdLabel: {
123
+ id: `${prefix}.rcsSenderIdLabel`,
124
+ defaultMessage: 'RCS sender ID',
125
+ },
126
+ /** RCS: "Fallback SMS sender ID" */
127
+ fallbackSmsSenderIdLabel: {
128
+ id: `${prefix}.fallbackSmsSenderIdLabel`,
129
+ defaultMessage: 'Fallback SMS sender ID',
130
+ },
131
+ /** RCS: "Domain" (for domain · sender ID display) */
132
+ domainLabel: {
133
+ id: `${prefix}.domainLabel`,
134
+ defaultMessage: 'Domain',
135
+ },
136
+ /** RCS: placeholder for sender ID dropdown */
137
+ selectSenderId: {
138
+ id: `${prefix}.selectSenderId`,
139
+ defaultMessage: 'Select sender ID',
140
+ },
111
141
  });