@capillarytech/creatives-library 8.0.141 → 8.0.142

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 (40) hide show
  1. package/initialReducer.js +2 -0
  2. package/package.json +2 -2
  3. package/services/api.js +5 -0
  4. package/services/tests/api.test.js +17 -0
  5. package/v2Components/MobilePushPreviewV2/index.js +8 -0
  6. package/v2Components/NavigationBar/saga.js +1 -1
  7. package/v2Components/NavigationBar/tests/saga.test.js +2 -2
  8. package/v2Components/TemplatePreview/assets/images/empty_android.svg +8 -0
  9. package/v2Components/TemplatePreview/assets/images/empty_ios.svg +5 -0
  10. package/v2Components/TemplatePreview/index.js +28 -2
  11. package/v2Containers/BeePopupEditor/constants.js +10 -0
  12. package/v2Containers/BeePopupEditor/index.js +169 -0
  13. package/v2Containers/BeePopupEditor/tests/index.test.js +628 -0
  14. package/v2Containers/CreativesContainer/SlideBoxContent.js +26 -8
  15. package/v2Containers/CreativesContainer/index.js +12 -2
  16. package/v2Containers/CreativesContainer/tests/__snapshots__/index.test.js.snap +5 -0
  17. package/v2Containers/InApp/actions.js +7 -0
  18. package/v2Containers/InApp/constants.js +5 -1
  19. package/v2Containers/InApp/index.js +76 -53
  20. package/v2Containers/InApp/reducer.js +17 -0
  21. package/v2Containers/InApp/sagas.js +27 -0
  22. package/v2Containers/InApp/selectors.js +23 -1
  23. package/v2Containers/InApp/tests/index.test.js +0 -9
  24. package/v2Containers/InApp/tests/reducer.test.js +33 -0
  25. package/v2Containers/InApp/tests/sagas.test.js +57 -1
  26. package/v2Containers/InApp/tests/selector.test.js +612 -0
  27. package/v2Containers/InappAdvanced/index.js +459 -0
  28. package/v2Containers/InappAdvanced/index.scss +11 -0
  29. package/v2Containers/InappAdvanced/tests/index.test.js +442 -0
  30. package/v2Containers/InappWrapper/_inappWrapper.scss +19 -0
  31. package/v2Containers/InappWrapper/index.js +194 -0
  32. package/v2Containers/InappWrapper/messages.js +38 -0
  33. package/v2Containers/InappWrapper/tests/index.test.js +247 -0
  34. package/v2Containers/Line/Container/ImageCarousel/tests/__snapshots__/content.test.js.snap +3 -0
  35. package/v2Containers/Line/Container/ImageCarousel/tests/__snapshots__/index.test.js.snap +2 -0
  36. package/v2Containers/Line/Container/Wrapper/tests/__snapshots__/index.test.js.snap +2 -0
  37. package/v2Containers/Line/Container/tests/__snapshots__/index.test.js.snap +9 -0
  38. package/v2Containers/Rcs/tests/__snapshots__/index.test.js.snap +18 -0
  39. package/v2Containers/SmsTrai/Edit/tests/__snapshots__/index.test.js.snap +4 -0
  40. package/v2Containers/Whatsapp/tests/__snapshots__/index.test.js.snap +35 -0
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.141",
4
+ "version": "8.0.142",
5
5
  "description": "Capillary creatives ui",
6
6
  "main": "./index.js",
7
7
  "module": "./index.es.js",
@@ -55,4 +55,4 @@
55
55
  "webpack-bugsnag-plugins": "^1.4.3",
56
56
  "whatwg-fetch": "3.0.0"
57
57
  }
58
- }
58
+ }
package/services/api.js CHANGED
@@ -684,4 +684,9 @@ export const updateTestMessageMeta = (payload) => {
684
684
  return request(url, getAPICallObject('POST', payload?.data, false, true));
685
685
  };
686
686
 
687
+ export const getBeePopupBuilderToken = () => {
688
+ const url = `${API_ENDPOINT}/common/getInappTokenData`;
689
+ return request(url, getAPICallObject('GET'));
690
+ };
691
+
687
692
  export {request, getAPICallObject};
@@ -23,6 +23,7 @@ import {
23
23
  getBulkCustomerDetails,
24
24
  createTestMessageMeta,
25
25
  updateTestMessageMeta,
26
+ getBeePopupBuilderToken,
26
27
  } from '../api';
27
28
  import { mockData } from './mockData';
28
29
  import getSchema from '../getSchema';
@@ -804,3 +805,19 @@ describe('updateTestMessageMeta', () => {
804
805
  });
805
806
  });
806
807
  });
808
+ describe('getBeePopupBuilderToken', () => {
809
+ it('should return correct response', async () => {
810
+ global.fetch.mockReturnValue(Promise.resolve({
811
+ status: 200,
812
+ json: () => Promise.resolve({
813
+ status: 200,
814
+ response: 'test',
815
+ }),
816
+ }));
817
+ const result = await getBeePopupBuilderToken();
818
+ expect(result).toEqual({
819
+ status: 200,
820
+ response: 'test',
821
+ });
822
+ });
823
+ });
@@ -45,6 +45,14 @@ class MobilePushPreviewV2 extends React.Component { // eslint-disable-line react
45
45
  if (channel === INAPP.toUpperCase()) {
46
46
  const androidContent = get(templateData, 'versions.base.content.ANDROID') || get(templateData, 'androidContent');
47
47
  const iosContent = get(templateData, 'versions.base.content.IOS') || get(templateData, 'iosContent');
48
+ const isBeeFreeTemplate = get(androidContent, 'isBEEeditor') || get(iosContent, 'isBEEeditor');
49
+ if (isBeeFreeTemplate) {
50
+ content = {
51
+ inAppPreviewContent: device === ANDROID.toLowerCase() ? androidContent?.beeHtml : iosContent?.beeHtml,
52
+ isBeeFreeTemplate: true,
53
+ };
54
+ return content;
55
+ }
48
56
  const androidPreviewContent = {
49
57
  templateTitle: androidContent?.title,
50
58
  templateMsg: androidContent?.message,
@@ -12,7 +12,7 @@ export default [
12
12
  {
13
13
  key: 'analyticsBotSaga',
14
14
  saga: function* analyticsBotSagaFn() {
15
- yield all(analyticsBotSaga.map(saga => saga.call()));
15
+ yield all(analyticsBotSaga?.map(saga => saga.call()));
16
16
  },
17
17
  },
18
18
  ];
@@ -11,8 +11,8 @@ describe("analyticsBotSagaFn", () => {
11
11
  );
12
12
  return expectSaga(analyticsBotSagaFn)
13
13
  .provide([
14
- [matchers.call.fn(analyticsBotSaga[0]), undefined],
15
- [matchers.call.fn(analyticsBotSaga[1]), undefined]
14
+ [matchers.call.fn(analyticsBotSaga?.[0]), undefined],
15
+ [matchers.call.fn(analyticsBotSaga?.[1]), undefined]
16
16
  ])
17
17
  .run();
18
18
  });
@@ -0,0 +1,8 @@
1
+ <svg width="220" height="472" viewBox="0 0 220 472" fill="none" xmlns="http://www.w3.org/2000/svg">
2
+ <rect width="220" height="472" rx="26" fill="#101211"/>
3
+ <rect x="9" y="36" width="202" height="404" rx="9" fill="#343434"/>
4
+ <rect x="84" y="14" width="52" height="5" rx="2.5" fill="#2E2E2E"/>
5
+ <rect x="84" y="455" width="52" height="5" rx="2.5" fill="#2E2E2E"/>
6
+ <circle cx="45.5" cy="19.5" r="5.5" fill="#2E2E2E"/>
7
+ <circle cx="65.5" cy="19.5" r="3.5" fill="#2E2E2E"/>
8
+ </svg>
@@ -0,0 +1,5 @@
1
+ <svg width="228" height="472" viewBox="0 0 228 472" fill="none" xmlns="http://www.w3.org/2000/svg">
2
+ <rect width="228" height="472" rx="32" fill="#101211"/>
3
+ <path fill-rule="evenodd" clip-rule="evenodd" d="M58 11H33C20.2975 11 10 21.2975 10 34V439C10 451.703 20.2975 462 33 462H195C207.703 462 218 451.703 218 439V34C218 21.2975 207.703 11 195 11H170V14C170 21.1797 164.18 27 157 27H71C63.8203 27 58 21.1797 58 14V11Z" fill="#343434"/>
4
+ <path fill-rule="evenodd" clip-rule="evenodd" d="M58 11H33C20.2975 11 10 21.2975 10 34V439C10 451.703 20.2975 462 33 462H195C207.703 462 218 451.703 218 439V34C218 21.2975 207.703 11 195 11H170V14C170 21.1797 164.18 27 157 27H71C63.8203 27 58 21.1797 58 14V11Z" fill="#343434"/>
5
+ </svg>
@@ -236,7 +236,7 @@ export class TemplatePreview extends React.Component { // eslint-disable-line re
236
236
  } = this.props;
237
237
  let content = channel && channel.toLowerCase() === 'sms' ? [this.props.content] : this.props.content;
238
238
  const { formatMessage } = intl;
239
- const { rcsPreviewContent, inAppPreviewContent, viberPreviewContent } = content || {};
239
+ const { rcsPreviewContent, inAppPreviewContent, viberPreviewContent, isBeeFreeTemplate } = content || {};
240
240
  const { rcsImageSrc, rcsTitle, rcsDesc, buttonText: rcsButtonText } = rcsPreviewContent || {};
241
241
  const {
242
242
  videoParams,
@@ -1326,6 +1326,31 @@ export class TemplatePreview extends React.Component { // eslint-disable-line re
1326
1326
  </div>
1327
1327
  )}
1328
1328
  {channel?.toUpperCase() === INAPP && (
1329
+ isBeeFreeTemplate ? (
1330
+ <div className="shell-v2 align-center">
1331
+ <div style={{ position: 'relative', display: 'inline-block', width: '100%', height: '100%' }}>
1332
+ <CapImage
1333
+ className="preview-image"
1334
+ src={this.props.device === ANDROID ? inAppMobileAndroidFull : inAppMobileIOSFull}
1335
+ alt={formatMessage(messages.previewGenerated)}
1336
+ />
1337
+ <iframe
1338
+ srcDoc={inAppPreviewContent?.value}
1339
+ title="Inapp Preview"
1340
+ style={{
1341
+ position: 'absolute',
1342
+ top: '3rem',
1343
+ left: '5rem',
1344
+ width: '60%',
1345
+ height: '100%',
1346
+ zIndex: 1,
1347
+ pointerEvents: 'none'
1348
+ }}
1349
+ frameBorder="0"
1350
+ />
1351
+ </div>
1352
+ </div>
1353
+ ) : (
1329
1354
  <div className="shell-v2 align-center">
1330
1355
  <CapImage
1331
1356
  className="preview-image"
@@ -1402,8 +1427,9 @@ export class TemplatePreview extends React.Component { // eslint-disable-line re
1402
1427
  )}
1403
1428
  </div>
1404
1429
  </div>
1430
+ </div>
1405
1431
  </div>
1406
- </div>
1432
+ )
1407
1433
  )}
1408
1434
  </CapRow>
1409
1435
  </CapColumn>
@@ -0,0 +1,10 @@
1
+ export const BEE_LAYOUT_OPTIONS = {
2
+ POPUP: "classic-center",
3
+ HEADER: "bar-top",
4
+ FOOTER: "bar-bottom",
5
+ FULLSCREEN: "classic-center",
6
+ };
7
+ export const MOBILE = "mobile";
8
+ export const UNSUBSCRIBE = 'unsubscribe';
9
+ export const ANDROID = 'ANDROID';
10
+ export const IOS = 'IOS';
@@ -0,0 +1,169 @@
1
+ import React, { useEffect, useRef, useState } from 'react';
2
+ import PropTypes from 'prop-types';
3
+ import { injectIntl } from 'react-intl';
4
+ import { connect } from 'react-redux';
5
+ // import { bindActionCreators } from 'redux';
6
+ import { createStructuredSelector } from 'reselect';
7
+ import { UserIsAuthenticated } from '../../utils/authWrapper';
8
+ import TagList from '../TagList';
9
+ import { ANDROID, BEE_LAYOUT_OPTIONS, MOBILE, UNSUBSCRIBE } from './constants';
10
+ import emptyAndroidSvg from '../../v2Components/TemplatePreview/assets/images/empty_android.svg';
11
+ import emptyIosSvg from '../../v2Components/TemplatePreview/assets/images/empty_ios.svg';
12
+ function BeePopupEditor(props) {
13
+ const {
14
+ uid,
15
+ id,
16
+ tokenData,
17
+ saveBeeInstance,
18
+ saveBeeData,
19
+ beeJson,
20
+ templateLayoutType,
21
+ moduleFilterEnabled,
22
+ label,
23
+ location,
24
+ injectedTags,
25
+ className,
26
+ userLocale,
27
+ selectedOfferDetails,
28
+ tags,
29
+ onContextChange,
30
+ device,
31
+ } = props;
32
+
33
+ let beePluginInstance = null;
34
+ let intervalTimer;
35
+ const savedCallback = useRef();
36
+
37
+ const [visibleTaglist, setVisibleTaglist] = useState(false);
38
+ const [selectedTag, setSelectedTag] = useState({});
39
+ const filteredTags = (tags || []).filter((obj) => obj.definition.value !== UNSUBSCRIBE);
40
+
41
+ useEffect(() => {
42
+ const beeConfig = {
43
+ uid,
44
+ trackChanges: true,
45
+ container: 'bee-plugin-container',
46
+ workspace: {
47
+ popup: {
48
+ backgroundImageMobile: device === ANDROID ? emptyAndroidSvg : emptyIosSvg,
49
+ layout: BEE_LAYOUT_OPTIONS[templateLayoutType],
50
+ customStyles: {
51
+ container: {
52
+ width: "90%",
53
+ margin: "1.5rem",
54
+ },
55
+ },
56
+ },
57
+ stage: MOBILE,
58
+ hideStageToggle: true,
59
+ },
60
+ contentDialog: {
61
+ mergeTags: {
62
+ label: 'Add Label',
63
+ handler: async (resolve, reject) => {
64
+ // this will open tag modal
65
+ await setVisibleTaglist(true);
66
+ // until tag modal will not open promise will not execute
67
+ // once tag modal is opened it will start 2 sec interval to wait use has selected any tag or cancel the tag selection
68
+ const promise = new Promise((resolveP) => {
69
+ intervalTimer = setInterval(() => {
70
+ // this will execute, if user cancel the tag selection
71
+ if ((savedCallback.current || {}).close === true) {
72
+ reject();
73
+ clearInterval(intervalTimer);
74
+ return;
75
+ }
76
+ // this block is checking use has selected any tag or not
77
+ if (Object.keys(savedCallback.current || {}).length > 0) {
78
+ resolveP(savedCallback.current);
79
+ setSelectedTag({});
80
+ clearInterval(intervalTimer);
81
+ }
82
+ }, 2000);
83
+ });
84
+ // once prmise will resolve , pass the resolve data to handler to show tags in bee edior
85
+ const result = await promise;
86
+ resolve(result);
87
+ },
88
+ },
89
+ },
90
+ onChange: (jsonFile, htmlFile) => {
91
+ saveBeeData(jsonFile, htmlFile, device);
92
+ },
93
+ };
94
+ window.BeePlugin.create(tokenData, beeConfig, (instance) => {
95
+ beePluginInstance = instance;
96
+ const parseJson = JSON.parse(beeJson);
97
+ beePluginInstance.start(parseJson);
98
+ saveBeeInstance(beePluginInstance);
99
+ });
100
+ return () => clearInterval(intervalTimer);
101
+ }, [templateLayoutType]);
102
+
103
+ useEffect(() => {
104
+ savedCallback.current = Object.keys(selectedTag).length > 0 && selectedTag;
105
+ }, [selectedTag]);
106
+
107
+ const onTagSelect = (result) => {
108
+ const msg = {
109
+ name: result,
110
+ value: `{{${result}}}`,
111
+ };
112
+ setSelectedTag(msg);
113
+ setVisibleTaglist(false);
114
+ };
115
+
116
+ const onCancelTagList = () => {
117
+ setVisibleTaglist(false);
118
+ setSelectedTag({close: true});
119
+ };
120
+
121
+ return (
122
+ <>
123
+ <div id="bee-plugin-container" style={{ height: "650px" }}></div>
124
+ <TagList
125
+ moduleFilterEnabled={moduleFilterEnabled}
126
+ label={label}
127
+ onTagSelect={onTagSelect}
128
+ location={location}
129
+ tags={filteredTags}
130
+ injectedTags={injectedTags}
131
+ className={className}
132
+ id={id}
133
+ userLocale={userLocale}
134
+ selectedOfferDetails={selectedOfferDetails}
135
+ visibleTaglist={visibleTaglist}
136
+ hidePopover
137
+ modalProps={{
138
+ onCancel: onCancelTagList,
139
+ style: { left: 135, top: 250 },
140
+ className: "bee-editor-tag-list",
141
+ }}
142
+ onContextChange={onContextChange}
143
+ />
144
+ </>
145
+ );
146
+ }
147
+ BeePopupEditor.propTypes = {
148
+ saveBeeData: PropTypes.func.isRequired,
149
+ saveBeeInstance: PropTypes.func.isRequired,
150
+ beeJson: PropTypes.object.isRequired,
151
+ tokenData: PropTypes.object.isRequired,
152
+ uid: PropTypes.string.isRequired,
153
+ templateLayoutType: PropTypes.string.isRequired,
154
+ id: PropTypes.string.isRequired,
155
+ moduleFilterEnabled: PropTypes.bool.isRequired,
156
+ label: PropTypes.string.isRequired,
157
+ location: PropTypes.object.isRequired,
158
+ injectedTags: PropTypes.array.isRequired,
159
+ className: PropTypes.string.isRequired,
160
+ userLocale: PropTypes.string.isRequired,
161
+ selectedOfferDetails: PropTypes.object.isRequired,
162
+ tags: PropTypes.array.isRequired,
163
+ onContextChange: PropTypes.func.isRequired,
164
+ device: PropTypes.string.isRequired,
165
+ };
166
+ const mapStateToProps = () => createStructuredSelector({});
167
+
168
+ function mapDispatchToProps() {}
169
+ export default UserIsAuthenticated(connect(mapStateToProps, mapDispatchToProps)(injectIntl(BeePopupEditor)));