@capillarytech/creatives-library 9.0.54-alpha.4 → 9.0.54

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.
@@ -38,86 +38,6 @@ export const CHANNEL_PRIORITY = 'CHANNEL_PRIORITY';
38
38
  export const AB_TEST = 'AB_TEST';
39
39
  export const SINGLE_TEMPLATE = 'SINGLE_TEMPLATE';
40
40
 
41
- // CCS CommDefinition strategyType — distinct from SINGLE_TEMPLATE above, which
42
- // is this UI's own communicationStrategy value. Only SINGLE is supported this
43
- // phase; CCS create is skipped entirely for CHANNEL_PRIORITY/AB_TEST.
44
- export const CCS_STRATEGY_TYPE_SINGLE = 'SINGLE';
45
-
46
- // Mirrors CCS's SingleChannelStrategy field names exactly (Cap Notify API
47
- // Design doc sample payloads, verified against real create responses). Kept
48
- // separate from CHANNEL_CONTENT_KEY_MAP/CHANNEL_DELIVERY_KEY_MAP below, which
49
- // are the legacy messageMeta payload's keys.
50
- export const CCS_CHANNEL_CONTENT_KEY_MAP = {
51
- SMS: 'smsMessageContent',
52
- EMAIL: 'emailMessageContent',
53
- WHATSAPP: 'whatsappMessageContent',
54
- // CCS's channel enum value for mobile push is 'PUSH' (verified against real
55
- // create responses), even though the content/delivery keys stay 'mpush*'.
56
- PUSH: 'mpushMessageContent',
57
- INAPP: 'inAppMessageContent',
58
- ANDROID: 'androidMessageContent',
59
- IOS: 'iosMessageContent',
60
- ZALO: 'zaloMessageContent',
61
- VIBER: 'viberMessageContent',
62
- LINE: 'lineMessageContent',
63
- WEBPUSH: 'webPushMessageContent',
64
- RCS: 'rcsMessageContent',
65
- };
66
-
67
- // contentItem.templateData is built by the legacy CreativesContainer content
68
- // editor (messageMeta-oriented field names) — for channels whose legacy field
69
- // names don't match CCS's own content schema, transform before sending rather
70
- // than dumping templateData as-is. EMAIL: legacy stores the subject as
71
- // `emailSubject` and the HTML body as `emailBody` (see
72
- // extractContentForPreview.js and CreativesContainer/index.js, where the Bee
73
- // editor's output is written back into templateData.emailBody — also
74
- // mirrored by the existing legacy emailMessageContent builder in
75
- // utils/transformerUtils.js). CCS expects `messageSubject`/`messageBody`.
76
- export const CCS_CONTENT_TRANSFORMS = {
77
- EMAIL: (templateData = {}) => ({
78
- messageSubject: templateData.emailSubject,
79
- messageBody: templateData.emailBody || templateData.emailHtml,
80
- }),
81
- // WEBPUSH: the legacy editor nests the real data under
82
- // messageContent.content (see CommunicationFlowCard.js's own comment on
83
- // this same wrapping, for the edit-mode case) — extracting it flat here
84
- // matches CCS's shape ({ messageSubject, accountId, content }); `offers`
85
- // (a legacy-only field) is deliberately dropped, not part of CCS's schema.
86
- WEBPUSH: (templateData = {}) => {
87
- const inner = templateData.messageContent?.content || templateData;
88
- return {
89
- messageSubject: inner.messageSubject,
90
- accountId: inner.accountId,
91
- content: inner.content,
92
- };
93
- },
94
- };
95
-
96
- export const CCS_CHANNEL_DELIVERY_KEY_MAP = {
97
- SMS: 'smsDeliverySettings',
98
- EMAIL: 'emailDeliverySettings',
99
- WHATSAPP: 'whatsappDeliverySettings',
100
- PUSH: 'mpushDeliverySettings',
101
- INAPP: 'inAppDeliverySettings',
102
- ANDROID: 'androidDeliverySettings',
103
- IOS: 'iosDeliverySettings',
104
- ZALO: 'zaloDeliverySettings',
105
- VIBER: 'viberDeliverySettings',
106
- LINE: 'lineDeliverySettings',
107
- WEBPUSH: 'webPushDeliverySettings',
108
- RCS: 'rcsDeliverySettings',
109
- };
110
-
111
- // The UI's own internal channel identifier for mobile push is 'MOBILEPUSH'
112
- // (see CreativesContainer/constants.js MOBILE_PUSH), but CCS's channel enum
113
- // value is 'PUSH' (verified against real create responses — the content/
114
- // delivery KEYS still say 'mpush*', only the enum VALUE is 'PUSH') —
115
- // normalize before building the CCS payload. Every other channel identifier
116
- // matches CCS as-is.
117
- export const CCS_CHANNEL_NAME_MAP = {
118
- MOBILEPUSH: 'PUSH',
119
- };
120
-
121
41
  // Channel config - single source of truth for CreativesContainer and TemplatesV2
122
42
  // paneKey: TemplatesV2 defaultPanes object key (for channelsToHide)
123
43
  // channelProp: CreativesContainer channel prop (must match pane.key for tab to be active)
@@ -312,4 +232,4 @@ export const INCENTIVE_TYPES = [
312
232
  {
313
233
  value: 'badges', label: <FormattedMessage {...messages.badges} />, isActive: false, disabled: false,
314
234
  },
315
- ];
235
+ ];
@@ -9,6 +9,7 @@
9
9
  import React from 'react';
10
10
  import PropTypes from 'prop-types';
11
11
  import CommunicationFlow from './CommunicationFlow';
12
+ import { hasSupportEngagementModule } from '../../utils/common';
12
13
 
13
14
  const CommunicationFlowContainer = ({
14
15
  config,
@@ -17,16 +18,22 @@ const CommunicationFlowContainer = ({
17
18
  onCancel,
18
19
  onChange,
19
20
  ...otherProps
20
- }) => (
21
- <CommunicationFlow
22
- config={config}
23
- initialData={initialData}
24
- onSave={onSave}
25
- onCancel={onCancel}
26
- onChange={onChange}
27
- {...otherProps}
28
- />
29
- );
21
+ }) => {
22
+ if (!hasSupportEngagementModule()) {
23
+ return null;
24
+ }
25
+
26
+ return (
27
+ <CommunicationFlow
28
+ config={config}
29
+ initialData={initialData}
30
+ onSave={onSave}
31
+ onCancel={onCancel}
32
+ onChange={onChange}
33
+ {...otherProps}
34
+ />
35
+ );
36
+ };
30
37
 
31
38
  CommunicationFlowContainer.propTypes = {
32
39
  config: PropTypes.shape({
@@ -80,13 +87,11 @@ CommunicationFlowContainer.propTypes = {
80
87
  controls: PropTypes.array,
81
88
  }),
82
89
  }),
83
- context: PropTypes.object, // ouId, campaignId, programId; name (required for CCS create),
84
- // referenceId (optional, auto-generated from name if absent), description (optional).
85
- useCCS: PropTypes.bool, // If false, skips the CCS createCommDefinition call on save. Defaults to true.
90
+ context: PropTypes.object, // ouId, campaignId, programId, etc.
91
+ useCCS: PropTypes.bool, // If false, skips CCS bulk-claim-approve on save. Defaults to true.
86
92
  }).isRequired,
87
93
  initialData: PropTypes.object, // for edit/preview mode
88
- onSave: PropTypes.func.isRequired, // (data) => void - called when user saves; data.ccsCommDefinition
89
- // ({id, referenceId, version, status}) is present when the CCS create succeeded
94
+ onSave: PropTypes.func.isRequired, // (data) => void - called when user saves
90
95
  onCancel: PropTypes.func.isRequired, // () => void - called when user cancels
91
96
  onChange: PropTypes.func, // (data) => void - optional, called on data changes
92
97
  };
@@ -363,8 +363,4 @@ export default {
363
363
  id: `${prefix}.senderNotConfiguredError`,
364
364
  defaultMessage: 'Selected domain gateway id is not correct. Please change the domain id or contact the gateway team to register them with Capillary.',
365
365
  },
366
- duplicateReferenceIdError: {
367
- id: `${prefix}.duplicateReferenceIdError`,
368
- defaultMessage: 'This reference ID is already in use in your organization. Please use a different reference ID.',
369
- },
370
366
  };
@@ -29,7 +29,6 @@ import {
29
29
  getEmailDefaultsForDomainId,
30
30
  getSmsDefaultsForDomainId,
31
31
  getRcsAccountName,
32
- getEmailDomainGatewayMapIdByDomainId,
33
32
  } from './deliverySettingsConfig';
34
33
  import messages from '../../messages';
35
34
  import './SenderDetails.scss';
@@ -152,11 +151,6 @@ const SenderDetails = ({
152
151
  saveValues.whatsappDomainId = matchedDomain?.domainProperties?.id ?? matchedDomain?.domainId ?? matchedDomain?.id;
153
152
  }
154
153
  }
155
- // Include EMAIL domainGatewayMapId derived from the selected domain for persistence -
156
- // CCS needs it alongside domainId, but it's not a user-facing field.
157
- if (entity && fieldValues.emailDomain != null && fieldValues.emailDomain !== '') {
158
- saveValues.emailDomainGatewayMapId = getEmailDomainGatewayMapIdByDomainId(entity, fieldValues.emailDomain);
159
- }
160
154
  onSave(saveValues);
161
155
  }
162
156
  onClose();
@@ -83,7 +83,6 @@ const ENTITIES = {
83
83
  emailTwoDomains: {
84
84
  EMAIL: [
85
85
  {
86
- id: 'gwmap-a',
87
86
  domainProperties: {
88
87
  id: 'em-a',
89
88
  domainName: 'Mail Alpha',
@@ -102,7 +101,6 @@ const ENTITIES = {
102
101
  },
103
102
  },
104
103
  {
105
- id: 'gwmap-b',
106
104
  domainProperties: {
107
105
  id: 'em-b',
108
106
  domainName: 'Mail Beta',
@@ -324,29 +322,6 @@ describe('SenderDetails', () => {
324
322
  });
325
323
  });
326
324
 
327
- it('persists emailDomainGatewayMapId derived from the selected email domain on save', async () => {
328
- const { onSave } = renderSenderDetails({
329
- channels: ['EMAIL'],
330
- preloadedDomainProperties: ENTITIES.emailTwoDomains,
331
- });
332
- const root = document.querySelector('.sender-details');
333
- await waitFor(() => expect(within(root).getByText('Mail Alpha')).toBeInTheDocument());
334
-
335
- await openSelectAndChoose(root, 0, 'Mail Beta');
336
- await waitFor(() => expect(within(root).getByText('beta@other.com')).toBeInTheDocument());
337
-
338
- const saveBtn = within(root).getByRole('button', { name: /save changes/i });
339
- await waitFor(() => expect(saveBtn).not.toBeDisabled());
340
- fireEvent.click(saveBtn);
341
-
342
- expect(onSave).toHaveBeenCalledWith(
343
- expect.objectContaining({
344
- emailDomain: 'em-b',
345
- emailDomainGatewayMapId: 'gwmap-b',
346
- }),
347
- );
348
- });
349
-
350
325
  it('resets email domain row back to the first gateway', async () => {
351
326
  renderSenderDetails({
352
327
  channels: ['EMAIL'],
@@ -438,7 +438,6 @@ describe('deliverySettingsConfig — user-facing flows', () => {
438
438
  smsDomain: 'd1',
439
439
  smsSenderId: 'g1',
440
440
  emailDomain: 'ed',
441
- emailDomainGatewayMapId: 'gwmap-1',
442
441
  emailSenderId: 'mail@x.com',
443
442
  emailSenderName: 'N',
444
443
  emailReplyToId: 'r@x.com',
@@ -456,10 +455,9 @@ describe('deliverySettingsConfig — user-facing flows', () => {
456
455
  SMS: { domainId: 'd1', gsmSenderId: 'g1' },
457
456
  EMAIL: {
458
457
  domainId: 'ed',
459
- domainGatewayMapId: 'gwmap-1',
460
- senderId: 'mail@x.com',
458
+ senderEmail: 'mail@x.com',
461
459
  senderLabel: 'N',
462
- replyToId: 'r@x.com',
460
+ senderReplyTo: 'r@x.com',
463
461
  },
464
462
  WHATSAPP: { domainId: 'wd', senderMobNum: '+w' },
465
463
  RCS: { senderMobNum: '+r', rcsSender: '+r' },
@@ -474,10 +472,9 @@ describe('deliverySettingsConfig — user-facing flows', () => {
474
472
  SMS: { domainId: 'd', gsmSenderId: 'g' },
475
473
  EMAIL: {
476
474
  domainId: 'ed',
477
- domainGatewayMapId: 'gwmap-2',
478
- senderId: 'e@e.com',
475
+ senderEmail: 'e@e.com',
479
476
  senderLabel: 'L',
480
- replyToId: 'r@e.com',
477
+ senderReplyTo: 'r@e.com',
481
478
  },
482
479
  WHATSAPP: { senderMobNum: '+w', domainId: 'wid' },
483
480
  RCS: { rcsSender: '+r' },
@@ -489,10 +486,6 @@ describe('deliverySettingsConfig — user-facing flows', () => {
489
486
  smsDomain: 'd',
490
487
  smsSenderId: 'g',
491
488
  emailDomain: 'ed',
492
- emailDomainGatewayMapId: 'gwmap-2',
493
- emailSenderId: 'e@e.com',
494
- emailSenderName: 'L',
495
- emailReplyToId: 'r@e.com',
496
489
  whatsappDomainId: 'wid',
497
490
  viberSenderId: 'vx',
498
491
  });
@@ -181,14 +181,6 @@ const getEmailDomainValue = (entity) => {
181
181
  return emailData.domainProperties?.id ?? emailData.domainId ?? emailData.id ?? '';
182
182
  };
183
183
 
184
- // CCS's domainGatewayMapId is the domainProperties API's own outer `id`
185
- // (distinct from `domainProperties.id`, which is the numeric domainId) - the
186
- // domain-gateway-mapping id for the selected domain entry.
187
- const getEmailDomainGatewayMapIdByDomainId = (entity, domainId) => {
188
- const domainEntry = getEmailDomainById(entity, domainId);
189
- return domainEntry?.id ?? '';
190
- };
191
-
192
184
  /** Domain name for summary display (parseEntityForDisplay) */
193
185
  const getEmailDomainNameForDisplay = (entity) => {
194
186
  const emailData = getEmailData(entity);
@@ -270,8 +262,6 @@ const getEmailDefaultsForDomain = (domainData) => {
270
262
  * context.fieldValues has current form state (e.g. selected emailDomain)
271
263
  * Aligned with adiona-ui/cap-campaigns-v2: default = contactInfo item with default:true, or first
272
264
  */
273
- export { getEmailDomainGatewayMapIdByDomainId };
274
-
275
265
  export const getDefaultValueForField = (fieldKey, entity, context = {}) => {
276
266
  if (!entity) return '';
277
267
  const fieldValues = context?.fieldValues || {};
@@ -584,11 +574,7 @@ export const parseEntityForDisplay = (entity, context = {}) => {
584
574
  senderDetails: entity,
585
575
  smsSenderId: getSmsSenderIdValue(entity),
586
576
  smsDomain: getSmsDomainValue(entity),
587
- // emailDomain here is the domain NAME (for display only) - buildChannelSettingFromFieldValues
588
- // needs the numeric domainId/domainGatewayMapId, sourced separately below.
589
577
  emailDomain: getEmailDomainNameForDisplay(entity),
590
- emailDomainId: getEmailDomainValue(entity),
591
- emailDomainGatewayMapId: getEmailDomainGatewayMapIdByDomainId(entity, getEmailDomainValue(entity)),
592
578
  emailSenderId: getEmailSenderIdValue(entity),
593
579
  viberSenderId: getSenderIdFromContactInfo(entity, 'VIBER'),
594
580
  zaloSenderId: getSenderIdFromContactInfo(entity, 'ZALO'),
@@ -614,14 +600,10 @@ export const buildChannelSettingFromFieldValues = (fieldValues = {}) => {
614
600
  }
615
601
  if (fieldValues.emailDomain != null || fieldValues.emailSenderId != null || fieldValues.emailSenderName != null || fieldValues.emailReplyToId != null) {
616
602
  channelSetting.EMAIL = {
617
- // emailDomainId (numeric, from the auto-save-defaults path via parseEntityForDisplay)
618
- // takes priority over emailDomain, which is numeric when sourced from SenderDetails'
619
- // own field state but a display NAME string when sourced from parseEntityForDisplay.
620
- domainId: fieldValues.emailDomainId ?? fieldValues.emailDomain,
621
- domainGatewayMapId: fieldValues.emailDomainGatewayMapId,
622
- senderId: fieldValues.emailSenderId,
603
+ domainId: fieldValues.emailDomain,
604
+ senderEmail: fieldValues.emailSenderId,
623
605
  senderLabel: fieldValues.emailSenderName,
624
- replyToId: fieldValues.emailReplyToId,
606
+ senderReplyTo: fieldValues.emailReplyToId,
625
607
  };
626
608
  }
627
609
  if (fieldValues.whatsappSenderNumber != null || fieldValues.whatsappAccount != null) {
@@ -691,10 +673,9 @@ export const parseChannelSettingForDisplay = (channelSetting = {}) => {
691
673
  }
692
674
  if (channelSetting.EMAIL) {
693
675
  out.emailDomain = channelSetting.EMAIL.domainId;
694
- out.emailDomainGatewayMapId = channelSetting.EMAIL.domainGatewayMapId;
695
- out.emailSenderId = channelSetting.EMAIL.senderId;
676
+ out.emailSenderId = channelSetting.EMAIL.senderEmail;
696
677
  out.emailSenderName = channelSetting.EMAIL.senderLabel;
697
- out.emailReplyToId = channelSetting.EMAIL.replyToId;
678
+ out.emailReplyToId = channelSetting.EMAIL.senderReplyTo;
698
679
  }
699
680
  if (channelSetting.WHATSAPP) {
700
681
  out.whatsappSenderNumber = channelSetting.WHATSAPP.senderMobNum;
@@ -1139,8 +1139,7 @@ export class Edit extends React.Component { // eslint-disable-line react/prefer-
1139
1139
  this.props.globalActions.addMessageToQueue(message);
1140
1140
  } else {
1141
1141
  const name = data.file.name.split('.');
1142
- const blob = data.file.slice(0, -1, 'image');
1143
- const newFile = new File([blob], `${name[0]}${Date.now()}.${name[1]}`, {type: 'image'});
1142
+ const newFile = new File([data.file], `${name[0]}${Date.now()}.${name[1]}`, {type: 'image'});
1144
1143
  this.props.actions.uploadAsset(newFile, data.type, data.fileParams);
1145
1144
  }
1146
1145
  };