@capillarytech/creatives-library 8.0.329 → 8.0.330-alpha.1

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 (89) hide show
  1. package/constants/unified.js +4 -0
  2. package/package.json +1 -1
  3. package/utils/commonUtils.js +19 -1
  4. package/utils/templateVarUtils.js +35 -6
  5. package/utils/tests/tagValidations.test.js +20 -0
  6. package/utils/tests/templateVarUtils.test.js +44 -0
  7. package/v2Components/CapActionButton/constants.js +7 -0
  8. package/v2Components/CapActionButton/index.js +167 -109
  9. package/v2Components/CapActionButton/index.scss +157 -6
  10. package/v2Components/CapActionButton/messages.js +19 -3
  11. package/v2Components/CapActionButton/tests/index.test.js +41 -17
  12. package/v2Components/CapTagList/index.js +28 -23
  13. package/v2Components/CapTagList/style.scss +29 -0
  14. package/v2Components/CapTagListWithInput/__tests__/CapTagListWithInput.test.js +63 -0
  15. package/v2Components/CapTagListWithInput/index.js +4 -0
  16. package/v2Components/CapWhatsappCTA/index.js +2 -0
  17. package/v2Components/CommonTestAndPreview/ExistingCustomerModal.js +1 -0
  18. package/v2Components/CommonTestAndPreview/UnifiedPreview/RcsPreviewContent.js +160 -15
  19. package/v2Components/CommonTestAndPreview/UnifiedPreview/RcsPreviewContent.js.rej +18 -0
  20. package/v2Components/CommonTestAndPreview/UnifiedPreview/_unifiedPreview.scss +323 -77
  21. package/v2Components/CommonTestAndPreview/index.js +49 -57
  22. package/v2Components/CommonTestAndPreview/messages.js +8 -0
  23. package/v2Components/CommonTestAndPreview/reducer.js +3 -1
  24. package/v2Components/CommonTestAndPreview/sagas.js +2 -1
  25. package/v2Components/CommonTestAndPreview/tests/PreviewSection.test.js +8 -1
  26. package/v2Components/CommonTestAndPreview/tests/UnifiedPreview/RcsPreviewContent.test.js +281 -283
  27. package/v2Components/FormBuilder/index.js +1 -0
  28. package/v2Components/HtmlEditor/HTMLEditor.js +6 -1
  29. package/v2Components/HtmlEditor/__tests__/HTMLEditor.apiErrors.test.js +1 -0
  30. package/v2Components/HtmlEditor/__tests__/HTMLEditor.test.js +927 -2
  31. package/v2Components/HtmlEditor/components/CodeEditorPane/index.js +3 -0
  32. package/v2Components/SmsFallback/smsFallbackUtils.js +14 -3
  33. package/v2Components/SmsFallback/tests/smsFallbackUtils.test.js +16 -0
  34. package/v2Components/TemplatePreview/_templatePreview.scss +33 -23
  35. package/v2Components/TemplatePreview/constants.js +2 -0
  36. package/v2Components/TemplatePreview/index.js +143 -28
  37. package/v2Components/TemplatePreview/tests/index.test.js +142 -0
  38. package/v2Components/TestAndPreviewSlidebox/index.js +5 -0
  39. package/v2Components/mockdata.js +1 -0
  40. package/v2Containers/BeeEditor/index.js +19 -1
  41. package/v2Containers/CreativesContainer/SlideBoxContent.js +28 -1
  42. package/v2Containers/CreativesContainer/index.js +9 -3
  43. package/v2Containers/CreativesContainer/tests/__snapshots__/index.test.js.snap +5 -0
  44. package/v2Containers/Email/index.js +78 -39
  45. package/v2Containers/Email/reducer.js +2 -2
  46. package/v2Containers/Email/sagas.js +3 -1
  47. package/v2Containers/Email/tests/__snapshots__/reducer.test.js.snap +2 -2
  48. package/v2Containers/Email/tests/sagas.test.js +230 -0
  49. package/v2Containers/EmailWrapper/components/EmailHTMLEditor.js +6 -1
  50. package/v2Containers/EmailWrapper/components/EmailWrapperView.js +3 -0
  51. package/v2Containers/EmailWrapper/components/__tests__/EmailHTMLEditor.test.js +20 -2
  52. package/v2Containers/EmailWrapper/components/__tests__/EmailWrapperView.test.js +16 -1
  53. package/v2Containers/EmailWrapper/hooks/useEmailWrapper.js +3 -1
  54. package/v2Containers/EmailWrapper/index.js +4 -0
  55. package/v2Containers/EmailWrapper/tests/useEmailWrapper.edgeCases.test.js +1 -0
  56. package/v2Containers/EmailWrapper/tests/useEmailWrapper.test.js +9 -0
  57. package/v2Containers/InAppWrapper/hooks/__tests__/useInAppWrapper.test.js +1 -0
  58. package/v2Containers/MobilePush/Create/index.js +2 -0
  59. package/v2Containers/MobilePush/Edit/index.js +2 -0
  60. package/v2Containers/MobilepushWrapper/index.js +3 -1
  61. package/v2Containers/Rcs/constants.js +85 -7
  62. package/v2Containers/Rcs/index.js +1592 -156
  63. package/v2Containers/Rcs/index.js.rej +1336 -0
  64. package/v2Containers/Rcs/index.scss +191 -0
  65. package/v2Containers/Rcs/index.scss.rej +74 -0
  66. package/v2Containers/Rcs/messages.js +28 -2
  67. package/v2Containers/Rcs/rcsLibraryHydrationUtils.js +20 -0
  68. package/v2Containers/Rcs/tests/__snapshots__/index.test.js.snap +69178 -117691
  69. package/v2Containers/Rcs/tests/__snapshots__/utils.test.js.snap.rej +128 -0
  70. package/v2Containers/Rcs/tests/index.test.js +132 -94
  71. package/v2Containers/Rcs/tests/rcsLibraryHydrationUtils.test.js +67 -0
  72. package/v2Containers/Rcs/tests/utils.test.js +276 -38
  73. package/v2Containers/Rcs/utils.js +130 -7
  74. package/v2Containers/Sms/Edit/index.js +2 -0
  75. package/v2Containers/SmsTrai/Edit/index.js +27 -0
  76. package/v2Containers/SmsTrai/Edit/messages.js +5 -0
  77. package/v2Containers/SmsTrai/Edit/tests/__snapshots__/index.test.js.snap +6 -6
  78. package/v2Containers/SmsWrapper/index.js +2 -0
  79. package/v2Containers/TagList/index.js +73 -20
  80. package/v2Containers/TagList/messages.js +4 -0
  81. package/v2Containers/TagList/tests/TagList.test.js +124 -20
  82. package/v2Containers/TagList/tests/mockdata.js +17 -0
  83. package/v2Containers/Templates/_templates.scss +99 -0
  84. package/v2Containers/Templates/index.js +29 -14
  85. package/v2Containers/Viber/index.js +3 -0
  86. package/v2Containers/WebPush/Create/hooks/useTagManagement.js +0 -2
  87. package/v2Containers/WebPush/Create/index.js +10 -2
  88. package/v2Containers/Whatsapp/index.js +5 -0
  89. package/v2Containers/Zalo/index.js +2 -0
@@ -97,6 +97,7 @@ import {
97
97
  extractPreviewFromLiquidResponse,
98
98
  getSmsFallbackTextForTagExtraction,
99
99
  } from './previewApiUtils';
100
+ import { pickFirstSmsFallbackTemplateString } from '../../v2Containers/Rcs/rcsLibraryHydrationUtils';
100
101
 
101
102
  import { isValidEmail, isValidMobile, formatPhoneNumber } from '../../utils/commonUtils';
102
103
  import { getMembersLookup } from '../../services/api';
@@ -1039,78 +1040,77 @@ const CommonTestAndPreview = (props) => {
1039
1040
  * rcsMessageContent: { channel, accountId?, rcsRichCardContent: { contentType, cardType, cardSettings, cardContent }, smsFallBackContent? }
1040
1041
  * Then rcsDeliverySettings, executionParams, clientName last.
1041
1042
  */
1042
- const buildRcsTestMessagePayload = (formDataObj, _contentStr, customValuesObj, deliverySettingsOverride, basePayload, rcsExtra = {}) => {
1043
- const plainCustom =
1044
- customValuesObj != null && typeof customValuesObj.toJS === 'function'
1045
- ? customValuesObj.toJS()
1046
- : (customValuesObj || {});
1047
- const userVarMap = Object.fromEntries(
1048
- Object.entries(plainCustom).filter(([, v]) => v != null && String(v).trim() !== '')
1049
- );
1050
- const rcsData = formDataObj?.versions?.base?.content?.RCS ?? formDataObj?.content?.RCS ?? {};
1051
- const rcsContent = rcsData?.rcsContent || {};
1052
- const smsFallback = rcsData?.smsFallBackContent || {};
1053
- let cardContentList = [];
1054
- if (Array.isArray(rcsContent?.cardContent)) {
1055
- cardContentList = rcsContent.cardContent;
1056
- } else if (rcsContent?.cardContent) {
1057
- cardContentList = [rcsContent.cardContent];
1043
+ const buildRcsTestMessagePayload = (
1044
+ creativeFormData,
1045
+ _unusedEditorContentString,
1046
+ _customValuesObj,
1047
+ deliverySettingsOverride,
1048
+ basePayload,
1049
+ _rcsTestMetaExtras = {},
1050
+ ) => {
1051
+ const rcsSectionFromForm =
1052
+ creativeFormData?.versions?.base?.content?.RCS ?? creativeFormData?.content?.RCS ?? {};
1053
+ const rcsContentFromForm = rcsSectionFromForm?.rcsContent || {};
1054
+ const smsFallbackFromCreativeForm = rcsSectionFromForm?.smsFallBackContent || {};
1055
+ let rcsCardPayloadList = [];
1056
+ if (Array.isArray(rcsContentFromForm?.cardContent)) {
1057
+ rcsCardPayloadList = rcsContentFromForm.cardContent;
1058
+ } else if (rcsContentFromForm?.cardContent) {
1059
+ rcsCardPayloadList = [rcsContentFromForm.cardContent];
1058
1060
  }
1059
- // Merge test customValues into cardVarMapped (template snapshot + user-entered RCS + fallback SMS tags).
1060
- const cardContent = cardContentList.map((rcsCard) => {
1061
- const baseMap = rcsCard.cardVarMapped || {};
1062
- const mergedCardVarMapped =
1063
- Object.keys(userVarMap).length > 0 ? { ...baseMap, ...userVarMap } : baseMap;
1064
- const mediaNorm = rcsCard?.media ? normalizeRcsTestCardMedia(rcsCard.media) : undefined;
1065
- const suggestionsRaw = Array.isArray(rcsCard?.suggestions) ? rcsCard.suggestions : [];
1066
- const suggestionsMapped = suggestionsRaw.map((suggestionItem, i) =>
1067
- mapRcsSuggestionForTestMeta(suggestionItem, i));
1061
+ // Raw title/description with template tags; SMS fallback uses tagged template fields (pickFirst…).
1062
+ const cardContentForTestMetaApi = rcsCardPayloadList.map((singleRcsCardPayload) => {
1063
+ const normalizedCardMediaForTestApi = singleRcsCardPayload?.media
1064
+ ? normalizeRcsTestCardMedia(singleRcsCardPayload.media)
1065
+ : undefined;
1066
+ const suggestionsFromCard = Array.isArray(singleRcsCardPayload?.suggestions)
1067
+ ? singleRcsCardPayload.suggestions
1068
+ : [];
1069
+ const suggestionsFormattedForTestMeta = suggestionsFromCard.map((suggestionItem, index) =>
1070
+ mapRcsSuggestionForTestMeta(suggestionItem, index));
1068
1071
  return {
1069
- title: rcsCard?.title ?? '',
1070
- description: rcsCard?.description ?? '',
1071
- mediaType: rcsCard?.mediaType ?? MEDIA_TYPE_TEXT,
1072
- ...(mediaNorm && { media: mediaNorm }),
1073
- ...(Object.keys(mergedCardVarMapped).length > 0 && { cardVarMapped: mergedCardVarMapped }),
1074
- ...(suggestionsMapped.length > 0 && { suggestions: suggestionsMapped }),
1072
+ title: singleRcsCardPayload?.title ?? '',
1073
+ description: singleRcsCardPayload?.description ?? '',
1074
+ mediaType: singleRcsCardPayload?.mediaType ?? MEDIA_TYPE_TEXT,
1075
+ ...(normalizedCardMediaForTestApi && { media: normalizedCardMediaForTestApi }),
1076
+ ...(suggestionsFormattedForTestMeta.length > 0 && {
1077
+ suggestions: suggestionsFormattedForTestMeta,
1078
+ }),
1075
1079
  };
1076
1080
  });
1077
- // Prefer parent `smsFallbackContent` snapshot (rcsExtra) — includes VarSegment-resolved body via
1078
- // getSmsFallbackTextForTagExtraction. Nested formData.smsFallBackContent is often stale vs live editor.
1079
- const rcsExtraFallbackTemplate = rcsExtra?.smsFallbackTemplateContent;
1080
- const hasResolvedFallbackBodyFromRcsExtra =
1081
- rcsExtraFallbackTemplate != null
1082
- && String(rcsExtraFallbackTemplate).trim() !== '';
1083
- const smsMessageRaw = hasResolvedFallbackBodyFromRcsExtra
1084
- ? String(rcsExtraFallbackTemplate)
1085
- : (smsFallback?.smsContent ?? smsFallback?.message ?? '');
1081
+ const smsFallbackTaggedTemplateBody = pickFirstSmsFallbackTemplateString(
1082
+ smsFallbackFromCreativeForm,
1083
+ ) || '';
1086
1084
  const smsSenderFromDelivery = deliverySettingsOverride?.cdmaSenderId?.includes('|')
1087
1085
  ? deliverySettingsOverride.cdmaSenderId.split('|')[1]
1088
1086
  : deliverySettingsOverride?.cdmaSenderId;
1089
1087
  const deliveryFallbackSmsId =
1090
1088
  typeof smsSenderFromDelivery === 'string' ? smsSenderFromDelivery.trim() : '';
1091
1089
  const creativeFallbackSmsId =
1092
- smsFallback?.senderId != null ? String(smsFallback.senderId).trim() : '';
1090
+ smsFallbackFromCreativeForm?.senderId != null
1091
+ ? String(smsFallbackFromCreativeForm.senderId).trim()
1092
+ : '';
1093
1093
  const fallbackSmsSenderIdForChannel = deliveryFallbackSmsId || creativeFallbackSmsId || '';
1094
1094
 
1095
1095
  const smsFallBackContent =
1096
- smsMessageRaw.trim() !== ''
1097
- ? { message: smsMessageRaw }
1096
+ smsFallbackTaggedTemplateBody.trim() !== ''
1097
+ ? { message: smsFallbackTaggedTemplateBody }
1098
1098
  : undefined;
1099
1099
 
1100
1100
  // accountId: WeCRM account id (not sourceAccountIdentifier) for createMessageMeta
1101
1101
  const accountIdForMeta =
1102
- rcsContent?.accountId != null && String(rcsContent.accountId).trim() !== ''
1103
- ? String(rcsContent.accountId)
1102
+ rcsContentFromForm?.accountId != null && String(rcsContentFromForm.accountId).trim() !== ''
1103
+ ? String(rcsContentFromForm.accountId)
1104
1104
  : undefined;
1105
1105
 
1106
1106
  const rcsRichCardContent = {
1107
1107
  contentType: RCS_TEST_META_CONTENT_TYPE_RICHCARD,
1108
- cardType: rcsContent?.cardType ?? RCS_TEST_META_CARD_TYPE_STANDALONE,
1109
- cardSettings: rcsContent?.cardSettings ?? {
1108
+ cardType: rcsContentFromForm?.cardType ?? RCS_TEST_META_CARD_TYPE_STANDALONE,
1109
+ cardSettings: rcsContentFromForm?.cardSettings ?? {
1110
1110
  cardOrientation: RCS_TEST_META_CARD_ORIENTATION_VERTICAL,
1111
1111
  cardWidth: RCS_TEST_META_CARD_WIDTH_SMALL,
1112
1112
  },
1113
- ...(cardContent.length > 0 && { cardContent }),
1113
+ ...(cardContentForTestMetaApi.length > 0 && { cardContent: cardContentForTestMetaApi }),
1114
1114
  };
1115
1115
 
1116
1116
  const rcsMessageContent = {
@@ -3299,15 +3299,7 @@ const CommonTestAndPreview = (props) => {
3299
3299
  uniqueUserIds,
3300
3300
  previewData,
3301
3301
  deliveryOverride,
3302
- channel === CHANNELS.RCS
3303
- ? {
3304
- smsFallbackTemplateContent:
3305
- smsFallbackTextForTagExtraction
3306
- || smsFallbackContent?.templateContent
3307
- || smsFallbackContent?.content
3308
- || '',
3309
- }
3310
- : {},
3302
+ {},
3311
3303
  );
3312
3304
 
3313
3305
  actions.createMessageMetaRequested(
@@ -340,6 +340,14 @@ export default defineMessages({
340
340
  id: `${scope}.videoPreviewTooltip`,
341
341
  defaultMessage: 'Video Preview',
342
342
  },
343
+ rcsCarouselPreviewTitlePlaceholder: {
344
+ id: `${scope}.rcsCarouselPreviewTitlePlaceholder`,
345
+ defaultMessage: 'Card title',
346
+ },
347
+ rcsCarouselPreviewBodyPlaceholder: {
348
+ id: `${scope}.rcsCarouselPreviewBodyPlaceholder`,
349
+ defaultMessage: 'Card description',
350
+ },
343
351
  toMe: {
344
352
  id: `${scope}.toMe`,
345
353
  defaultMessage: 'to me',
@@ -220,8 +220,10 @@ const previewAndTestReducer = (state = initialState, action) => {
220
220
  case ADD_TEST_CUSTOMER: {
221
221
  const raw = state.get('testCustomers');
222
222
  const list = Array.isArray(raw) ? raw : (raw && raw.toArray ? raw.toArray().map((i) => (i && i.toJS ? i.toJS() : i)) : []);
223
- const customer = action.payload.customer;
223
+ const customer = action.payload?.customer;
224
+ if (!customer) return state;
224
225
  const newId = customer.userId || customer.customerId;
226
+ if (!newId) return state;
225
227
  if (list.some((c) => (c.userId || c.customerId) === newId)) return state;
226
228
  return state.set('testCustomers', list.concat([customer]));
227
229
  }
@@ -161,9 +161,10 @@ export function* getBulkCustomerDetails({fetchedUserIds}) {
161
161
  const emailIdentifier = profile?.identifiers?.find(
162
162
  (identifier) => identifier.type === IDENTIFIER_TYPE_EMAIL,
163
163
  );
164
+ const nameParts = [profile?.firstName, profile?.lastName].filter(Boolean);
164
165
  return {
165
166
  userId: item?.entity?.id,
166
- name: `${profile?.firstName} ${profile?.lastName}`,
167
+ name: nameParts.join(' '),
167
168
  mobile: mobileIdentifier?.value,
168
169
  email: emailIdentifier?.value,
169
170
  };
@@ -8,7 +8,7 @@ import React from 'react';
8
8
  import { render, screen } from '@testing-library/react';
9
9
  import PreviewSection from '../PreviewSection';
10
10
 
11
- // Mock UnifiedPreview component
11
+ // Mock UnifiedPreview component (lightweight DOM for this suite only).
12
12
  const mockUnifiedPreview = jest.fn();
13
13
  jest.mock('../UnifiedPreview', () => {
14
14
  // eslint-disable-next-line global-require, import/no-extraneous-dependencies
@@ -232,3 +232,10 @@ describe('PreviewSection', () => {
232
232
  });
233
233
  });
234
234
  });
235
+
236
+ // This suite mocks ../UnifiedPreview. resetModules() alone is not enough — Jest still applies the
237
+ // manual mock on the next load. Unmock + reset so later test files in this worker get the real module.
238
+ afterAll(() => {
239
+ jest.unmock('../UnifiedPreview');
240
+ jest.resetModules();
241
+ });