@capillarytech/creatives-library 9.0.56-alpha.7 → 9.0.56-betaa.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.
- package/constants/unified.js +4 -2
- package/package.json +1 -1
- package/services/api.js +0 -20
- package/utils/common.js +12 -0
- package/utils/templateVarUtils.js +0 -16
- package/utils/tests/templateVarUtils.test.js +0 -44
- package/v2Components/CommonTestAndPreview/UnifiedPreview/index.js +0 -13
- package/v2Components/CommonTestAndPreview/actions.js +0 -13
- package/v2Components/CommonTestAndPreview/constants.js +0 -8
- package/v2Components/CommonTestAndPreview/index.js +3 -55
- package/v2Components/CommonTestAndPreview/reducer.js +0 -20
- package/v2Components/CommonTestAndPreview/sagas.js +0 -28
- package/v2Components/CommonTestAndPreview/selectors.js +0 -6
- package/v2Components/CommonTestAndPreview/tests/UnifiedPreview/index.test.js +0 -106
- package/v2Components/CommonTestAndPreview/tests/actions.test.js +0 -15
- package/v2Components/CommonTestAndPreview/tests/constants.test.js +1 -9
- package/v2Components/CommonTestAndPreview/tests/index.test.js +0 -101
- package/v2Components/CommonTestAndPreview/tests/reducer.test.js +0 -41
- package/v2Components/CommonTestAndPreview/tests/sagas.test.js +0 -84
- package/v2Components/CommonTestAndPreview/tests/selectors.test.js +0 -12
- package/v2Components/FormBuilder/Functional/FormBuilderShell.js +320 -46
- package/v2Components/FormBuilder/Functional/channels/mobilepush/buildSubmitPayload.js +10 -0
- package/v2Components/FormBuilder/Functional/channels/mobilepush/config.js +82 -0
- package/v2Components/FormBuilder/Functional/channels/mobilepush/getEditorErrorDescriptor.js +74 -0
- package/v2Components/FormBuilder/Functional/channels/mobilepush/index.js +28 -0
- package/v2Components/FormBuilder/Functional/channels/mobilepush/modals.js +19 -0
- package/v2Components/FormBuilder/Functional/channels/mobilepush/runSubmitPipeline.js +45 -0
- package/v2Components/FormBuilder/Functional/channels/mobilepush/tests/getEditorErrorDescriptor.test.js +162 -0
- package/v2Components/FormBuilder/Functional/channels/mobilepush/tests/modals.test.js +37 -0
- package/v2Components/FormBuilder/Functional/channels/mobilepush/tests/runSubmitPipeline.test.js +70 -0
- package/v2Components/FormBuilder/Functional/channels/mobilepush/tests/validate.test.js +274 -0
- package/v2Components/FormBuilder/Functional/channels/mobilepush/validate.js +251 -0
- package/v2Components/FormBuilder/Functional/channels/registry.js +2 -0
- package/v2Components/FormBuilder/Functional/constants.js +43 -8
- package/v2Components/FormBuilder/Functional/core/schema/initializeFormState.js +175 -28
- package/v2Components/FormBuilder/Functional/core/store/formReducer.js +75 -6
- package/v2Components/FormBuilder/Functional/core/store/toLegacyFormData.js +10 -20
- package/v2Components/FormBuilder/Functional/layout/FieldSlot.js +9 -1
- package/v2Components/FormBuilder/Functional/layout/SchemaForm.js +20 -3
- package/v2Components/FormBuilder/Functional/layout/Section.js +6 -1
- package/v2Components/FormBuilder/Functional/layout/TabsContainer.js +89 -0
- package/v2Components/FormBuilder/Functional/renderers/mpushRenderers.js +440 -0
- package/v2Components/FormBuilder/Functional/tests/fieldSlot.test.js +9 -2
- package/v2Components/FormBuilder/Functional/tests/mpush.crossFlowParity.test.js +430 -0
- package/v2Components/FormBuilder/Functional/tests/mpush.ctaFlows.parity.test.js +282 -0
- package/v2Components/FormBuilder/Functional/tests/mpush.editContainer.parity.test.js +141 -0
- package/v2Components/FormBuilder/Functional/tests/mpush.engine.test.js +306 -0
- package/v2Components/FormBuilder/Functional/tests/mpush.shellEvents.test.js +151 -0
- package/v2Components/FormBuilder/Functional/tests/mpushRenderers.test.js +342 -0
- package/v2Components/FormBuilder/Functional/tests/schemaForm.test.js +17 -0
- package/v2Components/FormBuilder/Functional/tests/tabsContainer.test.js +110 -0
- package/v2Components/FormBuilder/index.js +34 -12
- package/v2Components/FormBuilder/tests/entryGate.test.js +94 -7
- package/v2Components/FormBuilder/tests/mpush.characterization.test.js +459 -0
- package/v2Components/TestAndPreviewSlidebox/index.js +0 -9
- package/v2Containers/CommunicationFlow/CommunicationFlow.js +75 -140
- package/v2Containers/CommunicationFlow/CommunicationFlow.scss +2 -18
- package/v2Containers/CommunicationFlow/CommunicationFlowCard.js +27 -58
- package/v2Containers/CommunicationFlow/Tests/CommunicationFlow.test.js +51 -503
- package/v2Containers/CommunicationFlow/Tests/CommunicationFlowCard.test.js +4 -40
- package/v2Containers/CommunicationFlow/constants.js +4 -65
- package/v2Containers/CommunicationFlow/index.js +23 -16
- package/v2Containers/CommunicationFlow/messages.js +3 -11
- package/v2Containers/CommunicationFlow/steps/ChannelSelectionStep/ChannelSelectionStep.js +11 -24
- package/v2Containers/CommunicationFlow/steps/ChannelSelectionStep/ChannelSelectionStep.scss +0 -4
- package/v2Containers/CommunicationFlow/steps/ChannelSelectionStep/Tests/ChannelSelectionStep.test.js +4 -176
- package/v2Containers/CommunicationFlow/steps/DeliverySettingsStep/DeliverySettingsSection.js +0 -3
- 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 +3 -2
- package/v2Containers/CreativesContainer/tests/__snapshots__/index.test.js.snap +5 -5
- package/v2Containers/CreativesContainer/tests/index.test.js +0 -12
- package/v2Containers/Rcs/tests/__snapshots__/index.test.js.snap +19 -115
- package/v2Containers/SmsTrai/Edit/tests/__snapshots__/index.test.js.snap +3 -27
- package/v2Containers/WebPush/Create/preview/WebPushPreview.js +12 -17
- package/v2Containers/WebPush/Create/preview/tests/WebPushPreview.test.js +0 -5
- package/v2Containers/Whatsapp/index.js +3 -6
- package/v2Containers/Whatsapp/tests/__snapshots__/index.test.js.snap +34 -306
- package/v2Containers/mockdata.js +0 -25
- package/v2Containers/CommunicationFlow/Tests/constants.test.js +0 -85
|
@@ -13,14 +13,14 @@ import { injectIntl } from 'react-intl';
|
|
|
13
13
|
import { compose } from 'redux';
|
|
14
14
|
import { connect } from 'react-redux';
|
|
15
15
|
import { createStructuredSelector } from 'reselect';
|
|
16
|
+
// import { CouponsCapContainer } from '@capillarytech/cap-coupons'; // Commented - cap-coupons flows disabled
|
|
16
17
|
import CapRow from '@capillarytech/cap-ui-library/CapRow';
|
|
17
18
|
import CapDivider from '@capillarytech/cap-ui-library/CapDivider';
|
|
18
19
|
import CapButton from '@capillarytech/cap-ui-library/CapButton';
|
|
19
|
-
import
|
|
20
|
-
import injectReducer from '../../utils/injectReducer';
|
|
20
|
+
// import injectSaga from '../../utils/injectSaga'; // cap-coupons flows disabled
|
|
21
|
+
// import injectReducer from '../../utils/injectReducer';
|
|
21
22
|
import { makeSelectAuthenticated } from '../Cap/selectors';
|
|
22
|
-
import
|
|
23
|
-
import { createCommDefinition, editCommDefinition } from '../../services/api';
|
|
23
|
+
import { createCentralCommsMetaId, getCentralCommsMetaIds } from '../../services/api';
|
|
24
24
|
import DynamicControlsStep from './steps/DynamicControlsStep';
|
|
25
25
|
import MessageTypeStep from './steps/MessageTypeStep';
|
|
26
26
|
import CommunicationStrategyStep from './steps/CommunicationStrategyStep';
|
|
@@ -35,20 +35,23 @@ import {
|
|
|
35
35
|
CHANNELS,
|
|
36
36
|
INCENTIVE_TYPES,
|
|
37
37
|
DYNAMIC_CONTROLS_CONFIG,
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
CCS_CHANNEL_NAME_MAP,
|
|
42
|
-
CCS_CONTENT_TRANSFORMS,
|
|
43
|
-
REFERENCE_ID_EXISTS,
|
|
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';
|
|
47
44
|
import './CommunicationFlow.scss';
|
|
48
45
|
|
|
49
|
-
//
|
|
50
|
-
//
|
|
51
|
-
|
|
46
|
+
// Inject couponsCap reducer and saga - commented out (cap-coupons flows disabled)
|
|
47
|
+
// const withCouponsReducer = injectReducer({
|
|
48
|
+
// key: 'couponsCap',
|
|
49
|
+
// reducer: CouponsCapContainer.couponsCapReducer,
|
|
50
|
+
// });
|
|
51
|
+
// const withCouponsSaga = injectSaga({
|
|
52
|
+
// key: 'couponsCapSaga',
|
|
53
|
+
// saga: CouponsCapContainer.couponsCapSaga,
|
|
54
|
+
// });
|
|
52
55
|
|
|
53
56
|
const getDeliveryChannels = (contentItems) => {
|
|
54
57
|
const channels = contentItems.map((item) => (item.channel || '').toUpperCase()).filter(Boolean);
|
|
@@ -61,9 +64,6 @@ const hasDeliverySettingForChannel = (channelSetting, channel) => {
|
|
|
61
64
|
return !!settings && Object.values(settings).some((v) => v !== null && v !== '' && v !== undefined);
|
|
62
65
|
};
|
|
63
66
|
|
|
64
|
-
// Duplicate referenceId within the org returns a 409 CCS error envelope.
|
|
65
|
-
const isDuplicateReferenceIdError = (res) => res?.success === false && res?.status?.message === REFERENCE_ID_EXISTS;
|
|
66
|
-
|
|
67
67
|
const CommunicationFlow = ({
|
|
68
68
|
config,
|
|
69
69
|
initialData,
|
|
@@ -91,7 +91,6 @@ const CommunicationFlow = ({
|
|
|
91
91
|
};
|
|
92
92
|
});
|
|
93
93
|
const [validationErrors, setValidationErrors] = useState({});
|
|
94
|
-
const [saveError, setSaveError] = useState(null);
|
|
95
94
|
|
|
96
95
|
// Memoize enabled steps
|
|
97
96
|
const enabledSteps = useMemo(() => getEnabledSteps(config), [config]);
|
|
@@ -151,123 +150,74 @@ const CommunicationFlow = ({
|
|
|
151
150
|
}, []);
|
|
152
151
|
|
|
153
152
|
const handleSave = useCallback(async () => {
|
|
154
|
-
setSaveError(null);
|
|
155
153
|
const aggregatedData = getAggregatedData();
|
|
156
154
|
const shouldUseCCS = config?.useCCS !== false;
|
|
157
|
-
let ccsCommDefinition = null;
|
|
158
155
|
|
|
159
156
|
if (shouldUseCCS) {
|
|
160
|
-
const
|
|
161
|
-
const
|
|
162
|
-
|
|
163
|
-
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);
|
|
164
160
|
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
const rawChannel = (contentItem.channel || '').toUpperCase();
|
|
168
|
-
const channel = CCS_CHANNEL_NAME_MAP[rawChannel] || rawChannel;
|
|
169
|
-
const contentKey = CCS_CHANNEL_CONTENT_KEY_MAP[channel];
|
|
170
|
-
const deliveryKey = CCS_CHANNEL_DELIVERY_KEY_MAP[channel];
|
|
171
|
-
const contentTransform = CCS_CONTENT_TRANSFORMS[channel];
|
|
172
|
-
const contentPayload = contentTransform ? contentTransform(contentItem.templateData) : contentItem.templateData;
|
|
173
|
-
const { dynamicControls = {} } = aggregatedData;
|
|
174
|
-
const channelSettings = aggregatedData.deliverySetting?.channelSetting?.[channel] || {};
|
|
175
|
-
// Optional fields — sent as '' rather than omitted when left blank.
|
|
176
|
-
const referenceId = config?.context?.referenceId || '';
|
|
177
|
-
const description = config?.context?.description || '';
|
|
161
|
+
const channelContentKeyMap = CHANNEL_CONTENT_KEY_MAP;
|
|
162
|
+
const channelDeliveryKeyMap = CHANNEL_DELIVERY_KEY_MAP;
|
|
178
163
|
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
name,
|
|
182
|
-
description,
|
|
183
|
-
strategyType: CCS_STRATEGY_TYPE_SINGLE,
|
|
184
|
-
settings: {
|
|
185
|
-
additionalSettings: {
|
|
186
|
-
useTinyUrl: dynamicControls.useTinyUrl ?? false,
|
|
187
|
-
encryptUrl: dynamicControls.sendToControlCustomers ?? false,
|
|
188
|
-
linkTrackingEnabled: dynamicControls.overrideDailyLimit ?? false,
|
|
189
|
-
userSubscriptionDisabled: dynamicControls.sendToBrandPocs ?? false,
|
|
190
|
-
},
|
|
191
|
-
executionParams: {},
|
|
192
|
-
},
|
|
193
|
-
singleChannelStrategy: {
|
|
194
|
-
variant: {
|
|
195
|
-
channel,
|
|
196
|
-
// `channel` spread last so CCS's normalized enum overrides the UI's internal identifier.
|
|
197
|
-
...(contentKey && { [contentKey]: { ...contentPayload, channel } }),
|
|
198
|
-
...(deliveryKey && { [deliveryKey]: { channelSettings: { ...channelSettings, channel } } }),
|
|
199
|
-
},
|
|
200
|
-
},
|
|
201
|
-
};
|
|
164
|
+
const contentItems = aggregatedData.contentItems || [];
|
|
165
|
+
const { dynamicControls = {} } = aggregatedData;
|
|
202
166
|
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
|
|
206
|
-
|
|
207
|
-
|
|
208
|
-
|
|
209
|
-
strategyType,
|
|
210
|
-
settings,
|
|
211
|
-
singleChannelStrategy,
|
|
212
|
-
} = payload;
|
|
167
|
+
const additionalSettings = {
|
|
168
|
+
useTinyUrl: dynamicControls.useTinyUrl ?? false,
|
|
169
|
+
encryptUrl: dynamicControls.sendToControlCustomers ?? false,
|
|
170
|
+
linkTrackingEnabled: dynamicControls.overrideDailyLimit ?? false,
|
|
171
|
+
userSubscriptionDisabled: dynamicControls.sendToBrandPocs ?? false,
|
|
172
|
+
};
|
|
213
173
|
|
|
174
|
+
if (contentItems.length > 0) {
|
|
214
175
|
try {
|
|
215
|
-
const
|
|
216
|
-
|
|
217
|
-
|
|
218
|
-
|
|
219
|
-
|
|
220
|
-
|
|
221
|
-
|
|
222
|
-
|
|
223
|
-
|
|
224
|
-
|
|
225
|
-
|
|
226
|
-
|
|
227
|
-
|
|
228
|
-
|
|
229
|
-
|
|
230
|
-
|
|
231
|
-
|
|
232
|
-
|
|
233
|
-
|
|
234
|
-
|
|
235
|
-
|
|
236
|
-
|
|
237
|
-
|
|
238
|
-
|
|
239
|
-
|
|
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
|
+
},
|
|
240
201
|
};
|
|
241
|
-
|
|
242
|
-
|
|
243
|
-
|
|
244
|
-
|
|
245
|
-
|
|
246
|
-
|
|
247
|
-
|
|
248
|
-
|
|
249
|
-
|
|
250
|
-
|
|
251
|
-
|
|
252
|
-
} else {
|
|
253
|
-
setSaveError(formatMessage(messages.genericSaveError));
|
|
254
|
-
return;
|
|
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
|
|
258
|
-
setSaveError(formatMessage(messages.genericSaveError));
|
|
259
|
-
return;
|
|
215
|
+
console.error('[CommunicationFlow] CCS createCentralCommsMetaId error:', error);
|
|
260
216
|
}
|
|
261
|
-
} else if (!name) {
|
|
262
|
-
console.warn('[CommunicationFlow] Skipping CCS createCommDefinition — config.context.name is required');
|
|
263
|
-
} else if (isMultiChannel) {
|
|
264
|
-
console.warn('[CommunicationFlow] Skipping CCS createCommDefinition — CHANNEL_PRIORITY/AB_TEST strategies are not supported by CCS create yet (SINGLE only)');
|
|
265
|
-
} else if (!contentItem) {
|
|
266
|
-
console.warn('[CommunicationFlow] Skipping CCS createCommDefinition — no content item found (contentItems is empty)');
|
|
267
217
|
}
|
|
268
218
|
}
|
|
269
219
|
|
|
270
|
-
onSave(
|
|
220
|
+
onSave(aggregatedData);
|
|
271
221
|
}, [getAggregatedData, config, onSave]);
|
|
272
222
|
|
|
273
223
|
// Call onChange callback when stepData changes
|
|
@@ -302,17 +252,9 @@ const CommunicationFlow = ({
|
|
|
302
252
|
<CapDivider />
|
|
303
253
|
</CapRow>
|
|
304
254
|
);
|
|
305
|
-
case STEPS.COMMUNICATION_STRATEGY:
|
|
306
|
-
// No divider when there's no content yet, but the spacing above the Channel
|
|
307
|
-
// card must stay either way — see .communication-strategy-row in the scss.
|
|
308
|
-
const templateStepFollows = enabledSteps.includes(STEPS.CHANNEL_SELECTION);
|
|
309
|
-
const hasContent = stepData.contentItems?.length > 0;
|
|
255
|
+
case STEPS.COMMUNICATION_STRATEGY:
|
|
310
256
|
return (
|
|
311
|
-
<CapRow
|
|
312
|
-
useLegacy
|
|
313
|
-
key={step}
|
|
314
|
-
className={(!templateStepFollows || hasContent) ? '' : 'communication-strategy-row--no-divider'}
|
|
315
|
-
>
|
|
257
|
+
<CapRow useLegacy key={step}>
|
|
316
258
|
<CommunicationStrategyStep
|
|
317
259
|
{...commonProps}
|
|
318
260
|
value={stepData.communicationStrategy}
|
|
@@ -321,10 +263,9 @@ const CommunicationFlow = ({
|
|
|
321
263
|
disabled={communicationStrategyData.disabled}
|
|
322
264
|
onChange={(communicationStrategy) => handleStepChange(step, { communicationStrategy })}
|
|
323
265
|
/>
|
|
324
|
-
|
|
266
|
+
<CapDivider />
|
|
325
267
|
</CapRow>
|
|
326
268
|
);
|
|
327
|
-
}
|
|
328
269
|
case STEPS.CHANNEL_SELECTION:
|
|
329
270
|
// Only show ChannelSelectionStep if communication strategy is selected
|
|
330
271
|
if (!stepData.communicationStrategy) {
|
|
@@ -339,7 +280,6 @@ const CommunicationFlow = ({
|
|
|
339
280
|
onChange={(data) => handleStepChange(step, data)}
|
|
340
281
|
channelsToHide={contentTemplateData.channelsToHide}
|
|
341
282
|
channelsToDisable={contentTemplateData.channelsToDisable}
|
|
342
|
-
disablePreviewAndTest={!!contentTemplateData.disablePreviewAndTest}
|
|
343
283
|
creativesMode={config.mode || 'create'}
|
|
344
284
|
selectedOfferDetails={stepData.selectedOfferDetails}
|
|
345
285
|
incentivesData={{
|
|
@@ -350,7 +290,7 @@ const CommunicationFlow = ({
|
|
|
350
290
|
config={config}
|
|
351
291
|
capData={cap || capData}
|
|
352
292
|
/>
|
|
353
|
-
|
|
293
|
+
<CapDivider />
|
|
354
294
|
</CapRow>
|
|
355
295
|
);
|
|
356
296
|
case STEPS.DYNAMIC_CONTROLS:
|
|
@@ -377,11 +317,6 @@ const CommunicationFlow = ({
|
|
|
377
317
|
{renderSteps()}
|
|
378
318
|
{onSave && (
|
|
379
319
|
<CapRow useLegacy className="communication-flow-container__footer">
|
|
380
|
-
{saveError && (
|
|
381
|
-
<CapLabel type="label2" className="communication-flow-container__save-error">
|
|
382
|
-
{saveError}
|
|
383
|
-
</CapLabel>
|
|
384
|
-
)}
|
|
385
320
|
<CapButton type="primary" onClick={handleSave} disabled={isSaveDisabled}>
|
|
386
321
|
{formatMessage(messages.save)}
|
|
387
322
|
</CapButton>
|
|
@@ -393,7 +328,7 @@ const CommunicationFlow = ({
|
|
|
393
328
|
|
|
394
329
|
CommunicationFlow.propTypes = {
|
|
395
330
|
config: PropTypes.shape({
|
|
396
|
-
consumer: PropTypes.oneOf(['campaigns', 'loyalty', 'adiona'
|
|
331
|
+
consumer: PropTypes.oneOf(['campaigns', 'loyalty', 'adiona']).isRequired,
|
|
397
332
|
channel: PropTypes.string,
|
|
398
333
|
mode: PropTypes.oneOf(['create', 'edit', 'preview']).isRequired,
|
|
399
334
|
channelsToHide: PropTypes.arrayOf(PropTypes.string),
|
|
@@ -427,7 +362,6 @@ CommunicationFlow.propTypes = {
|
|
|
427
362
|
contentTemplateData: PropTypes.shape({
|
|
428
363
|
required: PropTypes.bool,
|
|
429
364
|
channels: PropTypes.object,
|
|
430
|
-
disablePreviewAndTest: PropTypes.bool,
|
|
431
365
|
}),
|
|
432
366
|
enableIncentives: PropTypes.bool,
|
|
433
367
|
enableDeliverySettings: PropTypes.bool,
|
|
@@ -460,7 +394,8 @@ const mapStateToProps = createStructuredSelector({
|
|
|
460
394
|
const withConnect = connect(mapStateToProps);
|
|
461
395
|
|
|
462
396
|
export default compose(
|
|
463
|
-
|
|
397
|
+
// withCouponsReducer, // cap-coupons flows disabled
|
|
398
|
+
// withCouponsSaga, // cap-coupons flows disabled
|
|
464
399
|
withConnect,
|
|
465
400
|
injectIntl,
|
|
466
401
|
)(CommunicationFlow);
|
|
@@ -128,32 +128,16 @@
|
|
|
128
128
|
}
|
|
129
129
|
|
|
130
130
|
.communication-flow-container {
|
|
131
|
-
// Anchor the Save footer to the bottom without flex, avoiding .ant-row-legacy overrides and flexbox stretching nested fixed-size content.
|
|
132
|
-
&.ant-row-legacy {
|
|
133
|
-
position: relative !important;
|
|
134
|
-
min-height: calc(100vh - 6.571rem) !important;
|
|
135
|
-
padding-bottom: 6rem !important;
|
|
136
|
-
}
|
|
137
|
-
|
|
138
131
|
.step-divider {
|
|
139
132
|
margin: $CAP_SPACE_32 0;
|
|
140
133
|
}
|
|
141
134
|
|
|
142
|
-
// Hide the divider when empty but preserve its margin gap so the section doesn’t sit flush against the Channel card.
|
|
143
|
-
.communication-strategy-row--no-divider {
|
|
144
|
-
margin-bottom: $CAP_SPACE_32;
|
|
145
|
-
}
|
|
146
|
-
|
|
147
135
|
.heading-style {
|
|
148
136
|
margin-bottom: $CAP_SPACE_08;
|
|
149
137
|
}
|
|
150
138
|
|
|
151
|
-
&__footer
|
|
152
|
-
|
|
153
|
-
left: 0;
|
|
154
|
-
right: 0;
|
|
155
|
-
bottom: 0 !important;
|
|
156
|
-
padding: 3.142rem 0 $CAP_SPACE_08;
|
|
139
|
+
&__footer {
|
|
140
|
+
padding: $CAP_SPACE_16 0 $CAP_SPACE_08;
|
|
157
141
|
}
|
|
158
142
|
}
|
|
159
143
|
|
|
@@ -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
|
|
@@ -111,9 +107,6 @@ const CommunicationFlowCard = ({
|
|
|
111
107
|
const senderIdValue = getSenderIdValue(firstItem, savedData);
|
|
112
108
|
const controls = config?.features?.dynamicControlsData?.controls || DYNAMIC_CONTROLS_CONFIG;
|
|
113
109
|
const dynamicControlKeys = Object.keys(savedData?.dynamicControls || {});
|
|
114
|
-
// Consumers that set showDynamicControls: false render their own "Advanced
|
|
115
|
-
// controls" section elsewhere, so skip this card's redundant control list.
|
|
116
|
-
const showDynamicControls = config?.features?.showDynamicControls !== false;
|
|
117
110
|
const channel = firstItem.channel?.toUpperCase();
|
|
118
111
|
const senderLabel = [WHATSAPP, RCS].includes(channel)
|
|
119
112
|
? formatMessage(messages.senderNumberLabel)
|
|
@@ -127,11 +120,7 @@ const CommunicationFlowCard = ({
|
|
|
127
120
|
<CapLabel type="label8">Message:</CapLabel>
|
|
128
121
|
<CapLabel type="label2">{strategyLabel}</CapLabel>
|
|
129
122
|
{messageTypeLabel && (
|
|
130
|
-
<CapLabel type="label1">
|
|
131
|
-
(
|
|
132
|
-
{messageTypeLabel}
|
|
133
|
-
)
|
|
134
|
-
</CapLabel>
|
|
123
|
+
<CapLabel type="label1">({messageTypeLabel})</CapLabel>
|
|
135
124
|
)}
|
|
136
125
|
</CapRow>
|
|
137
126
|
)}
|
|
@@ -146,41 +135,33 @@ const CommunicationFlowCard = ({
|
|
|
146
135
|
bodyStyle={{ padding: 0 }}
|
|
147
136
|
>
|
|
148
137
|
<CapRow gutter={0} className="card-body-row">
|
|
149
|
-
<CapColumn span={
|
|
138
|
+
<CapColumn span={12} className="card-body-left-col">
|
|
150
139
|
<CapRow type="flex" align="middle" className="channel-header-row">
|
|
151
140
|
<CapIcon type={channelConfig?.iconType || 'sms'} size="s" />
|
|
152
141
|
<CapLabel type="label8">{channelConfig?.label || firstItem.channel}</CapLabel>
|
|
153
142
|
{senderIdValue && (
|
|
154
|
-
<CapLabel type="label1">
|
|
155
|
-
(
|
|
156
|
-
{senderLabel}
|
|
157
|
-
:
|
|
158
|
-
{senderIdValue}
|
|
159
|
-
)
|
|
160
|
-
</CapLabel>
|
|
143
|
+
<CapLabel type="label1">({senderLabel}: {senderIdValue})</CapLabel>
|
|
161
144
|
)}
|
|
162
145
|
</CapRow>
|
|
163
146
|
{getContentBody(firstItem)}
|
|
164
147
|
</CapColumn>
|
|
165
|
-
{
|
|
166
|
-
<
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
<
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
</CapColumn>
|
|
183
|
-
)}
|
|
148
|
+
<CapColumn span={12} className="card-body-right-col">
|
|
149
|
+
<CapLabel type="label8">{formatMessage(messages.dynamicControlsTitle)}</CapLabel>
|
|
150
|
+
{dynamicControlKeys.map((key) => {
|
|
151
|
+
const controlConfig = controls.find((c) => c.key === key);
|
|
152
|
+
if (!controlConfig) return null;
|
|
153
|
+
return (
|
|
154
|
+
<CapRow key={key} type="flex" justify="space-between" className="control-row">
|
|
155
|
+
<CapLabel type="label2">{controlConfig.label}</CapLabel>
|
|
156
|
+
<CapLabel type="label2">
|
|
157
|
+
{savedData.dynamicControls[key]
|
|
158
|
+
? formatMessage(messages.yes)
|
|
159
|
+
: formatMessage(messages.no)}
|
|
160
|
+
</CapLabel>
|
|
161
|
+
</CapRow>
|
|
162
|
+
);
|
|
163
|
+
})}
|
|
164
|
+
</CapColumn>
|
|
184
165
|
</CapRow>
|
|
185
166
|
</CapCard>
|
|
186
167
|
);
|
|
@@ -201,17 +182,9 @@ const CommunicationFlowCard = ({
|
|
|
201
182
|
<CapImage src={addCreativesIllustration} />
|
|
202
183
|
</CapColumn>
|
|
203
184
|
<CapColumn span={14} className="empty-card-action-col">
|
|
204
|
-
|
|
205
|
-
|
|
206
|
-
|
|
207
|
-
{formatMessage(messages.addCreatives)}
|
|
208
|
-
</CapButton>
|
|
209
|
-
</CapTooltip>
|
|
210
|
-
) : (
|
|
211
|
-
<CapButton type="secondary" onClick={handleOpen} disabled={disabled}>
|
|
212
|
-
{formatMessage(messages.addCreatives)}
|
|
213
|
-
</CapButton>
|
|
214
|
-
)}
|
|
185
|
+
<CapButton type="secondary" onClick={handleOpen}>
|
|
186
|
+
{formatMessage(messages.addCreatives)}
|
|
187
|
+
</CapButton>
|
|
215
188
|
</CapColumn>
|
|
216
189
|
</CapRow>
|
|
217
190
|
</CapCard>
|
|
@@ -223,10 +196,10 @@ const CommunicationFlowCard = ({
|
|
|
223
196
|
<CapSlideBox
|
|
224
197
|
show={showSlideBox}
|
|
225
198
|
handleClose={handleClose}
|
|
226
|
-
size="size-
|
|
199
|
+
size="size-xl"
|
|
227
200
|
header={(
|
|
228
201
|
<CapHeader
|
|
229
|
-
title={formatMessage(messages.
|
|
202
|
+
title={formatMessage(messages.addMessage)}
|
|
230
203
|
handleClose={handleClose}
|
|
231
204
|
/>
|
|
232
205
|
)}
|
|
@@ -254,8 +227,6 @@ CommunicationFlowCard.propTypes = {
|
|
|
254
227
|
onChange: PropTypes.func,
|
|
255
228
|
cap: PropTypes.object,
|
|
256
229
|
intl: PropTypes.object.isRequired,
|
|
257
|
-
disabled: PropTypes.bool, // Disables the "Add creatives" trigger (e.g. until a consumer-required field is filled)
|
|
258
|
-
disabledTooltip: PropTypes.node, // Shown on hover when disabled is true
|
|
259
230
|
};
|
|
260
231
|
|
|
261
232
|
CommunicationFlowCard.defaultProps = {
|
|
@@ -264,8 +235,6 @@ CommunicationFlowCard.defaultProps = {
|
|
|
264
235
|
onCancel: null,
|
|
265
236
|
onChange: null,
|
|
266
237
|
cap: null,
|
|
267
|
-
disabled: false,
|
|
268
|
-
disabledTooltip: null,
|
|
269
238
|
};
|
|
270
239
|
|
|
271
240
|
export default injectIntl(CommunicationFlowCard);
|