@capillarytech/creatives-library 7.12.0 → 7.12.3

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 (55) hide show
  1. package/index.js +6 -0
  2. package/package.json +1 -1
  3. package/routes.js +7 -2
  4. package/services/api.js +8 -2
  5. package/v2Components/CallTaskPreview/tests/__snapshots__/index.test.js.snap +30 -0
  6. package/v2Components/CapImageUpload/index.js +24 -11
  7. package/v2Components/CapImageUpload/index.scss +12 -27
  8. package/v2Components/CapImageUpload/messages.js +10 -5
  9. package/v2Components/TemplatePreview/_templatePreview.scss +13 -1
  10. package/v2Components/TemplatePreview/index.js +43 -2
  11. package/v2Components/TemplatePreview/tests/__snapshots__/index.test.js.snap +33 -1
  12. package/v2Components/TemplatePreview/tests/index.test.js +7 -7
  13. package/v2Containers/App/constants.js +2 -1
  14. package/v2Containers/Assets/images/addCreativesIllustration.svg +30 -0
  15. package/v2Containers/Assets/images/rcsIllustration.png +0 -0
  16. package/v2Containers/Cap/messages.js +20 -1
  17. package/v2Containers/CreativesContainer/SlideBoxContent.js +57 -11
  18. package/v2Containers/CreativesContainer/SlideBoxHeader.js +1 -0
  19. package/v2Containers/CreativesContainer/constants.js +1 -0
  20. package/v2Containers/CreativesContainer/messages.js +4 -0
  21. package/v2Containers/CreativesContainer/tests/SlideBoxContent.test.js +24 -4
  22. package/v2Containers/CreativesContainer/tests/SlideBoxHeader.test.js +23 -4
  23. package/v2Containers/CreativesContainer/tests/__snapshots__/SlideBoxContent.test.js.snap +147 -2
  24. package/v2Containers/CreativesContainer/tests/__snapshots__/SlideBoxHeader.test.js.snap +98 -0
  25. package/v2Containers/CreativesContainer/tests/__snapshots__/index.test.js.snap +71 -0
  26. package/v2Containers/CreativesContainer/tests/index.test.js +21 -9
  27. package/v2Containers/Facebook/Advertisement/index.js +4 -2
  28. package/v2Containers/MobilePush/Edit/index.js +21 -34
  29. package/v2Containers/Rcs/actions.js +57 -0
  30. package/v2Containers/Rcs/constants.js +50 -0
  31. package/v2Containers/Rcs/index.js +1064 -0
  32. package/v2Containers/Rcs/index.scss +72 -0
  33. package/v2Containers/Rcs/messages.js +122 -0
  34. package/v2Containers/Rcs/reducer.js +107 -0
  35. package/v2Containers/Rcs/sagas.js +141 -0
  36. package/v2Containers/Rcs/selectors.js +8 -0
  37. package/v2Containers/Rcs/tests/__snapshots__/index.test.js.snap +145080 -0
  38. package/v2Containers/Rcs/tests/index.test.js +226 -0
  39. package/v2Containers/Rcs/tests/mockData.js +169 -0
  40. package/v2Containers/Rcs/utils.js +40 -0
  41. package/v2Containers/SmsTrai/Edit/tests/__snapshots__/index.test.js.snap +4 -4
  42. package/v2Containers/Templates/_templates.scss +9 -1
  43. package/v2Containers/Templates/actions.js +2 -1
  44. package/v2Containers/Templates/constants.js +1 -0
  45. package/v2Containers/Templates/index.js +234 -174
  46. package/v2Containers/Templates/messages.js +20 -0
  47. package/v2Containers/Templates/reducer.js +2 -0
  48. package/v2Containers/Templates/tests/__snapshots__/index.test.js.snap +520 -80
  49. package/v2Containers/TemplatesV2/index.js +2 -1
  50. package/v2Containers/TemplatesV2/messages.js +4 -0
  51. package/v2Containers/Whatsapp/index.js +4 -2
  52. package/v2Containers/Whatsapp/messages.js +0 -13
  53. package/v2Containers/Whatsapp/tests/__snapshots__/index.test.js.snap +13 -13
  54. package/v2Containers/Whatsapp/tests/__snapshots__/utils.test.js.snap +32 -26
  55. package/v2Containers/mockdata.js +567 -1588
@@ -0,0 +1,1064 @@
1
+ /* eslint-disable no-unused-expressions */
2
+ /* eslint-disable indent */
3
+ /* eslint-disable no-unused-vars */
4
+ import React, { useState, useEffect, useCallback } from 'react';
5
+ import { bindActionCreators } from 'redux';
6
+ import { createStructuredSelector } from 'reselect';
7
+ import { injectIntl, FormattedMessage } from 'react-intl';
8
+ import { get, isEmpty, cloneDeep } from 'lodash';
9
+ import styled from 'styled-components';
10
+ import CapSpin from '@capillarytech/cap-ui-library/CapSpin';
11
+ import CapRow from '@capillarytech/cap-ui-library/CapRow';
12
+ import CapColumn from '@capillarytech/cap-ui-library/CapColumn';
13
+ import CapButton from '@capillarytech/cap-ui-library/CapButton';
14
+ import CapInput from '@capillarytech/cap-ui-library/CapInput';
15
+ import CapHeading from '@capillarytech/cap-ui-library/CapHeading';
16
+ import CapRadioGroup from '@capillarytech/cap-ui-library/CapRadioGroup';
17
+ import CapTooltip from '@capillarytech/cap-ui-library/CapTooltip';
18
+ import CapLabel from '@capillarytech/cap-ui-library/CapLabel';
19
+ import CapHeader from '@capillarytech/cap-ui-library/CapHeader';
20
+ import CapDivider from '@capillarytech/cap-ui-library/CapDivider';
21
+ import CapIcon from '@capillarytech/cap-ui-library/CapIcon';
22
+ import CapImage from '@capillarytech/cap-ui-library/CapImage';
23
+ import CapCard from '@capillarytech/cap-ui-library/CapCard';
24
+ import CapSlideBox from '@capillarytech/cap-ui-library/CapSlideBox';
25
+ import CapCustomCard from '@capillarytech/cap-ui-library/CapCustomCard';
26
+ import CapDropdown from '@capillarytech/cap-ui-library/CapDropdown';
27
+ import CapMenu from '@capillarytech/cap-ui-library/CapMenu';
28
+ import CapNotification from '@capillarytech/cap-ui-library/CapNotification';
29
+ import CapTooltipWithInfo from '@capillarytech/cap-ui-library/CapTooltipWithInfo';
30
+ import CapError from '@capillarytech/cap-ui-library/CapError';
31
+ import {
32
+ CAP_G01,
33
+ CAP_SPACE_16,
34
+ CAP_SPACE_24,
35
+ CAP_SPACE_28,
36
+ CAP_SPACE_32,
37
+ CAP_WHITE,
38
+ CAP_SECONDARY,
39
+ } from '@capillarytech/cap-ui-library/styled/variables';
40
+ import { makeSelectRcs } from './selectors';
41
+ import {
42
+ isLoadingMetaEntities,
43
+ makeSelectMetaEntities,
44
+ setInjectedTags,
45
+ } from '../Cap/selectors';
46
+ import * as RcsActions from './actions';
47
+ import * as TemplatesActions from '../Templates/actions'
48
+ import './index.scss';
49
+ import {
50
+ RCS,
51
+ SMS,
52
+ RCS_MEDIA_TYPES,
53
+ TEMPLATE_MESSAGE_MAX_LENGTH,
54
+ FALLBACK_MESSAGE_MAX_LENGTH,
55
+ TAG,
56
+ EMBEDDED,
57
+ DEFAULT,
58
+ FULL,
59
+ ALL,
60
+ LIBRARY,
61
+ ALLOWED_IMAGE_EXTENSIONS_REGEX,
62
+ RCS_IMG_WIDTH,
63
+ RCS_IMG_HEIGHT,
64
+ RCS_IMG_SIZE,
65
+ RCS_DLT_MODE,
66
+ MEDIUM,
67
+ VERTICAL,
68
+ RIGHT,
69
+ STANDALONE,
70
+ RICHCARD,
71
+ } from './constants';
72
+ import globalMessages from '../Cap/messages';
73
+ import messages from './messages';
74
+ import withCreatives from '../../hoc/withCreatives';
75
+ import TemplatePreview from '../../v2Components/TemplatePreview';
76
+ import CapImageUpload from '../../v2Components/CapImageUpload';
77
+ import addCreativesIcon from '../Assets/images/addCreativesIllustration.svg';
78
+ import Templates from '../Templates';
79
+ import SmsTraiEdit from '../SmsTrai/Edit';
80
+ import TagList from '../TagList';
81
+ import { validateTags } from '../../utils/tagValidations';
82
+ export const Rcs = (props) => {
83
+ const {
84
+ intl,
85
+ actions,
86
+ isFullMode,
87
+ onCreateComplete,
88
+ params,
89
+ templateData = {},
90
+ rcsData = {},
91
+ templatesActions,
92
+ globalActions,
93
+ location,
94
+ getDefaultTags,
95
+ supportedTags,
96
+ metaEntities,
97
+ injectedTags,
98
+ loadingTags,
99
+ getFormData,
100
+ isDltEnabled,
101
+ smsRegister,
102
+ } = props || {};
103
+ const { formatMessage } = intl;
104
+ const { TextArea } = CapInput;
105
+ const { CapCustomCardList } = CapCustomCard;
106
+ const [isEditFlow, setEditFlow] = useState(false);
107
+ const [tags, updateTags] = useState([]);
108
+ const [rcsImageSrc, updateRcsImageSrc] = useState('');
109
+ const [spin, setSpin] = useState(false);
110
+ //template
111
+ const [templateName, setTemplateName] = useState('');
112
+ const [templateNameError, setTemplateNameError] = useState(false);
113
+ const [templateMediaType, setTemplateMediaType] = useState(
114
+ RCS_MEDIA_TYPES.NONE,
115
+ );
116
+ const [templateTitle, setTemplateTitle] = useState('');
117
+ const [templateDesc, setTemplateDesc] = useState('');
118
+ const [templateDescError, setTemplateDescError] = useState(false);
119
+ //fallback
120
+ const [fallbackMessage, setFallbackMessage] = useState('');
121
+ const [fallbackMessageError, setFallbackMessageError] = useState(false);
122
+ //fallback dlt
123
+ const [showDltContainer, setShowDltContainer] = useState(false);
124
+ const [dltMode, setDltMode] = useState('');
125
+ const [dltEditData, setDltEditData] = useState({});
126
+ const [showDltCard, setShowDltCard] = useState(false);
127
+ const [fallbackPreviewmode, setFallbackPreviewmode] = useState(false);
128
+ const [dltPreviewData, setDltPreviewData] = useState('');
129
+
130
+ const mediaRadioOptions = [
131
+ {
132
+ value: RCS_MEDIA_TYPES.NONE,
133
+ label: formatMessage(messages.mediaNone),
134
+ },
135
+ {
136
+ value: RCS_MEDIA_TYPES.IMAGE,
137
+ label: formatMessage(messages.mediaImage),
138
+ },
139
+ {
140
+ value: RCS_MEDIA_TYPES.VIDEO,
141
+ label: (
142
+ <CapTooltip title={formatMessage(messages.disabledMediaTooltip)}>
143
+ {formatMessage(messages.mediaVideo)}
144
+ </CapTooltip>
145
+ ),
146
+ disabled: true,
147
+ },
148
+ ];
149
+
150
+ const isMediaTypeNone = templateMediaType === RCS_MEDIA_TYPES.NONE;
151
+ const RcsFooter = styled.div`
152
+ background-color: ${CAP_WHITE};
153
+ position: fixed;
154
+ bottom: 0;
155
+ width: 100%;
156
+ margin-left: -32px;
157
+ padding: ${CAP_SPACE_32} ${CAP_SPACE_24};
158
+
159
+ .ant-btn {
160
+ margin-right: ${CAP_SPACE_16};
161
+ }
162
+ }
163
+ `;
164
+
165
+ const RcsLabel = styled.div`
166
+ display: flex;
167
+ margin-top: 20px;
168
+ margin-bottom: 6px;
169
+ `;
170
+
171
+ //gets template details
172
+ const paramObj = params || {};
173
+ useEffect(() => {
174
+ const { id } = paramObj;
175
+ if (id) {
176
+ if (isFullMode) {
177
+ setSpin(true);
178
+ actions.getTemplateDetails(id, setSpin);
179
+ }
180
+ }
181
+ //cleanup code
182
+ return () => {
183
+ actions.clearEditResponse();
184
+ };
185
+ }, [paramObj.id]);
186
+
187
+ useEffect(() => {
188
+ const { name = '', versions = {} } = isFullMode
189
+ ? rcsData.templateDetails || {}
190
+ : templateData || {};
191
+ const editContent = get(versions, `base.content.RCS`, {});
192
+ if (editContent && !isEmpty(editContent)) {
193
+ const { cardContent = [], smsFallBackContent = {} } = editContent;
194
+ const {
195
+ media = { mediaUrl: '' },
196
+ mediaType,
197
+ title,
198
+ description,
199
+ } = cardContent[0] || {};
200
+ const { message, templateConfigs = {} } = smsFallBackContent;
201
+ setTemplateName(name);
202
+ setFallbackMessage(message);
203
+ setTemplateDesc(description);
204
+ setTemplateTitle(title);
205
+ setTemplateMediaType(mediaType);
206
+ updateRcsImageSrc(media.mediaUrl);
207
+ setEditFlow(true);
208
+ // for DLT Fallback message
209
+ if (isDltEnabled) {
210
+ const {
211
+ registeredSenderIds: header = [],
212
+ template = {},
213
+ templateId = '',
214
+ templateName: tmpName = '',
215
+ templateVariableMapping = {},
216
+ } = templateConfigs;
217
+ if (header.length > 0) {
218
+ const tempData = {
219
+ versions: {
220
+ // eslint-disable-next-line no-undef
221
+ base: {
222
+ header,
223
+ "template_id": templateId,
224
+ "template_name": tmpName,
225
+ 'sms-editor': template,
226
+ 'var-mapped': templateVariableMapping,
227
+ },
228
+ },
229
+ };
230
+ setDltEditData(tempData);
231
+ setShowDltCard(true);
232
+ } else {
233
+ setShowDltCard(false);
234
+ }
235
+ }
236
+ }
237
+ }, [rcsData.templateDetails || templateData]);
238
+
239
+ // tag Code start from here
240
+ useEffect(() => {
241
+ if (!showDltContainer) {
242
+ //fetching tags
243
+ const { type, module } = location.query || {};
244
+ const isEmbedded = type === EMBEDDED;
245
+ const context = isEmbedded ? module : DEFAULT;
246
+ const embedded = isEmbedded ? type : FULL;
247
+ const query = {
248
+ layout: SMS,
249
+ type: TAG,
250
+ context,
251
+ embedded,
252
+ };
253
+ if (getDefaultTags) {
254
+ query.context = getDefaultTags;
255
+ }
256
+ globalActions.fetchSchemaForEntity(query);
257
+ }
258
+ }, [showDltContainer]);
259
+
260
+ useEffect(() => {
261
+ let tag = get(metaEntities, `tags.standard`, []);
262
+ const { type, module } = location.query || {};
263
+ if (type === EMBEDDED && module === LIBRARY && !getDefaultTags) {
264
+ tag = supportedTags;
265
+ }
266
+ updateTags(tag);
267
+ }, [metaEntities]);
268
+
269
+ const handleOnTagsContextChange = (data) => {
270
+ const { type } = location.query || {};
271
+ const tempData = (data || '').toLowerCase();
272
+ const isEmbedded = type === EMBEDDED;
273
+ const embedded = isEmbedded ? type : FULL;
274
+ const context = tempData === ALL ? DEFAULT : tempData;
275
+ const query = {
276
+ layout: SMS,
277
+ type: TAG,
278
+ context,
279
+ embedded,
280
+ };
281
+ globalActions.fetchSchemaForEntity(query);
282
+ };
283
+
284
+ const onTagSelect = (data) => {
285
+ const tempMsg = `${templateDesc}{{${data}}}`;
286
+ const error = templateDescErrorHandler(tempMsg);
287
+ setTemplateDesc(tempMsg);
288
+ setTemplateDescError(error);
289
+ };
290
+
291
+ const onTagSelectFallback = (data) => {
292
+ const tempMsg = `${fallbackMessage}{{${data}}}`;
293
+ const error = fallbackMessageErrorHandler(tempMsg);
294
+ setFallbackMessage(tempMsg);
295
+ setFallbackMessageError(error);
296
+ };
297
+
298
+ //removing optout tag for rcs
299
+ const getRcsTags = () => {
300
+ const tempTags = cloneDeep(tags);
301
+ // eslint-disable-next-line no-undef
302
+ if (tempTags?.length > 0 && tempTags[0]?.definition?.value === 'optout') {
303
+ tempTags.shift();
304
+ }
305
+ return tempTags;
306
+ };
307
+ // tag Code end
308
+
309
+ const renderLabel = (value, showLabel) => (
310
+ <RcsLabel>
311
+ <CapHeading type="h4">{formatMessage(messages[value])}</CapHeading>
312
+ {showLabel && (
313
+ <CapHeading type="h4" className="rcs-optional-label">
314
+ {formatMessage(messages.optional)}
315
+ </CapHeading>
316
+ )}
317
+ </RcsLabel>
318
+ );
319
+
320
+ const onTemplateNameChange = ({ target: { value } }) => {
321
+ setTemplateName(value);
322
+ templateNameErrorHandler(value);
323
+ };
324
+
325
+ const templateNameErrorHandler = (value) => {
326
+ let errorMessage = false;
327
+ if (value === '') {
328
+ errorMessage = formatMessage(
329
+ globalMessages.emptyTemplateNameErrorMessage,
330
+ );
331
+ }
332
+ setTemplateNameError(errorMessage);
333
+ };
334
+
335
+ const onTemplateMediaTypeChange = ({ target: { value } }) => {
336
+ setTemplateMediaType(value);
337
+ if (templateDesc.trim() === '') {
338
+ setTemplateDescError(false);
339
+ }
340
+ };
341
+
342
+ const onTemplateTitleChange = ({ target: { value } }) => {
343
+ setTemplateTitle(value);
344
+ };
345
+
346
+ const onTemplateDescChange = ({ target: { value } }) => {
347
+ const error = templateDescErrorHandler(value);
348
+ setTemplateDesc(value);
349
+ setTemplateDescError(error);
350
+ };
351
+
352
+ const templateDescErrorHandler = (value) => {
353
+ let errorMessage = false;
354
+ const { unsupportedTags } =
355
+ validateTags({
356
+ content: value,
357
+ tagsParam: tags,
358
+ injectedTagsParams: injectedTags,
359
+ location,
360
+ tagModule: getDefaultTags,
361
+ }) || {};
362
+ if (value === '' && isMediaTypeNone) {
363
+ errorMessage = formatMessage(messages.emptyTemplateDescErrorMessage);
364
+ } else if (value?.length > TEMPLATE_MESSAGE_MAX_LENGTH) {
365
+ errorMessage = formatMessage(messages.templateDescLengthError);
366
+ } else if (unsupportedTags?.length > 0) {
367
+ errorMessage = formatMessage(
368
+ globalMessages.unsupportedTagsValidationError,
369
+ {
370
+ unsupportedTags,
371
+ },
372
+ );
373
+ }
374
+ return errorMessage;
375
+ };
376
+
377
+ const onFallbackMessageChange = ({ target: { value } }) => {
378
+ const error = fallbackMessageErrorHandler(value);
379
+ setFallbackMessage(value);
380
+ setFallbackMessageError(error);
381
+ };
382
+
383
+ const fallbackMessageErrorHandler = (value) => {
384
+ let errorMessage = false;
385
+ const { unsupportedTags } =
386
+ validateTags({
387
+ content: value,
388
+ tagsParam: tags,
389
+ injectedTagsParams: injectedTags,
390
+ location,
391
+ tagModule: getDefaultTags,
392
+ }) || {};
393
+ if (value?.length > FALLBACK_MESSAGE_MAX_LENGTH) {
394
+ errorMessage = formatMessage(messages.fallbackMsgLenError);
395
+ } else if (unsupportedTags?.length > 0) {
396
+ errorMessage = formatMessage(
397
+ globalMessages.unsupportedTagsValidationError,
398
+ {
399
+ unsupportedTags,
400
+ },
401
+ );
402
+ }
403
+ return errorMessage;
404
+ };
405
+
406
+ const renderTextComponent = (
407
+ <>
408
+ {/* template title */}
409
+ {renderLabel('templateTitle', true)}
410
+ <CapInput
411
+ id={`rcs-template-title-input`}
412
+ onChange={onTemplateTitleChange}
413
+ placeholder={formatMessage(messages.templateTitlePlaceholder)}
414
+ value={templateTitle || ''}
415
+ size="default"
416
+ maxLength={200}
417
+ suffix={
418
+ <CapLabel type="label1">{`${templateTitle.length} / 200`}</CapLabel>
419
+ }
420
+ />
421
+ {/* template message */}
422
+ <CapRow id={`rcs-template-message-label`}>
423
+ <CapHeader
424
+ title={
425
+ <CapRow style={{ display: 'flex' }}>
426
+ <CapHeading type="h4">
427
+ {formatMessage(messages.templateDescLabel)}
428
+ </CapHeading>
429
+ {!isMediaTypeNone && (
430
+ <CapHeading type="h4" className="rcs-optional-label">
431
+ {formatMessage(messages.optional)}
432
+ </CapHeading>
433
+ )}
434
+ </CapRow>
435
+ }
436
+ suffix={
437
+ <TagList
438
+ label={formatMessage(globalMessages.addLabels)}
439
+ onTagSelect={onTagSelect}
440
+ location={location}
441
+ tags={getRcsTags()}
442
+ onContextChange={handleOnTagsContextChange}
443
+ injectedTags={injectedTags || {}}
444
+ />
445
+ }
446
+ />
447
+ </CapRow>
448
+ <TextArea
449
+ id={`rcs_template_message_textarea`}
450
+ autosize={{ minRows: 3, maxRows: 5 }}
451
+ placeholder={formatMessage(messages.templateDescPlaceholder)}
452
+ onChange={onTemplateDescChange}
453
+ errorMessage={templateDescError}
454
+ value={templateDesc || ''}
455
+ maxLength={1000}
456
+ />
457
+ </>
458
+ );
459
+
460
+ const fallbackSmsLength = () => (
461
+ <CapLabel type="label1" className="fallback-sms-length">
462
+ {formatMessage(messages.totalCharacters, {
463
+ smsCount: Math.ceil(fallbackMessage.length / 160),
464
+ number: fallbackMessage.length,
465
+ })}
466
+ </CapLabel>
467
+ );
468
+
469
+ //adding creative dlt fallback sms handlers
470
+ const addDltMsgHandler = () => {
471
+ setShowDltContainer(true);
472
+ setDltMode(RCS_DLT_MODE.TEMPLATES);
473
+ setDltEditData({});
474
+ setFallbackMessage('');
475
+ };
476
+
477
+ const closeDltContainerHandler = () => {
478
+ setShowDltContainer(false);
479
+ setDltMode('');
480
+ templatesActions.getAllTemplates('Rcs', { page: 1, perPage: 25 })
481
+ };
482
+
483
+ const rcsDltEditSelectHandler = (data) => {
484
+ setShowDltContainer(true);
485
+ setDltMode(RCS_DLT_MODE.EDIT);
486
+ setDltEditData(data);
487
+ };
488
+
489
+ const rcsDltEditCompletionHandler = (data) => {
490
+ const tempData = {
491
+ versions: {
492
+ // eslint-disable-next-line no-undef
493
+ base: data?.value?.base || {},
494
+ },
495
+ };
496
+ const fallMsg = get(tempData, `versions.base.updated-sms-editor`, []).join(
497
+ '',
498
+ );
499
+ closeDltContainerHandler();
500
+ setDltEditData(tempData);
501
+ setFallbackMessage(fallMsg);
502
+ setFallbackMessageError(fallMsg?.length > FALLBACK_MESSAGE_MAX_LENGTH);
503
+ setShowDltCard(true);
504
+ };
505
+
506
+ const rcsDltCardDeleteHandler = () => {
507
+ closeDltContainerHandler();
508
+ setDltEditData({});
509
+ setFallbackMessage('');
510
+ setFallbackMessageError(false);
511
+ setShowDltCard(false);
512
+ };
513
+
514
+ const dltFallbackListingPreviewhandler = (data) => {
515
+ const {
516
+ 'updated-sms-editor': updatedSmsEditor = [],
517
+ 'sms-editor': smsEditor = '',
518
+ } = data.versions.base || {};
519
+ setFallbackPreviewmode(true);
520
+ setDltPreviewData(
521
+ updatedSmsEditor === '' ? smsEditor : updatedSmsEditor.join(''),
522
+ );
523
+ };
524
+
525
+ const getDltContentCardList = (content, channel) => {
526
+ const extra = [
527
+ <CapIcon
528
+ type="edit"
529
+ style={{ marginRight: '8px' }}
530
+ onClick={() => rcsDltEditSelectHandler(dltEditData)}
531
+ />,
532
+ <CapDropdown
533
+ overlay={
534
+ <CapMenu>
535
+ <>
536
+ <CapMenu.Item
537
+ className="ant-dropdown-menu-item"
538
+ onClick={() => setFallbackPreviewmode(true)}
539
+ >
540
+ {formatMessage(globalMessages.preview)}
541
+ </CapMenu.Item>
542
+ <CapMenu.Item
543
+ className="ant-dropdown-menu-item"
544
+ onClick={rcsDltCardDeleteHandler}
545
+ >
546
+ {formatMessage(globalMessages.delete)}
547
+ </CapMenu.Item>
548
+ </>
549
+ </CapMenu>
550
+ }
551
+ >
552
+ <CapIcon type="more" />
553
+ </CapDropdown>,
554
+ ];
555
+ return {
556
+ title: channel,
557
+ content,
558
+ cardType: channel,
559
+ extra,
560
+ };
561
+ };
562
+
563
+ const getDltSlideBoxContent = () => {
564
+ const loc = {
565
+ pathname: `/sms/edit`,
566
+ query: { type: EMBEDDED, module: LIBRARY },
567
+ search: '',
568
+ };
569
+ const route = { name: SMS.toLowerCase() };
570
+ let dltHeader = '';
571
+ let dltContent = '';
572
+ if (dltMode === RCS_DLT_MODE.TEMPLATES) {
573
+ dltHeader = (
574
+ <CapHeader
575
+ title={formatMessage(messages.rcsDltTitle)}
576
+ description={formatMessage(messages.rcsDltDesc)}
577
+ />
578
+ );
579
+ dltContent = (
580
+ <Templates
581
+ location={loc}
582
+ route={route}
583
+ smsRegister={smsRegister}
584
+ isFullMode={isFullMode}
585
+ isDltFromRcs
586
+ onSelectTemplate={rcsDltEditSelectHandler}
587
+ handlePeviewTemplate={dltFallbackListingPreviewhandler}
588
+ />
589
+ );
590
+ } else if (dltMode === RCS_DLT_MODE.EDIT) {
591
+ dltHeader = formatMessage(messages.dltEditHeader);
592
+ dltContent = (
593
+ <SmsTraiEdit
594
+ location={loc}
595
+ route={route}
596
+ getDefaultTags="outbound"
597
+ handleClose={closeDltContainerHandler}
598
+ templateData={dltEditData}
599
+ getFormSubscriptionData={rcsDltEditCompletionHandler}
600
+ isFullMode={false}
601
+ />
602
+ );
603
+ }
604
+ return { dltHeader, dltContent };
605
+ };
606
+
607
+ const renderFallBackSmsComponent = () => {
608
+ const contentArr = [];
609
+ const showAddCreativeBtnForDlt = isDltEnabled && !showDltCard;
610
+ const showCardForDlt = isDltEnabled && showDltCard;
611
+ const showNonDltFallbackComp = !showAddCreativeBtnForDlt && !showCardForDlt;
612
+ //pushing common fallback sms headings
613
+ contentArr.push(
614
+ <CapRow
615
+ style={{
616
+ marginBottom: isDltEnabled ? '20px' : '10px',
617
+ }}
618
+ >
619
+ <CapHeader
620
+ title={
621
+ <CapRow style={{ display: 'flex' }}>
622
+ <CapHeading type="h4">
623
+ {formatMessage(messages.fallbackLabel)}
624
+ </CapHeading>
625
+ <CapHeading type="h4" className="rcs-optional-label">
626
+ {formatMessage(messages.optional)}
627
+ </CapHeading>
628
+ <CapTooltipWithInfo
629
+ placement="right"
630
+ infoIconProps={{
631
+ style: { marginLeft: '4px', marginTop: '3px' },
632
+ }}
633
+ title={formatMessage(messages.fallbackToolTip)}
634
+ />
635
+ </CapRow>
636
+ }
637
+ description={formatMessage(messages.fallbackDesc)}
638
+ suffix={
639
+ isDltEnabled ? null : (
640
+ <CapButton
641
+ type="flat"
642
+ className="fallback-preview-btn"
643
+ prefix={<CapIcon type="eye" />}
644
+ style={{ color: CAP_SECONDARY.base }}
645
+ onClick={() => setFallbackPreviewmode(true)}
646
+ disabled={fallbackMessage === '' || fallbackMessageError}
647
+ >
648
+ {formatMessage(globalMessages.preview)}
649
+ </CapButton>
650
+ )
651
+ }
652
+ />
653
+ </CapRow>,
654
+ );
655
+
656
+ //dlt is enabled, and dlt content is not yet added, show button to add dlt creative
657
+ showAddCreativeBtnForDlt &&
658
+ contentArr.push(
659
+ <CapCard className="rcs-dlt-fallback-card">
660
+ <CapRow type="flex" justify="center" align="middle">
661
+ <CapColumn span={10}>
662
+ <CapImage src={addCreativesIcon} />
663
+ </CapColumn>
664
+ <CapColumn span={14}>
665
+ <CapButton
666
+ className="add-dlt-btn"
667
+ type="secondary"
668
+ onClick={addDltMsgHandler}
669
+ >
670
+ {formatMessage(messages.addSmsCreative)}
671
+ </CapButton>
672
+ </CapColumn>
673
+ </CapRow>
674
+ </CapCard>,
675
+ );
676
+
677
+ //dlt is enabled and dlt content is added, show it in a card
678
+ showCardForDlt &&
679
+ contentArr.push(
680
+ <CapCustomCardList
681
+ cardList={[getDltContentCardList(fallbackMessage, SMS)]}
682
+ className="rcs-dlt-card"
683
+ />,
684
+ fallbackMessageError && (
685
+ <CapError className="rcs-fallback-len-error">
686
+ {formatMessage(messages.fallbackMsgLenError)}
687
+ </CapError>
688
+ ),
689
+ );
690
+
691
+ //dlt is not enabled, show non dlt text area
692
+ showNonDltFallbackComp &&
693
+ contentArr.push(
694
+ <>
695
+ <CapRow>
696
+ <CapHeader
697
+ title={
698
+ <CapHeading type="h4">
699
+ {formatMessage(messages.fallbackTextAreaLabel)}
700
+ </CapHeading>
701
+ }
702
+ suffix={
703
+ <TagList
704
+ label={formatMessage(globalMessages.addLabels)}
705
+ onTagSelect={onTagSelectFallback}
706
+ location={location}
707
+ tags={tags || []}
708
+ onContextChange={handleOnTagsContextChange}
709
+ injectedTags={injectedTags || {}}
710
+ />
711
+ }
712
+ />
713
+ </CapRow>
714
+ <TextArea
715
+ id={`rcs_fallback_message_textarea`}
716
+ autosize={{ minRows: 3, maxRows: 5 }}
717
+ placeholder={formatMessage(messages.fallbackMsgPlaceholder)}
718
+ onChange={onFallbackMessageChange}
719
+ errorMessage={fallbackMessageError}
720
+ value={fallbackMessage || ''}
721
+ />
722
+ <CapRow>{fallbackSmsLength()}</CapRow>
723
+ </>,
724
+ );
725
+
726
+ return <>{contentArr}</>;
727
+ };
728
+
729
+ const uploadRcsImage = useCallback((file, type, fileParams) => {
730
+ actions.uploadRcsAsset(file, type, fileParams, 0);
731
+ }, []);
732
+
733
+ const setUpdateRcsImageSrc = useCallback(
734
+ (val) => {
735
+ updateRcsImageSrc(val);
736
+ actions.clearRcsAsset(0);
737
+ },
738
+ [rcsImageSrc],
739
+ );
740
+
741
+ const updateOnRcsImageReUpload = useCallback(() => {
742
+ updateRcsImageSrc('');
743
+ }, [rcsImageSrc]);
744
+
745
+ const getMediaBasedComponent = () => {
746
+ switch (templateMediaType) {
747
+ case RCS_MEDIA_TYPES.NONE: {
748
+ return renderTextComponent;
749
+ }
750
+ case RCS_MEDIA_TYPES.IMAGE: {
751
+ return (
752
+ <>
753
+ <CapImageUpload
754
+ style={{ paddingTop: '20px' }}
755
+ allowedExtensionsRegex={ALLOWED_IMAGE_EXTENSIONS_REGEX}
756
+ imgWidth={RCS_IMG_WIDTH}
757
+ imgHeight={RCS_IMG_HEIGHT}
758
+ imgSize={RCS_IMG_SIZE}
759
+ uploadAsset={uploadRcsImage}
760
+ isFullMode={isFullMode}
761
+ imageSrc={rcsImageSrc}
762
+ updateImageSrc={setUpdateRcsImageSrc}
763
+ updateOnReUpload={updateOnRcsImageReUpload}
764
+ index={0}
765
+ className={'cap-custom-image-upload'}
766
+ key={`rcs-uploaded-image`}
767
+ imageData={rcsData}
768
+ channel={RCS}
769
+ />
770
+ {renderTextComponent}
771
+ </>
772
+ );
773
+ }
774
+ default:
775
+ return null;
776
+ }
777
+ };
778
+
779
+ const getRcsPreview = () => (
780
+ <TemplatePreview
781
+ channel={RCS}
782
+ content={{
783
+ rcsPreviewContent: {
784
+ rcsTitle: templateTitle,
785
+ rcsDesc: templateDesc,
786
+ ...(!isMediaTypeNone && {
787
+ rcsImageSrc,
788
+ }),
789
+ },
790
+ }}
791
+ />
792
+ );
793
+
794
+ const createPayload = () => {
795
+ const base = get(dltEditData, `versions.base`, {});
796
+ const {
797
+ template_id: templateId = '',
798
+ // eslint-disable-next-line camelcase
799
+ template_name = '',
800
+ 'sms-editor': template = '',
801
+ header: registeredSenderIds = [],
802
+ 'var-mapped': templateVariableMapping = {},
803
+ } = base;
804
+ const tempMediaSrc = !isMediaTypeNone ? rcsImageSrc : '';
805
+
806
+ return {
807
+ name: templateName,
808
+ versions: {
809
+ base: {
810
+ content: {
811
+ RCS: {
812
+ cardContent: [
813
+ {
814
+ title: templateTitle,
815
+ description: templateDesc,
816
+ mediaType: templateMediaType,
817
+ media: {
818
+ mediaUrl: tempMediaSrc,
819
+ height: MEDIUM,
820
+ },
821
+ },
822
+ ],
823
+ cardSettings: {
824
+ cardOrientation: VERTICAL,
825
+ mediaAlignment: RIGHT,
826
+ },
827
+ cardType: STANDALONE,
828
+ contentType: RICHCARD,
829
+ smsFallBackContent: {
830
+ message: fallbackMessage,
831
+ ...(isDltEnabled && {
832
+ templateConfigs: {
833
+ templateId,
834
+ templateName: template_name,
835
+ template,
836
+ registeredSenderIds,
837
+ templateVariableMapping,
838
+ },
839
+ }),
840
+ },
841
+ },
842
+ },
843
+ },
844
+ },
845
+ type: RCS,
846
+ };
847
+ };
848
+
849
+ const actionCallback = ({ errorMessage, resp }, isEdit) => {
850
+ // eslint-disable-next-line no-undef
851
+ const error = errorMessage?.message || errorMessage;
852
+ if (!error) {
853
+ CapNotification.success({
854
+ message: isEdit
855
+ ? formatMessage(messages.rcsEditNotification)
856
+ : formatMessage(messages.rcsCreateNotification),
857
+ });
858
+ if (isEdit) {
859
+ actions.clearEditResponse();
860
+ } else {
861
+ actions.clearCreateResponse();
862
+ }
863
+ } else {
864
+ CapNotification.error({
865
+ message: error,
866
+ });
867
+ }
868
+ };
869
+
870
+ const onCreateRcs = () => {
871
+ setSpin(true);
872
+ actions.createTemplate(createPayload(), (resp, errorMessage) => {
873
+ actionCallback({ resp, errorMessage });
874
+ if (!errorMessage) {
875
+ onCreateComplete();
876
+ } else {
877
+ setSpin(false);
878
+ }
879
+ });
880
+ };
881
+
882
+ const onEditRcs = () => {
883
+ setSpin(true);
884
+ actions.editTemplate(
885
+ {
886
+ ...createPayload(),
887
+ _id: params.id,
888
+ },
889
+ (resp, errorMessage) => {
890
+ actionCallback({ resp, errorMessage }, true);
891
+ if (!errorMessage) {
892
+ onCreateComplete();
893
+ } else {
894
+ setSpin(false);
895
+ }
896
+ },
897
+ );
898
+ };
899
+
900
+ const onDoneCallback = () => {
901
+ if (isFullMode) {
902
+ if (isEditFlow) {
903
+ return onEditRcs;
904
+ }
905
+ return onCreateRcs;
906
+ }
907
+ return () => getFormData({});
908
+ };
909
+
910
+ const isDisableDone = () => {
911
+ //if template name is not entered
912
+ if (templateName.trim() === '' || templateNameError) {
913
+ return true;
914
+ }
915
+ //if template message is not entered
916
+ if (isMediaTypeNone && templateDesc.trim() === '') {
917
+ return true;
918
+ }
919
+ //if image is not uploaded
920
+ if (!isMediaTypeNone && rcsImageSrc === '') {
921
+ return true;
922
+ }
923
+ if (templateDescError || fallbackMessageError) {
924
+ return true;
925
+ }
926
+ return false;
927
+ };
928
+
929
+ const getMainContent = () => {
930
+ if (showDltContainer && !fallbackPreviewmode) {
931
+ const dltSlideBoxContent = showDltContainer && getDltSlideBoxContent();
932
+ const { dltHeader = '', dltContent = '' } = dltSlideBoxContent;
933
+ return (
934
+ <CapSlideBox
935
+ show={showDltContainer}
936
+ header={dltHeader}
937
+ content={dltContent}
938
+ handleClose={closeDltContainerHandler}
939
+ size="size-xl"
940
+ />
941
+ );
942
+ }
943
+ const tempMsg = dltPreviewData === '' ? fallbackMessage : dltPreviewData;
944
+ const mediaTypeMsg = isMediaTypeNone ? 'textMessage' : 'image';
945
+ return (
946
+ <>
947
+ <CapRow className="cap-rcs-creatives">
948
+ <CapColumn span={14}>
949
+ {/* template name */}
950
+ {isFullMode && (
951
+ <CapInput
952
+ id={`rcs_template_name_input`}
953
+ onChange={onTemplateNameChange}
954
+ errorMessage={templateNameError}
955
+ placeholder={formatMessage(
956
+ globalMessages.templateNamePlaceholder,
957
+ )}
958
+ value={templateName || ''}
959
+ size="default"
960
+ label={formatMessage(globalMessages.creativeNameLabel)}
961
+ />
962
+ )}
963
+ {/* template mdeia type */}
964
+ {renderLabel('mediaLabel')}
965
+ <CapRadioGroup
966
+ options={mediaRadioOptions || []}
967
+ value={templateMediaType}
968
+ onChange={onTemplateMediaTypeChange}
969
+ className={'rcs-radio'}
970
+ />
971
+ {getMediaBasedComponent()}
972
+ <CapDivider style={{ margin: `${CAP_SPACE_28} 0` }} />
973
+ {renderFallBackSmsComponent()}
974
+ <div className="rcs-scroll-div" />
975
+ </CapColumn>
976
+ <CapColumn span={10} className="rcs-preview-container">
977
+ {getRcsPreview()}
978
+ </CapColumn>
979
+ </CapRow>
980
+ <RcsFooter>
981
+ {/* show tooltip only if button is disabled */}
982
+ <CapTooltip
983
+ title={
984
+ isDisableDone()
985
+ ? formatMessage(messages.rcsDoneBtnToolTip, {
986
+ type: formatMessage(messages[mediaTypeMsg]),
987
+ })
988
+ : ''
989
+ }
990
+ placement={'right'}
991
+ >
992
+ <div className="button-disabled-tooltip-wrapper">
993
+ <CapButton
994
+ onClick={onDoneCallback()}
995
+ disabled={isDisableDone()}
996
+ className="rcs-done-btn"
997
+ >
998
+ <FormattedMessage {...globalMessages.done} />
999
+ </CapButton>
1000
+ </div>
1001
+ </CapTooltip>
1002
+ </RcsFooter>
1003
+
1004
+ {fallbackPreviewmode && (
1005
+ <CapSlideBox
1006
+ className="rcs-fallback-preview"
1007
+ show={fallbackPreviewmode}
1008
+ header={
1009
+ <CapHeading type="h7" style={{ color: CAP_G01 }}>
1010
+ {formatMessage(messages.fallbackPreviewtitle)}
1011
+ </CapHeading>
1012
+ }
1013
+ content={
1014
+ <>
1015
+ <TemplatePreview
1016
+ channel={RCS}
1017
+ content={{
1018
+ rcsPreviewContent: {
1019
+ rcsDesc: tempMsg,
1020
+ },
1021
+ }}
1022
+ />
1023
+ <CapHeading
1024
+ type="h3"
1025
+ style={{ textAlign: 'center' }}
1026
+ className="margin-t-16"
1027
+ >
1028
+ {formatMessage(messages.totalCharacters, {
1029
+ smsCount: Math.ceil(tempMsg.length / 160),
1030
+ number: tempMsg.length,
1031
+ })}
1032
+ </CapHeading>
1033
+ </>
1034
+ }
1035
+ handleClose={() => {
1036
+ setFallbackPreviewmode(false);
1037
+ setDltPreviewData('');
1038
+ }}
1039
+ />
1040
+ )}
1041
+ </>
1042
+ );
1043
+ };
1044
+ return <CapSpin spinning={loadingTags || spin}>{getMainContent()}</CapSpin>;
1045
+ };
1046
+
1047
+ const mapStateToProps = createStructuredSelector({
1048
+ rcsData: makeSelectRcs(),
1049
+ metaEntities: makeSelectMetaEntities(),
1050
+ loadingTags: isLoadingMetaEntities(),
1051
+ injectedTags: setInjectedTags(),
1052
+ });
1053
+
1054
+ const mapDispatchToProps = (dispatch) => ({
1055
+ actions: bindActionCreators(RcsActions, dispatch),
1056
+ templatesActions: bindActionCreators(TemplatesActions, dispatch),
1057
+ });
1058
+
1059
+ export default withCreatives({
1060
+ WrappedComponent: injectIntl(Rcs),
1061
+ mapStateToProps,
1062
+ mapDispatchToProps,
1063
+ userAuth: true,
1064
+ });