@capillarytech/creatives-library 8.0.123 → 8.0.125-alpha.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/containers/App/constants.js +1 -0
- package/package.json +1 -1
- package/services/api.js +1 -1
- package/tests/integration/TemplateCreation/TemplateCreation.integration.test.js +8 -3
- package/tests/integration/TemplateCreation/api-response.js +5 -0
- package/tests/integration/TemplateCreation/msw-handler.js +42 -63
- package/utils/common.js +7 -0
- package/utils/commonUtils.js +2 -6
- package/utils/createPayload.js +240 -0
- package/utils/tests/createPayload.test.js +761 -0
- package/v2Components/CapDeviceContent/index.js +1 -0
- package/v2Components/CapImageUpload/index.js +51 -45
- package/v2Components/CapInAppCTA/index.js +1 -0
- package/v2Components/CapMpushCTA/constants.js +25 -0
- package/v2Components/CapMpushCTA/index.js +332 -0
- package/v2Components/CapMpushCTA/index.scss +95 -0
- package/v2Components/CapMpushCTA/messages.js +89 -0
- package/v2Components/CapTagList/index.js +177 -120
- package/v2Components/CapVideoUpload/constants.js +3 -0
- package/v2Components/CapVideoUpload/index.js +167 -110
- package/v2Components/CapVideoUpload/messages.js +16 -0
- package/v2Components/Carousel/index.js +15 -13
- package/v2Components/ErrorInfoNote/style.scss +1 -0
- package/v2Components/MobilePushPreviewV2/index.js +37 -5
- package/v2Components/TemplatePreview/_templatePreview.scss +114 -72
- package/v2Components/TemplatePreview/assets/images/Android _ With date and time.svg +29 -0
- package/v2Components/TemplatePreview/assets/images/android.svg +9 -0
- package/v2Components/TemplatePreview/assets/images/iOS _ With date and time.svg +26 -0
- package/v2Components/TemplatePreview/assets/images/ios.svg +9 -0
- package/v2Components/TemplatePreview/index.js +178 -50
- package/v2Components/TemplatePreview/messages.js +4 -0
- package/v2Containers/CreativesContainer/SlideBoxContent.js +7 -8
- package/v2Containers/CreativesContainer/index.js +194 -138
- package/v2Containers/InApp/constants.js +1 -1
- package/v2Containers/InApp/index.js +13 -13
- package/v2Containers/MobilePush/Create/index.js +1 -0
- package/v2Containers/MobilePushNew/actions.js +116 -0
- package/v2Containers/MobilePushNew/components/CtaButtons.js +170 -0
- package/v2Containers/MobilePushNew/components/MediaUploaders.js +686 -0
- package/v2Containers/MobilePushNew/components/PlatformContentFields.js +279 -0
- package/v2Containers/MobilePushNew/components/index.js +5 -0
- package/v2Containers/MobilePushNew/components/tests/CtaButtons.test.js +779 -0
- package/v2Containers/MobilePushNew/components/tests/MediaUploaders.test.js +2114 -0
- package/v2Containers/MobilePushNew/components/tests/PlatformContentFields.test.js +343 -0
- package/v2Containers/MobilePushNew/constants.js +115 -0
- package/v2Containers/MobilePushNew/hooks/tests/usePlatformSync.test.js +1299 -0
- package/v2Containers/MobilePushNew/hooks/tests/useUpload.test.js +1223 -0
- package/v2Containers/MobilePushNew/hooks/usePlatformSync.js +246 -0
- package/v2Containers/MobilePushNew/hooks/useUpload.js +709 -0
- package/v2Containers/MobilePushNew/index.js +1937 -0
- package/v2Containers/MobilePushNew/index.scss +308 -0
- package/v2Containers/MobilePushNew/messages.js +226 -0
- package/v2Containers/MobilePushNew/reducer.js +160 -0
- package/v2Containers/MobilePushNew/sagas.js +198 -0
- package/v2Containers/MobilePushNew/selectors.js +55 -0
- package/v2Containers/MobilePushNew/tests/reducer.test.js +741 -0
- package/v2Containers/MobilePushNew/tests/sagas.test.js +863 -0
- package/v2Containers/MobilePushNew/tests/selectors.test.js +425 -0
- package/v2Containers/MobilePushNew/tests/utils.test.js +322 -0
- package/v2Containers/MobilePushNew/utils.js +33 -0
- package/v2Containers/Rcs/tests/__snapshots__/index.test.js.snap +5 -5
- package/v2Containers/TagList/index.js +56 -10
- package/v2Containers/Templates/_templates.scss +101 -1
- package/v2Containers/Templates/index.js +147 -35
- package/v2Containers/Templates/messages.js +8 -0
- package/v2Containers/Templates/sagas.js +2 -0
- package/v2Containers/Whatsapp/constants.js +1 -0
|
@@ -3,7 +3,9 @@
|
|
|
3
3
|
* CapVideoUpload
|
|
4
4
|
*
|
|
5
5
|
*/
|
|
6
|
-
import React, {
|
|
6
|
+
import React, {
|
|
7
|
+
useCallback, useState, Fragment, useRef, useEffect,
|
|
8
|
+
} from 'react';
|
|
7
9
|
import PropTypes from "prop-types";
|
|
8
10
|
import get from 'lodash/get';
|
|
9
11
|
import CapDrawer from '@capillarytech/cap-ui-library/CapDrawer';
|
|
@@ -19,9 +21,12 @@ import {
|
|
|
19
21
|
} from '@capillarytech/cap-ui-library';
|
|
20
22
|
import messages from './messages';
|
|
21
23
|
import {bytes2Size, getDecodedFileName} from '../../utils/common';
|
|
22
|
-
import {
|
|
24
|
+
import {
|
|
25
|
+
SUPPORTED_FILE_FORMATS, WHATSAPP, DEFAULT, MAX_DURATION, MOBILEPUSH,
|
|
26
|
+
} from './constants';
|
|
23
27
|
import './index.scss';
|
|
24
28
|
import { VIBER } from '../../v2Containers/CreativesContainer/constants';
|
|
29
|
+
import { GIF, VIDEO } from '../../v2Containers/MobilePushNew/constants';
|
|
25
30
|
|
|
26
31
|
function CapVideoUpload(props) {
|
|
27
32
|
const {
|
|
@@ -40,6 +45,7 @@ function CapVideoUpload(props) {
|
|
|
40
45
|
showVideoNameAndDuration = true,
|
|
41
46
|
formClassName = 'video-form',
|
|
42
47
|
showReUploadButton = true,
|
|
48
|
+
mediaType = VIDEO.toLowerCase(),
|
|
43
49
|
} = props;
|
|
44
50
|
const [isVideoError, updateVideoErrorMessage] = useState(false);
|
|
45
51
|
const [isVideo, updateVideoStatus] = useState(false);
|
|
@@ -68,6 +74,7 @@ function CapVideoUpload(props) {
|
|
|
68
74
|
const _URL = window.URL || window.webkitURL;
|
|
69
75
|
let incorrectFile = false;
|
|
70
76
|
const file = files[0];
|
|
77
|
+
|
|
71
78
|
if (!allowedExtensionsRegex.test(file.name)) {
|
|
72
79
|
incorrectFile = true;
|
|
73
80
|
}
|
|
@@ -79,7 +86,7 @@ function CapVideoUpload(props) {
|
|
|
79
86
|
error: false,
|
|
80
87
|
isGenerateVideoThumbnail: true,
|
|
81
88
|
};
|
|
82
|
-
submitVideoAction({ file, type:
|
|
89
|
+
submitVideoAction({ file, type: mediaType, fileParams }, incorrectFile);
|
|
83
90
|
if (e) {
|
|
84
91
|
const event = e;
|
|
85
92
|
event.target.value = null;
|
|
@@ -87,10 +94,18 @@ function CapVideoUpload(props) {
|
|
|
87
94
|
}, []);
|
|
88
95
|
|
|
89
96
|
useEffect(() => {
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
97
|
+
}, [videoData, index]);
|
|
98
|
+
|
|
99
|
+
useEffect(() => {
|
|
100
|
+
if (!isEmpty(videoData[`uploadedAssetData${index}`])) {
|
|
101
|
+
const {
|
|
102
|
+
metaInfo: {
|
|
103
|
+
secure_file_path: metaVideoSrc = '',
|
|
104
|
+
file_name: metaVideoName = '',
|
|
105
|
+
preview_image_url: previewImgUrl = '',
|
|
106
|
+
} = {},
|
|
107
|
+
} = videoData[`uploadedAssetData${index}`] || {};
|
|
108
|
+
|
|
94
109
|
const metaVideoId = get(videoData, `uploadedAssetData${index}.videoIdResponse.fbVideo.id`, '');
|
|
95
110
|
const karixFileHandle = get(videoData, `uploadedAssetData${index}.metaInfo.karixFileHandle`, '');
|
|
96
111
|
|
|
@@ -102,14 +117,13 @@ function CapVideoUpload(props) {
|
|
|
102
117
|
videoId: metaVideoId,
|
|
103
118
|
fileHandle: karixFileHandle,
|
|
104
119
|
videoDuration: null,
|
|
105
|
-
}
|
|
106
|
-
);
|
|
120
|
+
});
|
|
107
121
|
}
|
|
108
122
|
}
|
|
109
|
-
}, [videoData
|
|
123
|
+
}, [videoData, index, videoSrc, onVideoUploadUpdateAssestList]);
|
|
110
124
|
|
|
111
125
|
useEffect(() => {
|
|
112
|
-
if (videoData[`assetUploadingVideo_${index}`] && videoData
|
|
126
|
+
if (videoData[`assetUploadingVideo_${index}`] && videoData.assetUploading !== false) {
|
|
113
127
|
const isSpinner = get(videoData, `assetUploadingVideo_${index}`, false);
|
|
114
128
|
setSpinning(isSpinner);
|
|
115
129
|
}
|
|
@@ -123,7 +137,12 @@ function CapVideoUpload(props) {
|
|
|
123
137
|
} = uploadedAssetList || {};
|
|
124
138
|
if (metaVideoSrc) {
|
|
125
139
|
updateVideoStatus(true);
|
|
140
|
+
} else {
|
|
141
|
+
updateVideoStatus(false);
|
|
126
142
|
}
|
|
143
|
+
} else {
|
|
144
|
+
// When uploadedAssetList is empty, reset video status to show upload interface
|
|
145
|
+
updateVideoStatus(false);
|
|
127
146
|
}
|
|
128
147
|
}, [uploadedAssetList]);
|
|
129
148
|
|
|
@@ -136,6 +155,7 @@ function CapVideoUpload(props) {
|
|
|
136
155
|
fileParams,
|
|
137
156
|
type,
|
|
138
157
|
} = data;
|
|
158
|
+
|
|
139
159
|
if (incorrectFile || size > videoSize) {
|
|
140
160
|
if (errorMessage) {
|
|
141
161
|
updateVideoErrorMessage(errorMessage);
|
|
@@ -155,11 +175,7 @@ function CapVideoUpload(props) {
|
|
|
155
175
|
|
|
156
176
|
const {
|
|
157
177
|
formatMessage,
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
const capUploaderCustomVideoRequest = useCallback((uploadData) => {
|
|
161
|
-
uploadVideo(undefined, { files: [uploadData.file] });
|
|
162
|
-
}, []);
|
|
178
|
+
} = intl || {};
|
|
163
179
|
|
|
164
180
|
const playVideo = useCallback((e) => {
|
|
165
181
|
if (e.target.paused && !isPlaying) {
|
|
@@ -173,78 +189,86 @@ function CapVideoUpload(props) {
|
|
|
173
189
|
}
|
|
174
190
|
}, [isPlaying]);
|
|
175
191
|
|
|
192
|
+
const onReUpload = useCallback(() => {
|
|
193
|
+
updateVideoStatus(false);
|
|
194
|
+
updateVideoDuration(null);
|
|
195
|
+
onVideoUploadUpdateAssestList(
|
|
196
|
+
index,
|
|
197
|
+
{
|
|
198
|
+
previewUrl: "",
|
|
199
|
+
videoName: "",
|
|
200
|
+
videoHeight: "",
|
|
201
|
+
videoWidth: "",
|
|
202
|
+
videoSrc: "",
|
|
203
|
+
videoDuration: null,
|
|
204
|
+
videoId: "",
|
|
205
|
+
fileHandle: "",
|
|
206
|
+
}
|
|
207
|
+
);
|
|
208
|
+
setTimeout(() => {
|
|
209
|
+
const fileInput = document.getElementById("videoFileName");
|
|
210
|
+
if (fileInput) {
|
|
211
|
+
fileInput.click();
|
|
212
|
+
}
|
|
213
|
+
}, 100);
|
|
214
|
+
}, [index, onVideoUploadUpdateAssestList]);
|
|
215
|
+
|
|
216
|
+
const updateMetadataLoaded = useCallback(() => {
|
|
217
|
+
const { current: { duration, videoHeight: metaVideoHeight, videoWidth: metaVideoWidth } = {} } = videoEl;
|
|
218
|
+
if (duration) {
|
|
219
|
+
updateVideoDuration(duration);
|
|
220
|
+
if (videoWidth === undefined && videoHeight === undefined) {
|
|
221
|
+
if (duration <= MAX_DURATION) {
|
|
222
|
+
onVideoUploadUpdateAssestList(index, {
|
|
223
|
+
videoSrc,
|
|
224
|
+
videoId,
|
|
225
|
+
videoName,
|
|
226
|
+
videoHeight: metaVideoHeight,
|
|
227
|
+
videoWidth: metaVideoWidth,
|
|
228
|
+
previewUrl,
|
|
229
|
+
fileHandle,
|
|
230
|
+
videoDuration: duration,
|
|
231
|
+
});
|
|
232
|
+
} else {
|
|
233
|
+
onReUpload();
|
|
234
|
+
updateVideoErrorMessage(formatMessage(messages.videoDurationError));
|
|
235
|
+
}
|
|
236
|
+
}
|
|
237
|
+
}
|
|
238
|
+
}, [videoSrc, videoId, videoName, previewUrl, fileHandle, videoWidth, videoHeight, index, onVideoUploadUpdateAssestList, formatMessage, onReUpload]);
|
|
239
|
+
|
|
240
|
+
const videoDurationValue = videoDuration ? moment('1900-01-01 00:00:00').add(videoDuration, 'seconds').format("HH.mm.ss") : '';
|
|
241
|
+
|
|
242
|
+
const capUploaderCustomVideoRequest = useCallback((uploadData) => {
|
|
243
|
+
uploadVideo(undefined, { files: [uploadData.file] });
|
|
244
|
+
}, [uploadVideo]);
|
|
245
|
+
|
|
176
246
|
const getVideoSection = () => {
|
|
177
247
|
if (!isVideo) {
|
|
178
248
|
return (
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
>
|
|
186
|
-
<
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
<
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
<
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
</>
|
|
200
|
-
)
|
|
249
|
+
<>
|
|
250
|
+
<CapUploader.CapDragger
|
|
251
|
+
customRequest={(data) => capUploaderCustomVideoRequest(data)}
|
|
252
|
+
className="form-builder-dragger whatsapp-background"
|
|
253
|
+
showUploadList={!isVideoError}
|
|
254
|
+
>
|
|
255
|
+
<CapHeading className="dragger-title" type="h7">
|
|
256
|
+
<FormattedMessage {...messages.dragAndDrop} />
|
|
257
|
+
</CapHeading>
|
|
258
|
+
<CapHeading className="dragger-or" type="label6">
|
|
259
|
+
<FormattedMessage {...messages.or} />
|
|
260
|
+
</CapHeading>
|
|
261
|
+
<CapButton className="dragger-button upload-video" type="secondary">
|
|
262
|
+
<FormattedMessage {...messages.selectFromComputer} />
|
|
263
|
+
</CapButton>
|
|
264
|
+
</CapUploader.CapDragger>
|
|
265
|
+
<CapError type="error" className="upload-video-error">
|
|
266
|
+
{isVideoError}
|
|
267
|
+
</CapError>
|
|
268
|
+
</>
|
|
201
269
|
);
|
|
202
270
|
}
|
|
203
|
-
const onReUpload = () => {
|
|
204
|
-
updateVideoStatus(false);
|
|
205
|
-
updateVideoDuration(null);
|
|
206
|
-
onVideoUploadUpdateAssestList(
|
|
207
|
-
index,
|
|
208
|
-
{
|
|
209
|
-
previewUrl: "",
|
|
210
|
-
videoName: "",
|
|
211
|
-
videoHeight: "",
|
|
212
|
-
videoWidth: "",
|
|
213
|
-
videoSrc: "",
|
|
214
|
-
videoDuration: null,
|
|
215
|
-
videoId: "",
|
|
216
|
-
fileHandle: "",
|
|
217
|
-
}
|
|
218
|
-
);
|
|
219
|
-
};
|
|
220
271
|
|
|
221
|
-
const updateMetadataLoaded = () => {
|
|
222
|
-
const { current: { duration, videoHeight: metaVideoHeight, videoWidth: metaVideoWidth } = {} } = videoEl;
|
|
223
|
-
if (duration) {
|
|
224
|
-
updateVideoDuration(duration);
|
|
225
|
-
if (videoWidth === undefined && videoHeight === undefined) {
|
|
226
|
-
if (
|
|
227
|
-
channel !== VIBER ||
|
|
228
|
-
(channel === VIBER && duration <= VIBER_MAX_DURATION)
|
|
229
|
-
) {
|
|
230
|
-
onVideoUploadUpdateAssestList(index, {
|
|
231
|
-
videoSrc,
|
|
232
|
-
videoId,
|
|
233
|
-
videoName,
|
|
234
|
-
videoHeight: metaVideoHeight,
|
|
235
|
-
videoWidth: metaVideoWidth,
|
|
236
|
-
previewUrl,
|
|
237
|
-
fileHandle,
|
|
238
|
-
videoDuration: duration,
|
|
239
|
-
});
|
|
240
|
-
} else {
|
|
241
|
-
onReUpload();
|
|
242
|
-
updateVideoErrorMessage(formatMessage(messages.videoDurationError));
|
|
243
|
-
}
|
|
244
|
-
}
|
|
245
|
-
}
|
|
246
|
-
};
|
|
247
|
-
const videoDurationValue = moment('1900-01-01 00:00:00').add(videoDuration, 'seconds').format("HH.mm.ss"); // to get the duration of video
|
|
248
272
|
return (
|
|
249
273
|
<Fragment key={videoSrc}>
|
|
250
274
|
{showReUploadButton && (
|
|
@@ -259,21 +283,35 @@ function CapVideoUpload(props) {
|
|
|
259
283
|
</div>
|
|
260
284
|
)}
|
|
261
285
|
<div className={showVideoNameAndDuration ? 'video-panel' : 'video-panel-wp'}>
|
|
262
|
-
|
|
263
|
-
|
|
264
|
-
|
|
265
|
-
|
|
266
|
-
|
|
267
|
-
|
|
268
|
-
|
|
269
|
-
|
|
270
|
-
|
|
271
|
-
|
|
272
|
-
|
|
273
|
-
|
|
274
|
-
|
|
275
|
-
|
|
276
|
-
|
|
286
|
+
{mediaType === GIF.toLowerCase() ? (
|
|
287
|
+
<img
|
|
288
|
+
width="230"
|
|
289
|
+
src={videoSrc}
|
|
290
|
+
alt="GIF preview"
|
|
291
|
+
className="line-image-src"
|
|
292
|
+
key={`${index}-gif`}
|
|
293
|
+
style={{ maxWidth: '230px', maxHeight: '200px', objectFit: 'contain' }}
|
|
294
|
+
/>
|
|
295
|
+
) : (
|
|
296
|
+
<video
|
|
297
|
+
width="230"
|
|
298
|
+
poster={previewUrl}
|
|
299
|
+
className="line-image-src"
|
|
300
|
+
key={`${index}-video`}
|
|
301
|
+
onLoadedMetadata={updateMetadataLoaded}
|
|
302
|
+
onPlaying={() => updateIsPlaying(true)}
|
|
303
|
+
onPause={() => updateIsPlaying(false)}
|
|
304
|
+
onMouseOver={playVideo}
|
|
305
|
+
onMouseOut={pauseVideo}
|
|
306
|
+
onFocus={playVideo}
|
|
307
|
+
onBlur={pauseVideo}
|
|
308
|
+
ref={videoEl}
|
|
309
|
+
>
|
|
310
|
+
<source src={videoSrc} type="video/mp4" />
|
|
311
|
+
<track kind="captions" />
|
|
312
|
+
</video>
|
|
313
|
+
)}
|
|
314
|
+
{showVideoNameAndDuration && (
|
|
277
315
|
<div className="video-info">
|
|
278
316
|
<CapHeading type="h4">
|
|
279
317
|
{getDecodedFileName(videoName)}
|
|
@@ -282,7 +320,7 @@ function CapVideoUpload(props) {
|
|
|
282
320
|
{videoDurationValue}
|
|
283
321
|
</CapHeading>
|
|
284
322
|
</div>
|
|
285
|
-
}
|
|
323
|
+
)}
|
|
286
324
|
</div>
|
|
287
325
|
</Fragment>
|
|
288
326
|
);
|
|
@@ -300,23 +338,24 @@ function CapVideoUpload(props) {
|
|
|
300
338
|
return (
|
|
301
339
|
<CapSpin spinning={isSpinning}>
|
|
302
340
|
<div style={style} className="cap-custom-video-upload">
|
|
303
|
-
<form encType="multipart/form-data" id=
|
|
341
|
+
<form encType="multipart/form-data" id="form" className={formClassName}>
|
|
304
342
|
<input
|
|
305
|
-
key=
|
|
343
|
+
key="videoFile"
|
|
306
344
|
style={{ display: 'none' }}
|
|
307
|
-
id="
|
|
345
|
+
id="videoFileName"
|
|
308
346
|
type="file"
|
|
309
347
|
onChange={(e) => uploadVideo(e, { files: e.target.files })}
|
|
310
|
-
accept={supportedExtensions || "video/*"}
|
|
311
|
-
|
|
348
|
+
accept={mediaType === GIF.toLowerCase() ? '.gif' : (supportedExtensions || "video/*")}
|
|
349
|
+
/>
|
|
312
350
|
{getVideoSection()}
|
|
313
351
|
<CapDrawer
|
|
314
352
|
visible={isTemplateDrawerRequired}
|
|
315
353
|
width={624}
|
|
316
354
|
onClose={() => updateTemplateDrawerRequirement(false)}
|
|
317
|
-
|
|
355
|
+
/>
|
|
318
356
|
</form>
|
|
319
|
-
{![WHATSAPP, VIBER].includes(channel)
|
|
357
|
+
{![WHATSAPP, VIBER, MOBILEPUSH].includes(channel)
|
|
358
|
+
&& (
|
|
320
359
|
<>
|
|
321
360
|
<CapHeading.CapHeadingSpan type="h6" className="video-description">
|
|
322
361
|
<FormattedMessage {...messages.videoRatioDescription} />
|
|
@@ -328,15 +367,18 @@ function CapVideoUpload(props) {
|
|
|
328
367
|
<CapHeading.CapHeadingSpan type="h6" className="video-description video-details">
|
|
329
368
|
<FormattedMessage {...messages.videoSizeDescription} values={{size: bytes2Size(videoSize)}} />
|
|
330
369
|
</CapHeading.CapHeadingSpan>
|
|
331
|
-
</>
|
|
332
|
-
|
|
370
|
+
</>
|
|
371
|
+
)}
|
|
372
|
+
{channel === WHATSAPP
|
|
373
|
+
&& (
|
|
333
374
|
<>
|
|
334
375
|
{getVideoSizeDescription()}
|
|
335
376
|
<CapHeading.CapHeadingSpan type="label2" className="whatsapp-format">
|
|
336
377
|
<FormattedMessage {...messages.channelFileFormat} values={{ format: SUPPORTED_FILE_FORMATS[DEFAULT] }} />
|
|
337
378
|
</CapHeading.CapHeadingSpan>
|
|
338
|
-
</>
|
|
339
|
-
|
|
379
|
+
</>
|
|
380
|
+
)}
|
|
381
|
+
{channel === VIBER && (
|
|
340
382
|
<>
|
|
341
383
|
{getVideoSizeDescription()}
|
|
342
384
|
<CapHeading.CapHeadingSpan type="label2" className="whatsapp-format">
|
|
@@ -345,7 +387,20 @@ function CapVideoUpload(props) {
|
|
|
345
387
|
<CapHeading.CapHeadingSpan type="label2" className="video-duration">
|
|
346
388
|
<FormattedMessage {...messages.viberMaxDuration} />
|
|
347
389
|
</CapHeading.CapHeadingSpan>
|
|
348
|
-
</>
|
|
390
|
+
</>
|
|
391
|
+
)}
|
|
392
|
+
{channel === MOBILEPUSH
|
|
393
|
+
&& (
|
|
394
|
+
<>
|
|
395
|
+
{getVideoSizeDescription()}
|
|
396
|
+
<CapHeading.CapHeadingSpan type="label2" className="whatsapp-format">
|
|
397
|
+
<FormattedMessage {...messages.channelFileFormat} values={{ format: SUPPORTED_FILE_FORMATS.MOBILEPUSH }} />
|
|
398
|
+
</CapHeading.CapHeadingSpan>
|
|
399
|
+
<CapHeading.CapHeadingSpan type="label2" className="video-duration">
|
|
400
|
+
<FormattedMessage {...messages.maxDuration} />
|
|
401
|
+
</CapHeading.CapHeadingSpan>
|
|
402
|
+
</>
|
|
403
|
+
)}
|
|
349
404
|
</div>
|
|
350
405
|
</CapSpin>
|
|
351
406
|
);
|
|
@@ -366,6 +421,8 @@ CapVideoUpload.propTypes = {
|
|
|
366
421
|
channel: PropTypes.string,
|
|
367
422
|
errorMessage: PropTypes.string,
|
|
368
423
|
formClassName: PropTypes.string,
|
|
424
|
+
showReUploadButton: PropTypes.bool,
|
|
425
|
+
mediaType: PropTypes.string,
|
|
369
426
|
};
|
|
370
427
|
|
|
371
428
|
export default injectIntl(CapVideoUpload);
|
|
@@ -63,8 +63,24 @@ export default defineMessages({
|
|
|
63
63
|
id: `${scope}.viberMaxDuration`,
|
|
64
64
|
defaultMessage: 'Max Duration: 600 seconds',
|
|
65
65
|
},
|
|
66
|
+
maxDuration: {
|
|
67
|
+
id: `${scope}.maxDuration`,
|
|
68
|
+
defaultMessage: 'Max duration: 600 seconds',
|
|
69
|
+
},
|
|
66
70
|
videoDurationError: {
|
|
67
71
|
id: `${scope}.videoDurationError`,
|
|
68
72
|
defaultMessage: 'Video duration should not exceed 600 seconds',
|
|
69
73
|
},
|
|
74
|
+
uploadVideo: {
|
|
75
|
+
id: `${scope}.uploadVideo`,
|
|
76
|
+
defaultMessage: 'Upload Video',
|
|
77
|
+
},
|
|
78
|
+
reUpload: {
|
|
79
|
+
id: `${scope}.reUpload`,
|
|
80
|
+
defaultMessage: 'Re-upload',
|
|
81
|
+
},
|
|
82
|
+
videoDuration: {
|
|
83
|
+
id: `${scope}.videoDuration`,
|
|
84
|
+
defaultMessage: 'Duration: {duration}',
|
|
85
|
+
},
|
|
70
86
|
});
|
|
@@ -1,11 +1,11 @@
|
|
|
1
|
-
import React
|
|
2
|
-
import { Carousel
|
|
1
|
+
import React from "react";
|
|
2
|
+
import { Carousel } from 'antd';
|
|
3
3
|
import './style.scss';
|
|
4
4
|
import CapImage from '@capillarytech/cap-ui-library/CapImage';
|
|
5
5
|
import CapButton from '@capillarytech/cap-ui-library/CapButton';
|
|
6
6
|
import CapIcon from '@capillarytech/cap-ui-library/CapIcon';
|
|
7
|
+
import { CAP_WHITE } from '@capillarytech/cap-ui-library/styled/variables';
|
|
7
8
|
const lineImgPlaceholder = require('../../assets/line-image-placeholder.svg');
|
|
8
|
-
import { CAP_WHITE, CAP_G08 } from '@capillarytech/cap-ui-library/styled/variables';
|
|
9
9
|
|
|
10
10
|
const arrowStyle = {
|
|
11
11
|
background: 'rgba(0, 0, 0, 0.1)',
|
|
@@ -16,10 +16,12 @@ const arrowStyle = {
|
|
|
16
16
|
height: 24,
|
|
17
17
|
width: 24,
|
|
18
18
|
borderRadius: '50%',
|
|
19
|
-
}
|
|
19
|
+
};
|
|
20
20
|
|
|
21
|
-
const Arrow = props => {
|
|
22
|
-
const {
|
|
21
|
+
const Arrow = (props) => {
|
|
22
|
+
const {
|
|
23
|
+
className, style, onClick, extraStyle, type,
|
|
24
|
+
} = props;
|
|
23
25
|
return (
|
|
24
26
|
<CapButton
|
|
25
27
|
className={className}
|
|
@@ -35,8 +37,8 @@ const Arrow = props => {
|
|
|
35
37
|
type={type}
|
|
36
38
|
/>
|
|
37
39
|
</CapButton>
|
|
38
|
-
)
|
|
39
|
-
}
|
|
40
|
+
);
|
|
41
|
+
};
|
|
40
42
|
|
|
41
43
|
const settings = {
|
|
42
44
|
nextArrow: (
|
|
@@ -56,7 +58,7 @@ const settings = {
|
|
|
56
58
|
type="chevron-left"
|
|
57
59
|
/>
|
|
58
60
|
),
|
|
59
|
-
}
|
|
61
|
+
};
|
|
60
62
|
|
|
61
63
|
const CarouselComponent = ({
|
|
62
64
|
imageCarousel,
|
|
@@ -81,11 +83,11 @@ const CarouselComponent = ({
|
|
|
81
83
|
|
|
82
84
|
return (
|
|
83
85
|
<div style={{ position: 'relative' }} className={`template-carousel ${imageCarouselLength ? 'single-img' : ''}`}>
|
|
84
|
-
<Carousel ref={node => (carousel = node)} {...prop} {...settings}>
|
|
86
|
+
<Carousel ref={(node) => (carousel = node)} {...prop} {...settings}>
|
|
85
87
|
{
|
|
86
88
|
imageCarousel.map(({
|
|
87
89
|
actionLabel,
|
|
88
|
-
imageUrl = lineImgPlaceholder
|
|
90
|
+
imageUrl = lineImgPlaceholder,
|
|
89
91
|
}) => (
|
|
90
92
|
<div className="carousel-section">
|
|
91
93
|
<CapImage
|
|
@@ -115,6 +117,6 @@ const CarouselComponent = ({
|
|
|
115
117
|
</Carousel>
|
|
116
118
|
</div>
|
|
117
119
|
);
|
|
118
|
-
}
|
|
120
|
+
};
|
|
119
121
|
|
|
120
|
-
export default CarouselComponent;
|
|
122
|
+
export default CarouselComponent;
|
|
@@ -15,6 +15,7 @@ import { MOBILE_PUSH } from '../../v2Containers/CreativesContainer/constants';
|
|
|
15
15
|
import { INAPP } from '../../v2Containers/App/constants';
|
|
16
16
|
import { ANDROID, IOS } from '../../v2Containers/InApp/constants';
|
|
17
17
|
import { getCtaObject } from '../../v2Containers/InApp/utils';
|
|
18
|
+
import { VIDEO } from '../../v2Containers/MobilePushNew/constants';
|
|
18
19
|
|
|
19
20
|
class MobilePushPreviewV2 extends React.Component { // eslint-disable-line react/prefer-stateless-function
|
|
20
21
|
constructor(props) {
|
|
@@ -64,14 +65,40 @@ class MobilePushPreviewV2 extends React.Component { // eslint-disable-line react
|
|
|
64
65
|
const androidContent = get(templateData, 'versions.base.ANDROID') || get(templateData, 'androidContent');
|
|
65
66
|
const iosContent = get(templateData, 'versions.base.IOS') || get(templateData, 'iosContent');
|
|
66
67
|
|
|
67
|
-
const data = device === "android" ? androidContent : iosContent;
|
|
68
|
-
const { title = '', message = '', expandableDetails: { ctas = [], image = '' } = {}} = data || {};
|
|
68
|
+
const data = device?.toLowerCase() === "android" ? androidContent : iosContent;
|
|
69
|
+
const { title = '', message = '', expandableDetails: { ctas = [], image = '', media = [], carouselData = [] } = {}} = data || {};
|
|
70
|
+
|
|
71
|
+
// Handle video/GIF content from expandableDetails.media array (new format)
|
|
72
|
+
let bodyVideo = {};
|
|
73
|
+
let bodyGif = '';
|
|
74
|
+
let bodyImage = image;
|
|
75
|
+
|
|
76
|
+
if (media && Array.isArray(media) && media.length > 0) {
|
|
77
|
+
const mediaItem = media[0];
|
|
78
|
+
if (mediaItem.type === VIDEO) {
|
|
79
|
+
// Distinguish between actual video and GIF based on URL extension
|
|
80
|
+
if (mediaItem.url && mediaItem.url.toLowerCase().includes('.gif')) {
|
|
81
|
+
bodyGif = mediaItem.url;
|
|
82
|
+
} else {
|
|
83
|
+
bodyVideo = {
|
|
84
|
+
videoSrc: mediaItem.url,
|
|
85
|
+
videoPreview: mediaItem.url,
|
|
86
|
+
};
|
|
87
|
+
}
|
|
88
|
+
// Clear bodyImage when we have video/GIF content
|
|
89
|
+
bodyImage = '';
|
|
90
|
+
}
|
|
91
|
+
}
|
|
92
|
+
|
|
69
93
|
content = {
|
|
70
94
|
header: title,
|
|
71
95
|
bodyText: message,
|
|
72
|
-
bodyImage
|
|
96
|
+
bodyImage,
|
|
97
|
+
bodyVideo,
|
|
98
|
+
bodyGif,
|
|
73
99
|
actions: [],
|
|
74
100
|
appName: templateData?.appName,
|
|
101
|
+
carouselData,
|
|
75
102
|
};
|
|
76
103
|
if (ctas && ctas?.length) {
|
|
77
104
|
if (device === "android" ) {
|
|
@@ -83,6 +110,7 @@ class MobilePushPreviewV2 extends React.Component { // eslint-disable-line react
|
|
|
83
110
|
}
|
|
84
111
|
return content;
|
|
85
112
|
}
|
|
113
|
+
|
|
86
114
|
getPreview(device) {
|
|
87
115
|
const deviceParam = device === ANDROID.toLowerCase() ? ANDROID : IOS;
|
|
88
116
|
return (
|
|
@@ -95,17 +123,21 @@ class MobilePushPreviewV2 extends React.Component { // eslint-disable-line react
|
|
|
95
123
|
/>
|
|
96
124
|
);
|
|
97
125
|
}
|
|
126
|
+
|
|
98
127
|
goToDuplicate() {
|
|
99
128
|
this.props.onDuplicateClick(this.props.templateData);
|
|
100
129
|
this.props.handleClose();
|
|
101
130
|
}
|
|
131
|
+
|
|
102
132
|
changeDevice(device) {
|
|
103
133
|
const content = this.setContent(this.props.templateData, device, this.props.channel);
|
|
104
134
|
this.setState({device, content });
|
|
105
135
|
}
|
|
136
|
+
|
|
106
137
|
goToEdit(e, path) {
|
|
107
138
|
this.props.onEditClick(e, this.props.templateData._id, this.props.templateData.modeType, path);
|
|
108
139
|
}
|
|
140
|
+
|
|
109
141
|
render() {
|
|
110
142
|
const {templateData} = this.props;
|
|
111
143
|
let hasAndroid;
|
|
@@ -121,8 +153,8 @@ class MobilePushPreviewV2 extends React.Component { // eslint-disable-line react
|
|
|
121
153
|
return (
|
|
122
154
|
<div>
|
|
123
155
|
<div className="devices">
|
|
124
|
-
{!isEmpty(templateData)
|
|
125
|
-
( hasBothAndroidAndIos ? (
|
|
156
|
+
{!isEmpty(templateData)
|
|
157
|
+
&& ( hasBothAndroidAndIos ? (
|
|
126
158
|
<CapTab
|
|
127
159
|
panes={[
|
|
128
160
|
{
|