@capillarytech/creatives-library 9.0.36-alpha.0 → 9.0.36

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 (61) hide show
  1. package/app.js +175 -10
  2. package/entry.js +1 -67
  3. package/mfe-exposed-components.js +4 -2
  4. package/package.json +2 -2
  5. package/services/api.js +1 -9
  6. package/styles/containers/layout/_layoutPage.scss +6 -8
  7. package/utils/gtmTrackers/gtmEvents/creativeDetails.js +1 -2
  8. package/utils/rcsPayloadUtils.js +2 -5
  9. package/utils/tests/rcsPayloadUtils.test.js +2 -54
  10. package/v2Components/CapActionButton/constants.js +0 -1
  11. package/v2Components/CapActionButton/index.js +9 -77
  12. package/v2Components/CapActionButton/index.scss +0 -13
  13. package/v2Components/CapActionButton/messages.js +0 -13
  14. package/v2Components/CapActionButton/tests/index.test.js +1 -32
  15. package/v2Components/CommonTestAndPreview/UnifiedPreview/ViberPreviewContent.js +15 -108
  16. package/v2Components/CommonTestAndPreview/UnifiedPreview/_unifiedPreview.scss +1 -139
  17. package/v2Components/CommonTestAndPreview/index.js +41 -284
  18. package/v2Components/CommonTestAndPreview/tests/UnifiedPreview/ViberPreviewContent.test.js +0 -364
  19. package/v2Components/CommonTestAndPreview/tests/index.test.js +0 -78
  20. package/v2Components/CommonTestAndPreview/utils.js +0 -34
  21. package/v2Components/NavigationBar/index.js +7 -9
  22. package/v2Components/NavigationBar/tests/index.test.js +19 -39
  23. package/v2Components/SmsFallback/index.js +0 -6
  24. package/v2Containers/Cap/constants.js +0 -1
  25. package/v2Containers/Cap/index.js +27 -57
  26. package/v2Containers/CreativesContainer/index.js +8 -11
  27. package/v2Containers/CreativesContainer/tests/index.test.js +0 -53
  28. package/v2Containers/Rcs/carouselUtils.js +73 -46
  29. package/v2Containers/Rcs/components/CarouselCard.js +9 -11
  30. package/v2Containers/Rcs/components/CarouselCardButtons.js +0 -20
  31. package/v2Containers/Rcs/constants.js +7 -2
  32. package/v2Containers/Rcs/index.js +205 -226
  33. package/v2Containers/Rcs/rcsLibraryHydrationUtils.js +47 -60
  34. package/v2Containers/Rcs/tests/CarouselCard.test.js +2 -1
  35. package/v2Containers/Rcs/tests/__snapshots__/index.test.js.snap +0 -286
  36. package/v2Containers/Rcs/tests/carouselUtils.test.js +32 -28
  37. package/v2Containers/Rcs/tests/index.test.js +238 -151
  38. package/v2Containers/Rcs/tests/rcsLibraryHydrationUtils.test.js +0 -110
  39. package/v2Containers/Rcs/tests/utils.test.js +17 -36
  40. package/v2Containers/Rcs/utils.js +55 -28
  41. package/v2Containers/SmsTrai/Edit/index.js +24 -35
  42. package/v2Containers/Templates/_templates.scss +1 -115
  43. package/v2Containers/Templates/index.js +10 -91
  44. package/v2Containers/Templates/tests/__snapshots__/index.test.js.snap +0 -5
  45. package/v2Containers/TemplatesV2/TemplatesV2.style.js +3 -8
  46. package/v2Containers/TemplatesV2/index.js +9 -22
  47. package/v2Containers/Viber/constants.js +0 -21
  48. package/v2Containers/Viber/index.js +49 -719
  49. package/v2Containers/Viber/index.scss +0 -175
  50. package/v2Containers/Viber/messages.js +0 -121
  51. package/v2Containers/Viber/tests/index.test.js +0 -80
  52. package/AppRoot.js +0 -124
  53. package/app-config.js +0 -61
  54. package/bootstrap.js +0 -185
  55. package/utils/getDataLayer.js +0 -15
  56. package/utils/mfeDetect.js +0 -1
  57. package/utils/mfeFirstPaintReady.js +0 -29
  58. package/utils/mfeHistory.js +0 -62
  59. package/v2Components/CommonTestAndPreview/UnifiedPreview/ViberCarouselPreviewCards.js +0 -132
  60. package/v2Components/CommonTestAndPreview/UnifiedPreview/_viberCarouselPreviewCards.scss +0 -131
  61. package/v2Components/NavigationBar/mfeModuleHeader.config.js +0 -16
package/app.js CHANGED
@@ -1,10 +1,175 @@
1
- /**
2
- * app.js
3
- *
4
- * Async boundary for Module Federation. Shared deps (react, react-dom, …) are
5
- * configured with `eager: false` in the production build, so the entry module
6
- * must not import them synchronously — webpack needs this dynamic import to
7
- * load the shared-scope modules before any application code runs. All real
8
- * bootstrap code lives in bootstrap.js.
9
- */
10
- import('./bootstrap');
1
+ import 'babel-polyfill';
2
+ import 'whatwg-fetch';
3
+ import React from 'react';
4
+ import { createRoot } from 'react-dom/client';
5
+ import { Provider } from 'react-redux';
6
+ // import createHistory from 'history/lib/createBrowserHistory';
7
+ // import { applyRouterMiddleware, Router, useRouterHistory } from 'react-router';
8
+ // import { useScroll } from 'react-router-scroll';
9
+ import history from 'utils/history';
10
+ import CapSomethingWentWrong from '@capillarytech/cap-ui-library/CapSomethingWentWrong';
11
+ import { addLocizeSavedHandler, startStandalone } from 'locize';
12
+ import Bugsnag from '@bugsnag/js';
13
+ import BugsnagPluginReact from '@bugsnag/plugin-react';
14
+ // import { makeSelectLocationState } from 'containers/Cap/selectors';
15
+ import LanguageProvider from 'v2Containers/LanguageProvider';
16
+ import FontFaceObserver from 'fontfaceobserver';
17
+ /* eslint-disable import/no-unresolved, import/extensions */
18
+ import '!file-loader?name=[name].[ext]!./favicon.ico';
19
+ /* eslint-enable import/no-unresolved, import/extensions */
20
+ import { configureStore } from '@capillarytech/vulcan-react-sdk/utils';
21
+ import { initialReducer } from './initialReducer';
22
+ import { translationMessages } from './i18n';
23
+ import './global-styles';
24
+ import initialState from './initialState';
25
+ import './styles/vendor/semantic/dist/semantic.min.css';
26
+ import './styles/main.scss';
27
+ import pathConfig from './config/path';
28
+ import ignoredErrorMessages from './utils/ignoredErrorMessages';
29
+ import App from './containers/App';
30
+ import ConfigProvider from 'antd/lib/config-provider';
31
+ import { getCapThemeConfig, loadCapUI } from '@capillarytech/cap-ui-library/utils';
32
+
33
+ loadCapUI();
34
+
35
+ try {
36
+ const { setupNewrelicWebVitals } = require('./newRelic/utils');
37
+ // Setup New Relic WebVitals tracking
38
+ setupNewrelicWebVitals();
39
+ } catch (error) {
40
+ Bugsnag.notify(error);
41
+ }
42
+
43
+ // const browserHistory = useRouterHistory(createHistory)({
44
+ // basename: pathConfig.publicPath,
45
+ // });
46
+
47
+ const store = configureStore(initialState, initialReducer, history);
48
+ const MOUNT_NODE = document.getElementById('app');
49
+
50
+ // const history = syncHistoryWithStore(browserHistory, store, {
51
+ // selectLocationState: makeSelectLocationState(),
52
+ // });
53
+ const BUGSNAG_APP_VERSION = `creatives-ui__${new Date().getTime()}`;
54
+ const BUGSNAG_API_KEY = 'c4d96446438ff7dc7c08da08ef94c5b2';
55
+
56
+ const bugSnagErrorCallback = (event) => {
57
+ const { app: { releaseStage } = {}, originalError } = event || {};
58
+ const errorMessage = originalError && originalError.message;
59
+ if (
60
+ (releaseStage || '').includes('nightly') ||
61
+ process.env.NODE_ENV !== 'production' ||
62
+ ignoredErrorMessages.includes(errorMessage)
63
+ ) {
64
+ return false;
65
+ }
66
+ let userId;
67
+ let userName;
68
+ let userEmail;
69
+ let orgId;
70
+ let orgName;
71
+ try {
72
+ const {
73
+ id,
74
+ firstName,
75
+ lastName,
76
+ loginName,
77
+ proxyOrgList,
78
+ } = JSON.parse(window.localStorage.getItem('user'));
79
+ orgId = window.localStorage.getItem('orgID');
80
+ userId = id;
81
+ userName = `${firstName} ${lastName}`;
82
+ userEmail = loginName;
83
+ orgName = proxyOrgList.find(({ orgID }) => orgID === Number(orgId)).orgName;
84
+ } catch (error) {
85
+ userId = '';
86
+ userName = '';
87
+ userEmail = '';
88
+ orgId = '';
89
+ orgName = '';
90
+ }
91
+ event.addMetadata('org', {
92
+ name: orgName,
93
+ id: orgId,
94
+ });
95
+ event.setUser(userId, userEmail, userName);
96
+ if (window.FS && window.FS.getCurrentSessionURL) {
97
+ event.addMetadata('fullstory', {
98
+ urlAtTime: window.FS.getCurrentSessionURL(true),
99
+ });
100
+ }
101
+ };
102
+
103
+ Bugsnag.start({
104
+ appVersion: BUGSNAG_APP_VERSION,
105
+ apiKey: BUGSNAG_API_KEY,
106
+ releaseStage: window.location.hostname,
107
+ plugins: [new BugsnagPluginReact()],
108
+ onError: bugSnagErrorCallback,
109
+ });
110
+
111
+ const ErrorBoundary = Bugsnag.getPlugin('react').createErrorBoundary(React);
112
+
113
+ export const BugsnagClient = Bugsnag;
114
+
115
+ const ErrorScreen = () => <CapSomethingWentWrong url={`${pathConfig.publicPath}/v2`} />
116
+ const root = createRoot(MOUNT_NODE);
117
+ const render = (messages) => {
118
+ root.render(
119
+ <Provider store={store}>
120
+ <LanguageProvider messages={messages}>
121
+ <ErrorBoundary FallbackComponent={ErrorScreen}>
122
+ <ConfigProvider theme={getCapThemeConfig()}>
123
+ <App />
124
+ </ConfigProvider>
125
+ </ErrorBoundary>
126
+ </LanguageProvider>
127
+ </Provider>,
128
+ );
129
+ };
130
+
131
+ // Hot reloadable translation json files
132
+ if (module.hot) {
133
+ // modules.hot.accept does not accept dynamic dependencies,
134
+ // have to be constants at compile-time
135
+ module.hot.accept('./i18n', () => {
136
+ render(translationMessages);
137
+ });
138
+ }
139
+
140
+ // for auto render UI on locize saved, since we cache the translations in redis it can't be update on real time as of now
141
+ // need to comment as of now
142
+ // addLocizeSavedHandler(res => {
143
+ // res.updated.forEach(item => {
144
+ // const { lng, ns, key, data } = item
145
+ // // load the translations somewhere...
146
+ // // and maybe rerender your UI
147
+ // })
148
+ // })
149
+
150
+ // start
151
+ startStandalone();
152
+
153
+ const openSansObserver = new FontFaceObserver('Roboto', {});
154
+ // When Open Sans is loaded, add a font-family using Open Sans to the body
155
+ openSansObserver.load().then(() => {
156
+ document.body.classList.add('fontLoaded');
157
+ }, () => {
158
+ document.body.classList.remove('fontLoaded');
159
+ });
160
+
161
+ // Chunked polyfill for browsers without Intl support
162
+ if (!window.Intl) {
163
+ (new Promise((resolve) => {
164
+ resolve(import('intl'));
165
+ }))
166
+ .then(() => Promise.all([
167
+ import('intl/locale-data/jsonp/en.js'),
168
+ ]))
169
+ .then(() => render(translationMessages))
170
+ .catch((err) => {
171
+ throw err;
172
+ });
173
+ } else {
174
+ render(translationMessages);
175
+ }
package/entry.js CHANGED
@@ -1,68 +1,2 @@
1
1
  import { publicPath } from './config/path';
2
-
3
- function normalizeTrailingSlash(url) {
4
- if (!url) return url;
5
- return url.endsWith('/') ? url : `${url}/`;
6
- }
7
-
8
- function getCreativesRemoteEntryScript() {
9
- if (typeof document === 'undefined') return null;
10
- const all = Array.from(
11
- document.querySelectorAll('script[src*="remoteEntry"]'),
12
- );
13
- const match =
14
- all.find(s => /cap-creatives-ui/i.test(s.src)) || all[all.length - 1];
15
- return match;
16
- }
17
-
18
- function getRemoteEntryOrigin() {
19
- const el = getCreativesRemoteEntryScript();
20
- if (!el || !el.src) return '';
21
- try {
22
- return new URL(el.src, window.location.href).origin;
23
- } catch (e) {
24
- return '';
25
- }
26
- }
27
-
28
- function getRemoteEntryBaseUrl() {
29
- const el = getCreativesRemoteEntryScript();
30
- if (!el || !el.src) return '';
31
- try {
32
- const u = new URL(el.src, window.location.href);
33
- const dir = u.pathname.replace(/\/[^/]+\.js(\?.*)?$/, '/');
34
- return normalizeTrailingSlash(`${u.origin}${dir}`);
35
- } catch (e) {
36
- return '';
37
- }
38
- }
39
-
40
- function resolveWebpackPublicPath() {
41
- const envPath = process.env.MFE_PUBLIC_PATH;
42
-
43
- if (envPath && envPath.length > 0) {
44
- if (/^https?:\/\//i.test(envPath)) {
45
- return normalizeTrailingSlash(envPath);
46
- }
47
- const origin = getRemoteEntryOrigin();
48
- if (origin) {
49
- const p = envPath.startsWith('/') ? envPath : `/${envPath}`;
50
- return normalizeTrailingSlash(new URL(p, origin).href);
51
- }
52
- return normalizeTrailingSlash(
53
- `${window.location.origin}${envPath.startsWith('/') ? '' : '/'}${envPath}`,
54
- );
55
- }
56
-
57
- const fromRemote = getRemoteEntryBaseUrl();
58
- if (fromRemote) {
59
- return fromRemote;
60
- }
61
-
62
- const origin = new URL(
63
- ((document || {}).currentScript || {}).src || window.location,
64
- ).origin;
65
- return `${origin}${publicPath}/`;
66
- }
67
-
68
- __webpack_public_path__ = resolveWebpackPublicPath();
2
+ __webpack_public_path__ = ((new URL(((document || {}).currentScript || {}).src || window.location)).origin) + `${publicPath}/`;
@@ -2,5 +2,7 @@
2
2
  // Contents of this file are used in webpack config's ModuleFederationPlugin.
3
3
  //
4
4
  module.exports = {
5
- './AppRoot': './app/AppRoot',
6
- };
5
+ // which exposes
6
+ // ADD MFE COMPONENT YOU WANT TO EXPORT example:
7
+ // './Home': './app/components/pages/Home',
8
+ };
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@capillarytech/creatives-library",
3
3
  "author": "meharaj",
4
- "version": "9.0.36-alpha.0",
4
+ "version": "9.0.36",
5
5
  "description": "Capillary creatives ui",
6
6
  "main": "./index.js",
7
7
  "module": "./index.es.js",
@@ -16,7 +16,7 @@
16
16
  "@babel/polyfill": "7.4.3",
17
17
  "@bugsnag/js": "^7.2.1",
18
18
  "@bugsnag/plugin-react": "7.2.1",
19
- "@capillarytech/cap-ui-utils": "3.0.20",
19
+ "@capillarytech/cap-ui-utils": "3.0.4",
20
20
  "@capillarytech/vulcan-react-sdk": "3.0.1",
21
21
  "@codemirror/autocomplete": "^6.19.0",
22
22
  "@codemirror/lang-css": "^6.3.1",
package/services/api.js CHANGED
@@ -5,7 +5,6 @@ import 'whatwg-fetch';
5
5
  import { GA, decompressJsonObject } from '@capillarytech/cap-ui-utils';
6
6
  import get from 'lodash/get';
7
7
  import { loadItem, clearItem } from './localStorageApi';
8
- import { isMFEMode } from '../utils/mfeDetect';
9
8
  import config from '../config/app';
10
9
  import pathConfig from '../config/path';
11
10
  import getSchema from './getSchema';
@@ -259,13 +258,6 @@ export const getSidebar = () => {
259
258
 
260
259
  // if 403, show SWR page
261
260
  export const getUserData = () => {
262
- // In MFE mode the host (cap-intouch-ui) owns the single auth call and exposes
263
- // the full response via window.getCapAuthData(); consume it instead of hitting
264
- // the auth endpoint again. The promise waits until the host call completes,
265
- // then resolves instantly for later callers.
266
- if (isMFEMode() && typeof window.getCapAuthData === 'function') {
267
- return window.getCapAuthData();
268
- }
269
261
  const url = `${API_AUTH_ENDPOINT}/user?include_features=1`;
270
262
  return request(url, getAPICallObject('GET'), true);
271
263
  };
@@ -687,7 +679,7 @@ export const getSupportVideosConfig = () => {
687
679
  };
688
680
 
689
681
  export const getNavigationConfigApi = async () => {
690
- const url = `${ARYA_ENDPOINT}/mfe_navigations`;
682
+ const url = `${ARYA_ENDPOINT}/navigations`;
691
683
  return request(url, getAPICallObject('GET'));
692
684
  };
693
685
 
@@ -79,6 +79,7 @@
79
79
  flex: 1;
80
80
  height: calc(100vh - 50px);
81
81
  overflow: auto;
82
+ padding: 8px 16px 0;
82
83
  color: #333333;
83
84
  }
84
85
 
@@ -153,19 +154,16 @@
153
154
  }
154
155
 
155
156
  .cap-loader-box {
156
- position: absolute;
157
+ position: fixed;
157
158
  top: 0;
158
- left: 0;
159
159
  width: 100%;
160
- min-height: calc(100vh - 48px);
161
- background: #ffffff;
162
- display: flex;
163
- align-items: center;
164
- justify-content: center;
160
+ height: 100%;
161
+ background: rgb(255,255,255);
162
+ text-align: center;
165
163
 
166
164
  .loader-image {
167
165
  width: 80px;
168
- height: auto;
166
+ margin-top: 20%;
169
167
  }
170
168
  }
171
169
 
@@ -1,5 +1,4 @@
1
1
  import { CREATIVES } from "../../../v2Containers/App/constants";
2
- import { getDataLayer } from '../../getDataLayer';
3
2
 
4
3
  const creativeDetails = ({
5
4
  name,
@@ -24,7 +23,7 @@ const creativeDetails = ({
24
23
  videoAdded,
25
24
  stickersAdded
26
25
  };
27
- getDataLayer().push({
26
+ window.dataLayer.push({
28
27
  creativeDetails: parsedObj,
29
28
  event: 'creativeDetails',
30
29
  });
@@ -59,12 +59,9 @@ export const normalizeRcsMessageContentForApi = messageContentItem => {
59
59
  rcsCardPayloadOnly.cardContent.forEach(card => {
60
60
  if (Array.isArray(card?.suggestions)) {
61
61
  card.suggestions.forEach(suggestion => {
62
- // isSaved and urlType are UI-only editor state: campaigns' send-for-approval API
63
- // rejects them, and they aren't part of the persisted payload shape. The dynamic tag
64
- // (if any) already lives inline in `url` (e.g. "https://x.com{{first_name}}") — no
65
- // separate dynamicUrlPayload field is sent for RCS.
62
+ // isSaved is UI-only editor state: campaigns' send-for-approval API rejects it, and it
63
+ // isn't part of the persisted payload shape.
66
64
  delete suggestion?.isSaved;
67
- delete suggestion?.urlType;
68
65
  });
69
66
  }
70
67
  });
@@ -209,7 +209,7 @@ describe('normalizeRcsMessageContentForApi', () => {
209
209
  expect(item.rcsContent.cardContent).toEqual([{ title: 'Card' }]);
210
210
  });
211
211
 
212
- it('strips isSaved and urlType from each suggestion in cardContent', () => {
212
+ it('strips isSaved from each suggestion in cardContent', () => {
213
213
  const item = {
214
214
  rcsContent: {
215
215
  cardContent: [
@@ -217,9 +217,7 @@ describe('normalizeRcsMessageContentForApi', () => {
217
217
  title: 'Card 1',
218
218
  suggestions: [
219
219
  { type: 'QUICK_REPLY', text: 'Yes', isSaved: true },
220
- {
221
- type: 'CTA', text: 'Go', url: 'https://example.com', urlType: 'STATIC', isSaved: false,
222
- },
220
+ { type: 'CTA', text: 'Go', url: 'https://example.com', isSaved: false },
223
221
  ],
224
222
  },
225
223
  ],
@@ -232,56 +230,6 @@ describe('normalizeRcsMessageContentForApi', () => {
232
230
  ]);
233
231
  });
234
232
 
235
- it('keeps type "CTA" and the inline tag in url, but drops urlType, for a dynamic-URL suggestion', () => {
236
- const item = {
237
- rcsContent: {
238
- cardContent: [
239
- {
240
- title: 'Card 1',
241
- suggestions: [
242
- {
243
- type: 'CTA',
244
- text: 'Visit here',
245
- url: 'https://example.com/{{first_name}}',
246
- urlType: 'DYNAMIC',
247
- isSaved: true,
248
- },
249
- ],
250
- },
251
- ],
252
- },
253
- };
254
- normalizeRcsMessageContentForApi(item);
255
- expect(item.rcsContent.cardContent[0].suggestions).toEqual([
256
- {
257
- type: 'CTA',
258
- text: 'Visit here',
259
- url: 'https://example.com/{{first_name}}',
260
- },
261
- ]);
262
- });
263
-
264
- it('leaves phone number and quick reply suggestions untouched by the urlType stripping', () => {
265
- const item = {
266
- rcsContent: {
267
- cardContent: [
268
- {
269
- title: 'Card 1',
270
- suggestions: [
271
- {
272
- type: 'PHONE_NUMBER', text: 'Call', phoneNumber: '918987678', isSaved: true,
273
- },
274
- ],
275
- },
276
- ],
277
- },
278
- };
279
- normalizeRcsMessageContentForApi(item);
280
- expect(item.rcsContent.cardContent[0].suggestions).toEqual([
281
- { type: 'PHONE_NUMBER', text: 'Call', phoneNumber: '918987678' },
282
- ]);
283
- });
284
-
285
233
  it('handles cardContent with no suggestions gracefully', () => {
286
234
  const item = {
287
235
  rcsContent: {
@@ -43,7 +43,6 @@ export const RCS_CTA_URL_TYPE = {
43
43
  export const BTN_MAX_LENGTH = 20;
44
44
  export const PHONE_NUMBER_MAX_LENGTH = 15;
45
45
  export const URL_MAX_LENGTH = 2000;
46
- export const DYNAMIC_URL_SUFFIX = '{{1}}';
47
46
 
48
47
  export const CTA_TYPE_RADIO_OPTIONS = [
49
48
  { label: <FormattedMessage {...messages.ctaPhoneNo} />, value: RCS_BUTTON_TYPES.PHONE_NUMBER },
@@ -17,8 +17,7 @@ import CapButton from '@capillarytech/cap-ui-library/CapButton';
17
17
  import CapTooltip from '@capillarytech/cap-ui-library/CapTooltip';
18
18
  import CapTooltipWithInfo from '@capillarytech/cap-ui-library/CapTooltipWithInfo';
19
19
  import { CAP_SPACE_04 } from '@capillarytech/cap-ui-library/styled/variables';
20
- import globalMessages from '../../v2Containers/Cap/messages';
21
- import TagList from '../../v2Containers/TagList';
20
+ import globalMessages from '../../v2Containers/Cap/messages';import CapTagListWithInput from '../CapTagListWithInput';
22
21
 
23
22
  import { isUrl, isValidText } from '../../v2Containers/Line/Container/Wrapper/utils';
24
23
  import messages from './messages';
@@ -31,7 +30,6 @@ import {
31
30
  RCS_CTA_URL_TYPE,
32
31
  CTA_TYPE_RADIO_OPTIONS,
33
32
  CTA_URL_TYPE_SELECT_OPTIONS,
34
- DYNAMIC_URL_SUFFIX,
35
33
  } from './constants';
36
34
  import './index.scss';
37
35
  import { INITIAL_SUGGESTIONS, RCS_BUTTON_TYPES, HOST_ICS} from '../../v2Containers/Rcs/constants';
@@ -58,7 +56,6 @@ export const CapActionButton = (props) => {
58
56
  minSavedSuggestions = 0,
59
57
  hideDeleteSuggestionIndexes = [],
60
58
  } = props;
61
- const { formatMessage } = intl;
62
59
  const isHostIcs = host === HOST_ICS;
63
60
  const [urlError, setUrlError] = useState(false);
64
61
  const [buttonError, setButtonError] = useState(false);
@@ -125,8 +122,7 @@ export const CapActionButton = (props) => {
125
122
  return formatMessage(messages.ctaWebsiteUrlErrorMessage);
126
123
  }
127
124
  if (urlSubtype === RCS_CTA_URL_TYPE.DYNAMIC) {
128
- const baseUrl = trimmedUrl.replace(invalidVarRegex, '');
129
- return isUrl(baseUrl) ? false : formatMessage(messages.ctaWebsiteUrlErrorMessage);
125
+ return false;
130
126
  }
131
127
  if (!isUrl(trimmedUrl)) {
132
128
  return formatMessage(messages.ctaWebsiteUrlErrorMessage);
@@ -138,12 +134,9 @@ export const CapActionButton = (props) => {
138
134
  };
139
135
 
140
136
  const onUrlChange = ({ target }) => {
141
- const { id } = target;
137
+ const { value, id } = target;
142
138
  const row = suggestions[id] || {};
143
139
  const subtype = row.urlType || RCS_CTA_URL_TYPE.STATIC;
144
- const value = subtype === RCS_CTA_URL_TYPE.DYNAMIC
145
- ? target.value.replace(invalidVarRegex, '')
146
- : target.value;
147
140
  setUrlError(validateCtaUrlValue(value, subtype));
148
141
  updateHandler(HANDLERS.URL, value, id);
149
142
  };
@@ -156,14 +149,6 @@ export const CapActionButton = (props) => {
156
149
  updateButtonChange(cloned, index);
157
150
  };
158
151
 
159
- const onTagSelect = (data, index, url) => {
160
- updateHandler(HANDLERS.URL, (url || '').replace(DYNAMIC_URL_SUFFIX, `{{${data}}}`), index);
161
- };
162
-
163
- const revertTagSelect = (index, url) => {
164
- updateHandler(HANDLERS.URL, (url || '').replace(invalidVarRegex, DYNAMIC_URL_SUFFIX), index);
165
- };
166
-
167
152
  const onPhoneNoChange = (value, index) => {
168
153
  updateHandler(HANDLERS.PHONE_NUMBER, value, index);
169
154
  };
@@ -176,25 +161,12 @@ export const CapActionButton = (props) => {
176
161
  return true;
177
162
  } if (type === RCS_BUTTON_TYPES.CTA) {
178
163
  const subtype = urlType || RCS_CTA_URL_TYPE.STATIC;
179
- if (validateCtaUrlValue(url, subtype)) {
180
- return true;
181
- }
182
- // A dynamic URL still holding the unresolved {{1}} placeholder has no real
183
- // personalization tag assigned yet — block save until one is picked via "Add URL label".
184
- return subtype === RCS_CTA_URL_TYPE.DYNAMIC && (url || '').includes(DYNAMIC_URL_SUFFIX);
164
+ return !!validateCtaUrlValue(url, subtype);
185
165
  }
186
166
  return false;
187
167
  };
188
168
 
189
169
  const saveCta = (index) => {
190
- const cta = suggestions[index];
191
- if (
192
- cta?.type === RCS_BUTTON_TYPES.CTA
193
- && cta?.urlType === RCS_CTA_URL_TYPE.DYNAMIC
194
- && !(cta?.url || '').includes(DYNAMIC_URL_SUFFIX)
195
- ) {
196
- cta.url = `${cta.url || ''}${DYNAMIC_URL_SUFFIX}`;
197
- }
198
170
  updateHandler(HANDLERS.IS_SAVED, true, index);
199
171
  };
200
172
 
@@ -208,6 +180,8 @@ export const CapActionButton = (props) => {
208
180
  updateButtonChange(newSuggestion, suggestions?.length);
209
181
  };
210
182
 
183
+ const { formatMessage } = intl;
184
+
211
185
  const hideDeleteForSuggestionIndex = (idx) =>
212
186
  Array.isArray(hideDeleteSuggestionIndexes) && hideDeleteSuggestionIndexes.includes(idx);
213
187
 
@@ -230,7 +204,6 @@ export const CapActionButton = (props) => {
230
204
  const urlSubtype = type === RCS_BUTTON_TYPES.CTA
231
205
  ? (cta.urlType || RCS_CTA_URL_TYPE.STATIC)
232
206
  : RCS_CTA_URL_TYPE.STATIC;
233
- const isDynamicUrlSubtype = urlSubtype === RCS_CTA_URL_TYPE.DYNAMIC;
234
207
  const phoneNumber = type !== RCS_BUTTON_TYPES.PHONE_NUMBER ? null : cta.phoneNumber;
235
208
  if (isFullMode && !isEditFlow && !isSaved) {
236
209
  renderArray.push(
@@ -342,32 +315,13 @@ export const CapActionButton = (props) => {
342
315
  </CapColumn>
343
316
  <CapColumn span={18} className="rcs-cta-url-value-col">
344
317
  <CapHeading type="h4" className="cta-label">
345
- {formatMessage(messages.ctaWebsiteUrl)}
346
- {isDynamicUrlSubtype && (
347
- <CapTooltipWithInfo
348
- infoIconProps={{
349
- style: { marginLeft: CAP_SPACE_04 },
350
- }}
351
- autoAdjustOverflow
352
- placement="right"
353
- title={formatMessage(messages.ctaDynamicUrlTooltip, { one: DYNAMIC_URL_SUFFIX })}
354
- />
355
- )}
318
+ {formatMessage(messages.ctaUrlField)}
356
319
  </CapHeading>
357
320
  <CapInput
358
321
  id={index}
359
- addonAfter={
360
- isDynamicUrlSubtype
361
- && !(url || '').includes(DYNAMIC_URL_SUFFIX)
362
- && DYNAMIC_URL_SUFFIX
363
- }
364
322
  className="rcs-cta-url"
365
323
  onChange={onUrlChange}
366
- placeholder={
367
- isDynamicUrlSubtype
368
- ? formatMessage(messages.ctaDynamicPlaceholder)
369
- : formatMessage(messages.ctaEnterUrlPlaceholder)
370
- }
324
+ placeholder={formatMessage(messages.ctaEnterUrlPlaceholder)}
371
325
  value={url || ''}
372
326
  size="large"
373
327
  maxLength={URL_MAX_LENGTH}
@@ -449,7 +403,7 @@ export const CapActionButton = (props) => {
449
403
  span={1}
450
404
  className={`${ctaIsPhone ? 'whatsapp-saved-cta-phone-icon' : ''}`}
451
405
  >
452
- <CapIcon size="s" type={ctaIsPhone ? 'call' : (ctaIsReply ? 'small-link' : 'open-in-new')} />
406
+ <CapIcon size="s" type={ctaIsPhone ? 'call' : (ctaIsReply ? 'small-link' : 'launch')} />
453
407
  </CapColumn>
454
408
  <CapColumn span={6}>
455
409
  <CapLabel
@@ -476,28 +430,6 @@ export const CapActionButton = (props) => {
476
430
  </CapTooltip>
477
431
  </>
478
432
  )}
479
- {isDynamicUrlSubtype && (url || '').includes(DYNAMIC_URL_SUFFIX) && (
480
- <TagList
481
- className="rcs-cta-taglist"
482
- label={formatMessage(messages.ctaTagListLabel)}
483
- onTagSelect={(data) => onTagSelect(data, index, url)}
484
- location={location}
485
- tags={tags}
486
- injectedTags={injectedTags}
487
- selectedOfferDetails={selectedOfferDetails}
488
- onContextChange={onContextChange}
489
- />
490
- )}
491
- {isDynamicUrlSubtype && !(url || '').includes(DYNAMIC_URL_SUFFIX) && (
492
- <CapTooltip title={formatMessage(messages.ctaTagListRevert)} placement="top">
493
- <CapIcon
494
- size="s"
495
- type="return"
496
- className="rcs-cta-tag-revert"
497
- onClick={() => revertTagSelect(index, url)}
498
- />
499
- </CapTooltip>
500
- )}
501
433
  {(isFullMode && !isEditFlow) && (
502
434
  <div className="rcs-saved-cta-action-icons">
503
435
  <CapIcon
@@ -84,19 +84,6 @@
84
84
  .rcs-saved-cta-delete-icon {
85
85
  cursor: pointer;
86
86
  }
87
-
88
- // Dynamic-URL tag controls: keep them from stretching the flex row's
89
- // height/width — same treatment as the edit/delete icons above.
90
- .rcs-cta-tag-revert {
91
- display: flex;
92
- align-items: center;
93
- flex-shrink: 0;
94
- cursor: pointer;
95
- }
96
-
97
- .rcs-cta-taglist {
98
- flex-shrink: 0;
99
- }
100
87
  }
101
88
 
102
89
  // Button text / URL: count via CapInput `suffix` (antd affix, right-aligned inside field).