@capillarytech/creatives-library 6.11.5 → 6.11.7

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 (80) hide show
  1. package/app.js +3 -3
  2. package/assets/rich-video-placeholder.svg +20 -0
  3. package/components/TemplatePreview/_templatePreview.scss +14 -0
  4. package/components/TemplatePreview/index.js +83 -3
  5. package/components/TemplatePreview/messages.js +8 -0
  6. package/config/app.js +2 -2
  7. package/containers/Cap/sagas.js +2 -3
  8. package/index.js +0 -5
  9. package/package.json +4 -4
  10. package/services/getSchema.js +0 -3
  11. package/translations/en.json +14 -15
  12. package/translations/zh.json +14 -15
  13. package/v2Components/BeeEditor/index.js +263 -0
  14. package/v2Components/BeeEditor/index.scss +11 -0
  15. package/v2Components/BeeEditor/messages.js +71 -0
  16. package/v2Components/BeeEditor/tests/index.test.js +10 -0
  17. package/v2Components/TemplatePreview/WechatRichmediaTemplatePreview/_wechatRichmediaTemplatePrev.scss +151 -151
  18. package/v2Components/TemplatePreview/WechatRichmediaTemplatePreview/messages.js +33 -33
  19. package/v2Components/TemplatePreview/WechatRichmediaTemplatePreview/tests/index.test.js +10 -10
  20. package/v2Components/TemplatePreview/_templatePreview.scss +14 -0
  21. package/v2Components/TemplatePreview/assets/images/androidPushMessage.svg +44 -44
  22. package/v2Components/TemplatePreview/assets/images/home-screen-android.svg +21 -21
  23. package/v2Components/TemplatePreview/assets/images/home-screen-ios.svg +16 -16
  24. package/v2Components/TemplatePreview/assets/images/iPhonePushMessage.svg +134 -134
  25. package/v2Components/TemplatePreview/assets/images/mobile.svg +23 -23
  26. package/v2Components/TemplatePreview/assets/images/sms_mobile_android.svg +22 -22
  27. package/v2Components/TemplatePreview/assets/images/user-icon.svg +18 -18
  28. package/v2Components/TemplatePreview/assets/images/wechat-home-screen-android.svg +21 -21
  29. package/v2Components/TemplatePreview/assets/images/wechat-mobile.svg +77 -77
  30. package/v2Components/TemplatePreview/assets/images/wechat_mobile_android.svg +20 -20
  31. package/v2Components/TemplatePreview/index.js +81 -2
  32. package/v2Components/TemplatePreview/messages.js +8 -0
  33. package/v2Components/TemplatePreview/tests/index.test.js +10 -10
  34. package/v2Containers/BeeEditor/index.js +1 -1
  35. package/v2Containers/Cap/actions.js +1 -1
  36. package/v2Containers/Cap/constants.js +3 -3
  37. package/v2Containers/Cap/reducer.js +3 -3
  38. package/v2Containers/Cap/sagas.js +8 -8
  39. package/v2Containers/CreativesContainer/SlideBoxContent.js +11 -0
  40. package/v2Containers/CreativesContainer/actions.js +27 -27
  41. package/v2Containers/CreativesContainer/constants.js +17 -17
  42. package/v2Containers/CreativesContainer/index.scss +44 -44
  43. package/v2Containers/CreativesContainer/messages.js +305 -305
  44. package/v2Containers/CreativesContainer/reducer.js +29 -29
  45. package/v2Containers/CreativesContainer/sagas.js +11 -11
  46. package/v2Containers/CreativesContainer/selectors.js +30 -30
  47. package/v2Containers/CreativesContainer/tests/actions.test.js +18 -18
  48. package/v2Containers/CreativesContainer/tests/index.test.js +10 -10
  49. package/v2Containers/CreativesContainer/tests/reducer.test.js +9 -9
  50. package/v2Containers/CreativesContainer/tests/sagas.test.js +15 -15
  51. package/v2Containers/CreativesContainer/tests/selectors.test.js +10 -10
  52. package/v2Containers/LanguageProvider/index.js +1 -1
  53. package/v2Containers/Line/Container/ImageMap/index.js +2 -1
  54. package/v2Containers/Line/Container/Video/constants.js +10 -0
  55. package/v2Containers/Line/Container/Video/index.js +767 -0
  56. package/v2Containers/Line/Container/Video/messages.js +142 -0
  57. package/v2Containers/Line/Container/Video/style.js +61 -0
  58. package/v2Containers/Line/Container/Wrapper/index.js +2 -0
  59. package/v2Containers/Line/Container/Wrapper/messages.js +4 -0
  60. package/v2Containers/Line/Container/Wrapper/utils.js +8 -3
  61. package/v2Containers/Line/Container/constants.js +2 -0
  62. package/v2Containers/Line/Container/index.js +109 -2
  63. package/v2Containers/Line/Container/messages.js +4 -0
  64. package/v2Containers/Templates/index.js +15 -1
  65. package/v2Containers/Templates/messages.js +4 -0
  66. package/v2Containers/Templates/tests/actions.test.js +18 -18
  67. package/v2Containers/Templates/tests/index.test.js +10 -10
  68. package/v2Containers/Templates/tests/reducer.test.js +9 -9
  69. package/v2Containers/Templates/tests/sagas.test.js +15 -15
  70. package/v2Containers/Templates/tests/selectors.test.js +10 -10
  71. package/v2Containers/TemplatesV2/TemplatesV2.style.js +29 -29
  72. package/v2Containers/TemplatesV2/actions.js +16 -16
  73. package/v2Containers/TemplatesV2/constants.js +10 -10
  74. package/v2Containers/TemplatesV2/messages.js +61 -61
  75. package/v2Containers/TemplatesV2/selectors.js +25 -25
  76. package/v2Containers/TemplatesV2/tests/actions.test.js +18 -18
  77. package/v2Containers/TemplatesV2/tests/index.test.js +10 -10
  78. package/v2Containers/TemplatesV2/tests/reducer.test.js +9 -9
  79. package/v2Containers/TemplatesV2/tests/sagas.test.js +15 -15
  80. package/v2Containers/TemplatesV2/tests/selectors.test.js +10 -10
@@ -0,0 +1,767 @@
1
+ import React, { Fragment, useState, useEffect, useRef, useCallback } from 'react';
2
+ import { injectIntl, FormattedMessage } from 'react-intl';
3
+ import get from 'lodash/get';
4
+ import moment from 'moment';
5
+ import CapInput from '@capillarytech/cap-ui-library/CapInput';
6
+ import CapUploader from '@capillarytech/cap-ui-library/CapUploader';
7
+ import CapHeading from '@capillarytech/cap-ui-library/CapHeading';
8
+ import CapButton from '@capillarytech/cap-ui-library/CapButton';
9
+ import CapDrawer from '@capillarytech/cap-ui-library/CapDrawer';
10
+ import CapHeader from '@capillarytech/cap-ui-library/CapHeader';
11
+ import CapError from '@capillarytech/cap-ui-library/CapError';
12
+ import CapRadioGroup from '@capillarytech/cap-ui-library/CapRadioGroup';
13
+ import { isUrl } from '../Wrapper/utils';
14
+ import LineDrawer from '../Drawer';
15
+ import { CAP_SPACE_12, CAP_SPACE_08, FONT_COLOR_05, CAP_SPACE_24, CAP_SPACE_04 } from '@capillarytech/cap-ui-library/styled/variables';
16
+ import style from './style';
17
+ import { CAP_G06, CAP_G09 } from '@capillarytech/cap-ui-library/styled/variables';
18
+ import withStyles from '../../../../hoc/withStyles';
19
+
20
+ import messages from './messages';
21
+ import {
22
+ ALLOWED_EXTENSIONS_REGEX,
23
+ LINE_VIDEO_SIZE,
24
+ MAX_ALLOWED_TITLE_LENGTH,
25
+ HIDE_ACTION_BUTTON,
26
+ DISPLAY_ACTION_BUTTON,
27
+ MAX_ACTION_LABEL_LENGTH,
28
+ } from './constants';
29
+
30
+ export const LineVideo = ({
31
+ className,
32
+ id,
33
+ intl: { formatMessage },
34
+ isFullMode,
35
+ inheritedTitleStyle,
36
+ supportedExtensions,
37
+ actions = {},
38
+ Line,
39
+ index,
40
+ updateMessageState,
41
+ content,
42
+ activeKey,
43
+ Templates,
44
+ getAllTemplates,
45
+ uploadedAssetList,
46
+ updateUploadedAssetList,
47
+ deleteUploadedImgList,
48
+ }) => {
49
+
50
+ if (activeKey !== 'video') {
51
+ return null;
52
+ }
53
+
54
+ const videoEl = useRef(null);
55
+
56
+ const [errorMessageTitle, updateErrorMessageTitle] = useState(false);
57
+ const [isCreateNew, updateCreateNew] = useState(isFullMode);
58
+ const [messageTitle, updateTextMessageTitle] = useState('');
59
+ const [isTemplateDrawerRequired, updateTemplateDrawerRequirement] = useState(false);
60
+ const [selectedTemplate, updateSelectedTemplate] = useState();
61
+
62
+ const [videoSrc, updateVideoSrc] = useState('');
63
+ const [videoName, updateVideoName] = useState('');
64
+ const [isVideo, updateVideoStatus] = useState(false);
65
+ const [isVideoError, updateVideoErrorMessage] = useState(false);
66
+ const [imagePreview, updateImagePreview] = useState();
67
+ const [altText, updateTitle] = useState('');
68
+ const [errorTitle, updateErrorTitle] = useState(false);
69
+ const [selectedAction, updateSelectedAction] = useState(HIDE_ACTION_BUTTON);
70
+ const [actionLabel, updateActionLabel] = useState('');
71
+ const [actionLabelErrorMessage, updateActionLabelErrorMessage] = useState(false);
72
+ const [actionUrl, updateActionUrl] = useState('');
73
+ const [actionUrlErrorMessage, updateActionUrlErrorMessage] = useState(false);
74
+ const [videoDuration, updateVideoDuration] = useState('');
75
+ const [videoHeight, updateVideoHeight] = useState();
76
+ const [videoWidth, updateVideoWidth] = useState();
77
+
78
+
79
+ useEffect(() => {
80
+ const {
81
+ messageTitle = '',
82
+ type,
83
+ actionLabel,
84
+ actionUrl,
85
+ previewImageUrl: rootPreviewImageUrl,
86
+ video: {
87
+ originalContentUrl = '',
88
+ previewImageUrl = '',
89
+ externalLink: {
90
+ label = '',
91
+ linkUri = '',
92
+ } = {},
93
+ area: {
94
+ height,
95
+ width,
96
+ } = {},
97
+ } = {},
98
+ videoName = '',
99
+ videoDuration = '',
100
+ altText,
101
+ videoSrc,
102
+ videoHeight,
103
+ videoWidth,
104
+ selectedAction,
105
+ } = content;
106
+ const videoUrl = originalContentUrl || videoSrc;
107
+ const videoActionLabel = label || actionLabel;
108
+ if (videoUrl && type === 'video') {
109
+ updateVideoStatus(true);
110
+ updateCreateNew(true);
111
+ updateVideoSrc(videoUrl);
112
+ updateTextMessageTitle(messageTitle);
113
+ updateImagePreview(previewImageUrl || rootPreviewImageUrl);
114
+ updateVideoName(videoName);
115
+ updateVideoWidth(width || videoWidth);
116
+ updateVideoHeight(height || videoHeight);
117
+ updateVideoDuration(videoDuration);
118
+ updateActionUrl(linkUri || actionUrl);
119
+ updateActionLabel(videoActionLabel);
120
+ updateSelectedAction(selectedAction || (!!videoActionLabel ? DISPLAY_ACTION_BUTTON : HIDE_ACTION_BUTTON));
121
+ updateTitle(altText);
122
+ }
123
+ }, [content]);
124
+
125
+ useEffect(() => {
126
+ if (videoSrc && (isFullMode ? messageTitle : true) && imagePreview) {
127
+ updateMessageState({
128
+ isError: !videoSrc || !imagePreview || !altText || !checkAction() || !(isFullMode ? messageTitle : true),
129
+ videoSrc,
130
+ previewImageUrl: imagePreview,
131
+ videoName,
132
+ messageTitle,
133
+ altText,
134
+ index,
135
+ type: 'video',
136
+ actionLabel,
137
+ actionUrl,
138
+ videoHeight,
139
+ videoWidth,
140
+ videoDuration,
141
+ selectedAction,
142
+ messageType: 'videoSrc',
143
+ });
144
+ }
145
+ }, [errorMessageTitle, videoSrc, messageTitle, isVideoError]);
146
+
147
+ useEffect(() => {
148
+ if (Line[`uploadedAssetDataVideo_${index}`] && Object.keys(Line[`uploadedAssetDataVideo_${index}`]).length) {
149
+ const videoSrc = get(Line, `uploadedAssetDataVideo_${index}.metaInfo.secure_file_path`, '');
150
+ const imgPreview = get(Line, `uploadedAssetDataVideo_${index}.metaInfo.video_file_path_preview`, '');
151
+ const videoName = get(Line, `uploadedAssetDataVideo_${index}.metaInfo.name`, '');
152
+ actions.clearAsset(`Video_${index}`);
153
+ if (videoSrc) {
154
+ updateUploadedAssetList({
155
+ ...uploadedAssetList,
156
+ [index]: {
157
+ imgPreview,
158
+ videoSrc,
159
+ videoName,
160
+ },
161
+ });
162
+ }
163
+ }
164
+ }, [Line[`uploadedAssetDataVideo_${index}`]]);
165
+
166
+ useEffect(() => {
167
+ const videoSrc = get(uploadedAssetList[index], 'videoSrc', '');
168
+ const imgPreview = get(uploadedAssetList[index], 'imgPreview', '');
169
+ const videoName = get(uploadedAssetList[index], 'videoName', '');
170
+ const { type } = content;
171
+
172
+ if (videoSrc && type === 'video') {
173
+ updateVideoSrc(videoSrc);
174
+ updateVideoName(videoName);
175
+ updateVideoStatus(true);
176
+ updateImagePreview(imgPreview);
177
+
178
+ updateMessageState({
179
+ isError: !videoSrc || !imagePreview || !altText || !checkAction() || !(isFullMode ? messageTitle : true),
180
+ videoSrc,
181
+ previewImageUrl: imagePreview,
182
+ videoName,
183
+ messageTitle,
184
+ altText,
185
+ index,
186
+ type: 'video',
187
+ actionLabel,
188
+ actionUrl,
189
+ videoHeight,
190
+ videoWidth,
191
+ videoDuration,
192
+ selectedAction,
193
+ messageType: 'videoSrc',
194
+ });
195
+ }
196
+ }, [uploadedAssetList]);
197
+
198
+ const updateMetadataLoaded = () => {
199
+ const { current: { duration, videoHeight, videoWidth } = {} } = videoEl;
200
+ if (duration) {
201
+ updateVideoDuration(moment('1900-01-01 00:00:00').add(duration, 'seconds').format("HH.mm.ss"));
202
+ updateVideoHeight(videoHeight);
203
+ updateVideoWidth(videoWidth);
204
+ updateMessageState({
205
+ isError: !videoSrc || !imagePreview || !altText || !checkAction() || !(isFullMode ? messageTitle : true),
206
+ videoSrc,
207
+ previewImageUrl: imagePreview,
208
+ videoName,
209
+ messageTitle,
210
+ altText,
211
+ index,
212
+ type: 'video',
213
+ actionLabel,
214
+ actionUrl,
215
+ videoHeight,
216
+ videoWidth,
217
+ videoDuration,
218
+ selectedAction,
219
+ messageType: 'videoSrc',
220
+ });
221
+ }
222
+ }
223
+
224
+ const checkAction = useCallback((label = actionLabel, url = actionUrl, type = selectedAction) => {
225
+ return type === DISPLAY_ACTION_BUTTON ? (url && label && !updateActionLabelError(label) && !updateActionUrlError(url)) : true;
226
+ }, [actionLabel, actionUrl, selectedAction]);
227
+
228
+ const submitVideoAction = useCallback((data, incorrectFile) => {
229
+ const {
230
+ file: {
231
+ size,
232
+ },
233
+ file,
234
+ fileParams,
235
+ type,
236
+ } = data;
237
+ if (incorrectFile || size > LINE_VIDEO_SIZE) {
238
+ updateVideoErrorMessage(formatMessage(messages.lineVideoIncorrectSize));
239
+ } else {
240
+ updateVideoErrorMessage('');
241
+ actions.uploadAsset(
242
+ file,
243
+ type,
244
+ fileParams,
245
+ `Video_${index}`,
246
+ );
247
+ }
248
+ }, []);
249
+
250
+ const uploadVideo = useCallback((e, { files }) => {
251
+ if (e) {
252
+ e.preventDefault();
253
+ }
254
+ const _URL = window.URL || window.webkitURL;
255
+ let incorrectFile = false;
256
+ const file = files[0];
257
+ if (!ALLOWED_EXTENSIONS_REGEX.test(file.name)) {
258
+ incorrectFile = true;
259
+ }
260
+ const video = new FileReader();
261
+ video.src = _URL.createObjectURL(file);
262
+ const fileParams = {
263
+ width: video.width,
264
+ height: video.height,
265
+ error: false,
266
+ isGenerateVideoThumbnail: true,
267
+ };
268
+ submitVideoAction({ file, type: 'video', fileParams }, incorrectFile);
269
+ if (e) {
270
+ const event = e;
271
+ event.target.value = null;
272
+ }
273
+ }, []);
274
+
275
+ const capUploaderCustomVideoRequest = useCallback((uploadData) => {
276
+ uploadVideo(undefined, { files: [uploadData.file] });
277
+ }, []);
278
+
279
+ const onTextTitleChange = ({ target: { value } }) => {
280
+ updateTextMessageTitle(value);
281
+ let errorMessage = false;
282
+ if (value === '') {
283
+ errorMessage = formatMessage(messages.emptyTitleErrorMessage);
284
+ }
285
+ updateErrorMessageTitle(errorMessage);
286
+ updateMessageState({
287
+ isError: !videoSrc || !imagePreview || !altText || !checkAction() || !(isFullMode ? value : true),
288
+ videoSrc,
289
+ previewImageUrl: imagePreview,
290
+ videoName,
291
+ messageTitle: value,
292
+ altText,
293
+ index,
294
+ type: 'video',
295
+ actionLabel,
296
+ actionUrl,
297
+ videoHeight,
298
+ videoWidth,
299
+ videoDuration,
300
+ selectedAction,
301
+ messageType: 'videoSrc',
302
+ });
303
+ }
304
+
305
+ const onReUpload = () => {
306
+ updateVideoStatus(false);
307
+ if (!isFullMode) {
308
+ updateCreateNew(false);
309
+ }
310
+ deleteUploadedImgList(index);
311
+ updateVideoSrc('');
312
+ updateImagePreview('');
313
+ updateMessageState({
314
+ isError: true,
315
+ videoSrc: '',
316
+ previewImageUrl: '',
317
+ videoName: '',
318
+ messageTitle,
319
+ altText,
320
+ index,
321
+ type: 'video',
322
+ actionLabel,
323
+ actionUrl,
324
+ videoHeight,
325
+ videoWidth,
326
+ videoDuration,
327
+ selectedAction,
328
+ messageType: 'videoSrc',
329
+ });
330
+ }
331
+
332
+ const onSelectTemplate = useCallback((event) => {
333
+ event.stopPropagation();
334
+ updateTemplateDrawerRequirement(true);
335
+ }, [])
336
+
337
+ const getVideoSection = () => {
338
+ if (!isVideo) {
339
+ return (
340
+ (
341
+ <>
342
+ <CapHeading type="h4" style={{ marginBotton: 20, color: 'unset' }}>
343
+ <FormattedMessage {...messages.uploadVideoLabel} />
344
+ </CapHeading>
345
+ <CapUploader.CapDragger
346
+ customRequest={(data) => capUploaderCustomVideoRequest(data)}
347
+ className="form-builder-dragger"
348
+ >
349
+ <CapHeading className="dragger-title" type="h7">
350
+ <FormattedMessage {...messages.dragAndDrop} />
351
+ </CapHeading>
352
+ <CapHeading className="dragger-or" type="label6">
353
+ <FormattedMessage {...messages.or} />
354
+ </CapHeading>
355
+ <CapButton className="dragger-button" type="secondary" style={{ marginRight: CAP_SPACE_08 }}>
356
+ <FormattedMessage {...messages.uploadComputer} />
357
+ </CapButton>
358
+ </CapUploader.CapDragger>
359
+ <CapError type="error" style={{ marginTop: CAP_SPACE_04 }}>
360
+ {isVideoError}
361
+ </CapError>
362
+ <CapHeading type="h6" style={{ marginTop: CAP_SPACE_12 }} className="video-description">
363
+ <FormattedMessage {...messages.videoFormatDescription} />
364
+ <FormattedMessage {...messages.videoSizeDescription} />
365
+ </CapHeading>
366
+ </>
367
+ )
368
+ );
369
+ }
370
+ return (
371
+ <Fragment key={videoSrc}>
372
+ <div style={{ overflow: 'hidden' }}>
373
+ <CapButton
374
+ className="dragger-button"
375
+ type="flat"
376
+ style={{
377
+ float: 'right',
378
+ color: FONT_COLOR_05,
379
+ padding: 0,
380
+ }}
381
+ onClick={onReUpload}
382
+ >
383
+ <FormattedMessage {...messages.imageReUpload} />
384
+ </CapButton>
385
+ </div>
386
+ <div style={{ display: 'flex' }}>
387
+ <video
388
+ width="230"
389
+ poster={imagePreview}
390
+ className="line-image-src"
391
+ onLoadedMetadata={() => updateMetadataLoaded(true)}
392
+ onMouseOver={e => e.target.play()}
393
+ onMouseOut={e => e.target.pause()}
394
+ ref={videoEl}
395
+ >
396
+ <source src={videoSrc} type="video/mp4" />
397
+ </video>
398
+ <div style={{ marginLeft: CAP_SPACE_24 }}>
399
+ <CapHeading type="h6">
400
+ {videoName}
401
+ </CapHeading>
402
+ <CapHeading type="h6">
403
+ {videoDuration}
404
+ </CapHeading>
405
+ </div>
406
+ </div>
407
+ </Fragment>
408
+ );
409
+ }
410
+
411
+ const onTitleChange = ({ target: { value } }) => {
412
+ updateTitle(value);
413
+ let errorMessage;
414
+ if (value === '') {
415
+ errorMessage = formatMessage(messages.emptyAltTextErrorMessage);
416
+ }
417
+ updateErrorTitle(errorMessage);
418
+ updateMessageState({
419
+ isError: !videoSrc || !imagePreview || !value || !checkAction() || !(isFullMode ? messageTitle : true),
420
+ videoSrc,
421
+ previewImageUrl: imagePreview,
422
+ videoName,
423
+ messageTitle,
424
+ altText: value,
425
+ index,
426
+ type: 'video',
427
+ actionLabel,
428
+ actionUrl,
429
+ videoHeight,
430
+ videoWidth,
431
+ videoDuration,
432
+ selectedAction,
433
+ messageType: 'videoSrc',
434
+ });
435
+ }
436
+
437
+ const onChangeSelectedAction = () => {
438
+ event.stopPropagation();
439
+ const { target: { value } } = event;
440
+ updateSelectedAction(value);
441
+ updateMessageState({
442
+ isError: !videoSrc || !imagePreview || !altText || !checkAction(undefined, undefined, value) || !(isFullMode ? messageTitle : true),
443
+ videoSrc,
444
+ previewImageUrl: imagePreview,
445
+ videoName,
446
+ messageTitle,
447
+ altText,
448
+ index,
449
+ type: 'video',
450
+ actionLabel: value === HIDE_ACTION_BUTTON ? '' : actionLabel,
451
+ actionUrl: value === HIDE_ACTION_BUTTON ? '' : actionUrl,
452
+ videoHeight,
453
+ videoWidth,
454
+ videoDuration,
455
+ selectedAction: value,
456
+ messageType: 'videoSrc',
457
+ });
458
+ }
459
+
460
+ const updateActionLabelError = (value = '') => {
461
+ if (value.length > MAX_ACTION_LABEL_LENGTH) {
462
+ updateActionLabelErrorMessage(formatMessage(messages.maxActionLabelErrorMessage));
463
+ return formatMessage(messages.maxActionLabelErrorMessage);
464
+ } else if (value === '') {
465
+ updateActionLabelErrorMessage(formatMessage(messages.emptyLabelErrorMessage));
466
+ return formatMessage(messages.emptyLabelErrorMessage);
467
+ } else {
468
+ updateActionLabelErrorMessage();
469
+ }
470
+ }
471
+
472
+ const updateActionUrlError = (value) => {
473
+ if (value === '') {
474
+ updateActionUrlErrorMessage(formatMessage(messages.emptyUrlErrorMessage));
475
+ return formatMessage(messages.emptyUrlErrorMessage);
476
+ } else if (!isUrl(value)) {
477
+ updateActionUrlErrorMessage(formatMessage(messages.inValidUrlErrorMessage));
478
+ return formatMessage(messages.inValidUrlErrorMessage);
479
+ } else {
480
+ updateActionUrlErrorMessage();
481
+ }
482
+ }
483
+
484
+ const onActionLabelChange = ({ target: { value } }) => {
485
+ updateActionLabel(value);
486
+ updateActionLabelError(value);
487
+ updateMessageState({
488
+ isError: !videoSrc || !imagePreview || !altText || !checkAction(value) || !(isFullMode ? messageTitle : true),
489
+ videoSrc,
490
+ previewImageUrl: imagePreview,
491
+ videoName,
492
+ messageTitle,
493
+ altText,
494
+ index,
495
+ type: 'video',
496
+ actionLabel: value,
497
+ actionUrl,
498
+ videoHeight,
499
+ videoWidth,
500
+ videoDuration,
501
+ selectedAction,
502
+ messageType: 'videoSrc',
503
+ });
504
+ }
505
+
506
+ const onActionUrlChange = ({ target: { value } }) => {
507
+ updateActionUrl(value);
508
+ updateActionUrlError(value);
509
+ updateMessageState({
510
+ isError: !videoSrc || !imagePreview || !altText || !checkAction(undefined, value) || !(isFullMode ? messageTitle : true),
511
+ videoSrc,
512
+ previewImageUrl: imagePreview,
513
+ videoName,
514
+ messageTitle,
515
+ altText,
516
+ index,
517
+ type: 'video',
518
+ actionLabel,
519
+ actionUrl: value,
520
+ videoHeight,
521
+ videoWidth,
522
+ videoDuration,
523
+ selectedAction,
524
+ messageType: 'videoSrc',
525
+ });
526
+ }
527
+
528
+ const getActionSection = () => {
529
+ return (
530
+ <>
531
+ <CapHeading type="h6" style={{ marginTop: CAP_SPACE_12 }}>
532
+ <FormattedMessage {...messages.actionButtonLabel} />
533
+ </CapHeading>
534
+ <CapRadioGroup
535
+ name="actionButton"
536
+ defaultValue={HIDE_ACTION_BUTTON}
537
+ onChange={onChangeSelectedAction}
538
+ value={selectedAction}
539
+ options={[
540
+ {
541
+ label: 'Hide',
542
+ value: HIDE_ACTION_BUTTON
543
+ },
544
+ {
545
+ label: 'Display',
546
+ value: DISPLAY_ACTION_BUTTON
547
+ }
548
+ ]}
549
+ />
550
+ {
551
+ selectedAction === DISPLAY_ACTION_BUTTON
552
+ ? (
553
+ <>
554
+ <CapInput
555
+ onChange={onActionUrlChange}
556
+ placeholder={formatMessage(messages.actionUrlPlaceholder)}
557
+ value={actionUrl}
558
+ errorMessage={actionUrlErrorMessage}
559
+ label={formatMessage(messages.actionUrlTitle)}
560
+ className="action-url-section"
561
+ />
562
+ <CapInput
563
+ onChange={onActionLabelChange}
564
+ placeholder={formatMessage(messages.actionLabelPlaceholder)}
565
+ value={actionLabel}
566
+ errorMessage={actionLabelErrorMessage}
567
+ label={formatMessage(messages.actionLabelTitle)}
568
+ inductiveText={formatMessage(messages.actionLabelInductiveTitle)}
569
+ addonAfter={<span>{(actionLabel || '').length} / ({MAX_ACTION_LABEL_LENGTH})</span>}
570
+ className="action-label-section"
571
+ />
572
+ </>
573
+ )
574
+ : null
575
+ }
576
+ </>
577
+ )
578
+ }
579
+
580
+ const getLineVideoSection = () => {
581
+ if (!isCreateNew) {
582
+ return (
583
+ <div className="form-builder-dragger" style={{
584
+ textAlign: 'center',
585
+ border: `1px dashed ${CAP_G06}`,
586
+ minHeight: 120,
587
+ padding: 60
588
+ }}>
589
+ <CapHeader
590
+ className="choice-title"
591
+ size="regular"
592
+ title={formatMessage(messages.textMessageAddLabel)}
593
+ style={{ marginBottom: 12 }}
594
+ />
595
+
596
+ <CapButton
597
+ className="dragger-button create-button"
598
+ type="secondary"
599
+ style={{ marginRight: CAP_SPACE_08 }}
600
+ onClick={setNewContent}
601
+ isAddBtn
602
+ >
603
+ <FormattedMessage {...messages.textMessageCreateNew} />
604
+ </CapButton>
605
+
606
+ <CapHeading className="dragger-or" type="label6" style={{ display: 'inline-block' }}>
607
+ <FormattedMessage {...messages.textMessageORLabel} />
608
+ </CapHeading>
609
+
610
+ <CapButton
611
+ className="dragger-button select-template-button"
612
+ type="secondary"
613
+ style={{ marginLeft: CAP_SPACE_08 }}
614
+ onClick={onSelectTemplate}
615
+ >
616
+ <FormattedMessage {...messages.textMessageSelectTemplate} />
617
+ </CapButton>
618
+ </div>);
619
+ } else {
620
+ return (
621
+ <>
622
+ <CapInput.TextArea
623
+ maxLength={MAX_ALLOWED_TITLE_LENGTH}
624
+ label={<FormattedMessage {...messages.titleLabel} />}
625
+ inductiveText={<FormattedMessage {...messages.titleDescription} />}
626
+ onChange={onTitleChange}
627
+ value={altText}
628
+ errorMessage={errorTitle}
629
+ className="title-textarea"
630
+ />
631
+ {getVideoSection()}
632
+ {getActionSection()}
633
+ </>
634
+ );
635
+ }
636
+ }
637
+
638
+ const setNewContent = useCallback(() => updateCreateNew(true), []);
639
+
640
+ const onTemplateSelection = (template) => {
641
+ const {
642
+ video: {
643
+ originalContentUrl = '',
644
+ previewImageUrl = '',
645
+ externalLink: {
646
+ label = '',
647
+ linkUri = '',
648
+ } = {},
649
+ area: {
650
+ height,
651
+ width,
652
+ } = {},
653
+ } = {},
654
+ videoName = '',
655
+ videoDuration = '',
656
+ altText,
657
+ } = get(template, 'versions.base.content.messages[0]', {});
658
+
659
+ updateSelectedTemplate(template);
660
+ updateVideoStatus(true);
661
+ updateTemplateDrawerRequirement(false);
662
+ updateCreateNew(true);
663
+ updateVideoSrc(originalContentUrl);
664
+ updateTextMessageTitle(messageTitle);
665
+ updateImagePreview(previewImageUrl);
666
+ updateVideoName(videoName);
667
+ updateVideoWidth(width);
668
+ updateVideoHeight(height);
669
+ updateVideoDuration(videoDuration);
670
+ updateActionUrl(linkUri);
671
+ updateActionLabel(label);
672
+ updateSelectedAction(!!label ? DISPLAY_ACTION_BUTTON : HIDE_ACTION_BUTTON);
673
+ updateTitle(altText);
674
+ }
675
+
676
+ const getLineVideoDrawerContent = () => {
677
+ const lineTextTemplates = Templates.templates;
678
+ if (!lineTextTemplates) {
679
+ return null;
680
+ }
681
+
682
+ const cardDataList = [];
683
+ lineTextTemplates.forEach(template => {
684
+ let templateData = {};
685
+ const {
686
+ content: {
687
+ messages: [{
688
+ video: {
689
+ originalContentUrl = '',
690
+ } = {},
691
+ }] = [{}],
692
+ } = {},
693
+ } = template.versions.base;
694
+ templateData.content = (
695
+ <video height="279">
696
+ <source src={originalContentUrl} type="video/mp4" />
697
+ </video>
698
+ );
699
+ templateData.title = template.name;
700
+ templateData.key = template.name;
701
+ templateData.hoverOption = (
702
+ <CapButton onClick={() => onTemplateSelection(template)}>
703
+ <FormattedMessage {...messages.select} />
704
+ </CapButton>
705
+ );
706
+ if (originalContentUrl) {
707
+ cardDataList.push(templateData);
708
+ }
709
+ });
710
+ return (
711
+ <>
712
+ <CapHeading type="h3" className="drawer-head">
713
+ {formatMessage(messages.lineTemplateImage)}
714
+ </CapHeading>
715
+ <LineDrawer
716
+ getAllTemplates={getAllTemplates}
717
+ cardDataList={cardDataList}
718
+ isDrawer={isTemplateDrawerRequired}
719
+ Templates={Templates}
720
+ searchPlaceholder={formatMessage(messages.searchImages)}
721
+ />
722
+ </>
723
+ );
724
+ };
725
+
726
+ return (
727
+ <div className={className}>
728
+ {
729
+ isFullMode
730
+ ? (
731
+ <CapInput
732
+ id={`${id}_input`}
733
+ onChange={onTextTitleChange}
734
+ errorMessage={errorMessageTitle}
735
+ className="image-template-title"
736
+ style={inheritedTitleStyle || {}}
737
+ placeholder={formatMessage(messages.textMessageTitlePlaceholder)}
738
+ defaultValue={messageTitle || ''}
739
+ value={messageTitle || ''}
740
+ size="default"
741
+ label={formatMessage(messages.textMessageTitleLabel)}
742
+ />
743
+ )
744
+ : null
745
+ }
746
+ <form encType="multipart/form-data" id={`${id}_form`}>
747
+ <input
748
+ key={`${id}_videoFile`}
749
+ style={{ display: 'none' }}
750
+ id="fileName"
751
+ type="file"
752
+ onChange={(e) => uploadVideo(e, { files: e.target.files })}
753
+ accept={supportedExtensions ? supportedExtensions : "video/*"}
754
+ />
755
+ {getLineVideoSection()}
756
+ <CapDrawer
757
+ content={getLineVideoDrawerContent()}
758
+ visible={isTemplateDrawerRequired}
759
+ width={624}
760
+ onClose={() => updateTemplateDrawerRequirement(false)}
761
+ />
762
+ </form>
763
+ </div>
764
+ )
765
+ }
766
+
767
+ export default injectIntl(withStyles(LineVideo, style));