@capillarytech/creatives-library 9.0.55-alpha.2 → 9.0.55
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.
- package/.vscode/settings.json +3 -0
- package/constants/unified.js +1 -0
- package/package.json +1 -1
- package/services/api.js +0 -12
- package/utils/common.js +4 -0
- package/v2Components/CommonTestAndPreview/UnifiedPreview/index.js +0 -13
- package/v2Components/CommonTestAndPreview/constants.js +0 -2
- package/v2Components/CommonTestAndPreview/index.js +4 -1
- package/v2Components/CommonTestAndPreview/tests/UnifiedPreview/index.test.js +0 -106
- package/v2Components/CommonTestAndPreview/tests/constants.test.js +1 -9
- package/v2Containers/CommunicationFlow/CommunicationFlow.js +56 -109
- package/v2Containers/CommunicationFlow/CommunicationFlow.scss +1 -1
- package/v2Containers/CommunicationFlow/CommunicationFlowCard.js +6 -22
- package/v2Containers/CommunicationFlow/Tests/CommunicationFlow.test.js +49 -421
- package/v2Containers/CommunicationFlow/Tests/CommunicationFlowCard.test.js +2 -18
- package/v2Containers/CommunicationFlow/constants.js +4 -63
- package/v2Containers/CommunicationFlow/index.js +20 -15
- package/v2Containers/CommunicationFlow/messages.js +0 -4
- package/v2Containers/CommunicationFlow/steps/DeliverySettingsStep/SenderDetails.js +0 -6
- package/v2Containers/CommunicationFlow/steps/DeliverySettingsStep/Tests/SenderDetails.test.js +0 -25
- package/v2Containers/CommunicationFlow/steps/DeliverySettingsStep/Tests/deliverySettingsConfig.test.js +4 -11
- package/v2Containers/CommunicationFlow/steps/DeliverySettingsStep/deliverySettingsConfig.js +5 -19
- package/v2Containers/CreativesContainer/index.js +7 -1
- package/v2Containers/CreativesContainer/tests/__snapshots__/index.test.js.snap +5 -5
- package/v2Containers/Rcs/constants.js +1 -0
- package/v2Containers/Rcs/index.js +10 -1
- package/v2Containers/Rcs/tests/__snapshots__/index.test.js.snap +120 -12
- package/v2Containers/Rcs/tests/index.test.js +121 -0
- package/v2Containers/SmsTrai/Edit/tests/__snapshots__/index.test.js.snap +3 -3
- package/v2Containers/Templates/index.js +26 -0
- package/v2Containers/Whatsapp/tests/__snapshots__/index.test.js.snap +34 -34
- package/v2Containers/CommunicationFlow/Tests/constants.test.js +0 -85
package/constants/unified.js
CHANGED
|
@@ -63,6 +63,7 @@ export const ENABLE_AI_SUGGESTIONS = 'ENABLE_AI_SUGGESTIONS';
|
|
|
63
63
|
export const AI_CONTENT_BOT_DISABLED = 'AI_CONTENT_BOT_DISABLED';
|
|
64
64
|
export const AI_DOCUMENTATION_BOT_ENABLED = 'AI_DOCUMENTATION_BOT_ENABLED';
|
|
65
65
|
export const ENABLE_PRODUCT_SUPPORT_VIDEOS = 'ENABLE_PRODUCT_SUPPORT_VIDEOS';
|
|
66
|
+
export const SUPPORT_ENGAGEMENT_MODULE = 'SUPPORT_ENGAGEMENT_MODULE';
|
|
66
67
|
export const EMBEDDED = 'embedded';
|
|
67
68
|
// --- Tag/Validation Constants ---
|
|
68
69
|
export const CARD_RELATED_TAGS = [
|
package/package.json
CHANGED
package/services/api.js
CHANGED
|
@@ -701,18 +701,6 @@ export const createCentralCommsMetaId = (payload, metaType = TRANSACTION) => {
|
|
|
701
701
|
return request(url, getAPICallObject('POST', payload, false, false, false, true));
|
|
702
702
|
};
|
|
703
703
|
|
|
704
|
-
// CCS CommDefinition API (new Veyron /api/v1/commdefinition surface, proxied through cap-creatives-api /comm-definitions); used by CommunicationFlow's Save, while legacy messageMeta functions remain for CreativesContainer's save flow (Cap/sagas.js).
|
|
705
|
-
export const createCommDefinition = (payload) => {
|
|
706
|
-
const url = `${API_ENDPOINT}/comm-definitions`;
|
|
707
|
-
return request(url, getAPICallObject('POST', payload, false, false, false, true));
|
|
708
|
-
};
|
|
709
|
-
|
|
710
|
-
// Opens a new DRAFT version with the supplied content on an existing CommDefinition (same id/referenceId); used by CommunicationFlow edit-mode saves to preserve the alert's identity instead of creating a new CommDefinition. Route verified against Veyron's /commdefinition/{id}/edit endpoint.
|
|
711
|
-
export const editCommDefinition = (commDefinitionId, payload) => {
|
|
712
|
-
const url = `${API_ENDPOINT}/comm-definitions/${commDefinitionId}/edit`;
|
|
713
|
-
return request(url, getAPICallObject('POST', payload, false, false, false, true));
|
|
714
|
-
};
|
|
715
|
-
|
|
716
704
|
export const getCentralCommsMetaIds = (metaIds, metaType = TRANSACTION) => {
|
|
717
705
|
const url = `${API_ENDPOINT}/common/central-comms/meta-id/${metaType}?metaIds=${metaIds}`;
|
|
718
706
|
return request(url, getAPICallObject('GET', null, false, false, false, true));
|
package/utils/common.js
CHANGED
|
@@ -99,6 +99,10 @@ export const hasSupportCKEditor = Auth.hasFeatureAccess.bind(
|
|
|
99
99
|
null,
|
|
100
100
|
SUPPORT_CK_EDITOR,
|
|
101
101
|
);
|
|
102
|
+
export const hasSupportEngagementModule = Auth.hasFeatureAccess.bind(
|
|
103
|
+
null,
|
|
104
|
+
SUPPORT_ENGAGEMENT_MODULE,
|
|
105
|
+
);
|
|
102
106
|
|
|
103
107
|
export const hasGiftVoucherFeature = Auth.hasFeatureAccess.bind(
|
|
104
108
|
null,
|
|
@@ -139,19 +139,6 @@ const UnifiedPreview = ({
|
|
|
139
139
|
);
|
|
140
140
|
}
|
|
141
141
|
|
|
142
|
-
case CHANNELS.LINE:
|
|
143
|
-
// LINE currently carries a single text message; CCS stores lineMessageContent.messageBody as JSON for LINE's native messages[] (see testAndPreviewDataTransform.js), already reduced to plain text before this point, so reuse the SMS chat-bubble preview. Rich LINE types (image/video/sticker/imageMap/carousel/flex) are not specially rendered yet.
|
|
144
|
-
return (
|
|
145
|
-
<SmsPreviewContent
|
|
146
|
-
content={typeof content === 'string' ? content : (content?.resolvedBody || '')}
|
|
147
|
-
device={device}
|
|
148
|
-
isUpdating={isUpdating}
|
|
149
|
-
error={error}
|
|
150
|
-
formatMessage={formatMessage}
|
|
151
|
-
showHeader={showHeader}
|
|
152
|
-
/>
|
|
153
|
-
);
|
|
154
|
-
|
|
155
142
|
case CHANNELS.WHATSAPP: {
|
|
156
143
|
// WhatsApp content is an object with templateMsg, media, CTA, etc.
|
|
157
144
|
const whatsappContent = typeof content === 'object' ? content : {};
|
|
@@ -85,7 +85,6 @@ export const CHANNELS = {
|
|
|
85
85
|
VIBER: 'VIBER',
|
|
86
86
|
ZALO: 'ZALO',
|
|
87
87
|
WEBPUSH: 'WEBPUSH',
|
|
88
|
-
LINE: 'LINE',
|
|
89
88
|
};
|
|
90
89
|
|
|
91
90
|
/** Unified preview tab keys when RCS shows RCS + SMS fallback panes. */
|
|
@@ -101,7 +100,6 @@ export const CHANNELS_USING_ANDROID_PREVIEW_DEVICE = [
|
|
|
101
100
|
CHANNELS.INAPP,
|
|
102
101
|
CHANNELS.MOBILEPUSH,
|
|
103
102
|
CHANNELS.VIBER,
|
|
104
|
-
CHANNELS.LINE,
|
|
105
103
|
];
|
|
106
104
|
|
|
107
105
|
/** RCS createMessageMeta test payload — rich card envelope literals. */
|
|
@@ -1275,6 +1275,7 @@ const CommonTestAndPreview = (props) => {
|
|
|
1275
1275
|
...(suggestionsFormattedForTestMeta.length > 0 && {
|
|
1276
1276
|
suggestions: suggestionsFormattedForTestMeta,
|
|
1277
1277
|
}),
|
|
1278
|
+
...(singleRcsCardPayload?.cardVarMapped && { cardVarMapped: singleRcsCardPayload.cardVarMapped }),
|
|
1278
1279
|
};
|
|
1279
1280
|
});
|
|
1280
1281
|
// Use the component-level smsFallbackContent prop (has rcsSmsFallbackVarMapped) so DLT
|
|
@@ -1341,9 +1342,11 @@ const CommonTestAndPreview = (props) => {
|
|
|
1341
1342
|
...(cardContentForTestMetaApi.length > 0 && { cardContent: cardContentForTestMetaApi }),
|
|
1342
1343
|
};
|
|
1343
1344
|
|
|
1345
|
+
const vfTemplateId = rcsContentFromForm?.vfTemplateId;
|
|
1344
1346
|
const rcsMessageContent = {
|
|
1345
1347
|
channel: CHANNELS.RCS,
|
|
1346
1348
|
...(accountIdForMeta && { accountId: accountIdForMeta }),
|
|
1349
|
+
...(vfTemplateId && { templateId: vfTemplateId }),
|
|
1347
1350
|
rcsRichCardContent,
|
|
1348
1351
|
...(smsFallBackContent && { smsFallBackContent }),
|
|
1349
1352
|
};
|
|
@@ -3813,7 +3816,7 @@ const CommonTestAndPreview = (props) => {
|
|
|
3813
3816
|
header={slideboxHeader}
|
|
3814
3817
|
handleClose={handleClose}
|
|
3815
3818
|
show={show}
|
|
3816
|
-
size="size-
|
|
3819
|
+
size="size-xl"
|
|
3817
3820
|
content={(
|
|
3818
3821
|
<CapSpin
|
|
3819
3822
|
spinning={isCustomerDataLoading}
|
|
@@ -479,112 +479,6 @@ describe('UnifiedPreview', () => {
|
|
|
479
479
|
});
|
|
480
480
|
});
|
|
481
481
|
|
|
482
|
-
describe('Channel Routing - LINE', () => {
|
|
483
|
-
it('should render SmsPreviewContent for LINE channel with string content', () => {
|
|
484
|
-
const props = {
|
|
485
|
-
...defaultProps,
|
|
486
|
-
channel: CHANNELS.LINE,
|
|
487
|
-
content: 'Hello world',
|
|
488
|
-
};
|
|
489
|
-
|
|
490
|
-
render(
|
|
491
|
-
<TestWrapper>
|
|
492
|
-
<ComponentToRender {...props} />
|
|
493
|
-
</TestWrapper>
|
|
494
|
-
);
|
|
495
|
-
|
|
496
|
-
expect(screen.getByTestId('sms-preview')).toBeTruthy();
|
|
497
|
-
expect(screen.getByTestId('sms-content')).toHaveTextContent('Hello world');
|
|
498
|
-
});
|
|
499
|
-
|
|
500
|
-
it('should handle object content with resolvedBody for LINE channel', () => {
|
|
501
|
-
const props = {
|
|
502
|
-
...defaultProps,
|
|
503
|
-
channel: CHANNELS.LINE,
|
|
504
|
-
content: {
|
|
505
|
-
resolvedBody: 'some text',
|
|
506
|
-
},
|
|
507
|
-
};
|
|
508
|
-
|
|
509
|
-
render(
|
|
510
|
-
<TestWrapper>
|
|
511
|
-
<ComponentToRender {...props} />
|
|
512
|
-
</TestWrapper>
|
|
513
|
-
);
|
|
514
|
-
|
|
515
|
-
expect(screen.getByTestId('sms-preview')).toBeTruthy();
|
|
516
|
-
expect(screen.getByTestId('sms-content')).toHaveTextContent('some text');
|
|
517
|
-
});
|
|
518
|
-
|
|
519
|
-
it('should not crash and render empty content for LINE channel when content is undefined', () => {
|
|
520
|
-
const props = {
|
|
521
|
-
...defaultProps,
|
|
522
|
-
channel: CHANNELS.LINE,
|
|
523
|
-
content: undefined,
|
|
524
|
-
};
|
|
525
|
-
|
|
526
|
-
render(
|
|
527
|
-
<TestWrapper>
|
|
528
|
-
<ComponentToRender {...props} />
|
|
529
|
-
</TestWrapper>
|
|
530
|
-
);
|
|
531
|
-
|
|
532
|
-
expect(screen.getByTestId('sms-preview')).toBeTruthy();
|
|
533
|
-
expect(screen.getByTestId('sms-content')).toHaveTextContent('');
|
|
534
|
-
});
|
|
535
|
-
|
|
536
|
-
it('should not crash and render empty content for LINE channel when content is null', () => {
|
|
537
|
-
const props = {
|
|
538
|
-
...defaultProps,
|
|
539
|
-
channel: CHANNELS.LINE,
|
|
540
|
-
content: null,
|
|
541
|
-
};
|
|
542
|
-
|
|
543
|
-
render(
|
|
544
|
-
<TestWrapper>
|
|
545
|
-
<ComponentToRender {...props} />
|
|
546
|
-
</TestWrapper>
|
|
547
|
-
);
|
|
548
|
-
|
|
549
|
-
expect(screen.getByTestId('sms-preview')).toBeTruthy();
|
|
550
|
-
expect(screen.getByTestId('sms-content')).toHaveTextContent('');
|
|
551
|
-
});
|
|
552
|
-
|
|
553
|
-
it('should render empty content for LINE channel when content is not a string and has no resolvedBody', () => {
|
|
554
|
-
const props = {
|
|
555
|
-
...defaultProps,
|
|
556
|
-
channel: CHANNELS.LINE,
|
|
557
|
-
content: { someOtherField: 'value' },
|
|
558
|
-
};
|
|
559
|
-
|
|
560
|
-
render(
|
|
561
|
-
<TestWrapper>
|
|
562
|
-
<ComponentToRender {...props} />
|
|
563
|
-
</TestWrapper>
|
|
564
|
-
);
|
|
565
|
-
|
|
566
|
-
expect(screen.getByTestId('sms-preview')).toBeTruthy();
|
|
567
|
-
expect(screen.getByTestId('sms-content')).toHaveTextContent('');
|
|
568
|
-
});
|
|
569
|
-
|
|
570
|
-
it('should not render the Unknown Channel fallback for LINE channel', () => {
|
|
571
|
-
const props = {
|
|
572
|
-
...defaultProps,
|
|
573
|
-
channel: CHANNELS.LINE,
|
|
574
|
-
content: 'Hello world',
|
|
575
|
-
};
|
|
576
|
-
|
|
577
|
-
render(
|
|
578
|
-
<TestWrapper>
|
|
579
|
-
<ComponentToRender {...props} />
|
|
580
|
-
</TestWrapper>
|
|
581
|
-
);
|
|
582
|
-
|
|
583
|
-
expect(screen.queryByText('Unknown Channel')).toBeNull();
|
|
584
|
-
expect(screen.getByTestId('sms-preview')).toBeTruthy();
|
|
585
|
-
});
|
|
586
|
-
});
|
|
587
|
-
|
|
588
482
|
describe('Channel Routing - WHATSAPP', () => {
|
|
589
483
|
it('should render WhatsAppPreviewContent for WHATSAPP channel', () => {
|
|
590
484
|
const props = {
|
|
@@ -42,7 +42,6 @@ import {
|
|
|
42
42
|
CLEAR_PREVIEW_ERRORS,
|
|
43
43
|
// Channel Constants
|
|
44
44
|
CHANNELS,
|
|
45
|
-
CHANNELS_USING_ANDROID_PREVIEW_DEVICE,
|
|
46
45
|
// Device Constants
|
|
47
46
|
DESKTOP,
|
|
48
47
|
MOBILE,
|
|
@@ -181,22 +180,15 @@ describe('CommonTestAndPreview Constants', () => {
|
|
|
181
180
|
expect(CHANNELS.VIBER).toBe('VIBER');
|
|
182
181
|
expect(CHANNELS.ZALO).toBe('ZALO');
|
|
183
182
|
expect(CHANNELS.WEBPUSH).toBe('WEBPUSH');
|
|
184
|
-
expect(CHANNELS.LINE).toBe('LINE');
|
|
185
183
|
});
|
|
186
184
|
|
|
187
185
|
it('should have all required channel keys', () => {
|
|
188
|
-
const expectedChannels = ['EMAIL', 'SMS', 'RCS', 'WHATSAPP', 'INAPP', 'MOBILEPUSH', 'VIBER', 'ZALO', 'WEBPUSH'
|
|
186
|
+
const expectedChannels = ['EMAIL', 'SMS', 'RCS', 'WHATSAPP', 'INAPP', 'MOBILEPUSH', 'VIBER', 'ZALO', 'WEBPUSH'];
|
|
189
187
|
expect(Object.keys(CHANNELS)).toEqual(expect.arrayContaining(expectedChannels));
|
|
190
188
|
expect(Object.keys(CHANNELS).length).toBe(expectedChannels.length);
|
|
191
189
|
});
|
|
192
190
|
});
|
|
193
191
|
|
|
194
|
-
describe('CHANNELS_USING_ANDROID_PREVIEW_DEVICE', () => {
|
|
195
|
-
it('should include CHANNELS.LINE', () => {
|
|
196
|
-
expect(CHANNELS_USING_ANDROID_PREVIEW_DEVICE).toContain(CHANNELS.LINE);
|
|
197
|
-
});
|
|
198
|
-
});
|
|
199
|
-
|
|
200
192
|
describe('Device Constants', () => {
|
|
201
193
|
it('should export all device constants with correct values', () => {
|
|
202
194
|
expect(DESKTOP).toBe('desktop');
|
|
@@ -17,11 +17,10 @@ import { createStructuredSelector } from 'reselect';
|
|
|
17
17
|
import CapRow from '@capillarytech/cap-ui-library/CapRow';
|
|
18
18
|
import CapDivider from '@capillarytech/cap-ui-library/CapDivider';
|
|
19
19
|
import CapButton from '@capillarytech/cap-ui-library/CapButton';
|
|
20
|
-
import CapLabel from '@capillarytech/cap-ui-library/CapLabel';
|
|
21
20
|
// import injectSaga from '../../utils/injectSaga'; // cap-coupons flows disabled
|
|
22
21
|
// import injectReducer from '../../utils/injectReducer';
|
|
23
22
|
import { makeSelectAuthenticated } from '../Cap/selectors';
|
|
24
|
-
import {
|
|
23
|
+
import { createCentralCommsMetaId, getCentralCommsMetaIds } from '../../services/api';
|
|
25
24
|
import DynamicControlsStep from './steps/DynamicControlsStep';
|
|
26
25
|
import MessageTypeStep from './steps/MessageTypeStep';
|
|
27
26
|
import CommunicationStrategyStep from './steps/CommunicationStrategyStep';
|
|
@@ -36,11 +35,9 @@ import {
|
|
|
36
35
|
CHANNELS,
|
|
37
36
|
INCENTIVE_TYPES,
|
|
38
37
|
DYNAMIC_CONTROLS_CONFIG,
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
CCS_CHANNEL_NAME_MAP,
|
|
43
|
-
CCS_CONTENT_TRANSFORMS,
|
|
38
|
+
CHANNEL_CONTENT_KEY_MAP,
|
|
39
|
+
CHANNEL_DELIVERY_KEY_MAP,
|
|
40
|
+
CAMPAIGNS,
|
|
44
41
|
} from './constants';
|
|
45
42
|
import { getEnabledSteps } from './utils/getEnabledSteps';
|
|
46
43
|
import messages from './messages';
|
|
@@ -67,21 +64,6 @@ const hasDeliverySettingForChannel = (channelSetting, channel) => {
|
|
|
67
64
|
return !!settings && Object.values(settings).some((v) => v !== null && v !== '' && v !== undefined);
|
|
68
65
|
};
|
|
69
66
|
|
|
70
|
-
// createCommDefinition resolves with the CCS error envelope for 4xx/5xx responses (see api.js request()/checkStatus); duplicate referenceId within the org returns a 409.
|
|
71
|
-
const isDuplicateReferenceIdError = (res) => res?.success === false && res?.status?.message === 'REFERENCE_ID_EXISTS';
|
|
72
|
-
|
|
73
|
-
/**
|
|
74
|
-
* CCS requires referenceId on create, while consumers require only the Alert/comm name; generate a stable fallback from the name when referenceId is omitted instead of failing the save.
|
|
75
|
-
*/
|
|
76
|
-
const buildCcsReferenceId = (name) => {
|
|
77
|
-
const slug = (name || 'COMM')
|
|
78
|
-
.trim()
|
|
79
|
-
.toUpperCase()
|
|
80
|
-
.replace(/[^A-Z0-9]+/g, '_')
|
|
81
|
-
.replace(/^_+|_+$/g, '') || 'COMM';
|
|
82
|
-
return `${slug}_${Date.now()}`;
|
|
83
|
-
};
|
|
84
|
-
|
|
85
67
|
const CommunicationFlow = ({
|
|
86
68
|
config,
|
|
87
69
|
initialData,
|
|
@@ -109,7 +91,6 @@ const CommunicationFlow = ({
|
|
|
109
91
|
};
|
|
110
92
|
});
|
|
111
93
|
const [validationErrors, setValidationErrors] = useState({});
|
|
112
|
-
const [saveError, setSaveError] = useState(null);
|
|
113
94
|
|
|
114
95
|
// Memoize enabled steps
|
|
115
96
|
const enabledSteps = useMemo(() => getEnabledSteps(config), [config]);
|
|
@@ -169,103 +150,74 @@ const CommunicationFlow = ({
|
|
|
169
150
|
}, []);
|
|
170
151
|
|
|
171
152
|
const handleSave = useCallback(async () => {
|
|
172
|
-
setSaveError(null);
|
|
173
153
|
const aggregatedData = getAggregatedData();
|
|
174
154
|
const shouldUseCCS = config?.useCCS !== false;
|
|
175
|
-
let ccsCommDefinition = null;
|
|
176
155
|
|
|
177
156
|
if (shouldUseCCS) {
|
|
178
|
-
const
|
|
179
|
-
const
|
|
180
|
-
|
|
181
|
-
// has no name input of its own, so this is mandatory input from config.context.
|
|
182
|
-
const name = config?.context?.name;
|
|
157
|
+
const ouId = config?.context?.ouId || -1;
|
|
158
|
+
const module = config?.context?.module
|
|
159
|
+
|| (config?.consumer ? config.consumer.toUpperCase() : CAMPAIGNS);
|
|
183
160
|
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
if (!isMultiChannel && contentItem && name) {
|
|
187
|
-
const rawChannel = (contentItem.channel || '').toUpperCase();
|
|
188
|
-
const channel = CCS_CHANNEL_NAME_MAP[rawChannel] || rawChannel;
|
|
189
|
-
const contentKey = CCS_CHANNEL_CONTENT_KEY_MAP[channel];
|
|
190
|
-
const deliveryKey = CCS_CHANNEL_DELIVERY_KEY_MAP[channel];
|
|
191
|
-
const contentTransform = CCS_CONTENT_TRANSFORMS[channel];
|
|
192
|
-
const contentPayload = contentTransform ? contentTransform(contentItem.templateData) : contentItem.templateData;
|
|
193
|
-
const { dynamicControls = {} } = aggregatedData;
|
|
194
|
-
const channelSettings = aggregatedData.deliverySetting?.channelSetting?.[channel] || {};
|
|
195
|
-
const referenceId = config?.context?.referenceId || buildCcsReferenceId(name);
|
|
161
|
+
const channelContentKeyMap = CHANNEL_CONTENT_KEY_MAP;
|
|
162
|
+
const channelDeliveryKeyMap = CHANNEL_DELIVERY_KEY_MAP;
|
|
196
163
|
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
name,
|
|
200
|
-
description: config?.context?.description || undefined,
|
|
201
|
-
strategyType: CCS_STRATEGY_TYPE_SINGLE,
|
|
202
|
-
settings: {
|
|
203
|
-
additionalSettings: {
|
|
204
|
-
useTinyUrl: dynamicControls.useTinyUrl ?? false,
|
|
205
|
-
encryptUrl: dynamicControls.sendToControlCustomers ?? false,
|
|
206
|
-
linkTrackingEnabled: dynamicControls.overrideDailyLimit ?? false,
|
|
207
|
-
userSubscriptionDisabled: dynamicControls.sendToBrandPocs ?? false,
|
|
208
|
-
},
|
|
209
|
-
executionParams: {},
|
|
210
|
-
},
|
|
211
|
-
singleChannelStrategy: {
|
|
212
|
-
variant: {
|
|
213
|
-
channel,
|
|
214
|
-
// `channel` must be spread last in both objects so CCS's normalized enum (e.g. `PUSH`) overrides the UI's internal identifier (e.g. `MOBILEPUSH`) from templateData.
|
|
215
|
-
...(contentKey && { [contentKey]: { ...contentPayload, channel } }),
|
|
216
|
-
...(deliveryKey && { [deliveryKey]: { channelSettings: { ...channelSettings, channel } } }),
|
|
217
|
-
},
|
|
218
|
-
},
|
|
219
|
-
};
|
|
164
|
+
const contentItems = aggregatedData.contentItems || [];
|
|
165
|
+
const { dynamicControls = {} } = aggregatedData;
|
|
220
166
|
|
|
221
|
-
|
|
222
|
-
|
|
167
|
+
const additionalSettings = {
|
|
168
|
+
useTinyUrl: dynamicControls.useTinyUrl ?? false,
|
|
169
|
+
encryptUrl: dynamicControls.sendToControlCustomers ?? false,
|
|
170
|
+
linkTrackingEnabled: dynamicControls.overrideDailyLimit ?? false,
|
|
171
|
+
userSubscriptionDisabled: dynamicControls.sendToBrandPocs ?? false,
|
|
172
|
+
};
|
|
223
173
|
|
|
174
|
+
if (contentItems.length > 0) {
|
|
224
175
|
try {
|
|
225
|
-
const
|
|
226
|
-
|
|
227
|
-
|
|
228
|
-
|
|
229
|
-
|
|
230
|
-
|
|
231
|
-
|
|
232
|
-
|
|
233
|
-
|
|
234
|
-
|
|
235
|
-
|
|
236
|
-
|
|
237
|
-
|
|
238
|
-
|
|
239
|
-
|
|
240
|
-
|
|
241
|
-
|
|
242
|
-
|
|
243
|
-
|
|
244
|
-
|
|
245
|
-
|
|
176
|
+
const responses = await Promise.all(
|
|
177
|
+
contentItems.map((item) => {
|
|
178
|
+
const channel = (item.channel || '').toUpperCase();
|
|
179
|
+
const contentKey = channelContentKeyMap[channel];
|
|
180
|
+
const deliveryKey = channelDeliveryKeyMap[channel];
|
|
181
|
+
const payload = {
|
|
182
|
+
centralCommsPayload: {
|
|
183
|
+
ouId,
|
|
184
|
+
channel,
|
|
185
|
+
module,
|
|
186
|
+
executionParams: {},
|
|
187
|
+
clientName: 'EMF',
|
|
188
|
+
...(contentKey && {
|
|
189
|
+
[contentKey]: { channel, ...item.templateData },
|
|
190
|
+
}),
|
|
191
|
+
...(deliveryKey && {
|
|
192
|
+
[deliveryKey]: {
|
|
193
|
+
additionalSettings,
|
|
194
|
+
channelSettings: {
|
|
195
|
+
channel,
|
|
196
|
+
...(aggregatedData.deliverySetting?.channelSetting?.[channel] || {}),
|
|
197
|
+
},
|
|
198
|
+
},
|
|
199
|
+
}),
|
|
200
|
+
},
|
|
246
201
|
};
|
|
247
|
-
|
|
248
|
-
|
|
249
|
-
|
|
250
|
-
|
|
251
|
-
|
|
252
|
-
|
|
253
|
-
|
|
254
|
-
|
|
202
|
+
return createCentralCommsMetaId(payload);
|
|
203
|
+
}),
|
|
204
|
+
);
|
|
205
|
+
|
|
206
|
+
const metaIds = responses
|
|
207
|
+
.map((res) => res?.response?.data?.id)
|
|
208
|
+
.filter(Boolean)
|
|
209
|
+
.join(',');
|
|
210
|
+
|
|
211
|
+
if (metaIds) {
|
|
212
|
+
const getResponse = await getCentralCommsMetaIds(metaIds);
|
|
255
213
|
}
|
|
256
214
|
} catch (error) {
|
|
257
|
-
console.error('[CommunicationFlow] CCS
|
|
215
|
+
console.error('[CommunicationFlow] CCS createCentralCommsMetaId error:', error);
|
|
258
216
|
}
|
|
259
|
-
} else if (!name) {
|
|
260
|
-
console.warn('[CommunicationFlow] Skipping CCS createCommDefinition — config.context.name is required');
|
|
261
|
-
} else if (isMultiChannel) {
|
|
262
|
-
console.warn('[CommunicationFlow] Skipping CCS createCommDefinition — CHANNEL_PRIORITY/AB_TEST strategies are not supported by CCS create yet (SINGLE only)');
|
|
263
|
-
} else if (!contentItem) {
|
|
264
|
-
console.warn('[CommunicationFlow] Skipping CCS createCommDefinition — no content item found (contentItems is empty)');
|
|
265
217
|
}
|
|
266
218
|
}
|
|
267
219
|
|
|
268
|
-
onSave(
|
|
220
|
+
onSave(aggregatedData);
|
|
269
221
|
}, [getAggregatedData, config, onSave]);
|
|
270
222
|
|
|
271
223
|
// Call onChange callback when stepData changes
|
|
@@ -365,11 +317,6 @@ const CommunicationFlow = ({
|
|
|
365
317
|
{renderSteps()}
|
|
366
318
|
{onSave && (
|
|
367
319
|
<CapRow useLegacy className="communication-flow-container__footer">
|
|
368
|
-
{saveError && (
|
|
369
|
-
<CapLabel type="label2" className="communication-flow-container__save-error">
|
|
370
|
-
{saveError}
|
|
371
|
-
</CapLabel>
|
|
372
|
-
)}
|
|
373
320
|
<CapButton type="primary" onClick={handleSave} disabled={isSaveDisabled}>
|
|
374
321
|
{formatMessage(messages.save)}
|
|
375
322
|
</CapButton>
|
|
@@ -19,7 +19,6 @@ import CapIcon from '@capillarytech/cap-ui-library/CapIcon';
|
|
|
19
19
|
import CapLabel from '@capillarytech/cap-ui-library/CapLabel';
|
|
20
20
|
import CapHeader from '@capillarytech/cap-ui-library/CapHeader';
|
|
21
21
|
import CapSlideBox from '@capillarytech/cap-ui-library/CapSlideBox';
|
|
22
|
-
import CapTooltip from '@capillarytech/cap-ui-library/CapTooltip';
|
|
23
22
|
import CommunicationFlow from './index';
|
|
24
23
|
import { CHANNELS, DEFAULT_COMMUNICATION_STRATEGY_OPTIONS, DYNAMIC_CONTROLS_CONFIG } from './constants';
|
|
25
24
|
import {
|
|
@@ -42,7 +41,7 @@ const resolveValue = (val) => {
|
|
|
42
41
|
|
|
43
42
|
const SENDER_ID_RESOLVERS = {
|
|
44
43
|
[SMS]: (setting) => resolveValue(setting?.gsmSenderId),
|
|
45
|
-
[EMAIL]: (setting) => resolveValue(setting?.
|
|
44
|
+
[EMAIL]: (setting) => resolveValue(setting?.senderEmail),
|
|
46
45
|
[VIBER]: (setting) => resolveValue(setting?.sender) || resolveValue(setting?.gsmSenderId),
|
|
47
46
|
[WHATSAPP]: (setting) => resolveValue(setting?.senderMobNum),
|
|
48
47
|
[RCS]: (setting) => resolveValue(setting?.senderMobNum) || resolveValue(setting?.rcsSender),
|
|
@@ -75,8 +74,6 @@ const CommunicationFlowCard = ({
|
|
|
75
74
|
onChange,
|
|
76
75
|
cap,
|
|
77
76
|
intl,
|
|
78
|
-
disabled,
|
|
79
|
-
disabledTooltip,
|
|
80
77
|
}) => {
|
|
81
78
|
const { formatMessage } = intl || {};
|
|
82
79
|
const [showSlideBox, setShowSlideBox] = useState(false);
|
|
@@ -94,9 +91,8 @@ const CommunicationFlowCard = ({
|
|
|
94
91
|
}, [onCancel]);
|
|
95
92
|
|
|
96
93
|
const handleOpen = useCallback(() => {
|
|
97
|
-
if (disabled) return;
|
|
98
94
|
setShowSlideBox(true);
|
|
99
|
-
}, [
|
|
95
|
+
}, []);
|
|
100
96
|
|
|
101
97
|
const firstItem = savedData?.contentItems?.[0];
|
|
102
98
|
const channelConfig = firstItem
|
|
@@ -186,17 +182,9 @@ const CommunicationFlowCard = ({
|
|
|
186
182
|
<CapImage src={addCreativesIllustration} />
|
|
187
183
|
</CapColumn>
|
|
188
184
|
<CapColumn span={14} className="empty-card-action-col">
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
{formatMessage(messages.addCreatives)}
|
|
193
|
-
</CapButton>
|
|
194
|
-
</CapTooltip>
|
|
195
|
-
) : (
|
|
196
|
-
<CapButton type="secondary" onClick={handleOpen} disabled={disabled}>
|
|
197
|
-
{formatMessage(messages.addCreatives)}
|
|
198
|
-
</CapButton>
|
|
199
|
-
)}
|
|
185
|
+
<CapButton type="secondary" onClick={handleOpen}>
|
|
186
|
+
{formatMessage(messages.addCreatives)}
|
|
187
|
+
</CapButton>
|
|
200
188
|
</CapColumn>
|
|
201
189
|
</CapRow>
|
|
202
190
|
</CapCard>
|
|
@@ -208,7 +196,7 @@ const CommunicationFlowCard = ({
|
|
|
208
196
|
<CapSlideBox
|
|
209
197
|
show={showSlideBox}
|
|
210
198
|
handleClose={handleClose}
|
|
211
|
-
size="size-
|
|
199
|
+
size="size-xl"
|
|
212
200
|
header={(
|
|
213
201
|
<CapHeader
|
|
214
202
|
title={formatMessage(messages.addMessage)}
|
|
@@ -239,8 +227,6 @@ CommunicationFlowCard.propTypes = {
|
|
|
239
227
|
onChange: PropTypes.func,
|
|
240
228
|
cap: PropTypes.object,
|
|
241
229
|
intl: PropTypes.object.isRequired,
|
|
242
|
-
disabled: PropTypes.bool, // Disables the "Add creatives" trigger (e.g. until a consumer-required field is filled)
|
|
243
|
-
disabledTooltip: PropTypes.node, // Shown on hover when disabled is true
|
|
244
230
|
};
|
|
245
231
|
|
|
246
232
|
CommunicationFlowCard.defaultProps = {
|
|
@@ -249,8 +235,6 @@ CommunicationFlowCard.defaultProps = {
|
|
|
249
235
|
onCancel: null,
|
|
250
236
|
onChange: null,
|
|
251
237
|
cap: null,
|
|
252
|
-
disabled: false,
|
|
253
|
-
disabledTooltip: null,
|
|
254
238
|
};
|
|
255
239
|
|
|
256
240
|
export default injectIntl(CommunicationFlowCard);
|