@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.
Files changed (82) hide show
  1. package/constants/unified.js +4 -2
  2. package/package.json +1 -1
  3. package/services/api.js +0 -20
  4. package/utils/common.js +12 -0
  5. package/utils/templateVarUtils.js +0 -16
  6. package/utils/tests/templateVarUtils.test.js +0 -44
  7. package/v2Components/CommonTestAndPreview/UnifiedPreview/index.js +0 -13
  8. package/v2Components/CommonTestAndPreview/actions.js +0 -13
  9. package/v2Components/CommonTestAndPreview/constants.js +0 -8
  10. package/v2Components/CommonTestAndPreview/index.js +3 -55
  11. package/v2Components/CommonTestAndPreview/reducer.js +0 -20
  12. package/v2Components/CommonTestAndPreview/sagas.js +0 -28
  13. package/v2Components/CommonTestAndPreview/selectors.js +0 -6
  14. package/v2Components/CommonTestAndPreview/tests/UnifiedPreview/index.test.js +0 -106
  15. package/v2Components/CommonTestAndPreview/tests/actions.test.js +0 -15
  16. package/v2Components/CommonTestAndPreview/tests/constants.test.js +1 -9
  17. package/v2Components/CommonTestAndPreview/tests/index.test.js +0 -101
  18. package/v2Components/CommonTestAndPreview/tests/reducer.test.js +0 -41
  19. package/v2Components/CommonTestAndPreview/tests/sagas.test.js +0 -84
  20. package/v2Components/CommonTestAndPreview/tests/selectors.test.js +0 -12
  21. package/v2Components/FormBuilder/Functional/FormBuilderShell.js +320 -46
  22. package/v2Components/FormBuilder/Functional/channels/mobilepush/buildSubmitPayload.js +10 -0
  23. package/v2Components/FormBuilder/Functional/channels/mobilepush/config.js +82 -0
  24. package/v2Components/FormBuilder/Functional/channels/mobilepush/getEditorErrorDescriptor.js +74 -0
  25. package/v2Components/FormBuilder/Functional/channels/mobilepush/index.js +28 -0
  26. package/v2Components/FormBuilder/Functional/channels/mobilepush/modals.js +19 -0
  27. package/v2Components/FormBuilder/Functional/channels/mobilepush/runSubmitPipeline.js +45 -0
  28. package/v2Components/FormBuilder/Functional/channels/mobilepush/tests/getEditorErrorDescriptor.test.js +162 -0
  29. package/v2Components/FormBuilder/Functional/channels/mobilepush/tests/modals.test.js +37 -0
  30. package/v2Components/FormBuilder/Functional/channels/mobilepush/tests/runSubmitPipeline.test.js +70 -0
  31. package/v2Components/FormBuilder/Functional/channels/mobilepush/tests/validate.test.js +274 -0
  32. package/v2Components/FormBuilder/Functional/channels/mobilepush/validate.js +251 -0
  33. package/v2Components/FormBuilder/Functional/channels/registry.js +2 -0
  34. package/v2Components/FormBuilder/Functional/constants.js +43 -8
  35. package/v2Components/FormBuilder/Functional/core/schema/initializeFormState.js +175 -28
  36. package/v2Components/FormBuilder/Functional/core/store/formReducer.js +75 -6
  37. package/v2Components/FormBuilder/Functional/core/store/toLegacyFormData.js +10 -20
  38. package/v2Components/FormBuilder/Functional/layout/FieldSlot.js +9 -1
  39. package/v2Components/FormBuilder/Functional/layout/SchemaForm.js +20 -3
  40. package/v2Components/FormBuilder/Functional/layout/Section.js +6 -1
  41. package/v2Components/FormBuilder/Functional/layout/TabsContainer.js +89 -0
  42. package/v2Components/FormBuilder/Functional/renderers/mpushRenderers.js +440 -0
  43. package/v2Components/FormBuilder/Functional/tests/fieldSlot.test.js +9 -2
  44. package/v2Components/FormBuilder/Functional/tests/mpush.crossFlowParity.test.js +430 -0
  45. package/v2Components/FormBuilder/Functional/tests/mpush.ctaFlows.parity.test.js +282 -0
  46. package/v2Components/FormBuilder/Functional/tests/mpush.editContainer.parity.test.js +141 -0
  47. package/v2Components/FormBuilder/Functional/tests/mpush.engine.test.js +306 -0
  48. package/v2Components/FormBuilder/Functional/tests/mpush.shellEvents.test.js +151 -0
  49. package/v2Components/FormBuilder/Functional/tests/mpushRenderers.test.js +342 -0
  50. package/v2Components/FormBuilder/Functional/tests/schemaForm.test.js +17 -0
  51. package/v2Components/FormBuilder/Functional/tests/tabsContainer.test.js +110 -0
  52. package/v2Components/FormBuilder/index.js +34 -12
  53. package/v2Components/FormBuilder/tests/entryGate.test.js +94 -7
  54. package/v2Components/FormBuilder/tests/mpush.characterization.test.js +459 -0
  55. package/v2Components/TestAndPreviewSlidebox/index.js +0 -9
  56. package/v2Containers/CommunicationFlow/CommunicationFlow.js +75 -140
  57. package/v2Containers/CommunicationFlow/CommunicationFlow.scss +2 -18
  58. package/v2Containers/CommunicationFlow/CommunicationFlowCard.js +27 -58
  59. package/v2Containers/CommunicationFlow/Tests/CommunicationFlow.test.js +51 -503
  60. package/v2Containers/CommunicationFlow/Tests/CommunicationFlowCard.test.js +4 -40
  61. package/v2Containers/CommunicationFlow/constants.js +4 -65
  62. package/v2Containers/CommunicationFlow/index.js +23 -16
  63. package/v2Containers/CommunicationFlow/messages.js +3 -11
  64. package/v2Containers/CommunicationFlow/steps/ChannelSelectionStep/ChannelSelectionStep.js +11 -24
  65. package/v2Containers/CommunicationFlow/steps/ChannelSelectionStep/ChannelSelectionStep.scss +0 -4
  66. package/v2Containers/CommunicationFlow/steps/ChannelSelectionStep/Tests/ChannelSelectionStep.test.js +4 -176
  67. package/v2Containers/CommunicationFlow/steps/DeliverySettingsStep/DeliverySettingsSection.js +0 -3
  68. package/v2Containers/CommunicationFlow/steps/DeliverySettingsStep/SenderDetails.js +0 -6
  69. package/v2Containers/CommunicationFlow/steps/DeliverySettingsStep/Tests/SenderDetails.test.js +0 -25
  70. package/v2Containers/CommunicationFlow/steps/DeliverySettingsStep/Tests/deliverySettingsConfig.test.js +4 -11
  71. package/v2Containers/CommunicationFlow/steps/DeliverySettingsStep/deliverySettingsConfig.js +5 -19
  72. package/v2Containers/CreativesContainer/index.js +3 -2
  73. package/v2Containers/CreativesContainer/tests/__snapshots__/index.test.js.snap +5 -5
  74. package/v2Containers/CreativesContainer/tests/index.test.js +0 -12
  75. package/v2Containers/Rcs/tests/__snapshots__/index.test.js.snap +19 -115
  76. package/v2Containers/SmsTrai/Edit/tests/__snapshots__/index.test.js.snap +3 -27
  77. package/v2Containers/WebPush/Create/preview/WebPushPreview.js +12 -17
  78. package/v2Containers/WebPush/Create/preview/tests/WebPushPreview.test.js +0 -5
  79. package/v2Containers/Whatsapp/index.js +3 -6
  80. package/v2Containers/Whatsapp/tests/__snapshots__/index.test.js.snap +34 -306
  81. package/v2Containers/mockdata.js +0 -25
  82. 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 CapLabel from '@capillarytech/cap-ui-library/CapLabel';
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 capReducer from '../Cap/reducer';
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
- CCS_STRATEGY_TYPE_SINGLE,
39
- CCS_CHANNEL_CONTENT_KEY_MAP,
40
- CCS_CHANNEL_DELIVERY_KEY_MAP,
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
- // Self-injects the same 'cap' reducer CreativesContainer already injects under this key;
50
- // idempotent, so it's a no-op if the consumer's own store already provides it.
51
- const withCapReducer = injectReducer({ key: 'cap', reducer: capReducer });
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 isMultiChannel = [CHANNEL_PRIORITY, AB_TEST].includes(aggregatedData.communicationStrategy);
161
- const contentItem = (aggregatedData.contentItems || [])[0];
162
- // Consumer-supplied (e.g. CapNotify's Alert Name field) — CommunicationFlow has no name input of its own.
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
- // CCS create only supports SINGLE strategy; CHANNEL_PRIORITY/AB_TEST have no CCS equivalent yet.
166
- if (!isMultiChannel && contentItem && name) {
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
- const payload = {
180
- referenceId,
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
- // existingCommDefinitionId (set when editing, e.g. a rejected alert) creates a new
204
- // DRAFT version on the same CommDefinition instead of a new one.
205
- const { existingCommDefinitionId } = config?.context || {};
206
- const {
207
- referenceId: payloadReferenceId,
208
- description: payloadDescription,
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 res = existingCommDefinitionId
216
- ? await editCommDefinition(existingCommDefinitionId, {
217
- referenceId: payloadReferenceId,
218
- description: payloadDescription,
219
- strategyType,
220
- settings,
221
- singleChannelStrategy,
222
- })
223
- : await createCommDefinition(payload);
224
- if (res?.isError) {
225
- setSaveError(formatMessage(messages.genericSaveError));
226
- return;
227
- }
228
- if (isDuplicateReferenceIdError(res)) {
229
- setSaveError(formatMessage(messages.duplicateReferenceIdError));
230
- return;
231
- }
232
- const data = res?.response?.data;
233
- if (existingCommDefinitionId) {
234
- if (data) {
235
- ccsCommDefinition = {
236
- id: existingCommDefinitionId,
237
- referenceId: referenceId || data.referenceId,
238
- version: data.version?.version ?? data.version ?? 1,
239
- status: data.status,
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
- } else {
242
- setSaveError(formatMessage(messages.genericSaveError));
243
- return;
244
- }
245
- } else if (data?.id) {
246
- ccsCommDefinition = {
247
- id: data.id,
248
- referenceId: data.referenceId,
249
- version: data.version?.version ?? 1,
250
- status: data.status,
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 createCommDefinition error:', error);
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(ccsCommDefinition ? { ...aggregatedData, ccsCommDefinition } : aggregatedData);
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
- {(!templateStepFollows || hasContent) && <CapDivider />}
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
- {stepData.contentItems?.length > 0 && <CapDivider />}
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', 'coupons', 'cartPromotions']).isRequired,
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
- withCapReducer,
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.ant-row-legacy {
152
- position: absolute !important;
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?.senderId),
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
- }, [disabled]);
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={showDynamicControls ? 12 : 24} className="card-body-left-col">
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
- {showDynamicControls && (
166
- <CapColumn span={12} className="card-body-right-col">
167
- <CapLabel type="label8">{formatMessage(messages.dynamicControlsTitle)}</CapLabel>
168
- {dynamicControlKeys.map((key) => {
169
- const controlConfig = controls.find((control) => control.key === key);
170
- if (!controlConfig) return null;
171
- return (
172
- <CapRow key={key} type="flex" justify="space-between" className="control-row">
173
- <CapLabel type="label2">{controlConfig.label}</CapLabel>
174
- <CapLabel type="label2">
175
- {savedData.dynamicControls[key]
176
- ? formatMessage(messages.yes)
177
- : formatMessage(messages.no)}
178
- </CapLabel>
179
- </CapRow>
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
- {disabled && disabledTooltip ? (
205
- <CapTooltip title={disabledTooltip}>
206
- <CapButton type="secondary" disabled>
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-l"
199
+ size="size-xl"
227
200
  header={(
228
201
  <CapHeader
229
- title={formatMessage(messages.addContent)}
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);