@capillarytech/creatives-library 7.17.79 → 7.17.81-alpha.0

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.
@@ -72,7 +72,6 @@ export const PROMO_ENGINE_RELATED_TAGS = [
72
72
  ];
73
73
 
74
74
  export const BADGES_RELATED_TAGS = [
75
- "Badge",
76
75
  "Badge_expiry_date",
77
76
  "badge_expiry_mm_slash_dd_slash_yyyy",
78
77
  "badge_expiry_dd_slash_mm_slash_yyyy",
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@capillarytech/creatives-library",
3
3
  "author": "meharaj",
4
- "version": "7.17.79",
4
+ "version": "7.17.81-alpha.0",
5
5
  "description": "Capillary creatives ui",
6
6
  "main": "./index.js",
7
7
  "module": "./index.es.js",
package/utils/common.js CHANGED
@@ -51,6 +51,15 @@ export function removeLinksFromHtmlContent(content) {
51
51
  return copyContent;
52
52
  }
53
53
 
54
+ export function iframePreviewAdjustWidth(content) {
55
+ const doc = document.createElement('html');
56
+ doc.innerHTML = content;
57
+ let copyContent = doc.cloneNode(true).outerHTML;
58
+ copyContent = copyContent.replace(/<img /g, '<img width="310" ');
59
+ doc.remove();
60
+ return copyContent;
61
+ }
62
+
54
63
  export const hasStore2DoorFeature = Auth.hasFeatureAccess.bind(
55
64
  null,
56
65
  STORE2DOOR_PLUS_ENABLED,
@@ -1,7 +1,7 @@
1
1
  import React from 'react';
2
2
  import { FormattedMessage } from 'react-intl';
3
3
  import "@testing-library/jest-dom";
4
- import { filterTags, getTreeStructuredTags, handleInjectedData, intlKeyGenerator, bytes2Size, getUserNameById } from "../common";
4
+ import { filterTags, getTreeStructuredTags, handleInjectedData, intlKeyGenerator, bytes2Size, getUserNameById, iframePreviewAdjustWidth } from "../common";
5
5
  import * as mockdata from "./common.mockdata";
6
6
 
7
7
  describe("getTreeStructuredTags test", () => {
@@ -208,3 +208,16 @@ describe('bytes2Size', () => {
208
208
  expect(bytes2Size(1024, -3)).toBe('1 KB');
209
209
  });
210
210
  });
211
+
212
+ describe('iframeAdjustWidth', () => {
213
+ it("should Add the width in iframe image", () => {
214
+ const data = [
215
+ <head>
216
+ <meta httpEquiv="Content-Type" content="text/html; charset=utf-8">
217
+ <meta name="viewport" content="width=device-width">
218
+ </meta></meta></head>,
219
+
220
+ ];
221
+ expect(iframePreviewAdjustWidth(data)).toBe("<html><head></head><body>[object Object]</body></html>");
222
+ });
223
+ });
@@ -18,7 +18,7 @@ import EmailPreviewV2 from '../EmailPreviewV2';
18
18
  import messages from '../EmailPreviewV2/messages';
19
19
  import './index.scss';
20
20
  import mobileBody from '../../assets/DeviceForEmail.png';
21
- import { removeLinksFromHtmlContent } from './../../utils/common';
21
+ import { iframePreviewAdjustWidth, removeLinksFromHtmlContent } from './../../utils/common';
22
22
  import {selectTemplateContent} from '../../containers/Templates/selectors';
23
23
  import * as templateActions from '../../containers/Templates/actions';
24
24
 
@@ -68,6 +68,8 @@ class EmailMobilePreview extends React.Component {
68
68
  templateSubject,
69
69
  } = this.props;
70
70
  const copyContent = templateContent && removeLinksFromHtmlContent(templateContent);
71
+ const updateCopyContent = templateContent && iframePreviewAdjustWidth(copyContent);
72
+
71
73
  const { showAllDevices } = this.state;
72
74
 
73
75
  const emailSubjectLabel = templateSubject && (
@@ -98,7 +100,7 @@ class EmailMobilePreview extends React.Component {
98
100
  <img src={mobileBody} alt="capillary" width="386" />
99
101
  <div className={`${messageContainerName} ${emailSubjectLabel ? 'with-subject' : ''}`}>
100
102
  {emailSubjectLabel}
101
- <iframe srcDoc={copyContent} {...deviceAspectRatio.mobile} >
103
+ <iframe srcDoc={updateCopyContent} {...deviceAspectRatio.mobile} >
102
104
  <p><FormattedMessage {...messages.noIframeSupport}/></p>
103
105
  </iframe>
104
106
  </div>
@@ -19,7 +19,7 @@ import messages from './messages';
19
19
  import './_emailPreviewV2.scss';
20
20
  import tabletBody from '../../assets/iPad.svg';
21
21
  import mobileBody from '../../assets/DeviceForEmail.png';
22
- import { removeLinksFromHtmlContent } from './../../utils/common';
22
+ import { iframePreviewAdjustWidth, removeLinksFromHtmlContent } from './../../utils/common';
23
23
 
24
24
  import {selectTemplateContent} from '../../v2Containers/Templates/selectors';
25
25
  import * as templateActions from '../../v2Containers/Templates/actions';
@@ -72,7 +72,8 @@ export class EmailPreviewV2 extends React.Component {
72
72
  let messageContainerName = '';
73
73
  const {currentDevice} = this.state;
74
74
  const { templateContent, templateData = {}, templateSubject } = this.props;
75
- const copyContent = removeLinksFromHtmlContent(templateContent);
75
+ const copyContent = templateContent && removeLinksFromHtmlContent(templateContent);
76
+ const updateCopyContent = templateContent && iframePreviewAdjustWidth(copyContent);
76
77
  let subjectClassName = 'email-subject-desktop';
77
78
  if (currentDevice === devices.tablet) {
78
79
  messageContainerName = 'tablet-message-container';
@@ -88,7 +89,7 @@ export class EmailPreviewV2 extends React.Component {
88
89
  );
89
90
  const iframeDiv = (<div className={`${messageContainerName}`}>
90
91
  {emailSubjectLabel}
91
- <iframe srcDoc={copyContent} {...deviceAspectRatio[currentDevice](emailSubject)} >
92
+ <iframe srcDoc={updateCopyContent} {...deviceAspectRatio[currentDevice](emailSubject)} >
92
93
  <p><FormattedMessage {...messages.browserDoesntSupportIframe} /></p>
93
94
  </iframe>
94
95
  </div>);
@@ -31,7 +31,6 @@ exports[`<EmailPreviewV2 /> <EmailPreviewV2 /> without the templateData 1`] = `
31
31
  >
32
32
  <iframe
33
33
  height="500"
34
- srcDoc="<html><head></head><body>undefined</body></html>"
35
34
  width="1024"
36
35
  >
37
36
  <p>
@@ -67,7 +66,6 @@ exports[`<EmailPreviewV2 /> <EmailPreviewV2 /> without the templateData 1`] = `
67
66
  >
68
67
  <iframe
69
68
  height="500"
70
- srcDoc="<html><head></head><body>undefined</body></html>"
71
69
  width="1024"
72
70
  >
73
71
  <p>
@@ -104,7 +102,6 @@ exports[`<EmailPreviewV2 /> <EmailPreviewV2 /> without the templateData 1`] = `
104
102
  >
105
103
  <iframe
106
104
  height="500"
107
- srcDoc="<html><head></head><body>undefined</body></html>"
108
105
  width="1024"
109
106
  >
110
107
  <p>
File without changes
@@ -0,0 +1,499 @@
1
+ /* eslint-disable camelcase */
2
+ /* eslint-disable react/jsx-indent */
3
+ import React, { useState, useEffect } from 'react';
4
+ import { bindActionCreators } from 'redux';
5
+ import { createStructuredSelector } from 'reselect';
6
+ import { injectIntl, FormattedMessage } from 'react-intl';
7
+ import { get, isEmpty } from 'lodash';
8
+ import styled from 'styled-components';
9
+ import CapSpin from '@capillarytech/cap-ui-library/CapSpin';
10
+ import CapRow from '@capillarytech/cap-ui-library/CapRow';
11
+ import CapColumn from '@capillarytech/cap-ui-library/CapColumn';
12
+ import CapLabel from '@capillarytech/cap-ui-library/CapLabel';
13
+ import CapAlert from '@capillarytech/cap-ui-library/CapAlert';
14
+ import CapInput from '@capillarytech/cap-ui-library/CapInput';
15
+ import CapHeading from '@capillarytech/cap-ui-library/CapHeading';
16
+ import CapHeader from '@capillarytech/cap-ui-library/CapHeader';
17
+ import CapNotification from '@capillarytech/cap-ui-library/CapNotification';
18
+ import CapTooltip from '@capillarytech/cap-ui-library/CapTooltip';
19
+ import CapButton from '@capillarytech/cap-ui-library/CapButton';
20
+ import {
21
+ CAP_SPACE_16,
22
+ CAP_SPACE_24,
23
+ CAP_SPACE_32,
24
+ CAP_WHITE,
25
+ } from '@capillarytech/cap-ui-library/styled/variables';
26
+ import { makeSelectZalo, makeSelectAccount } from './selectors';
27
+ import { makeSelectMetaEntities, setInjectedTags } from '../Cap/selectors';
28
+ import * as zaloActions from './actions';
29
+ import './index.scss';
30
+ import {
31
+ SUCCESS_ALERT,
32
+ REQUEST,
33
+ EMBEDDED,
34
+ DEFAULT,
35
+ TAG,
36
+ FULL,
37
+ ALL,
38
+ OUTBOUND,
39
+ LIBRARY,
40
+ ERROR_ALERT,
41
+ WARNING_ALERT,
42
+ ZALO_STATUSES,
43
+ } from './constants';
44
+ import { SMS, ZALO } from '../CreativesContainer/constants';
45
+ import messages from './messages';
46
+ import globalMessages from '../Cap/messages';
47
+ import withCreatives from '../../hoc/withCreatives';
48
+ import TagList from '../TagList';
49
+ import { validateTags } from '../../utils/tagValidations';
50
+ import TemplatePreview from '../../v2Components/TemplatePreview';
51
+
52
+ export const InApp = (props) => {
53
+ const {
54
+ intl,
55
+ actions,
56
+ isFullMode,
57
+ templateData = {},
58
+ editData = {},
59
+ accountData: { selectedZaloAccount = {} } = {},
60
+ globalActions,
61
+ location,
62
+ getDefaultTags,
63
+ supportedTags,
64
+ metaEntities,
65
+ injectedTags,
66
+ getFormData,
67
+ selectedOfferDetails,
68
+ } = props || {};
69
+ const { formatMessage } = intl;
70
+ const [oa_id, setOaId] = useState('');
71
+ const [token, setToken] = useState('');
72
+ const [username, setUsername] = useState('');
73
+ const [templateName, setTemplateName] = useState('');
74
+ const [templateId, setTemplateId] = useState('');
75
+ const [templateListParams, setTemplateListParams] = useState([]);
76
+ const [templatePreviewUrl, setTemplatePreviewUrl] = useState('');
77
+ const [templateStatus, setZaloTemplateStatus] = useState(
78
+ ZALO_STATUSES.ENABLE,
79
+ );
80
+ const [tags, updateTags] = useState([]);
81
+ const [textAreaId, updateTextAreaId] = useState('');
82
+ const { zaloTemplateInfoValue = {}, zaloTemplateInfoStatus = REQUEST } =
83
+ editData;
84
+ const {
85
+ _id = '',
86
+ accountId = '',
87
+ zaloAccountId = '',
88
+ accountName = '',
89
+ templateConfigs: { id = '', varMapped = {} } = {},
90
+ token: zaloToken = '',
91
+ } = templateData;
92
+ const zaloTempId = _id || id;
93
+ const ZaloFooter = styled.div`
94
+ background-color: ${CAP_WHITE};
95
+ position: fixed;
96
+ bottom: 0;
97
+ width: 100%;
98
+ margin-left: -32px;
99
+ padding: ${CAP_SPACE_32} ${CAP_SPACE_24};
100
+ z-index: 1;
101
+
102
+ .ant-btn {
103
+ margin-right: ${CAP_SPACE_16};
104
+ }
105
+ }
106
+ `;
107
+ //gets account details
108
+ useEffect(() => {
109
+ if (!isEmpty(selectedZaloAccount) || !isEmpty(templateData)) {
110
+ const {
111
+ sourceAccountIdentifier = '',
112
+ configs: { token: accessToken = '' } = {},
113
+ name = '',
114
+ } = selectedZaloAccount;
115
+ const oaId = getDefaultTags === OUTBOUND ? zaloAccountId : accountId;
116
+ setOaId(sourceAccountIdentifier || oaId);
117
+ setToken(accessToken || zaloToken);
118
+ setUsername(name || accountName);
119
+ }
120
+ }, [selectedZaloAccount, templateData]);
121
+
122
+ //gets template details
123
+ useEffect(() => {
124
+ if (zaloTempId && oa_id && token && username) {
125
+ actions.getTemplateInfoById({
126
+ username,
127
+ oa_id,
128
+ token,
129
+ id: zaloTempId,
130
+ actionCallback,
131
+ });
132
+ }
133
+ //cleanup code
134
+ return () => {
135
+ actions.resetTemplateInfoData();
136
+ };
137
+ }, [zaloTempId, oa_id, token, username]);
138
+
139
+ const handleSetValues = (paramsData = []) =>
140
+ paramsData.map((paramData) => {
141
+ for (const key in varMapped) {
142
+ if (paramData?.name === key) {
143
+ paramData.value = varMapped[key];
144
+ }
145
+ }
146
+ return paramData;
147
+ });
148
+
149
+ const setDataForEdit = (setValues) => {
150
+ const {
151
+ name = '',
152
+ _id: zaloId = '',
153
+ versions: {
154
+ base: {
155
+ content: {
156
+ zalo: {
157
+ listParams: paramsData = [],
158
+ previewUrl = '',
159
+ status = '',
160
+ } = {},
161
+ } = {},
162
+ } = {},
163
+ } = {},
164
+ } = zaloTemplateInfoValue;
165
+ setTemplateName(name);
166
+ setTemplateId(zaloId);
167
+ setTemplateListParams(setValues ? handleSetValues(paramsData) : paramsData);
168
+ setTemplatePreviewUrl(previewUrl);
169
+ setZaloTemplateStatus(status);
170
+ updateTextAreaId(paramsData[0]?.name);
171
+ };
172
+
173
+ useEffect(() => {
174
+ setDataForEdit(false);
175
+ }, [zaloTemplateInfoValue]);
176
+
177
+ useEffect(() => {
178
+ if (!isEmpty(varMapped)) {
179
+ setDataForEdit(true);
180
+ }
181
+ }, [varMapped, zaloTemplateInfoValue]);
182
+
183
+ useEffect(() => {
184
+ let tag = get(metaEntities, `tags.standard`, []);
185
+ const { type, module } = location?.query || {};
186
+ if (type === EMBEDDED && module === LIBRARY && !getDefaultTags) {
187
+ tag = supportedTags;
188
+ }
189
+ updateTags(tag);
190
+ }, [metaEntities]);
191
+
192
+ useEffect(() => {
193
+ //fetching tags
194
+ const { type, module } = location?.query || {};
195
+ const isEmbedded = type === EMBEDDED;
196
+ const query = {
197
+ layout: SMS,
198
+ type: TAG,
199
+ context: isEmbedded ? module : DEFAULT,
200
+ embedded: isEmbedded ? type : FULL,
201
+ };
202
+ if (getDefaultTags) {
203
+ query.context = getDefaultTags;
204
+ }
205
+ globalActions.fetchSchemaForEntity(query);
206
+ }, []);
207
+
208
+ const handleOnTagsContextChange = (data) => {
209
+ const { type } = location?.query || {};
210
+ const isEmbedded = type === EMBEDDED;
211
+ const query = {
212
+ layout: SMS,
213
+ type: TAG,
214
+ context:
215
+ (data || '').toLowerCase() === ALL
216
+ ? DEFAULT
217
+ : (data || '').toLowerCase(),
218
+ embedded: isEmbedded ? type : FULL,
219
+ };
220
+ globalActions.fetchSchemaForEntity(query);
221
+ };
222
+
223
+ const onTagSelect = (data) => {
224
+ if (data && textAreaId) {
225
+ const updatedZaloTemplateInfo = templateListParams?.map((listParams) => {
226
+ const { name = '', value = '', minLength, maxLength } = listParams;
227
+ if (name === textAreaId) {
228
+ const text = `${value}{{${data}}}`;
229
+ const isLengthError =
230
+ text.length <= minLength || text.length > maxLength;
231
+ return {
232
+ ...listParams,
233
+ value: text,
234
+ error: isLengthError
235
+ ? formatMessage(messages.maxMinLengthMessage, {
236
+ minLength,
237
+ maxLength,
238
+ })
239
+ : '',
240
+ };
241
+ }
242
+ return listParams;
243
+ });
244
+ setTemplateListParams(updatedZaloTemplateInfo);
245
+ }
246
+ };
247
+
248
+ const tagValidationErrorMessage = (message) => {
249
+ const tagValidationResponse =
250
+ validateTags({
251
+ content: message,
252
+ tagsParam: tags,
253
+ injectedTagsParams: injectedTags,
254
+ location,
255
+ tagModule: getDefaultTags,
256
+ }) || {};
257
+ const { unsupportedTags = [], isBraceError } = tagValidationResponse;
258
+ let tagError = '';
259
+ if (unsupportedTags.length > 0) {
260
+ tagError = formatMessage(globalMessages.unsupportedTagsValidationError, {
261
+ unsupportedTags,
262
+ });
263
+ }
264
+ if (isBraceError) {
265
+ tagError = formatMessage(globalMessages.unbalanacedCurlyBraces);
266
+ }
267
+ return tagError;
268
+ };
269
+
270
+ //this function is used for checking errror validation in this it validate tags error and length error
271
+ const handleErrorValidation = (e, field) => {
272
+ const { minLength, maxLength } = field;
273
+ let error = e ? tagValidationErrorMessage(e) : '';
274
+ if (!e || e.length <= minLength || e.length > maxLength) {
275
+ error = formatMessage(messages.maxMinLengthMessage, {
276
+ minLength,
277
+ maxLength,
278
+ });
279
+ }
280
+ return error;
281
+ };
282
+
283
+ // this function is used for handle form data change in this also handle error validtion on change of value
284
+ const handleFormDataChange = (e, field) => {
285
+ const {
286
+ target: { value },
287
+ } = e;
288
+ const updatedZaloTemplateInfo = templateListParams?.map((listParams) => {
289
+ if (listParams?.name === field?.name) {
290
+ const error = handleErrorValidation(value, field);
291
+ return {
292
+ ...listParams,
293
+ value,
294
+ error,
295
+ };
296
+ }
297
+ return listParams;
298
+ });
299
+ setTemplateListParams(updatedZaloTemplateInfo);
300
+ };
301
+
302
+ const renderTextBoxesForListParams = (listParam) => {
303
+ const { name, error, value } = listParam;
304
+ return (
305
+ <CapInput
306
+ id={`zalo-${name}`}
307
+ onChange={(e) => handleFormDataChange(e, listParam)}
308
+ errorMessage={error}
309
+ placeholder={formatMessage(messages.addVariableWithMessage)}
310
+ defaultValue={value || ''}
311
+ value={value || ''}
312
+ size="default"
313
+ onFocus={() => setTextAreaId(name)}
314
+ disabled={isFullMode}
315
+ />
316
+ );
317
+ };
318
+
319
+ const setTextAreaId = (fieldName) => {
320
+ updateTextAreaId(fieldName);
321
+ };
322
+
323
+ const getTemplateStatusType = () => {
324
+ switch (templateStatus) {
325
+ case ZALO_STATUSES.ENABLE:
326
+ return SUCCESS_ALERT;
327
+ case ZALO_STATUSES.REJECT:
328
+ return ERROR_ALERT;
329
+ default:
330
+ return WARNING_ALERT;
331
+ }
332
+ };
333
+
334
+ const actionCallback = () => {
335
+ CapNotification.error({
336
+ message: formatMessage(messages.zaloFailureNotificationTemplate),
337
+ });
338
+ };
339
+
340
+ const isEditDoneDisabled = () => {
341
+ let disableCheck = false;
342
+ templateListParams.forEach((listParams) => {
343
+ const { error, value } = listParams;
344
+ const errorMessage = !error
345
+ ? handleErrorValidation(value, listParams)
346
+ : error;
347
+ if (errorMessage) {
348
+ disableCheck = true;
349
+ }
350
+ });
351
+ return disableCheck;
352
+ };
353
+ const createPayload = () => {
354
+ const varMap = {};
355
+ templateListParams.forEach((listParam) => {
356
+ const { name, value } = listParam;
357
+ varMap[name] = value;
358
+ });
359
+ const payload = {
360
+ channel: ZALO,
361
+ accountId: oa_id,
362
+ ...(getDefaultTags === OUTBOUND && {
363
+ zaloAccountId: oa_id,
364
+ }),
365
+ accountName: username,
366
+ templateConfigs: {
367
+ id: templateId?.toString(),
368
+ name: templateName,
369
+ template: templatePreviewUrl,
370
+ varMapped: varMap,
371
+ },
372
+ token,
373
+ };
374
+ return payload;
375
+ };
376
+
377
+ const saveToMessage = () => {
378
+ getFormData({
379
+ value: createPayload(),
380
+ _id: templateId,
381
+ validity: true,
382
+ type: ZALO,
383
+ });
384
+ };
385
+
386
+ const renderContent = () =>
387
+ templateListParams?.map((listParam) => {
388
+ const { name = '', value = '', maxLength } = listParam;
389
+ return (
390
+ <>
391
+ {renderTextBoxesForListParams(listParam)}
392
+ <CapRow className="variable-field-container">
393
+ <CapLabel className="variable-field-name">
394
+ {formatMessage(messages.variableType, {
395
+ name,
396
+ })}
397
+ </CapLabel>
398
+ <CapLabel className="variable-field-length">
399
+ {formatMessage(messages.charactersCount, {
400
+ variableLength: value.length,
401
+ maxLength,
402
+ })}
403
+ </CapLabel>
404
+ </CapRow>
405
+ </>
406
+ );
407
+ });
408
+
409
+ return (
410
+ <CapSpin spinning={zaloTemplateInfoStatus === REQUEST}>
411
+ <CapRow type="flex" className="cap-zalo-creatives">
412
+ <CapColumn span={14}>
413
+ {templateStatus && (
414
+ <CapAlert
415
+ message={
416
+ <CapLabel type="label2">
417
+ {formatMessage(messages.approvedStatusMsg, {
418
+ status: formatMessage(messages?.[templateStatus]),
419
+ })}
420
+ </CapLabel>
421
+ }
422
+ type={getTemplateStatusType()}
423
+ />
424
+ )}
425
+ <CapRow>
426
+ <CapRow className="whatsapp-render-heading">
427
+ <CapHeader
428
+ className="zalo-variable-heading"
429
+ title={
430
+ <CapHeading type="h4">
431
+ {formatMessage(messages.variables)}
432
+ </CapHeading>
433
+ }
434
+ suffix={
435
+ <TagList
436
+ label={formatMessage(globalMessages.addLabels)}
437
+ onTagSelect={onTagSelect}
438
+ location={location}
439
+ tags={tags || []}
440
+ onContextChange={handleOnTagsContextChange}
441
+ injectedTags={injectedTags || {}}
442
+ selectedOfferDetails={selectedOfferDetails}
443
+ disabled={isFullMode}
444
+ />
445
+ }
446
+ />
447
+ </CapRow>
448
+ <CapRow className="zalo-variable-list">{renderContent()}</CapRow>
449
+ </CapRow>
450
+ </CapColumn>
451
+ <CapColumn span={10}>
452
+ <TemplatePreview
453
+ channel={ZALO}
454
+ templateData={{ templatePreviewUrl, fullMode: isFullMode }}
455
+ />
456
+ </CapColumn>
457
+ </CapRow>
458
+ {!isFullMode && (
459
+ <ZaloFooter>
460
+ <CapTooltip
461
+ title={
462
+ isEditDoneDisabled()
463
+ ? formatMessage(messages.btnDisabledTooltip)
464
+ : ''
465
+ }
466
+ placement={'right'}
467
+ >
468
+ <div className="button-disabled-tooltip-wrapper">
469
+ <CapButton
470
+ onClick={saveToMessage}
471
+ disabled={isEditDoneDisabled()}
472
+ >
473
+ <FormattedMessage {...globalMessages.done} />
474
+ </CapButton>
475
+ </div>
476
+ </CapTooltip>
477
+ </ZaloFooter>
478
+ )}
479
+ </CapSpin>
480
+ );
481
+ };
482
+
483
+ const mapStateToProps = createStructuredSelector({
484
+ editData: makeSelectZalo(),
485
+ accountData: makeSelectAccount(),
486
+ metaEntities: makeSelectMetaEntities(),
487
+ injectedTags: setInjectedTags(),
488
+ });
489
+
490
+ const mapDispatchToProps = (dispatch) => ({
491
+ actions: bindActionCreators(zaloActions, dispatch),
492
+ });
493
+
494
+ export default withCreatives({
495
+ WrappedComponent: injectIntl(InApp),
496
+ mapStateToProps,
497
+ mapDispatchToProps,
498
+ userAuth: true,
499
+ });
File without changes
File without changes