@capillarytech/creatives-library 9.0.56-alpha.6 → 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 -32
- package/utils/tests/templateVarUtils.test.js +0 -44
- package/v2Components/CommonTestAndPreview/UnifiedPreview/index.js +0 -14
- package/v2Components/CommonTestAndPreview/actions.js +0 -13
- package/v2Components/CommonTestAndPreview/constants.js +0 -8
- package/v2Components/CommonTestAndPreview/index.js +2 -57
- 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 -128
- package/v2Containers/CommunicationFlow/CommunicationFlow.scss +2 -30
- package/v2Containers/CommunicationFlow/CommunicationFlowCard.js +27 -58
- package/v2Containers/CommunicationFlow/Tests/CommunicationFlow.test.js +51 -471
- package/v2Containers/CommunicationFlow/Tests/CommunicationFlowCard.test.js +4 -40
- package/v2Containers/CommunicationFlow/constants.js +4 -67
- package/v2Containers/CommunicationFlow/index.js +23 -16
- package/v2Containers/CommunicationFlow/messages.js +3 -7
- package/v2Containers/CommunicationFlow/steps/ChannelSelectionStep/ChannelSelectionStep.js +10 -22
- package/v2Containers/CommunicationFlow/steps/ChannelSelectionStep/ChannelSelectionStep.scss +0 -4
- package/v2Containers/CommunicationFlow/steps/ChannelSelectionStep/Tests/ChannelSelectionStep.test.js +4 -112
- 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 -8
- 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,111 +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
|
-
|
|
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
|
+
},
|
|
236
201
|
};
|
|
237
|
-
|
|
238
|
-
|
|
239
|
-
|
|
240
|
-
|
|
241
|
-
|
|
242
|
-
|
|
243
|
-
|
|
244
|
-
|
|
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);
|
|
245
213
|
}
|
|
246
214
|
} catch (error) {
|
|
247
|
-
console.error('[CommunicationFlow] CCS
|
|
215
|
+
console.error('[CommunicationFlow] CCS createCentralCommsMetaId error:', error);
|
|
248
216
|
}
|
|
249
|
-
} else if (!name) {
|
|
250
|
-
console.warn('[CommunicationFlow] Skipping CCS createCommDefinition — config.context.name is required');
|
|
251
|
-
} else if (isMultiChannel) {
|
|
252
|
-
console.warn('[CommunicationFlow] Skipping CCS createCommDefinition — CHANNEL_PRIORITY/AB_TEST strategies are not supported by CCS create yet (SINGLE only)');
|
|
253
|
-
} else if (!contentItem) {
|
|
254
|
-
console.warn('[CommunicationFlow] Skipping CCS createCommDefinition — no content item found (contentItems is empty)');
|
|
255
217
|
}
|
|
256
218
|
}
|
|
257
219
|
|
|
258
|
-
onSave(
|
|
220
|
+
onSave(aggregatedData);
|
|
259
221
|
}, [getAggregatedData, config, onSave]);
|
|
260
222
|
|
|
261
223
|
// Call onChange callback when stepData changes
|
|
@@ -290,17 +252,9 @@ const CommunicationFlow = ({
|
|
|
290
252
|
<CapDivider />
|
|
291
253
|
</CapRow>
|
|
292
254
|
);
|
|
293
|
-
case STEPS.COMMUNICATION_STRATEGY:
|
|
294
|
-
// No divider when there's no content yet, but the spacing above the Channel
|
|
295
|
-
// card must stay either way — see .communication-strategy-row in the scss.
|
|
296
|
-
const templateStepFollows = enabledSteps.includes(STEPS.CHANNEL_SELECTION);
|
|
297
|
-
const hasContent = stepData.contentItems?.length > 0;
|
|
255
|
+
case STEPS.COMMUNICATION_STRATEGY:
|
|
298
256
|
return (
|
|
299
|
-
<CapRow
|
|
300
|
-
useLegacy
|
|
301
|
-
key={step}
|
|
302
|
-
className={(!templateStepFollows || hasContent) ? '' : 'communication-strategy-row--no-divider'}
|
|
303
|
-
>
|
|
257
|
+
<CapRow useLegacy key={step}>
|
|
304
258
|
<CommunicationStrategyStep
|
|
305
259
|
{...commonProps}
|
|
306
260
|
value={stepData.communicationStrategy}
|
|
@@ -309,10 +263,9 @@ const CommunicationFlow = ({
|
|
|
309
263
|
disabled={communicationStrategyData.disabled}
|
|
310
264
|
onChange={(communicationStrategy) => handleStepChange(step, { communicationStrategy })}
|
|
311
265
|
/>
|
|
312
|
-
|
|
266
|
+
<CapDivider />
|
|
313
267
|
</CapRow>
|
|
314
268
|
);
|
|
315
|
-
}
|
|
316
269
|
case STEPS.CHANNEL_SELECTION:
|
|
317
270
|
// Only show ChannelSelectionStep if communication strategy is selected
|
|
318
271
|
if (!stepData.communicationStrategy) {
|
|
@@ -327,7 +280,6 @@ const CommunicationFlow = ({
|
|
|
327
280
|
onChange={(data) => handleStepChange(step, data)}
|
|
328
281
|
channelsToHide={contentTemplateData.channelsToHide}
|
|
329
282
|
channelsToDisable={contentTemplateData.channelsToDisable}
|
|
330
|
-
disablePreviewAndTest={!!contentTemplateData.disablePreviewAndTest}
|
|
331
283
|
creativesMode={config.mode || 'create'}
|
|
332
284
|
selectedOfferDetails={stepData.selectedOfferDetails}
|
|
333
285
|
incentivesData={{
|
|
@@ -338,7 +290,7 @@ const CommunicationFlow = ({
|
|
|
338
290
|
config={config}
|
|
339
291
|
capData={cap || capData}
|
|
340
292
|
/>
|
|
341
|
-
|
|
293
|
+
<CapDivider />
|
|
342
294
|
</CapRow>
|
|
343
295
|
);
|
|
344
296
|
case STEPS.DYNAMIC_CONTROLS:
|
|
@@ -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>
|
|
@@ -381,7 +328,7 @@ const CommunicationFlow = ({
|
|
|
381
328
|
|
|
382
329
|
CommunicationFlow.propTypes = {
|
|
383
330
|
config: PropTypes.shape({
|
|
384
|
-
consumer: PropTypes.oneOf(['campaigns', 'loyalty', 'adiona'
|
|
331
|
+
consumer: PropTypes.oneOf(['campaigns', 'loyalty', 'adiona']).isRequired,
|
|
385
332
|
channel: PropTypes.string,
|
|
386
333
|
mode: PropTypes.oneOf(['create', 'edit', 'preview']).isRequired,
|
|
387
334
|
channelsToHide: PropTypes.arrayOf(PropTypes.string),
|
|
@@ -415,7 +362,6 @@ CommunicationFlow.propTypes = {
|
|
|
415
362
|
contentTemplateData: PropTypes.shape({
|
|
416
363
|
required: PropTypes.bool,
|
|
417
364
|
channels: PropTypes.object,
|
|
418
|
-
disablePreviewAndTest: PropTypes.bool,
|
|
419
365
|
}),
|
|
420
366
|
enableIncentives: PropTypes.bool,
|
|
421
367
|
enableDeliverySettings: PropTypes.bool,
|
|
@@ -448,7 +394,8 @@ const mapStateToProps = createStructuredSelector({
|
|
|
448
394
|
const withConnect = connect(mapStateToProps);
|
|
449
395
|
|
|
450
396
|
export default compose(
|
|
451
|
-
|
|
397
|
+
// withCouponsReducer, // cap-coupons flows disabled
|
|
398
|
+
// withCouponsSaga, // cap-coupons flows disabled
|
|
452
399
|
withConnect,
|
|
453
400
|
injectIntl,
|
|
454
401
|
)(CommunicationFlow);
|
|
@@ -128,44 +128,16 @@
|
|
|
128
128
|
}
|
|
129
129
|
|
|
130
130
|
.communication-flow-container {
|
|
131
|
-
// Anchors the Save footer to the bottom of the slidebox's scrollable content
|
|
132
|
-
// area regardless of how much step content is above it. <CapRow useLegacy>
|
|
133
|
-
// carries cap-ui-library's `.ant-row-legacy` rule (`display: block !important`),
|
|
134
|
-
// which silently defeats a plain `display:flex`/`min-height` here unless the
|
|
135
|
-
// selector is compounded with `.ant-row-legacy` and marked `!important` too.
|
|
136
|
-
// Deliberately position-based, not flex + margin-top: auto — a flex version
|
|
137
|
-
// makes this element (and its .ant-row-legacy children) a flex container, and
|
|
138
|
-
// flexbox's default align-items: stretch leaks into deeply nested descendants
|
|
139
|
-
// (e.g. ChannelSelectionStep's fixed-width empty-state card), stretching them
|
|
140
|
-
// to fill the container instead of keeping their own size.
|
|
141
|
-
&.ant-row-legacy {
|
|
142
|
-
position: relative !important;
|
|
143
|
-
min-height: calc(100vh - 6.571rem) !important;
|
|
144
|
-
padding-bottom: 6rem !important;
|
|
145
|
-
}
|
|
146
|
-
|
|
147
131
|
.step-divider {
|
|
148
132
|
margin: $CAP_SPACE_32 0;
|
|
149
133
|
}
|
|
150
134
|
|
|
151
|
-
// CommunicationStrategyStep's own trailing divider is hidden until content
|
|
152
|
-
// exists (no dangling line above an empty "Add creative" state), but the gap
|
|
153
|
-
// it would have provided (.step-divider's margin) must stay — otherwise the
|
|
154
|
-
// section sits flush against the Channel card in the empty state.
|
|
155
|
-
.communication-strategy-row--no-divider {
|
|
156
|
-
margin-bottom: $CAP_SPACE_32;
|
|
157
|
-
}
|
|
158
|
-
|
|
159
135
|
.heading-style {
|
|
160
136
|
margin-bottom: $CAP_SPACE_08;
|
|
161
137
|
}
|
|
162
138
|
|
|
163
|
-
&__footer
|
|
164
|
-
|
|
165
|
-
left: 0;
|
|
166
|
-
right: 0;
|
|
167
|
-
bottom: 0 !important;
|
|
168
|
-
padding: 3.142rem 0 $CAP_SPACE_08;
|
|
139
|
+
&__footer {
|
|
140
|
+
padding: $CAP_SPACE_16 0 $CAP_SPACE_08;
|
|
169
141
|
}
|
|
170
142
|
}
|
|
171
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);
|