@capillarytech/creatives-library 7.11.7 → 7.11.9

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