@capillarytech/creatives-library 8.0.353-alpha.6 → 8.0.353

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 (124) hide show
  1. package/constants/unified.js +0 -29
  2. package/package.json +1 -1
  3. package/services/tests/api.test.js +20 -35
  4. package/utils/commonUtils.js +1 -19
  5. package/v2Components/CapActionButton/constants.js +0 -7
  6. package/v2Components/CapActionButton/index.js +108 -166
  7. package/v2Components/CapActionButton/index.scss +6 -157
  8. package/v2Components/CapActionButton/messages.js +3 -19
  9. package/v2Components/CapActionButton/tests/index.test.js +17 -41
  10. package/v2Components/CapTagList/index.js +0 -10
  11. package/v2Components/CommonTestAndPreview/CustomValuesEditor.js +49 -72
  12. package/v2Components/CommonTestAndPreview/DeliverySettings/DeliverySettings.scss +2 -8
  13. package/v2Components/CommonTestAndPreview/DeliverySettings/ModifyDeliverySettings.js +21 -213
  14. package/v2Components/CommonTestAndPreview/DeliverySettings/constants.js +0 -16
  15. package/v2Components/CommonTestAndPreview/DeliverySettings/index.js +10 -85
  16. package/v2Components/CommonTestAndPreview/DeliverySettings/messages.js +0 -30
  17. package/v2Components/CommonTestAndPreview/DeliverySettings/utils/parseSenderDetailsResponse.js +11 -79
  18. package/v2Components/CommonTestAndPreview/SendTestMessage.js +5 -10
  19. package/v2Components/CommonTestAndPreview/UnifiedPreview/RcsPreviewContent.js +15 -157
  20. package/v2Components/CommonTestAndPreview/UnifiedPreview/_unifiedPreview.scss +76 -346
  21. package/v2Components/CommonTestAndPreview/UnifiedPreview/index.js +4 -133
  22. package/v2Components/CommonTestAndPreview/_commonTestAndPreview.scss +0 -11
  23. package/v2Components/CommonTestAndPreview/constants.js +2 -38
  24. package/v2Components/CommonTestAndPreview/index.js +186 -691
  25. package/v2Components/CommonTestAndPreview/messages.js +3 -45
  26. package/v2Components/CommonTestAndPreview/sagas.js +6 -25
  27. package/v2Components/CommonTestAndPreview/tests/CustomValuesEditor.test.js +284 -308
  28. package/v2Components/CommonTestAndPreview/tests/DeliverySettings/ModifyDeliverySettings.test.js +65 -231
  29. package/v2Components/CommonTestAndPreview/tests/DeliverySettings/index.test.js +5 -118
  30. package/v2Components/CommonTestAndPreview/tests/DeliverySettings/utils/parseSenderDetailsResponse.test.js +0 -341
  31. package/v2Components/CommonTestAndPreview/tests/PreviewSection.test.js +1 -8
  32. package/v2Components/CommonTestAndPreview/tests/SendTestMessage.test.js +13 -34
  33. package/v2Components/CommonTestAndPreview/tests/UnifiedPreview/RcsPreviewContent.test.js +283 -281
  34. package/v2Components/CommonTestAndPreview/tests/UnifiedPreview/index.test.js +1 -199
  35. package/v2Components/CommonTestAndPreview/tests/index.test.js +4 -132
  36. package/v2Components/CommonTestAndPreview/tests/sagas.test.js +26 -36
  37. package/v2Components/FormBuilder/index.js +168 -63
  38. package/v2Components/TemplatePreview/_templatePreview.scss +23 -38
  39. package/v2Components/TemplatePreview/index.js +31 -143
  40. package/v2Components/TemplatePreview/tests/index.test.js +0 -142
  41. package/v2Components/TestAndPreviewSlidebox/index.js +1 -13
  42. package/v2Components/TestAndPreviewSlidebox/sagas.js +4 -11
  43. package/v2Components/TestAndPreviewSlidebox/tests/saga.test.js +1 -3
  44. package/v2Containers/CreativesContainer/SlideBoxContent.js +4 -36
  45. package/v2Containers/CreativesContainer/SlideBoxFooter.js +1 -10
  46. package/v2Containers/CreativesContainer/SlideBoxHeader.js +4 -29
  47. package/v2Containers/CreativesContainer/constants.js +0 -9
  48. package/v2Containers/CreativesContainer/index.js +163 -346
  49. package/v2Containers/CreativesContainer/index.scss +1 -51
  50. package/v2Containers/CreativesContainer/tests/SlideBoxFooter.test.js +34 -78
  51. package/v2Containers/CreativesContainer/tests/SlideBoxHeader.test.js +16 -79
  52. package/v2Containers/CreativesContainer/tests/__snapshots__/SlideBoxContent.test.js.snap +0 -8
  53. package/v2Containers/CreativesContainer/tests/__snapshots__/SlideBoxHeader.test.js.snap +98 -357
  54. package/v2Containers/CreativesContainer/tests/__snapshots__/index.test.js.snap +15 -20
  55. package/v2Containers/CreativesContainer/tests/index.test.js +9 -71
  56. package/v2Containers/MobilePush/Create/test/saga.test.js +2 -2
  57. package/v2Containers/Rcs/constants.js +10 -119
  58. package/v2Containers/Rcs/index.js +818 -2450
  59. package/v2Containers/Rcs/index.scss +8 -280
  60. package/v2Containers/Rcs/messages.js +3 -34
  61. package/v2Containers/Rcs/tests/__snapshots__/index.test.js.snap +70073 -98018
  62. package/v2Containers/Rcs/tests/__snapshots__/utils.test.js.snap +5 -0
  63. package/v2Containers/Rcs/tests/index.test.js +121 -152
  64. package/v2Containers/Rcs/tests/mockData.js +0 -38
  65. package/v2Containers/Rcs/tests/utils.test.js +30 -646
  66. package/v2Containers/Rcs/utils.js +11 -478
  67. package/v2Containers/Sms/Create/index.js +40 -106
  68. package/v2Containers/SmsTrai/Create/index.js +4 -9
  69. package/v2Containers/SmsTrai/Edit/constants.js +0 -2
  70. package/v2Containers/SmsTrai/Edit/index.js +130 -640
  71. package/v2Containers/SmsTrai/Edit/messages.js +4 -14
  72. package/v2Containers/SmsTrai/Edit/tests/__snapshots__/index.test.js.snap +2296 -4249
  73. package/v2Containers/SmsWrapper/index.js +8 -37
  74. package/v2Containers/TagList/index.js +0 -6
  75. package/v2Containers/Templates/_templates.scss +9 -166
  76. package/v2Containers/Templates/actions.js +0 -11
  77. package/v2Containers/Templates/constants.js +0 -2
  78. package/v2Containers/Templates/index.js +52 -120
  79. package/v2Containers/Templates/sagas.js +12 -56
  80. package/v2Containers/Templates/tests/__snapshots__/index.test.js.snap +1017 -1062
  81. package/v2Containers/Templates/tests/sagas.test.js +16 -199
  82. package/v2Containers/TemplatesV2/TemplatesV2.style.js +1 -72
  83. package/v2Containers/TemplatesV2/index.js +23 -86
  84. package/v2Containers/WeChat/MapTemplates/test/saga.test.js +9 -9
  85. package/v2Containers/Whatsapp/index.js +20 -3
  86. package/v2Containers/Whatsapp/tests/__snapshots__/index.test.js.snap +34 -578
  87. package/utils/rcsPayloadUtils.js +0 -92
  88. package/utils/templateVarUtils.js +0 -201
  89. package/utils/tests/rcsPayloadUtils.test.js +0 -226
  90. package/utils/tests/templateVarUtils.test.js +0 -204
  91. package/v2Components/CommonTestAndPreview/previewApiUtils.js +0 -59
  92. package/v2Components/CommonTestAndPreview/tests/previewApiUtils.test.js +0 -67
  93. package/v2Components/SmsFallback/SmsFallbackLocalSelector.js +0 -91
  94. package/v2Components/SmsFallback/constants.js +0 -73
  95. package/v2Components/SmsFallback/index.js +0 -956
  96. package/v2Components/SmsFallback/index.scss +0 -265
  97. package/v2Components/SmsFallback/messages.js +0 -78
  98. package/v2Components/SmsFallback/smsFallbackUtils.js +0 -119
  99. package/v2Components/SmsFallback/tests/SmsFallbackLocalSelector.test.js +0 -50
  100. package/v2Components/SmsFallback/tests/rcsSmsFallback.acceptance.test.js +0 -147
  101. package/v2Components/SmsFallback/tests/smsFallbackHandlers.test.js +0 -304
  102. package/v2Components/SmsFallback/tests/smsFallbackUi.test.js +0 -223
  103. package/v2Components/SmsFallback/tests/smsFallbackUtils.test.js +0 -309
  104. package/v2Components/SmsFallback/tests/useLocalTemplateList.test.js +0 -422
  105. package/v2Components/SmsFallback/useLocalTemplateList.js +0 -92
  106. package/v2Components/TemplatePreview/constants.js +0 -2
  107. package/v2Components/VarSegmentMessageEditor/constants.js +0 -2
  108. package/v2Components/VarSegmentMessageEditor/index.js +0 -125
  109. package/v2Components/VarSegmentMessageEditor/index.scss +0 -46
  110. package/v2Containers/CreativesContainer/CreativesSlideBoxWrapper.js +0 -43
  111. package/v2Containers/CreativesContainer/embeddedSlideboxUtils.js +0 -79
  112. package/v2Containers/CreativesContainer/tests/SlideBoxContent.localTemplates.test.js +0 -90
  113. package/v2Containers/CreativesContainer/tests/embeddedSlideboxUtils.test.js +0 -258
  114. package/v2Containers/CreativesContainer/tests/useLocalTemplatesProp.test.js +0 -125
  115. package/v2Containers/Rcs/rcsLibraryHydrationUtils.js +0 -225
  116. package/v2Containers/Rcs/tests/rcsLibraryHydrationUtils.test.js +0 -318
  117. package/v2Containers/Sms/smsFormDataHelpers.js +0 -67
  118. package/v2Containers/Sms/tests/smsFormDataHelpers.test.js +0 -253
  119. package/v2Containers/SmsTrai/Edit/index.scss +0 -121
  120. package/v2Containers/Templates/TemplatesActionBar.js +0 -101
  121. package/v2Containers/Templates/tests/TemplatesActionBar.test.js +0 -120
  122. package/v2Containers/Templates/tests/smsTemplatesListApi.test.js +0 -180
  123. package/v2Containers/Templates/utils/smsTemplatesListApi.js +0 -79
  124. package/v2Containers/TemplatesV2/tests/TemplatesV2.localTemplates.test.js +0 -131
@@ -160,24 +160,6 @@ export const TAG_CONTENT_REGEX = /{{([^}]+)}}/g;
160
160
  export const ENTRY_TRIGGER_TAG_REGEX = /\bentryTrigger\.\w+(?:\.\w+)?(?:\(\w+\))?/g;
161
161
  export const SKIP_TAGS_REGEX_GROUPS = ["dynamic_expiry_date_after_\\d+_days.FORMAT_\\d", "unsubscribe\\(#[a-zA-Z\\d]{6}\\)", "Link_to_[a-zA-Z]", "SURVEY.*.TOKEN", "^[A-Za-z].*\\([a-zA-Z\\d]*\\)", "referral_unique_(code|url).*userid"];
162
162
 
163
- // --- Template variable tokens (`{{var}}`, DLT `{#var#}`) ---
164
- /** Global: all `{{…}}` placeholders in a string. */
165
- export const DEFAULT_MUSTACHE_VAR_REGEX = /\{\{[^}]+\}\}/g;
166
- /** Global: `{{…}}` or DLT `{#…#}` tokens (SMS combined mode). */
167
- export const COMBINED_SMS_TEMPLATE_VAR_REGEX = /\{\{[^}]+\}\}|\{\#[^#]*\#\}/g;
168
- /** Full-string check: one mustache token. */
169
- export const MUSTACHE_VAR_TOKEN_FULL_STRING_REGEX = /^\{\{[^}]+\}\}$/;
170
- /** Full-string check: one DLT hash token. */
171
- export const DLT_HASH_VAR_TOKEN_FULL_STRING_REGEX = /^\{\#[^#]*\#\}$/;
172
- /** Full-string with capture group: inner name for `{{ name }}`-style tokens (whitespace-tolerant). */
173
- export const MUSTACHE_TOKEN_INNER_NAME_REGEX = /^\{\{\s*([^}]+?)\s*\}\}$/;
174
- /** Full-string with capture group: inner name/body for `{# name #}` DLT tokens (whitespace-tolerant). */
175
- export const DLT_HASH_TOKEN_INNER_NAME_REGEX = /^\{#\s*(.*?)\s*#\}$/;
176
- /** Global with capture group: inner name inside `{{name}}`. */
177
- export const MUSTACHE_VAR_NAME_CAPTURE_REGEX = /\{\{([^}]+)\}\}/g;
178
- /** Global with capture group: inner body inside `{#body#}`. */
179
- export const DLT_VAR_BODY_CAPTURE_REGEX = /\{\#([^#]*)\#\}/g;
180
-
181
163
  export const GET_TRANSLATION_MAPPED = {
182
164
  'en': 'en-US',
183
165
  'zh-cn': 'zh',
@@ -215,14 +197,3 @@ export const LOGOUT_FAILURE = 'cap/LOGOUT_FAILURE';
215
197
  export const JAPANESE_HELP_TEXT = 'ヘルプ :トークンの定義';
216
198
 
217
199
  export const TAG_TRANSLATION_DOC = 'https://docs.capillarytech.com/docs/tags-translation';
218
-
219
- // --- RCS SMS fallback API contract (shared across modules: campaigns, journey, etc.) ---
220
-
221
- /** Keys on `messageContent.*.smsFallBackContent` sent to the API: only `message` + `templateConfigs`.
222
- * `rcsSmsFallbackVarMapped` is editor-only — merged into `message` at normalize, not sent on the wire. */
223
- export const RCS_API_SMS_FALLBACK_KEYS = Object.freeze({
224
- MESSAGE: 'message',
225
- TEMPLATE_CONFIGS: 'templateConfigs',
226
- RCS_SMS_FALLBACK_VAR_MAPPED: 'rcsSmsFallbackVarMapped',
227
- });
228
-
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@capillarytech/creatives-library",
3
3
  "author": "meharaj",
4
- "version": "8.0.353-alpha.6",
4
+ "version": "8.0.353",
5
5
  "description": "Capillary creatives ui",
6
6
  "main": "./index.js",
7
7
  "module": "./index.es.js",
@@ -89,26 +89,21 @@ describe('uploadFile -- whatsapp image upload', () => {
89
89
 
90
90
  it('Uploads the file with the original filename when encodeURIComponent fails', async () => {
91
91
  // Mocking the encodeURIComponent function to throw an error
92
- const originalEncodeURIComponent = global.encodeURIComponent;
93
92
  global.encodeURIComponent = jest.fn(() => { throw new Error('encodeURIComponent error'); });
94
93
  const blob = new Blob([''], { type: 'image/jpeg' });
95
94
  const file = new File([blob], '@%test.jpeg', { type: 'image/jpeg' });
96
- try {
97
- expect(
98
- uploadFile({
99
- file,
100
- assetType: 'image',
101
- fileParams: {
102
- width: 275,
103
- height: 183,
104
- error: false,
105
- },
106
- whatsappParams: {},
107
- }),
108
- ).toEqual(Promise.resolve());
109
- } finally {
110
- global.encodeURIComponent = originalEncodeURIComponent;
111
- }
95
+ expect(
96
+ uploadFile({
97
+ file,
98
+ assetType: 'image',
99
+ fileParams: {
100
+ width: 275,
101
+ height: 183,
102
+ error: false,
103
+ },
104
+ whatsappParams: {},
105
+ }),
106
+ ).toEqual(Promise.resolve());
112
107
  });
113
108
  });
114
109
 
@@ -1042,26 +1037,16 @@ describe('getMembersLookup', () => {
1042
1037
  expect(result).toBeInstanceOf(Promise);
1043
1038
  });
1044
1039
 
1045
- it('should call fetch with correct URL encoding and GET method', async () => {
1040
+ it('should call fetch with correct URL encoding and GET method', () => {
1046
1041
  global.fetch.mockClear();
1047
- await getMembersLookup('email', 'user+test@example.com');
1042
+ getMembersLookup('email', 'user+test@example.com');
1048
1043
  expect(global.fetch).toHaveBeenCalled();
1049
-
1050
- // Find the first call that uses both the members endpoint and proper encoding
1051
- const call = global.fetch.mock.calls.find(
1052
- ([url]) =>
1053
- url &&
1054
- url.includes('members') &&
1055
- url.includes('identifierType=email') &&
1056
- url.includes('identifierValue=user%2Btest%40example.com')
1057
- );
1058
- expect(call).toBeDefined();
1059
-
1060
- // Check URL structure
1061
- const [url, options] = call;
1062
- expect(url).toContain('identifierType=email');
1063
- expect(url).toContain('identifierValue=user%2Btest%40example.com');
1064
- expect((options && options.method) || 'GET').toBe('GET');
1044
+ const calls = global.fetch.mock.calls;
1045
+ const anyMembersCall = calls.find((c) => c[0] && String(c[0]).includes('members'));
1046
+ expect(anyMembersCall).toBeDefined();
1047
+ expect(anyMembersCall[0]).toContain('identifierType=');
1048
+ expect(anyMembersCall[0]).toContain('identifierValue=');
1049
+ expect(anyMembersCall[1]?.method || 'GET').toBe('GET');
1065
1050
  });
1066
1051
  });
1067
1052
 
@@ -539,22 +539,4 @@ export const isValidMobile = (mobile) => PHONE_REGEX.test(mobile);
539
539
  export const formatPhoneNumber = (phone) => {
540
540
  if (!phone) return '';
541
541
  return String(phone).replace(/[^\d]/g, '');
542
- };
543
-
544
- /**
545
- * TRAI sender IDs on persisted RCS SMS fallback: may live on the merged object, under
546
- * `templateConfigs`, or (legacy) `templateConfigs.header`. Same resolution order as
547
- * `createPayload` in `Rcs/index.js`.
548
- */
549
- export function extractRegisteredSenderIdsFromSmsFallbackRecord(record) {
550
- if (!record || typeof record !== 'object') return null;
551
- const tc = record.templateConfigs && typeof record.templateConfigs === 'object'
552
- ? record.templateConfigs
553
- : {};
554
- const candidates = [record.registeredSenderIds, tc.registeredSenderIds, tc.header];
555
- for (let i = 0; i < candidates.length; i += 1) {
556
- const a = candidates[i];
557
- if (Array.isArray(a) && a.length > 0) return a;
558
- }
559
- return null;
560
- }
542
+ };
@@ -32,13 +32,6 @@ export const CTA_OPTIONS = [
32
32
  ];
33
33
 
34
34
  export const invalidVarRegex = /{{(.*?)}}/g;
35
-
36
- /** URL CTA subtype (Figma: URL type dropdown). */
37
- export const RCS_CTA_URL_TYPE = {
38
- STATIC: 'STATIC',
39
- DYNAMIC: 'DYNAMIC',
40
- };
41
-
42
35
  export const BTN_MAX_LENGTH = 25;
43
36
  export const PHONE_NUMBER_MAX_LENGTH = 15;
44
37
  export const URL_MAX_LENGTH = 2000;
@@ -8,7 +8,6 @@ import CapRow from '@capillarytech/cap-ui-library/CapRow';
8
8
  import CapColumn from '@capillarytech/cap-ui-library/CapColumn';
9
9
  import CapHeading from '@capillarytech/cap-ui-library/CapHeading';
10
10
  import CapHeader from "@capillarytech/cap-ui-library/CapHeader";
11
- import CapRadioGroup from '@capillarytech/cap-ui-library/CapRadioGroup';
12
11
  import CapSelect from '@capillarytech/cap-ui-library/CapSelect';
13
12
  import CapInput from '@capillarytech/cap-ui-library/CapInput';
14
13
  import CapIcon from '@capillarytech/cap-ui-library/CapIcon';
@@ -21,16 +20,9 @@ import globalMessages from '../../v2Containers/Cap/messages';import CapTagListWi
21
20
 
22
21
  import { isUrl, isValidText } from '../../v2Containers/Line/Container/Wrapper/utils';
23
22
  import messages from './messages';
24
- import {
25
- BTN_MAX_LENGTH,
26
- URL_MAX_LENGTH,
27
- PHONE_NUMBER_MAX_LENGTH,
28
- invalidVarRegex,
29
- HANDLERS,
30
- RCS_CTA_URL_TYPE,
31
- } from './constants';
23
+ import { CTA_OPTIONS, BTN_MAX_LENGTH, URL_MAX_LENGTH, PHONE_NUMBER_MAX_LENGTH,invalidVarRegex, HANDLERS } from './constants';
32
24
  import './index.scss';
33
- import { INITIAL_SUGGESTIONS, RCS_BUTTON_TYPES, HOST_ICS} from '../../v2Containers/Rcs/constants';
25
+ import { INITIAL_SUGGESTIONS, RCS_BUTTON_TYPES} from '../../v2Containers/Rcs/constants';
34
26
 
35
27
  const { TextArea } = CapInput;
36
28
 
@@ -49,12 +41,9 @@ export const CapActionButton = (props) => {
49
41
  injectedTags = {},
50
42
  location = {},
51
43
  selectedOfferDetails = [],
52
- host = '',
44
+
53
45
  onContextChange,
54
- minSavedSuggestions = 0,
55
- hideDeleteSuggestionIndexes = [],
56
46
  } = props;
57
- const isHostIcs = host === HOST_ICS;
58
47
  const [urlError, setUrlError] = useState(false);
59
48
  const [buttonError, setButtonError] = useState(false);
60
49
  const updateHandler = (type, value, index) => {
@@ -77,7 +66,6 @@ export const CapActionButton = (props) => {
77
66
 
78
67
  const onCtaTypeChange = (value, index) => {
79
68
  let clonedCta = cloneDeep(suggestions[index]);
80
- const isCta = value === RCS_BUTTON_TYPES.CTA;
81
69
  clonedCta = {
82
70
  ...clonedCta,
83
71
  type: value,
@@ -85,7 +73,6 @@ export const CapActionButton = (props) => {
85
73
  phoneNumber: '',
86
74
  postback: '',
87
75
  url: value === RCS_BUTTON_TYPES.PHONE_NUMBER ? null : '',
88
- urlType: isCta ? RCS_CTA_URL_TYPE.STATIC : undefined,
89
76
  isSaved: false,
90
77
  };
91
78
  setUrlError(false);
@@ -105,61 +92,39 @@ export const CapActionButton = (props) => {
105
92
  updateDisplayAndPostback(value, id);
106
93
  };
107
94
 
108
- const renderInnerCharCount = (len, max) => (
109
- <CapHeading type="h5" className="rcs-cta-inner-char-count">
110
- {formatMessage(messages.ctaFieldCharCountInline, { current: len, max })}
95
+ const renderLength = (len, max) => (
96
+ <CapHeading type="label1" className="rcs-render-btn-length">
97
+ {formatMessage(messages.templateMessageLength, {
98
+ currentLength: len,
99
+ maxLength: max,
100
+ })}
111
101
  </CapHeading>
112
102
  );
113
103
 
114
- const validateCtaUrlValue = (value, urlSubtype) => {
115
- const v = String(value || '').trim();
116
- if (!v) {
117
- return formatMessage(messages.ctaWebsiteUrlErrorMessage);
118
- }
119
- if (v.length > URL_MAX_LENGTH) {
120
- return formatMessage(messages.ctaWebsiteUrlErrorMessage);
121
- }
122
- if (urlSubtype === RCS_CTA_URL_TYPE.DYNAMIC) {
123
- return false;
124
- }
125
- if (!isUrl(v)) {
126
- return formatMessage(messages.ctaWebsiteUrlErrorMessage);
127
- }
128
- if (v.match(invalidVarRegex)?.length > 0) {
129
- return formatMessage(messages.staticUrlWithVarErrorMessage);
130
- }
131
- return false;
132
- };
133
-
134
104
  const onUrlChange = ({ target }) => {
135
- const { value, id } = target;
136
- const row = suggestions[id] || {};
137
- const subtype = row.urlType || RCS_CTA_URL_TYPE.STATIC;
138
- setUrlError(validateCtaUrlValue(value, subtype));
105
+ let { value, id } = target;
106
+ let errorMessage = false;
107
+ if (!isUrl(value)) {
108
+ errorMessage = formatMessage(messages.ctaWebsiteUrlErrorMessage);
109
+ } else if (value.match(invalidVarRegex)?.length > 0) {
110
+ errorMessage = formatMessage(messages.staticUrlWithVarErrorMessage);
111
+ }
112
+ setUrlError(errorMessage);
139
113
  updateHandler(HANDLERS.URL, value, id);
140
114
  };
141
115
 
142
- const onUrlSubtypeChange = (nextSubtype, index) => {
143
- const cloned = cloneDeep(suggestions[index]);
144
- cloned.urlType = nextSubtype;
145
- cloned.isSaved = false;
146
- setUrlError(validateCtaUrlValue(cloned.url || '', nextSubtype));
147
- updateButtonChange(cloned, index);
148
- };
149
-
150
116
  const onPhoneNoChange = (value, index) => {
151
117
  updateHandler(HANDLERS.PHONE_NUMBER, value, index);
152
118
  };
153
119
 
154
120
  const ctaSaveDisabled = (index) => {
155
- const { type, text, phoneNumber, url, urlType } = suggestions[index] || {};
121
+ const { type, text, phoneNumber, url } = suggestions[index] || {};
156
122
  if (text === '' || buttonError) {
157
123
  return true;
158
- } if (type === RCS_BUTTON_TYPES.PHONE_NUMBER && (phoneNumber || '').length < 5) {
124
+ } if (type === RCS_BUTTON_TYPES.PHONE_NUMBER && phoneNumber.length < 5) {
125
+ return true;
126
+ } if (type === RCS_BUTTON_TYPES.CTA && (url === '' || urlError)) {
159
127
  return true;
160
- } if (type === RCS_BUTTON_TYPES.CTA) {
161
- const subtype = urlType || RCS_CTA_URL_TYPE.STATIC;
162
- return !!validateCtaUrlValue(url, subtype);
163
128
  }
164
129
  return false;
165
130
  };
@@ -178,58 +143,64 @@ export const CapActionButton = (props) => {
178
143
  updateButtonChange(newSuggestion, suggestions?.length);
179
144
  };
180
145
 
146
+ const renderCtaOptions = (label, tooltipLabel, isDisabled) => {
147
+ if (isDisabled) {
148
+ return (
149
+ <CapRow>
150
+ <CapColumn span={23}>{label}</CapColumn>
151
+ <CapColumn span={1}>
152
+ <CapTooltipWithInfo
153
+ // autoAdjustOverflow
154
+ placement="right"
155
+ title={tooltipLabel}
156
+ />
157
+ </CapColumn>
158
+ </CapRow>
159
+ );
160
+ }
161
+ return label;
162
+ };
163
+
181
164
  const { formatMessage } = intl;
182
165
  const renderedContent = () => {
183
166
  const renderArray = [];
184
- const addBtnDisabled = suggestions?.length > 0 && (suggestions.length >= maxButtons || !suggestions[suggestions.length - 1]?.isSaved);
185
- const savedSuggestionsCount = (suggestions || []).filter((s) => s && s.isSaved).length;
186
- const cannotDeleteSavedMandatory = (idx) => {
187
- const row = suggestions[idx];
188
- if (!row || !row.isSaved) return false;
189
- return minSavedSuggestions > 0 && savedSuggestionsCount <= minSavedSuggestions;
190
- };
191
-
192
- const hideDeleteForSuggestionIndex = (idx) =>
193
- Array.isArray(hideDeleteSuggestionIndexes) && hideDeleteSuggestionIndexes.includes(idx);
194
-
195
- const ctaTypeRadioOptions = [
196
- { label: formatMessage(messages.ctaPhoneNo), value: RCS_BUTTON_TYPES.PHONE_NUMBER },
197
- { label: formatMessage(messages.ctaUrlRadio), value: RCS_BUTTON_TYPES.CTA },
198
- { label: formatMessage(messages.ctaQr), value: RCS_BUTTON_TYPES.QUICK_REPLY },
199
- ];
167
+ const addBtnDisabled = suggestions.length >= maxButtons || !suggestions[suggestions.length - 1]?.isSaved;
200
168
 
201
- const urlTypeSelectOptions = [
202
- { value: RCS_CTA_URL_TYPE.STATIC, label: formatMessage(messages.ctaWebsiteTypeStatic) },
203
- { value: RCS_CTA_URL_TYPE.DYNAMIC, label: formatMessage(messages.ctaWebsiteTypeDynamic) },
204
- ];
169
+ const ctaOptions = CTA_OPTIONS.map((option) => {
170
+ const { value, label } = option;
171
+ const isDisabled = suggestions.length >= maxButtons && !suggestions[suggestions.length - 1];
172
+ return {
173
+ value,
174
+ label: renderCtaOptions(label, formatMessage(messages.ctaButtonTypeDisabled), isDisabled),
175
+ disabled: isDisabled,
176
+ };
177
+ });
205
178
 
206
- suggestions?.length > 0 && suggestions.forEach((cta) => {
179
+ suggestions.forEach((cta) => {
207
180
  const {
208
181
  index, type, text, isSaved,
209
182
  } = cta || {};
210
183
 
211
184
  const url = type !== RCS_BUTTON_TYPES.CTA ? null : cta.url;
212
- const urlSubtype = type === RCS_BUTTON_TYPES.CTA
213
- ? (cta.urlType || RCS_CTA_URL_TYPE.STATIC)
214
- : RCS_CTA_URL_TYPE.STATIC;
215
185
  const phoneNumber = type !== RCS_BUTTON_TYPES.PHONE_NUMBER ? null : cta.phoneNumber;
216
186
  if (isFullMode && !isEditFlow && !isSaved) {
217
187
  renderArray.push(
218
- <CapRow className="rcs-button-cta-create-container" key={`cta-edit-${index}`} gutter={0}>
219
- <CapRow className="rcs-button-cta-create" gutter={0}>
220
- <CapColumn span={24}>
221
- <CapHeading type="h4">
188
+ <div className="rcs-button-cta-create-container" key={`cta-edit-${index}`}>
189
+ <CapRow className="rcs-button-cta-create margin-t-16">
190
+ <CapColumn span={12}>
191
+ {/* Type of action */}
192
+ <CapHeading type="h4" className="cta-label">
222
193
  {formatMessage(messages.ctaType)}
223
194
  </CapHeading>
224
- <CapRadioGroup
225
- id={`rcs-cta-type-radio-${index}`}
226
- className="cap-rcs-cta-type-radio"
227
- options={ctaTypeRadioOptions}
195
+ <CapSelect
196
+ id="rcs-cta-type"
197
+ options={ctaOptions || []}
198
+ onChange={(value) => onCtaTypeChange(value, index)}
228
199
  value={type}
229
- onChange={(e) => onCtaTypeChange(e.target.value, index)}
200
+ disabled={false}
230
201
  />
231
202
  </CapColumn>
232
- <CapColumn span={24}>
203
+ <CapColumn span={12}>
233
204
  <CapHeading type="h4" className="cta-label">
234
205
  {formatMessage(messages.ctaButtonText)}
235
206
  <CapTooltipWithInfo
@@ -250,34 +221,28 @@ export const CapActionButton = (props) => {
250
221
  size="large"
251
222
  maxLength={BTN_MAX_LENGTH}
252
223
  errorMessage={buttonError}
253
- suffix={renderInnerCharCount((text || '').length, BTN_MAX_LENGTH)}
254
224
  />
225
+ {renderLength(text.length, BTN_MAX_LENGTH)}
255
226
  </CapColumn>
256
227
  </CapRow>
257
228
  {type === RCS_BUTTON_TYPES.PHONE_NUMBER && (
258
229
  <>
259
230
  <CapRow>
260
- <CapColumn span={24}>
231
+ <CapColumn span={11}>
232
+ {/* phone number */}
261
233
  <CapHeading type="h4" className="cta-label">
262
234
  {formatMessage(messages.ctaPhoneNo)}
263
235
  </CapHeading>
264
- <CapRow
265
- className="rcs-cta-input-with-inner-count rcs-cta-input-with-inner-count--phone"
266
- gutter={0}
267
- >
268
- <CapColumn span={24}>
269
- <PhoneInput
270
- placeholder={formatMessage(messages.ctaPhoneNoPlaceholder)}
271
- autoFormat={false}
272
- countryCodeEditable={false}
273
- value={phoneNumber}
274
- onChange={(value) => onPhoneNoChange(value, index)}
275
- country="in"
276
- className="cta-phone-number rcs-cta-phone-input"
277
- />
278
- {renderInnerCharCount((phoneNumber || '').length, PHONE_NUMBER_MAX_LENGTH)}
279
- </CapColumn>
280
- </CapRow>
236
+ <PhoneInput
237
+ placeholder={formatMessage(messages.ctaPhoneNoPlaceholder)}
238
+ autoFormat={false}
239
+ countryCodeEditable={false}
240
+ value={phoneNumber}
241
+ onChange={(value) => onPhoneNoChange(value, index)}
242
+ country="in"
243
+ className="cta-phone-number"
244
+ />
245
+ {renderLength(phoneNumber.length, PHONE_NUMBER_MAX_LENGTH)}
281
246
  </CapColumn>
282
247
  </CapRow>
283
248
  <CapRow className="rcs-cta-save-delete-btn">
@@ -285,7 +250,7 @@ export const CapActionButton = (props) => {
285
250
  title={ctaSaveDisabled(index) && formatMessage(messages.ctaSaveDisabled)}
286
251
  placement="bottom"
287
252
  >
288
- <CapRow className="button-disabled-tooltip-wrapper">
253
+ <div className="button-disabled-tooltip-wrapper">
289
254
  <CapButton
290
255
  onClick={() => saveCta(index)}
291
256
  disabled={ctaSaveDisabled(index)}
@@ -293,49 +258,36 @@ export const CapActionButton = (props) => {
293
258
  >
294
259
  {formatMessage(globalMessages.save)}
295
260
  </CapButton>
296
- </CapRow>
261
+ </div>
297
262
  </CapTooltip>
298
- {!hideDeleteForSuggestionIndex(index) && !cannotDeleteSavedMandatory(index) && (
299
- <CapButton
300
- onClick={() => deleteButtonHandler(index)}
301
- className="rcs-cta-delete-btn"
302
- type="secondary"
303
- >
304
- {formatMessage(globalMessages.delete)}
305
- </CapButton>
306
- )}
263
+ <CapButton
264
+ onClick={() => deleteButtonHandler(index)}
265
+ className="rcs-cta-delete-btn"
266
+ type="secondary"
267
+ >
268
+ {formatMessage(globalMessages.delete)}
269
+ </CapButton>
307
270
  </CapRow>
308
271
  </>
309
272
  )}
310
273
  {type === RCS_BUTTON_TYPES.CTA && (
311
274
  <>
312
- <CapRow className="rcs-cta-url-fields-row" gutter={8}>
313
- <CapColumn span={6} className="rcs-cta-url-type-col">
314
- <CapHeading type="h4" className="cta-label">
315
- {formatMessage(messages.ctaWebsiteType)}
316
- </CapHeading>
317
- <CapSelect
318
- id={`rcs-cta-url-type-${index}`}
319
- options={urlTypeSelectOptions}
320
- value={urlSubtype}
321
- onChange={(value) => onUrlSubtypeChange(value, index)}
322
- />
323
- </CapColumn>
324
- <CapColumn span={18} className="rcs-cta-url-value-col">
275
+ <CapRow>
276
+ <CapColumn span={24}>
325
277
  <CapHeading type="h4" className="cta-label">
326
- {formatMessage(messages.ctaUrlField)}
278
+ {formatMessage(messages.ctaWebsite)}
327
279
  </CapHeading>
328
280
  <CapInput
329
281
  id={index}
330
282
  className="rcs-cta-url"
331
283
  onChange={onUrlChange}
332
- placeholder={formatMessage(messages.ctaEnterUrlPlaceholder)}
333
- value={url || ''}
284
+ placeholder={formatMessage(messages.ctaStaticPlaceholder)}
285
+ value={url}
334
286
  size="large"
335
287
  maxLength={URL_MAX_LENGTH}
336
288
  errorMessage={urlError}
337
- suffix={renderInnerCharCount((url || '').length, URL_MAX_LENGTH)}
338
289
  />
290
+ {renderLength(url.length, URL_MAX_LENGTH)}
339
291
  </CapColumn>
340
292
  </CapRow>
341
293
  <CapRow className="rcs-cta-save-delete-btn">
@@ -345,7 +297,7 @@ export const CapActionButton = (props) => {
345
297
  }
346
298
  placement="bottom"
347
299
  >
348
- <CapRow className="button-disabled-tooltip-wrapper">
300
+ <div className="button-disabled-tooltip-wrapper">
349
301
  <CapButton
350
302
  onClick={() => saveCta(index)}
351
303
  disabled={ctaSaveDisabled(index)}
@@ -353,17 +305,15 @@ export const CapActionButton = (props) => {
353
305
  >
354
306
  {formatMessage(globalMessages.save)}
355
307
  </CapButton>
356
- </CapRow>
308
+ </div>
357
309
  </CapTooltip>
358
- {!hideDeleteForSuggestionIndex(index) && !cannotDeleteSavedMandatory(index) && (
359
- <CapButton
360
- onClick={() => deleteButtonHandler(index)}
361
- className="rcs-cta-delete-btn"
362
- type="secondary"
363
- >
364
- {formatMessage(globalMessages.delete)}
365
- </CapButton>
366
- )}
310
+ <CapButton
311
+ onClick={() => deleteButtonHandler(index)}
312
+ className="rcs-cta-delete-btn"
313
+ type="secondary"
314
+ >
315
+ {formatMessage(globalMessages.delete)}
316
+ </CapButton>
367
317
  </CapRow>
368
318
  </>
369
319
  )}
@@ -373,7 +323,7 @@ export const CapActionButton = (props) => {
373
323
  title={ctaSaveDisabled(index) && formatMessage(messages.ctaSaveDisabled)}
374
324
  placement="bottom"
375
325
  >
376
- <CapRow className="button-disabled-tooltip-wrapper">
326
+ <div className="button-disabled-tooltip-wrapper">
377
327
  <CapButton
378
328
  onClick={() => saveCta(index)}
379
329
  disabled={ctaSaveDisabled(index)}
@@ -381,9 +331,9 @@ export const CapActionButton = (props) => {
381
331
  >
382
332
  {formatMessage(globalMessages.save)}
383
333
  </CapButton>
384
- </CapRow>
334
+ </div>
385
335
  </CapTooltip>
386
- {!(isHostIcs && index === 0) && !hideDeleteForSuggestionIndex(index) && !cannotDeleteSavedMandatory(index) && (
336
+ {index !== 0 && (
387
337
  <CapButton
388
338
  onClick={() => deleteButtonHandler(index)}
389
339
  className="rcs-cta-delete-btn"
@@ -394,12 +344,12 @@ export const CapActionButton = (props) => {
394
344
  )}
395
345
  </CapRow>
396
346
  )}
397
- </CapRow>
347
+ </div>
398
348
  );
399
349
  } else {
400
350
  const ctaIsPhone = type === RCS_BUTTON_TYPES.PHONE_NUMBER;
401
351
  const ctaIsReply = type === RCS_BUTTON_TYPES.QUICK_REPLY;
402
- suggestions?.length > 0 && renderArray?.push(
352
+ renderArray.push(
403
353
  <CapRow
404
354
  key={`cta-saved-${index}`}
405
355
  className="cap-rcs-saved-cta margin-t-12"
@@ -429,9 +379,7 @@ export const CapActionButton = (props) => {
429
379
  <>
430
380
  <CapColumn span={3}>
431
381
  <CapLabel className="url-type" type="label2">
432
- {(cta.urlType || RCS_CTA_URL_TYPE.STATIC) === RCS_CTA_URL_TYPE.DYNAMIC
433
- ? formatMessage(messages.ctaWebsiteTypeDynamic)
434
- : formatMessage(messages.ctaWebsiteTypeStatic)}
382
+ {formatMessage(messages.ctaWebsiteTypeStatic)}
435
383
  </CapLabel>
436
384
  </CapColumn>
437
385
  <CapTooltip title={url} placement={'top'}>
@@ -450,7 +398,7 @@ export const CapActionButton = (props) => {
450
398
  >
451
399
  <CapIcon size="s" type="edit" />
452
400
  </CapColumn>
453
- {!(isHostIcs && index === 0) && !hideDeleteForSuggestionIndex(index) && !cannotDeleteSavedMandatory(index) && (
401
+ {index !== 0 && (
454
402
  <CapColumn className="rcs-saved-cta-delete-icon" span={1} onClick={() => deleteButtonHandler(index)}>
455
403
  <CapIcon size="s" type="delete" />
456
404
  </CapColumn>
@@ -462,7 +410,7 @@ export const CapActionButton = (props) => {
462
410
  }
463
411
  });
464
412
  {
465
- suggestions?.length < maxButtons &&
413
+ suggestions.length < maxButtons &&
466
414
  (isFullMode && !isEditFlow)
467
415
  && renderArray.push(
468
416
  <CapRow>
@@ -472,7 +420,7 @@ export const CapActionButton = (props) => {
472
420
  }
473
421
  placement={'right'}
474
422
  >
475
- <CapRow className="button-disabled-tooltip-wrapper">
423
+ <div className="button-disabled-tooltip-wrapper">
476
424
  <CapButton
477
425
  type="flat"
478
426
  id="rcs-cta-add-button"
@@ -483,7 +431,7 @@ export const CapActionButton = (props) => {
483
431
  >
484
432
  {formatMessage(messages.addButton)}
485
433
  </CapButton>
486
- </CapRow>
434
+ </div>
487
435
  </CapTooltip>
488
436
  </CapRow>,
489
437
  );
@@ -496,8 +444,6 @@ export const CapActionButton = (props) => {
496
444
  CapActionButton.propTypes = {
497
445
  intl: intlShape.isRequired,
498
446
  updateButtonChange: PropTypes.func,
499
- minSavedSuggestions: PropTypes.number,
500
- hideDeleteSuggestionIndexes: PropTypes.arrayOf(PropTypes.number),
501
447
  suggestions: PropTypes.array,
502
448
  tags: PropTypes.array,
503
449
  injectedTags: PropTypes.object,
@@ -505,15 +451,12 @@ CapActionButton.propTypes = {
505
451
  selectedOfferDetails: PropTypes.array,
506
452
  onTagSelect: PropTypes.func,
507
453
  onContextChange: PropTypes.func,
508
- host: PropTypes.string,
509
454
  };
510
455
 
511
456
  CapActionButton.defaultProps = {
512
457
  buttonTextlen: 20,
513
458
  type: '',
514
459
  updateButtonChange: () => {},
515
- minSavedSuggestions: 0,
516
- hideDeleteSuggestionIndexes: [],
517
460
  suggestions: [],
518
461
  tags: [],
519
462
  injectedTags: {},
@@ -521,7 +464,6 @@ CapActionButton.defaultProps = {
521
464
  selectedOfferDetails: [],
522
465
  onTagSelect: () => {},
523
466
  onContextChange: () => {},
524
- host: '',
525
467
  };
526
468
 
527
469
  export default injectIntl(CapActionButton);