@capillarytech/creatives-library 7.17.80 → 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.80",
4
+ "version": "7.17.81-alpha.0",
5
5
  "description": "Capillary creatives ui",
6
6
  "main": "./index.js",
7
7
  "module": "./index.es.js",
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