@capillarytech/creatives-library 8.0.235 → 8.0.236-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 (86) hide show
  1. package/assets/Android.png +0 -0
  2. package/assets/iOS.png +0 -0
  3. package/config/app.js +0 -1
  4. package/constants/unified.js +1 -1
  5. package/initialReducer.js +2 -0
  6. package/package.json +1 -1
  7. package/services/api.js +5 -2
  8. package/services/tests/api.test.js +18 -0
  9. package/utils/common.js +1 -2
  10. package/utils/commonUtils.js +14 -1
  11. package/utils/transformTemplateConfig.js +0 -10
  12. package/v2Components/CapDeviceContent/index.js +61 -56
  13. package/v2Components/CapTagList/index.js +4 -0
  14. package/v2Components/CapWhatsappCTA/tests/index.test.js +5 -0
  15. package/v2Components/HtmlEditor/HTMLEditor.js +165 -80
  16. package/v2Components/HtmlEditor/__tests__/HTMLEditor.test.js +532 -0
  17. package/v2Components/HtmlEditor/__tests__/index.lazy.test.js +17 -12
  18. package/v2Components/HtmlEditor/_htmlEditor.scss +0 -4
  19. package/v2Components/HtmlEditor/_index.lazy.scss +0 -1
  20. package/v2Components/HtmlEditor/components/CodeEditorPane/_codeEditorPane.scss +0 -98
  21. package/v2Components/HtmlEditor/components/CodeEditorPane/index.js +125 -148
  22. package/v2Components/HtmlEditor/components/DeviceToggle/_deviceToggle.scss +1 -0
  23. package/v2Components/HtmlEditor/components/DeviceToggle/index.js +3 -3
  24. package/v2Components/HtmlEditor/components/InAppPreviewPane/DeviceFrame.js +4 -7
  25. package/v2Components/HtmlEditor/components/InAppPreviewPane/__tests__/DeviceFrame.test.js +35 -45
  26. package/v2Components/HtmlEditor/components/InAppPreviewPane/_inAppPreviewPane.scss +1 -3
  27. package/v2Components/HtmlEditor/components/InAppPreviewPane/constants.js +33 -33
  28. package/v2Components/HtmlEditor/components/InAppPreviewPane/index.js +7 -6
  29. package/v2Components/HtmlEditor/constants.js +29 -20
  30. package/v2Components/HtmlEditor/hooks/__tests__/useInAppContent.test.js +158 -17
  31. package/v2Components/HtmlEditor/hooks/useInAppContent.js +53 -143
  32. package/v2Components/HtmlEditor/index.js +1 -1
  33. package/v2Components/HtmlEditor/messages.js +85 -85
  34. package/v2Components/MobilePushPreviewV2/index.js +32 -7
  35. package/v2Components/TemplatePreview/_templatePreview.scss +31 -21
  36. package/v2Components/TemplatePreview/index.js +47 -32
  37. package/v2Components/TemplatePreview/messages.js +4 -0
  38. package/v2Containers/BeeEditor/index.js +82 -80
  39. package/v2Containers/BeePopupEditor/constants.js +10 -0
  40. package/v2Containers/BeePopupEditor/index.js +180 -0
  41. package/v2Containers/BeePopupEditor/tests/index.test.js +627 -0
  42. package/v2Containers/CreativesContainer/SlideBoxContent.js +69 -34
  43. package/v2Containers/CreativesContainer/SlideBoxHeader.js +2 -1
  44. package/v2Containers/CreativesContainer/constants.js +1 -0
  45. package/v2Containers/CreativesContainer/index.js +65 -13
  46. package/v2Containers/CreativesContainer/tests/__snapshots__/SlideBoxContent.test.js.snap +4 -12
  47. package/v2Containers/CreativesContainer/tests/__snapshots__/index.test.js.snap +15 -0
  48. package/v2Containers/InApp/__tests__/InAppHTMLEditor.test.js +376 -0
  49. package/v2Containers/InApp/__tests__/sagas.test.js +363 -0
  50. package/v2Containers/InApp/actions.js +7 -0
  51. package/v2Containers/InApp/constants.js +18 -4
  52. package/v2Containers/InApp/index.js +642 -355
  53. package/v2Containers/InApp/index.scss +4 -3
  54. package/v2Containers/InApp/messages.js +7 -3
  55. package/v2Containers/InApp/reducer.js +21 -3
  56. package/v2Containers/InApp/sagas.js +29 -9
  57. package/v2Containers/InApp/selectors.js +25 -5
  58. package/v2Containers/InApp/tests/index.test.js +154 -50
  59. package/v2Containers/InApp/tests/reducer.test.js +34 -0
  60. package/v2Containers/InApp/tests/sagas.test.js +61 -9
  61. package/v2Containers/InApp/tests/selectors.test.js +612 -0
  62. package/v2Containers/InAppWrapper/components/InAppWrapperView.js +162 -0
  63. package/v2Containers/InAppWrapper/components/__tests__/InAppWrapperView.test.js +267 -0
  64. package/v2Containers/InAppWrapper/components/inAppWrapperView.scss +9 -0
  65. package/v2Containers/InAppWrapper/constants.js +16 -0
  66. package/v2Containers/InAppWrapper/hooks/__tests__/useInAppWrapper.test.js +473 -0
  67. package/v2Containers/InAppWrapper/hooks/useInAppWrapper.js +198 -0
  68. package/v2Containers/InAppWrapper/index.js +148 -0
  69. package/v2Containers/InAppWrapper/messages.js +49 -0
  70. package/v2Containers/InappAdvance/index.js +1006 -0
  71. package/v2Containers/InappAdvance/index.scss +10 -0
  72. package/v2Containers/InappAdvance/tests/index.test.js +448 -0
  73. package/v2Containers/Line/Container/ImageCarousel/tests/__snapshots__/content.test.js.snap +3 -0
  74. package/v2Containers/Line/Container/ImageCarousel/tests/__snapshots__/index.test.js.snap +2 -0
  75. package/v2Containers/Line/Container/Wrapper/tests/__snapshots__/index.test.js.snap +2 -0
  76. package/v2Containers/Line/Container/tests/__snapshots__/index.test.js.snap +9 -0
  77. package/v2Containers/Rcs/tests/__snapshots__/index.test.js.snap +12 -0
  78. package/v2Containers/SmsTrai/Edit/tests/__snapshots__/index.test.js.snap +4 -0
  79. package/v2Containers/TagList/index.js +65 -1
  80. package/v2Containers/Templates/_templates.scss +49 -1
  81. package/v2Containers/Templates/index.js +93 -5
  82. package/v2Containers/Templates/messages.js +4 -0
  83. package/v2Containers/Templates/reducer.js +20 -7
  84. package/v2Containers/Templates/tests/__snapshots__/index.test.js.snap +8 -88
  85. package/v2Containers/Templates/tests/reducer.test.js +125 -0
  86. package/v2Containers/Whatsapp/tests/__snapshots__/index.test.js.snap +35 -0
Binary file
package/assets/iOS.png CHANGED
Binary file
package/config/app.js CHANGED
@@ -21,7 +21,6 @@ const config = {
21
21
  },
22
22
  development: {
23
23
  api_endpoint: 'https://crm-nightly-new.cc.capillarytech.com/arya/api/v1/creatives',
24
- // api_endpoint: 'http://localhost:2022/arya/api/v1/creatives',
25
24
  campaigns_api_endpoint: 'https://crm-nightly-new.cc.capillarytech.com/iris/v2/campaigns',
26
25
  campaigns_api_org_endpoint: 'https://crm-nightly-new.cc.capillarytech.com/iris/v2/org/campaign',
27
26
  auth_endpoint: 'https://crm-nightly-new.cc.capillarytech.com/arya/api/v1/auth',
@@ -168,7 +168,7 @@ export const JAPANESE_HIDE_DATE_TAGS = [
168
168
  "dd.mm.yy",
169
169
  "dd Mon",
170
170
  "dd/m/yyyy",
171
- ];
171
+ ];
172
172
 
173
173
  export const LIQUID_SUPPORTED_CHANNELS = [EMAIL, SMS, MOBILE_PUSH, INAPP];
174
174
 
package/initialReducer.js CHANGED
@@ -15,6 +15,7 @@ import galleryReducer from './v2Containers/Assets/Gallery/reducer';
15
15
  import CapCollapsibleLeftNavigationReducer from '@capillarytech/cap-ui-library/CapCollapsibleLeftNavigation/reducer';
16
16
  import { AIRA_REDUCER_DOMAIN, askAiraReducer } from '@capillarytech/cap-ui-library/CapAskAira';
17
17
  import previewAndTestReducer from './v2Components/TestAndPreviewSlidebox/reducer';
18
+ import inAppReducer from './v2Containers/InApp/reducer';
18
19
 
19
20
  export const initialReducer = {
20
21
  language: languageProviderReducer,
@@ -33,4 +34,5 @@ export const initialReducer = {
33
34
  gallery: galleryReducer,
34
35
  navigationConfig: CapCollapsibleLeftNavigationReducer,
35
36
  previewAndTest: previewAndTestReducer,
37
+ inApp: inAppReducer,
36
38
  };
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@capillarytech/creatives-library",
3
3
  "author": "meharaj",
4
- "version": "8.0.235",
4
+ "version": "8.0.236-alpha.1",
5
5
  "description": "Capillary creatives ui",
6
6
  "main": "./index.js",
7
7
  "module": "./index.es.js",
package/services/api.js CHANGED
@@ -264,7 +264,6 @@ export const getUserData = () => {
264
264
 
265
265
  export const createTemplate = ({template}) => {
266
266
  const url = `${API_ENDPOINT}/templates/SMS`;
267
- console.log("creating template",template);
268
267
  return request(url, getAPICallObject('POST', template));
269
268
  };
270
269
 
@@ -347,7 +346,6 @@ export const getAllTemplates = async ({channel, queryParams = {}}) => {
347
346
 
348
347
  export const deleteTemplate = ({channel, id}) => {
349
348
  const url = `${API_ENDPOINT}/templates/${id}/${channel}`;
350
- console.log("deleting template", url);
351
349
  return request(url, getAPICallObject('DELETE'));
352
350
  //return API.deleteResource(url);
353
351
  };
@@ -711,4 +709,9 @@ export const updateTestMessageMeta = (payload) => {
711
709
  return request(url, getAPICallObject('POST', payload?.data, false, true));
712
710
  };
713
711
 
712
+ export const getBeePopupBuilderToken = () => {
713
+ const url = `${API_ENDPOINT}/common/getInappTokenData`;
714
+ return request(url, getAPICallObject('GET'));
715
+ };
716
+
714
717
  export {request, getAPICallObject};
@@ -25,6 +25,7 @@ import {
25
25
  updateTestMessageMeta,
26
26
  updateMetaConfig,
27
27
  getMediaDetails,
28
+ getBeePopupBuilderToken,
28
29
  } from '../api';
29
30
  import { mockData } from './mockData';
30
31
  import getSchema from '../getSchema';
@@ -849,3 +850,20 @@ describe('getMediaDetails', () => {
849
850
  });
850
851
  });
851
852
  });
853
+
854
+ describe('getBeePopupBuilderToken', () => {
855
+ it('should return correct response', async () => {
856
+ global.fetch.mockReturnValue(Promise.resolve({
857
+ status: 200,
858
+ json: () => Promise.resolve({
859
+ status: 200,
860
+ response: 'test',
861
+ }),
862
+ }));
863
+ const result = await getBeePopupBuilderToken();
864
+ expect(result).toEqual({
865
+ status: 200,
866
+ response: 'test',
867
+ });
868
+ });
869
+ });
package/utils/common.js CHANGED
@@ -22,8 +22,7 @@ import {
22
22
  BADGES_ISSUE,
23
23
  ENABLE_WECHAT,
24
24
  LIQUID_SUPPORT,
25
- ENABLE_NEW_MPUSH
26
- } from '../constants/unified';
25
+ ENABLE_NEW_MPUSH} from '../constants/unified';
27
26
  import { apiMessageFormatHandler } from './commonUtils';
28
27
 
29
28
  export function getUserNameById(userId, allUserList) {
@@ -398,7 +398,20 @@ export const validateMobilePushContent = async (formData, options) => {
398
398
  // Helper function to extract content for a platform
399
399
  export const extractContent = (platformData) => {
400
400
  if (!platformData) return '';
401
- const { title, message, ctas } = platformData;
401
+ const { title, message, ctas, isBEEeditor, beeHtml } = platformData;
402
+
403
+ // For BEE editor, extract content from beeHtml
404
+ if (isBEEeditor && beeHtml) {
405
+ // beeHtml can be an object with value property or a string
406
+ const beeHtmlContent = typeof beeHtml === 'string' ? beeHtml : (beeHtml?.value || '');
407
+ return [
408
+ title,
409
+ beeHtmlContent,
410
+ ...((ctas?.map((cta) => cta?.text || cta?.actionLink)) || []),
411
+ ].filter(Boolean).join(' ');
412
+ }
413
+
414
+ // For regular content
402
415
  return [
403
416
  title,
404
417
  message,
@@ -101,7 +101,6 @@ export async function transformTemplateConfigWithMediaDetails(templateConfig, ch
101
101
  const contentType = detectMediaContentType(templateConfig);
102
102
 
103
103
  if (contentType === MEDIA_CONTENT_TYPE.NONE) {
104
- console.log('No media content detected, returning original config');
105
104
  return templateConfig;
106
105
  }
107
106
 
@@ -109,24 +108,19 @@ export async function transformTemplateConfigWithMediaDetails(templateConfig, ch
109
108
  let transformDirection;
110
109
  if (forceDirection) {
111
110
  transformDirection = forceDirection;
112
- console.log(`Forced transformation direction: ${transformDirection}`);
113
111
  } else {
114
112
  // Auto-detect based on content
115
113
  if (contentType === MEDIA_CONTENT_TYPE.URLS) {
116
114
  transformDirection = TRANSFORM_DIRECTION.FORWARD; // URLs → tags
117
- console.log('Detected URLs, applying forward transformation (URLs → tags)');
118
115
  } else if (contentType === MEDIA_CONTENT_TYPE.TAGS) {
119
116
  transformDirection = TRANSFORM_DIRECTION.REVERSE; // tags → URLs
120
- console.log('Detected media_content tags, applying reverse transformation (tags → URLs)');
121
117
  } else if (contentType === MEDIA_CONTENT_TYPE.MIXED) {
122
118
  transformDirection = TRANSFORM_DIRECTION.SMART; // Handle mixed content intelligently
123
- console.log('Detected mixed content, applying smart transformation');
124
119
  }
125
120
  }
126
121
 
127
122
  const newConfig = cloneDeep(templateConfig);
128
123
  try {
129
- console.log(`Fetching media details for ${transformDirection} transformation, ID: ${mediaDetailsId}`);
130
124
 
131
125
  // Fetch media details mapping from API
132
126
  const response = await getMediaDetails({ id: mediaDetailsId })
@@ -145,7 +139,6 @@ export async function transformTemplateConfigWithMediaDetails(templateConfig, ch
145
139
  idToUrlMapping[mediaId] = url;
146
140
  });
147
141
 
148
- console.log(`Processing ${Object.keys(urlToIdMapping).length} media mappings`);
149
142
 
150
143
  // Apply transformations based on direction
151
144
  newConfig?.cards?.forEach(card => {
@@ -157,7 +150,6 @@ export async function transformTemplateConfigWithMediaDetails(templateConfig, ch
157
150
  // Forward transformation: URL → tag
158
151
  const mediaDetailId = urlToIdMapping[currentUrl];
159
152
  if (mediaDetailId) {
160
- console.log(`Forward: ${currentUrl} → {{media_content(${mediaDetailId})}}`);
161
153
  card.media.url = `{{media_content(${mediaDetailId})}}`;
162
154
  } else {
163
155
  console.warn(`No media detail ID found for URL: ${currentUrl}`);
@@ -169,7 +161,6 @@ export async function transformTemplateConfigWithMediaDetails(templateConfig, ch
169
161
  if (mediaId) {
170
162
  const actualUrl = idToUrlMapping[mediaId];
171
163
  if (actualUrl) {
172
- console.log(`Reverse: {{media_content(${mediaId})}} → ${actualUrl}`);
173
164
  card.media.url = actualUrl;
174
165
  } else {
175
166
  console.warn(`No URL found for media ID: ${mediaId}`);
@@ -185,7 +176,6 @@ export async function transformTemplateConfigWithMediaDetails(templateConfig, ch
185
176
  console.error('Failed to fetch media details for transformation:', error);
186
177
 
187
178
  // Fallback: try to extract/convert what we can without API
188
- console.log('Falling back to URL extraction method');
189
179
  newConfig.cards.forEach(card => {
190
180
  if (card.media && card.media.url) {
191
181
  if (transformDirection === TRANSFORM_DIRECTION.FORWARD) {
@@ -69,7 +69,7 @@ const CapDeviceContent = (props) => {
69
69
  templateDescErrorHandler,
70
70
  templateTitleError,
71
71
  setTemplateTitleError,
72
- isAiContentBotDisabled
72
+ isAiContentBotDisabled,
73
73
  } = props || {};
74
74
  const { TextArea } = CapInput;
75
75
  const { formatMessage } = intl;
@@ -167,21 +167,22 @@ const CapDeviceContent = (props) => {
167
167
  return (
168
168
  <>
169
169
  <CapRow className="creatives-device-content">
170
- <CapLink
170
+ <CapLink
171
171
  title={isAndroid
172
- ? formatMessage(messages.copyContentFromIOS)
173
- : formatMessage(messages.copyCotentFromAndroid)}
172
+ ? formatMessage(messages.copyContentFromIOS)
173
+ : formatMessage(messages.copyCotentFromAndroid)}
174
174
  className="inapp-copy-content"
175
175
  onClick={onCopyTitleAndContent}
176
- />
176
+ />
177
177
  <CapRow className="creatives-inapp-title">
178
178
  <CapColumn
179
- className="inapp-content-main"
179
+ className="inapp-content-main"
180
180
  >
181
181
  <CapHeading type="h5" className="inapp-title">
182
182
  {formatMessage(messages.title)}
183
183
  </CapHeading>
184
- {getTagList(0)} {/* here 0 signifies the tags for template title */}
184
+ {getTagList(0)}
185
+ {/* here 0 signifies the tags for template title */}
185
186
  </CapColumn>
186
187
  <CapInput
187
188
  id="inapp-title-name-input"
@@ -213,7 +214,7 @@ const CapDeviceContent = (props) => {
213
214
  </CapRow>
214
215
  <CapRow className={`creatives-inapp-message ${!isMediaTypeImage && "message-bottom-margin"}`}>
215
216
  <CapColumn
216
- className="inapp-message-header"
217
+ className="inapp-message-header"
217
218
  >
218
219
  <CapHeading type="h5" className="inapp-message-header-style">
219
220
  {formatMessage(messages.message)}
@@ -222,37 +223,37 @@ const CapDeviceContent = (props) => {
222
223
  {/* here 1 signifies the tags for template message */}
223
224
  </CapColumn>
224
225
  <div className="inapp-create-template-message-input-wrapper">
225
- <TextArea
226
- id="inapp-create-template-message-input"
227
- className="inapp-create-template-message-input"
228
- placeholder={formatMessage(messages.textAreaInputPlaceholder)}
229
- onChange={onTemplateMessageChange}
230
- value={templateMessage || ""}
231
- autosize={{ minRows: 5, maxRows: 5 }}
232
- errorMessage={
233
- templateMessageError && (
234
- <CapError className="inapp-template-message-error">
235
- {templateMessageError}
236
- </CapError>
237
- )
238
- }
239
- />
240
- {!isAiContentBotDisabled && (
241
- <CapAskAira.ContentGenerationBot
242
- text={templateMessage || ""}
243
- setText={(text) => {
244
- onTemplateMessageChange({ target: { value: text } });
245
- }}
246
- iconPlacement="float-br"
247
- iconSize="1.6rem"
248
- rootStyle={{
249
- bottom: "0.2rem",
250
- right: "0.2rem",
251
- left: "auto",
252
- position: "absolute",
253
- }}
226
+ <TextArea
227
+ id="inapp-create-template-message-input"
228
+ className="inapp-create-template-message-input"
229
+ placeholder={formatMessage(messages.textAreaInputPlaceholder)}
230
+ onChange={onTemplateMessageChange}
231
+ value={templateMessage || ""}
232
+ autosize={{ minRows: 5, maxRows: 5 }}
233
+ errorMessage={
234
+ templateMessageError && (
235
+ <CapError className="inapp-template-message-error">
236
+ {templateMessageError}
237
+ </CapError>
238
+ )
239
+ }
254
240
  />
255
- )}
241
+ {!isAiContentBotDisabled && (
242
+ <CapAskAira.ContentGenerationBot
243
+ text={templateMessage || ""}
244
+ setText={(text) => {
245
+ onTemplateMessageChange({ target: { value: text } });
246
+ }}
247
+ iconPlacement="float-br"
248
+ iconSize="1.6rem"
249
+ rootStyle={{
250
+ bottom: "0.2rem",
251
+ right: "0.2rem",
252
+ left: "auto",
253
+ position: "absolute",
254
+ }}
255
+ />
256
+ )}
256
257
  </div>
257
258
  {isMediaTypeImage && (
258
259
  <>
@@ -279,14 +280,16 @@ const CapDeviceContent = (props) => {
279
280
  </CapRow>
280
281
  </CapRow>
281
282
  <CapRow className="inapp-action-link">
282
- <CapCheckbox onChange={onActionLinkCheckBoxChange} checked={addActionLink}/>
283
+ <CapCheckbox onChange={onActionLinkCheckBoxChange} checked={addActionLink} />
283
284
  <CapRow className="inapp-render-heading">
284
285
  <CapHeader
285
- title={<CapRow type="flex">
286
- <CapHeading type="h4">
287
- {formatMessage(messages.addActionLink)}
288
- </CapHeading>
289
- </CapRow>}
286
+ title={(
287
+ <CapRow type="flex">
288
+ <CapHeading type="h4">
289
+ {formatMessage(messages.addActionLink)}
290
+ </CapHeading>
291
+ </CapRow>
292
+ )}
290
293
  description={<CapLabel type="label3">{formatMessage(messages.addActionLinkDesc)}</CapLabel>}
291
294
  />
292
295
  {addActionLink && (
@@ -310,19 +313,21 @@ const CapDeviceContent = (props) => {
310
313
  <CapRow className="inapp-cta-button">
311
314
  <CapHeader
312
315
  className="inapp-render-heading-cta-button"
313
- title={<CapRow type="flex">
314
- <CapHeading type="h4">
315
- {formatMessage(messages.btnLabel)}
316
- </CapHeading>
317
- <CapHeading
318
- type="h6"
319
- className="inapp-optional-label"
320
- >
321
- {formatMessage(messages.optional)}
322
- </CapHeading>
323
- </CapRow>}
316
+ title={(
317
+ <CapRow type="flex">
318
+ <CapHeading type="h4">
319
+ {formatMessage(messages.btnLabel)}
320
+ </CapHeading>
321
+ <CapHeading
322
+ type="h6"
323
+ className="inapp-optional-label"
324
+ >
325
+ {formatMessage(messages.optional)}
326
+ </CapHeading>
327
+ </CapRow>
328
+ )}
324
329
  description={<CapLabel type="label3">{formatMessage(messages.btnDesc)}</CapLabel>}
325
- />
330
+ />
326
331
  <CapRadioGroup
327
332
  options={BUTTON_RADIO_OPTIONS}
328
333
  value={buttonType}
@@ -227,6 +227,10 @@ class CapTagList extends React.Component { // eslint-disable-line react/prefer-s
227
227
 
228
228
  togglePopoverVisibility = (visible) => {
229
229
  this.setState({visible});
230
+ // Call onVisibleChange callback if provided (for triggering API calls when popover opens)
231
+ if (this.props.onVisibleChange) {
232
+ this.props.onVisibleChange(visible);
233
+ }
230
234
  };
231
235
 
232
236
  renderDynamicTagFlow = () => {
@@ -4,6 +4,11 @@ import '@testing-library/jest-dom';
4
4
  import { render, screen, fireEvent } from '../../../utils/test-utils';
5
5
  import { CapWhatsappCTA } from '../index';
6
6
 
7
+ // Mock the missing reducer
8
+ jest.mock('@capillarytech/cap-ui-library/CapCollapsibleLeftNavigation/reducer', () => {
9
+ return (state = {}) => state;
10
+ }, { virtual: true });
11
+
7
12
  const updateHandler = jest.fn();
8
13
  const deleteHandler = jest.fn();
9
14
  const initializeComponent = (