@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.
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 -32
  6. package/utils/tests/templateVarUtils.test.js +0 -44
  7. package/v2Components/CommonTestAndPreview/UnifiedPreview/index.js +0 -14
  8. package/v2Components/CommonTestAndPreview/actions.js +0 -13
  9. package/v2Components/CommonTestAndPreview/constants.js +0 -8
  10. package/v2Components/CommonTestAndPreview/index.js +2 -57
  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 -128
  57. package/v2Containers/CommunicationFlow/CommunicationFlow.scss +2 -30
  58. package/v2Containers/CommunicationFlow/CommunicationFlowCard.js +27 -58
  59. package/v2Containers/CommunicationFlow/Tests/CommunicationFlow.test.js +51 -471
  60. package/v2Containers/CommunicationFlow/Tests/CommunicationFlowCard.test.js +4 -40
  61. package/v2Containers/CommunicationFlow/constants.js +4 -67
  62. package/v2Containers/CommunicationFlow/index.js +23 -16
  63. package/v2Containers/CommunicationFlow/messages.js +3 -7
  64. package/v2Containers/CommunicationFlow/steps/ChannelSelectionStep/ChannelSelectionStep.js +10 -22
  65. package/v2Containers/CommunicationFlow/steps/ChannelSelectionStep/ChannelSelectionStep.scss +0 -4
  66. package/v2Containers/CommunicationFlow/steps/ChannelSelectionStep/Tests/ChannelSelectionStep.test.js +4 -112
  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 -8
  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,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 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 (isDuplicateReferenceIdError(res)) {
225
- setSaveError(formatMessage(messages.duplicateReferenceIdError));
226
- return;
227
- }
228
- const data = res?.response?.data;
229
- if (existingCommDefinitionId) {
230
- if (data) {
231
- ccsCommDefinition = {
232
- id: existingCommDefinitionId,
233
- referenceId: referenceId || data.referenceId,
234
- version: data.version?.version ?? data.version ?? 1,
235
- 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
+ },
236
201
  };
237
- }
238
- } else if (data?.id) {
239
- ccsCommDefinition = {
240
- id: data.id,
241
- referenceId: data.referenceId,
242
- version: data.version?.version ?? 1,
243
- status: data.status,
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 createCommDefinition error:', error);
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(ccsCommDefinition ? { ...aggregatedData, ccsCommDefinition } : aggregatedData);
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
- {(!templateStepFollows || hasContent) && <CapDivider />}
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
- {stepData.contentItems?.length > 0 && <CapDivider />}
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', 'coupons', 'cartPromotions']).isRequired,
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
- withCapReducer,
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.ant-row-legacy {
164
- position: absolute !important;
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?.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((c) => c.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);