@capillarytech/creatives-library 8.0.130 → 8.0.131
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/containers/Login/index.js +1 -2
- package/package.json +1 -1
- package/services/api.js +5 -0
- 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/createMobilePushPayload.js +322 -0
- package/utils/tests/createMobilePushPayload.test.js +1054 -0
- package/v2Components/CapDeviceContent/index.js +1 -1
- package/v2Components/CapImageUpload/index.js +57 -44
- package/v2Components/CapInAppCTA/index.js +1 -0
- package/v2Components/CapMpushCTA/constants.js +25 -0
- package/v2Components/CapMpushCTA/index.js +403 -0
- package/v2Components/CapMpushCTA/index.scss +95 -0
- package/v2Components/CapMpushCTA/messages.js +101 -0
- package/v2Components/CapTagList/index.js +178 -121
- package/v2Components/CapVideoUpload/constants.js +3 -0
- package/v2Components/CapVideoUpload/index.js +182 -115
- 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 +57 -12
- package/v2Components/TemplatePreview/_templatePreview.scss +218 -74
- 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 +234 -107
- package/v2Components/TemplatePreview/messages.js +4 -0
- package/v2Components/TemplatePreview/tests/__snapshots__/index.test.js.snap +10 -10
- package/v2Containers/CreativesContainer/SlideBoxContent.js +127 -62
- package/v2Containers/CreativesContainer/index.js +193 -136
- package/v2Containers/CreativesContainer/tests/__snapshots__/SlideBoxContent.test.js.snap +0 -22
- package/v2Containers/InApp/constants.js +1 -0
- package/v2Containers/InApp/index.js +13 -13
- package/v2Containers/Line/Container/tests/__snapshots__/index.test.js.snap +4748 -4658
- package/v2Containers/Login/index.js +1 -2
- package/v2Containers/MobilePush/Create/index.js +1 -0
- package/v2Containers/MobilePush/commonMethods.js +7 -14
- package/v2Containers/MobilePush/tests/commonMethods.test.js +401 -0
- package/v2Containers/MobilePushNew/actions.js +116 -0
- package/v2Containers/MobilePushNew/components/CtaButtons.js +183 -0
- package/v2Containers/MobilePushNew/components/MediaUploaders.js +835 -0
- package/v2Containers/MobilePushNew/components/PlatformContentFields.js +346 -0
- package/v2Containers/MobilePushNew/components/index.js +5 -0
- package/v2Containers/MobilePushNew/components/tests/CtaButtons.test.js +565 -0
- package/v2Containers/MobilePushNew/components/tests/MediaUploaders.test.js +3180 -0
- package/v2Containers/MobilePushNew/components/tests/PlatformContentFields.test.js +654 -0
- package/v2Containers/MobilePushNew/constants.js +116 -0
- package/v2Containers/MobilePushNew/hooks/tests/usePlatformSync.test.js +1462 -0
- package/v2Containers/MobilePushNew/hooks/tests/useUpload.test.js +1459 -0
- package/v2Containers/MobilePushNew/hooks/usePlatformSync.js +366 -0
- package/v2Containers/MobilePushNew/hooks/useUpload.js +740 -0
- package/v2Containers/MobilePushNew/index.js +2158 -0
- package/v2Containers/MobilePushNew/index.scss +308 -0
- package/v2Containers/MobilePushNew/messages.js +272 -0
- package/v2Containers/MobilePushNew/reducer.js +160 -0
- package/v2Containers/MobilePushNew/sagas.js +193 -0
- package/v2Containers/MobilePushNew/selectors.js +55 -0
- package/v2Containers/MobilePushNew/tests/reducer.test.js +741 -0
- package/v2Containers/MobilePushNew/tests/sagas.test.js +864 -0
- package/v2Containers/MobilePushNew/tests/selectors.test.js +665 -0
- package/v2Containers/MobilePushNew/tests/utils.test.js +421 -0
- package/v2Containers/MobilePushNew/utils.js +84 -0
- package/v2Containers/Rcs/tests/__snapshots__/index.test.js.snap +1176 -976
- package/v2Containers/SmsTrai/Edit/tests/__snapshots__/index.test.js.snap +684 -424
- package/v2Containers/TagList/index.js +56 -10
- package/v2Containers/Templates/_templates.scss +100 -1
- package/v2Containers/Templates/index.js +170 -31
- package/v2Containers/Templates/messages.js +8 -0
- package/v2Containers/Templates/sagas.js +1 -0
- package/v2Containers/Whatsapp/constants.js +1 -0
- package/v2Containers/Whatsapp/tests/__snapshots__/index.test.js.snap +3992 -3677
- package/assets/loading_img.gif +0 -0
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import React from 'react';
|
|
2
2
|
import PropTypes from 'prop-types';
|
|
3
|
-
import
|
|
3
|
+
import { CAP_SPACE_32, CAP_SPACE_56, CAP_SPACE_64 } from '@capillarytech/cap-ui-library/styled/variables';
|
|
4
|
+
|
|
4
5
|
import CapSlideBox from '@capillarytech/cap-ui-library/CapSlideBox';
|
|
5
6
|
import CapHeader from '@capillarytech/cap-ui-library/CapHeader';
|
|
6
7
|
import CapRow from '@capillarytech/cap-ui-library/CapRow';
|
|
@@ -14,18 +15,18 @@ import {
|
|
|
14
15
|
} from 'lodash';
|
|
15
16
|
import { connect } from 'react-redux';
|
|
16
17
|
import { createStructuredSelector } from 'reselect';
|
|
17
|
-
import { bindActionCreators } from 'redux';
|
|
18
|
+
import { bindActionCreators, compose } from 'redux';
|
|
18
19
|
import styled from 'styled-components';
|
|
19
20
|
import { GA } from '@capillarytech/cap-ui-utils';
|
|
21
|
+
import { DAEMON } from '@capillarytech/vulcan-react-sdk/utils/sagaInjectorTypes';
|
|
20
22
|
|
|
21
23
|
import * as actions from './actions';
|
|
22
24
|
import {
|
|
23
25
|
selectEmailLayout, uploadSelector, templateUserList, makeSelectTemplates,
|
|
24
26
|
} from '../Templates/selectors';
|
|
25
|
-
import SlideBoxContent from './SlideBoxContent';
|
|
26
27
|
import SlideBoxHeader from './SlideBoxHeader';
|
|
27
28
|
import SlideBoxFooter from './SlideBoxFooter';
|
|
28
|
-
import
|
|
29
|
+
import SlideBoxContent from './SlideBoxContent';
|
|
29
30
|
import * as constants from './constants';
|
|
30
31
|
import * as commonUtil from '../../utils/common';
|
|
31
32
|
import { gtmPush } from '../../utils/gtmTrackers';
|
|
@@ -44,20 +45,16 @@ import {
|
|
|
44
45
|
import { IMAGE, VIDEO } from '../Facebook/Advertisement/constant';
|
|
45
46
|
import { CREATIVE } from '../Facebook/constants';
|
|
46
47
|
import { LOYALTY } from '../App/constants';
|
|
47
|
-
import {
|
|
48
|
-
|
|
48
|
+
import {
|
|
49
|
+
WHATSAPP_STATUSES, WHATSAPP_MEDIA_TYPES, PHONE_NUMBER, URL,
|
|
50
|
+
} from '../Whatsapp/constants';
|
|
49
51
|
import { updateImagesInHtml } from '../../utils/cdnTransformation';
|
|
50
|
-
|
|
52
|
+
|
|
51
53
|
import injectReducer from '../../utils/injectReducer';
|
|
52
54
|
import injectSaga from '../../utils/injectSaga';
|
|
53
55
|
import creativesContainerReducer from './reducer';
|
|
54
|
-
import {
|
|
55
|
-
import { capSagaForFetchSchemaForEntity,capSagaLiquidEntity } from '../Cap/sagas';
|
|
56
|
+
import { capSagaForFetchSchemaForEntity, capSagaLiquidEntity } from '../Cap/sagas';
|
|
56
57
|
import { v2TemplateSagaWatchGetDefaultBeeTemplates } from '../Templates/sagas';
|
|
57
|
-
import {
|
|
58
|
-
CAP_SPACE_32, CAP_SPACE_56, CAP_SPACE_64,
|
|
59
|
-
} from '@capillarytech/cap-ui-library/styled/variables';
|
|
60
|
-
import { DAEMON } from '@capillarytech/vulcan-react-sdk/utils/sagaInjectorTypes';
|
|
61
58
|
import { DYNAMIC_URL } from '../../v2Components/CapWhatsappCTA/constants';
|
|
62
59
|
import ErrorInfoNote from '../../v2Components/ErrorInfoNote';
|
|
63
60
|
|
|
@@ -65,6 +62,7 @@ import {
|
|
|
65
62
|
transformChannelPayload,
|
|
66
63
|
// getTemplateDiffState
|
|
67
64
|
} from "../../utils/transformerUtils";
|
|
65
|
+
import { MANUAL_CAROUSEL } from '../MobilePushNew/constants';
|
|
68
66
|
|
|
69
67
|
const classPrefix = 'add-creatives-section';
|
|
70
68
|
const CREATIVES_CONTAINER = 'creativesContainer';
|
|
@@ -83,11 +81,14 @@ const SlideBoxWrapper = styled.div`
|
|
|
83
81
|
export class Creatives extends React.Component {
|
|
84
82
|
constructor(props) {
|
|
85
83
|
super(props);
|
|
84
|
+
|
|
85
|
+
const initialSlidBoxContent = this.getSlideBoxContent({ mode: props.creativesMode, templateData: props.templateData, isFullMode: props.isFullMode });
|
|
86
|
+
|
|
86
87
|
this.state = {
|
|
87
88
|
isLoadingContent: true,
|
|
88
89
|
templateStep: 1, //modeSelection: for template name and (for email selecting upload or editor), and createTemplate to create template create based on modeSelection
|
|
89
90
|
showSlideBox: true,
|
|
90
|
-
slidBoxContent:
|
|
91
|
+
slidBoxContent: initialSlidBoxContent,
|
|
91
92
|
templateData: this.getTemplateData(props.templateData),
|
|
92
93
|
templateNameExists: props.creativesMode === 'edit', // if edit mode templateNameExists will be true, and false in create flow.
|
|
93
94
|
currentChannel: this.props.channel || 'sms',
|
|
@@ -154,28 +155,26 @@ export class Creatives extends React.Component {
|
|
|
154
155
|
const userId = parseInt(template.updatedBy, 10);
|
|
155
156
|
templateData.updatedByName = commonUtil.getUserNameById(userId, usersList);
|
|
156
157
|
this.setState({ slidBoxContent: constants.PREVIEW, templateData });
|
|
158
|
+
} else if (get(template, 'versions.base.content.zalo.previewUrl')) {
|
|
159
|
+
commonUtil.handlePreviewInNewTab(
|
|
160
|
+
template.versions.base.content.zalo.previewUrl
|
|
161
|
+
);
|
|
157
162
|
} else {
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
host: hostName || this.props?.hostName || this.props.Templates?.senderDetails?.hostName,
|
|
174
|
-
id: template?._id,
|
|
175
|
-
preview: true,
|
|
176
|
-
actionCallback: this.actionCallback,
|
|
177
|
-
});
|
|
178
|
-
}
|
|
163
|
+
const {
|
|
164
|
+
name = "",
|
|
165
|
+
sourceAccountIdentifier = "",
|
|
166
|
+
configs: { token = "" } = {},
|
|
167
|
+
hostName = "",
|
|
168
|
+
} = get(this.props, "Templates.selectedZaloAccount", {});
|
|
169
|
+
this.props.zaloActions.getTemplateInfoById({
|
|
170
|
+
username: name,
|
|
171
|
+
oa_id: sourceAccountIdentifier,
|
|
172
|
+
token,
|
|
173
|
+
host: hostName || this.props?.hostName || this.props.Templates?.senderDetails?.hostName,
|
|
174
|
+
id: template?._id,
|
|
175
|
+
preview: true,
|
|
176
|
+
actionCallback: this.actionCallback,
|
|
177
|
+
});
|
|
179
178
|
}
|
|
180
179
|
};
|
|
181
180
|
|
|
@@ -244,38 +243,41 @@ export class Creatives extends React.Component {
|
|
|
244
243
|
this.setState({ isGetFormData: false });
|
|
245
244
|
};
|
|
246
245
|
|
|
247
|
-
mapCarouselDataToCreatives = (cards) => {
|
|
248
|
-
|
|
249
|
-
|
|
250
|
-
|
|
251
|
-
|
|
252
|
-
|
|
253
|
-
|
|
254
|
-
|
|
255
|
-
|
|
256
|
-
|
|
257
|
-
|
|
258
|
-
|
|
259
|
-
|
|
260
|
-
|
|
246
|
+
mapCarouselDataToCreatives = (cards) => cards.map((card) => {
|
|
247
|
+
const {
|
|
248
|
+
cardVarMapped, bodyTemplate, media, buttons, mediaType,
|
|
249
|
+
} = card || {};
|
|
250
|
+
const buttonData = buttons?.map((button) => {
|
|
251
|
+
const {
|
|
252
|
+
type, text, phoneNumber, url, dynamicUrlPayload,
|
|
253
|
+
} = button || {};
|
|
254
|
+
const buttonObj = { type, text };
|
|
255
|
+
if (type === PHONE_NUMBER) {
|
|
256
|
+
buttonObj.phone_number = phoneNumber;
|
|
257
|
+
}
|
|
258
|
+
if (type === URL) {
|
|
259
|
+
buttonObj.url = url;
|
|
260
|
+
if (dynamicUrlPayload) {
|
|
261
|
+
buttonObj.urlType = DYNAMIC_URL;
|
|
261
262
|
}
|
|
262
|
-
|
|
263
|
-
|
|
264
|
-
return {
|
|
265
|
-
bodyText: bodyTemplate,
|
|
266
|
-
varMap: cardVarMapped,
|
|
267
|
-
...(mediaType === IMAGE && {
|
|
268
|
-
imageUrl: media?.url,
|
|
269
|
-
}),
|
|
270
|
-
...(mediaType === VIDEO && {
|
|
271
|
-
videoUrl: media?.url,
|
|
272
|
-
videoPreviewImg: media?.previewUrl,
|
|
273
|
-
}),
|
|
274
|
-
buttons: buttonData,
|
|
275
|
-
mediaType: mediaType?.toLowerCase(),
|
|
276
|
-
};
|
|
263
|
+
}
|
|
264
|
+
return buttonObj;
|
|
277
265
|
});
|
|
278
|
-
|
|
266
|
+
const {url, previewUrl} = media || {};
|
|
267
|
+
return {
|
|
268
|
+
bodyText: bodyTemplate,
|
|
269
|
+
varMap: cardVarMapped,
|
|
270
|
+
...(mediaType === IMAGE && {
|
|
271
|
+
imageUrl: url,
|
|
272
|
+
}),
|
|
273
|
+
...(mediaType === VIDEO && {
|
|
274
|
+
videoUrl: url,
|
|
275
|
+
videoPreviewImg: previewUrl,
|
|
276
|
+
}),
|
|
277
|
+
buttons: buttonData,
|
|
278
|
+
mediaType: mediaType?.toLowerCase(),
|
|
279
|
+
};
|
|
280
|
+
})
|
|
279
281
|
|
|
280
282
|
getTemplateData = (templateData) => { //from consumers to creatives
|
|
281
283
|
const { isFullMode, messageDetails = {}, smsRegister } = this.props;
|
|
@@ -355,13 +357,33 @@ export class Creatives extends React.Component {
|
|
|
355
357
|
}
|
|
356
358
|
case constants.MOBILE_PUSH: {
|
|
357
359
|
const mode = get(templateData, 'androidContent.type') || get(templateData, 'iosContent.type') || '';
|
|
360
|
+
const androidCarouselMedia = get(templateData, 'androidContent.expandableDetails.media', []);
|
|
361
|
+
const iosCarouselMedia = get(templateData, 'iosContent.expandableDetails.media', []);
|
|
362
|
+
const androidContent = { ...(templateData?.androidContent || {}) };
|
|
363
|
+
const iosContent = { ...(templateData?.iosContent || {}) };
|
|
364
|
+
if (androidCarouselMedia?.length) {
|
|
365
|
+
androidContent.expandableDetails.carouselData = androidCarouselMedia.map((media) => ({
|
|
366
|
+
mediaType: media.type,
|
|
367
|
+
imageUrl: media.url,
|
|
368
|
+
buttons: [],
|
|
369
|
+
videoSrc: '',
|
|
370
|
+
}));
|
|
371
|
+
}
|
|
372
|
+
if (iosCarouselMedia?.length) {
|
|
373
|
+
iosContent.expandableDetails.carouselData = iosCarouselMedia.map((media) => ({
|
|
374
|
+
mediaType: media.type,
|
|
375
|
+
imageUrl: media.url,
|
|
376
|
+
buttons: [],
|
|
377
|
+
videoSrc: '',
|
|
378
|
+
}));
|
|
379
|
+
}
|
|
358
380
|
creativesTemplateData = {
|
|
359
381
|
type: channel,
|
|
360
382
|
name: templateData.messageSubject,
|
|
361
383
|
versions: {
|
|
362
384
|
base: {
|
|
363
|
-
ANDROID:
|
|
364
|
-
IOS:
|
|
385
|
+
ANDROID: androidContent,
|
|
386
|
+
IOS: iosContent,
|
|
365
387
|
},
|
|
366
388
|
},
|
|
367
389
|
definition: { accountId: templateData.accountId, mode: mode.toLowerCase() },
|
|
@@ -523,7 +545,9 @@ export class Creatives extends React.Component {
|
|
|
523
545
|
} = {},
|
|
524
546
|
} = templateData;
|
|
525
547
|
const mediaParams = {};
|
|
526
|
-
const {
|
|
548
|
+
const {
|
|
549
|
+
url = '', previewUrl = '', docParams = {}, footer = '', headerVarMapped = {}, headerTemplate = '',
|
|
550
|
+
} = whatsappMedia || {};
|
|
527
551
|
switch (mediaType) {
|
|
528
552
|
case (WHATSAPP_MEDIA_TYPES.IMAGE):
|
|
529
553
|
mediaParams.imageUrl = url;
|
|
@@ -543,7 +567,7 @@ export class Creatives extends React.Component {
|
|
|
543
567
|
break;
|
|
544
568
|
}
|
|
545
569
|
const modifiedButtons = cloneDeep(buttons)?.map((btn) => {
|
|
546
|
-
if (btn.type ===
|
|
570
|
+
if (btn.type === PHONE_NUMBER) {
|
|
547
571
|
btn.phone_number = btn.phoneNumber;
|
|
548
572
|
delete btn.phoneNumber;
|
|
549
573
|
return btn;
|
|
@@ -636,46 +660,61 @@ export class Creatives extends React.Component {
|
|
|
636
660
|
return templateData || null;
|
|
637
661
|
}
|
|
638
662
|
|
|
639
|
-
getCarouselMappedData = (carouselData = []) => {
|
|
640
|
-
|
|
641
|
-
|
|
642
|
-
|
|
643
|
-
|
|
644
|
-
|
|
645
|
-
|
|
646
|
-
|
|
647
|
-
|
|
648
|
-
|
|
649
|
-
|
|
650
|
-
|
|
651
|
-
}
|
|
652
|
-
if (type === URL) {
|
|
653
|
-
buttonObj.url = url;
|
|
654
|
-
if (urlType === DYNAMIC_URL) {
|
|
655
|
-
const dynamicUrlPayload = url?.match(/{{(.*?)}}/g);
|
|
656
|
-
buttonObj.dynamicUrlPayload = dynamicUrlPayload?.length === 1 ? dynamicUrlPayload[0] : '';
|
|
657
|
-
}
|
|
658
|
-
}
|
|
659
|
-
return buttonObj;
|
|
660
|
-
});
|
|
661
|
-
return {
|
|
662
|
-
body: bodyText,
|
|
663
|
-
cardVarMapped,
|
|
664
|
-
bodyTemplate,
|
|
665
|
-
media: {
|
|
666
|
-
...(mediaType?.toLowerCase() === IMAGE.toLowerCase() && {
|
|
667
|
-
url: imageUrl,
|
|
668
|
-
}),
|
|
669
|
-
...(mediaType?.toLowerCase() === VIDEO.toLowerCase() && {
|
|
670
|
-
url: videoUrl,
|
|
671
|
-
previewUrl: videoPreviewImg,
|
|
672
|
-
}),
|
|
673
|
-
},
|
|
674
|
-
buttons: buttonData,
|
|
675
|
-
mediaType: mediaType?.toUpperCase(),
|
|
663
|
+
getCarouselMappedData = (carouselData = []) => carouselData.map((carousel) => {
|
|
664
|
+
const {
|
|
665
|
+
bodyText, imageUrl, videoUrl, videoPreviewImg, buttons, mediaType, cardVarMapped, bodyTemplate,
|
|
666
|
+
} = carousel || {};
|
|
667
|
+
const buttonData = buttons.map((button, index) => {
|
|
668
|
+
const {
|
|
669
|
+
type, text, phone_number, urlType, url,
|
|
670
|
+
} = button || {};
|
|
671
|
+
const buttonObj = {
|
|
672
|
+
type,
|
|
673
|
+
text,
|
|
674
|
+
index,
|
|
676
675
|
};
|
|
676
|
+
if (type === PHONE_NUMBER) {
|
|
677
|
+
buttonObj.phoneNumber = phone_number;
|
|
678
|
+
}
|
|
679
|
+
if (type === URL) {
|
|
680
|
+
buttonObj.url = url;
|
|
681
|
+
if (urlType === DYNAMIC_URL) {
|
|
682
|
+
const dynamicUrlPayload = url?.match(/{{(.*?)}}/g);
|
|
683
|
+
buttonObj.dynamicUrlPayload = dynamicUrlPayload?.length === 1 ? dynamicUrlPayload[0] : '';
|
|
684
|
+
}
|
|
685
|
+
}
|
|
686
|
+
return buttonObj;
|
|
677
687
|
});
|
|
678
|
-
|
|
688
|
+
return {
|
|
689
|
+
body: bodyText,
|
|
690
|
+
cardVarMapped,
|
|
691
|
+
bodyTemplate,
|
|
692
|
+
media: {
|
|
693
|
+
...(mediaType?.toLowerCase() === IMAGE.toLowerCase() && {
|
|
694
|
+
url: imageUrl,
|
|
695
|
+
}),
|
|
696
|
+
...(mediaType?.toLowerCase() === VIDEO.toLowerCase() && {
|
|
697
|
+
url: videoUrl,
|
|
698
|
+
previewUrl: videoPreviewImg,
|
|
699
|
+
}),
|
|
700
|
+
},
|
|
701
|
+
buttons: buttonData,
|
|
702
|
+
mediaType: mediaType?.toUpperCase(),
|
|
703
|
+
};
|
|
704
|
+
});
|
|
705
|
+
|
|
706
|
+
getMobilePushCarouselData = (expandableDetails = []) => {
|
|
707
|
+
const newExpandableDetails = {...expandableDetails};
|
|
708
|
+
newExpandableDetails.style = expandableDetails.style || MANUAL_CAROUSEL;
|
|
709
|
+
newExpandableDetails.message = expandableDetails.message || '';
|
|
710
|
+
newExpandableDetails.ctas = expandableDetails.ctas || [];
|
|
711
|
+
newExpandableDetails.media = expandableDetails.carouselData.map((carousel) => ({
|
|
712
|
+
url: carousel.imageUrl,
|
|
713
|
+
type: carousel?.mediaType?.toUpperCase(),
|
|
714
|
+
text: '',
|
|
715
|
+
}));
|
|
716
|
+
return newExpandableDetails;
|
|
717
|
+
}
|
|
679
718
|
|
|
680
719
|
getCreativesData = async (channel, template, templateRecords) => { //from creatives to consumers
|
|
681
720
|
let templateData = { channel };
|
|
@@ -759,6 +798,9 @@ export class Creatives extends React.Component {
|
|
|
759
798
|
if (channel !== constants.MOBILE_PUSH) {
|
|
760
799
|
androidContent.custom = custom;
|
|
761
800
|
}
|
|
801
|
+
if (channel === constants.MOBILE_PUSH && androidContent?.expandableDetails?.carouselData?.length) {
|
|
802
|
+
androidContent.expandableDetails = this.getMobilePushCarouselData({...androidContent?.expandableDetails});
|
|
803
|
+
}
|
|
762
804
|
templateData.androidContent = androidContent;
|
|
763
805
|
templateData.androidContent.type = get(channelTemplate, 'definition.mode', '').toUpperCase();
|
|
764
806
|
templateData.androidContent.deviceType = constants.ANDROID;
|
|
@@ -778,6 +820,9 @@ export class Creatives extends React.Component {
|
|
|
778
820
|
if (channel !== constants.MOBILE_PUSH) {
|
|
779
821
|
iosContent.custom = custom;
|
|
780
822
|
}
|
|
823
|
+
if (channel === constants.MOBILE_PUSH && iosContent?.expandableDetails?.carouselData?.length) {
|
|
824
|
+
iosContent.expandableDetails = this.getMobilePushCarouselData({...iosContent?.expandableDetails});
|
|
825
|
+
}
|
|
781
826
|
templateData.iosContent = iosContent;
|
|
782
827
|
templateData.iosContent.type = get(channelTemplate, 'definition.mode').toUpperCase();
|
|
783
828
|
templateData.iosContent.deviceType = constants.IOS;
|
|
@@ -947,7 +992,7 @@ export class Creatives extends React.Component {
|
|
|
947
992
|
fBContent.forEach((obj) => {
|
|
948
993
|
const data = cloneDeep(obj);
|
|
949
994
|
const {
|
|
950
|
-
subType, linkDesc, imgSrc, webSiteLink, video
|
|
995
|
+
subType, linkDesc, imgSrc, webSiteLink, video,
|
|
951
996
|
} = obj;
|
|
952
997
|
delete data.type;
|
|
953
998
|
delete data.linkDesc;
|
|
@@ -985,7 +1030,7 @@ export class Creatives extends React.Component {
|
|
|
985
1030
|
break;
|
|
986
1031
|
case constants.RCS: {
|
|
987
1032
|
if (template.value) {
|
|
988
|
-
const { name = "", versions = {}
|
|
1033
|
+
const { name = "", versions = {} } = {
|
|
989
1034
|
} = template.value || {};
|
|
990
1035
|
const {
|
|
991
1036
|
cardContent = [],
|
|
@@ -1113,7 +1158,6 @@ export class Creatives extends React.Component {
|
|
|
1113
1158
|
}
|
|
1114
1159
|
|
|
1115
1160
|
getFormData = (template) => {
|
|
1116
|
-
|
|
1117
1161
|
if (template.validity) {
|
|
1118
1162
|
this.setState(
|
|
1119
1163
|
{
|
|
@@ -1131,7 +1175,7 @@ export class Creatives extends React.Component {
|
|
|
1131
1175
|
);
|
|
1132
1176
|
}
|
|
1133
1177
|
}
|
|
1134
|
-
|
|
1178
|
+
|
|
1135
1179
|
processCentralCommsMetaId = (channel, creativesData) => {
|
|
1136
1180
|
// Create the payload for the centralcommnsmetaId API call
|
|
1137
1181
|
const { isLoyaltyModule = false, loyaltyMetaData = {} } = this.props;
|
|
@@ -1222,13 +1266,16 @@ export class Creatives extends React.Component {
|
|
|
1222
1266
|
|
|
1223
1267
|
shouldShowFooter = () => {
|
|
1224
1268
|
const { isFullMode } = this.props;
|
|
1225
|
-
const {
|
|
1269
|
+
const {
|
|
1270
|
+
slidBoxContent, currentChannel, emailCreateMode, templateNameExists, templateStep, mobilePushCreateMode, weChatTemplateType, templateData,
|
|
1271
|
+
} = this.state;
|
|
1226
1272
|
const channel = currentChannel.toUpperCase();
|
|
1227
1273
|
const currentStep = this.creativesTemplateSteps[templateStep];
|
|
1228
1274
|
let showFooter = false;
|
|
1229
1275
|
showFooter = isFullMode && slidBoxContent === "preview";
|
|
1230
1276
|
const isMobilepush = channel === constants.MOBILE_PUSH;
|
|
1231
|
-
|
|
1277
|
+
|
|
1278
|
+
|
|
1232
1279
|
if (!isFullMode) {
|
|
1233
1280
|
const isEmailCreate = slidBoxContent === 'createTemplate' && channel === constants.EMAIL && currentStep !== 'createTemplateContent';
|
|
1234
1281
|
const isCreate = (slidBoxContent === 'editTemplate' || slidBoxContent === 'createTemplate') && !isEmailCreate;
|
|
@@ -1250,15 +1297,15 @@ export class Creatives extends React.Component {
|
|
|
1250
1297
|
if (slidBoxContent === "editTemplate" && ((channel === constants.EMAIL && currentStep === 'modeSelection'))) {
|
|
1251
1298
|
showFooter = true;
|
|
1252
1299
|
}
|
|
1253
|
-
if (channel === constants.MOBILE_PUSH
|
|
1254
|
-
((slidBoxContent === 'createTemplate' && !isEmpty(mobilePushCreateMode))
|
|
1255
|
-
|| (slidBoxContent === 'editTemplate' && currentStep === 'modeSelection')) &&
|
|
1300
|
+
if (channel === constants.MOBILE_PUSH
|
|
1301
|
+
&& ((slidBoxContent === 'createTemplate' && !isEmpty(mobilePushCreateMode))
|
|
1302
|
+
|| (slidBoxContent === 'editTemplate' && (currentStep === 'modeSelection' || isFullMode))) &&
|
|
1256
1303
|
templateNameExists) {
|
|
1257
1304
|
showFooter = true;
|
|
1258
1305
|
}
|
|
1259
1306
|
|
|
1260
|
-
if (channel === constants.WECHAT
|
|
1261
|
-
((slidBoxContent === 'createTemplate' && !isEmpty(weChatTemplateType))
|
|
1307
|
+
if (channel === constants.WECHAT
|
|
1308
|
+
&& ((slidBoxContent === 'createTemplate' && !isEmpty(weChatTemplateType))
|
|
1262
1309
|
|| (slidBoxContent === 'editTemplate' && currentStep === 'modeSelection'))) {
|
|
1263
1310
|
showFooter = true;
|
|
1264
1311
|
}
|
|
@@ -1267,9 +1314,9 @@ export class Creatives extends React.Component {
|
|
|
1267
1314
|
if (slidBoxContent === "createTemplate" && ((channel === constants.EMAIL && currentStep === 'createTemplateContent') ||
|
|
1268
1315
|
([constants.SMS, constants.WECHAT].includes(channel) && currentStep === 'modeSelection'))) {
|
|
1269
1316
|
showFooter = showFooter && !this.state.isLoadingContent;
|
|
1270
|
-
} else if (slidBoxContent === "editTemplate"
|
|
1271
|
-
([constants.SMS, constants.WECHAT, constants.EMAIL].includes(channel)
|
|
1272
|
-
currentStep === 'modeSelection')) {
|
|
1317
|
+
} else if (slidBoxContent === "editTemplate"
|
|
1318
|
+
&& ([constants.SMS, constants.WECHAT, constants.EMAIL].includes(channel)
|
|
1319
|
+
&& currentStep === 'modeSelection')) {
|
|
1273
1320
|
showFooter = showFooter && !this.state.isLoadingContent;
|
|
1274
1321
|
}
|
|
1275
1322
|
}
|
|
@@ -1278,6 +1325,8 @@ export class Creatives extends React.Component {
|
|
|
1278
1325
|
if ([constants.LINE, constants.VIBER, constants.FACEBOOK].includes(channel) || isLineViberChannel) {
|
|
1279
1326
|
showFooter = false;
|
|
1280
1327
|
}
|
|
1328
|
+
|
|
1329
|
+
|
|
1281
1330
|
return showFooter;
|
|
1282
1331
|
}
|
|
1283
1332
|
|
|
@@ -1290,13 +1339,21 @@ export class Creatives extends React.Component {
|
|
|
1290
1339
|
let showDone = false;
|
|
1291
1340
|
const channelName = !isFullMode && templateData ? templateData.type : currentChannel;
|
|
1292
1341
|
const channel = channelName?.toUpperCase();
|
|
1342
|
+
|
|
1343
|
+
|
|
1293
1344
|
if (channel === constants.EMAIL || channel === constants.SMS) {
|
|
1294
1345
|
const isEmailCreate = slidBoxContent === 'createTemplate' && channel === constants.EMAIL && currentStep !== 'createTemplateContent';
|
|
1295
1346
|
showDone = (slidBoxContent === 'editTemplate' || slidBoxContent === 'createTemplate') && !isEmailCreate;
|
|
1296
1347
|
} else if ([constants.WECHAT, constants.MOBILE_PUSH].includes(channel)) {
|
|
1297
1348
|
showDone = currentStep === "createTemplateContent" || slidBoxContent === "editTemplate";
|
|
1349
|
+
|
|
1350
|
+
// Additional condition for MobilePush edit in full mode
|
|
1351
|
+
if (channel === constants.MOBILE_PUSH && slidBoxContent === "editTemplate" && isFullMode) {
|
|
1352
|
+
showDone = true;
|
|
1353
|
+
}
|
|
1298
1354
|
}
|
|
1299
1355
|
|
|
1356
|
+
|
|
1300
1357
|
return showDone;
|
|
1301
1358
|
}
|
|
1302
1359
|
|
|
@@ -1356,7 +1413,9 @@ export class Creatives extends React.Component {
|
|
|
1356
1413
|
}
|
|
1357
1414
|
|
|
1358
1415
|
shouldShowContinueFooter = () => { // only for email for now, has to be modified according to channel
|
|
1359
|
-
const {
|
|
1416
|
+
const {
|
|
1417
|
+
slidBoxContent, templateStep, currentChannel, emailCreateMode, mobilePushCreateMode, inAppCreateMode, weChatTemplateType,
|
|
1418
|
+
} = this.state;
|
|
1360
1419
|
let isShowContinueFooter = false;
|
|
1361
1420
|
const currentStep = this.creativesTemplateSteps[templateStep];
|
|
1362
1421
|
const channel = currentChannel.toUpperCase();
|
|
@@ -1439,17 +1498,16 @@ export class Creatives extends React.Component {
|
|
|
1439
1498
|
loyaltyMetaData = {},
|
|
1440
1499
|
} = this.props;
|
|
1441
1500
|
const mapTemplateCreate =
|
|
1442
|
-
slidBoxContent === "createTemplate"
|
|
1443
|
-
weChatTemplateType === MAP_TEMPLATE
|
|
1444
|
-
templateStep !== "modeSelection";
|
|
1445
|
-
const slideBoxWrapperMargin =
|
|
1446
|
-
|
|
1447
|
-
|
|
1448
|
-
|
|
1449
|
-
|
|
1450
|
-
|
|
1451
|
-
|
|
1452
|
-
: 0;
|
|
1501
|
+
slidBoxContent === "createTemplate"
|
|
1502
|
+
&& weChatTemplateType === MAP_TEMPLATE
|
|
1503
|
+
&& templateStep !== "modeSelection";
|
|
1504
|
+
const slideBoxWrapperMargin = (get(liquidErrorMessage, 'STANDARD_ERROR_MSG.length', 0) > 0 && get(liquidErrorMessage, 'LIQUID_ERROR_MSG.length', 0) > 0)
|
|
1505
|
+
? CAP_SPACE_64
|
|
1506
|
+
: get(liquidErrorMessage, 'LIQUID_ERROR_MSG.length', 0) > 0
|
|
1507
|
+
? CAP_SPACE_56
|
|
1508
|
+
: get(liquidErrorMessage, 'STANDARD_ERROR_MSG.length', 0) > 0
|
|
1509
|
+
? CAP_SPACE_32
|
|
1510
|
+
: 0;
|
|
1453
1511
|
/* TODO: Instead of passing down same props separately to each component down, write common function to these props and pass it accordingly */
|
|
1454
1512
|
return (
|
|
1455
1513
|
<SlideBoxWrapper slideBoxWrapperMargin={slideBoxWrapperMargin} className={classnames(`${classPrefix} ${isFullMode ? 'creatives-full-mode' : 'creatives-library-mode'} ${mapTemplateCreate ? 'map-template-create' : ''}`)}>
|
|
@@ -1577,7 +1635,6 @@ export class Creatives extends React.Component {
|
|
|
1577
1635
|
) : isLiquidValidationError && (
|
|
1578
1636
|
<CapRow className="template-footer-width">
|
|
1579
1637
|
{(() => {
|
|
1580
|
-
|
|
1581
1638
|
const errorsToShow = get(liquidErrorMessage, constants.LIQUID_ERROR_MSG, []);
|
|
1582
1639
|
const standardErrorsToShow = get(liquidErrorMessage, constants.STANDARD_ERROR_MSG, []);
|
|
1583
1640
|
return <ErrorInfoNote currentTab={activeFormBuilderTab?.toUpperCase()} errorMessages={{LIQUID_ERROR_MSG: errorsToShow, STANDARD_ERROR_MSG: standardErrorsToShow}} />;
|
|
@@ -1647,7 +1704,7 @@ function mapDispatchToProps(dispatch) {
|
|
|
1647
1704
|
const withConnect = connect(mapStatesToProps, mapDispatchToProps);
|
|
1648
1705
|
const withReducer = injectReducer({ key: 'creativesContainer', reducer: creativesContainerReducer });
|
|
1649
1706
|
const withSaga = injectSaga({ key: 'cap', saga: capSagaForFetchSchemaForEntity });
|
|
1650
|
-
const withLiquidSaga = injectSaga({ key: 'liquid', saga: capSagaLiquidEntity
|
|
1707
|
+
const withLiquidSaga = injectSaga({ key: 'liquid', saga: capSagaLiquidEntity, mode: DAEMON });
|
|
1651
1708
|
const withDefaultTempSaga = injectSaga({ key: 'creativesContainer', saga: v2TemplateSagaWatchGetDefaultBeeTemplates });
|
|
1652
1709
|
|
|
1653
|
-
export default compose(withSaga,withLiquidSaga, withDefaultTempSaga, withReducer, withConnect)(injectIntl(Creatives));
|
|
1710
|
+
export default compose(withSaga, withLiquidSaga, withDefaultTempSaga, withReducer, withConnect)(injectIntl(Creatives));
|
|
@@ -640,17 +640,6 @@ exports[`Test SlideBoxContent container Should render correct component for rcs
|
|
|
640
640
|
<Connect(UserIsAuthenticated(Connect(InjectIntl(withStyles__StyledComponent))))
|
|
641
641
|
FTPMode="create"
|
|
642
642
|
channel="rcs"
|
|
643
|
-
location={
|
|
644
|
-
Object {
|
|
645
|
-
"pathname": "/sms/edit",
|
|
646
|
-
"query": Object {
|
|
647
|
-
"isEditFromCampaigns": undefined,
|
|
648
|
-
"module": "library",
|
|
649
|
-
"type": "embedded",
|
|
650
|
-
},
|
|
651
|
-
"search": "",
|
|
652
|
-
}
|
|
653
|
-
}
|
|
654
643
|
loyaltyMetaData={Object {}}
|
|
655
644
|
messageDetails={Object {}}
|
|
656
645
|
onCreateComplete={[MockFunction]}
|
|
@@ -1032,17 +1021,6 @@ exports[`Test SlideBoxContent container Should render correct component for what
|
|
|
1032
1021
|
<Connect(UserIsAuthenticated(Connect(InjectIntl(withStyles__StyledComponent))))
|
|
1033
1022
|
FTPMode="create"
|
|
1034
1023
|
channel="whatsapp"
|
|
1035
|
-
location={
|
|
1036
|
-
Object {
|
|
1037
|
-
"pathname": "/sms/edit",
|
|
1038
|
-
"query": Object {
|
|
1039
|
-
"isEditFromCampaigns": undefined,
|
|
1040
|
-
"module": "library",
|
|
1041
|
-
"type": "embedded",
|
|
1042
|
-
},
|
|
1043
|
-
"search": "",
|
|
1044
|
-
}
|
|
1045
|
-
}
|
|
1046
1024
|
loyaltyMetaData={Object {}}
|
|
1047
1025
|
messageDetails={Object {}}
|
|
1048
1026
|
onCreateComplete={[MockFunction]}
|
|
@@ -46,10 +46,12 @@ import {
|
|
|
46
46
|
INITIAL_CTA_DATA,
|
|
47
47
|
IOS,
|
|
48
48
|
LAYOUT_RADIO_OPTIONS,
|
|
49
|
-
AI_CONTENT_BOT_DISABLED
|
|
49
|
+
AI_CONTENT_BOT_DISABLED,
|
|
50
50
|
} from "./constants";
|
|
51
51
|
import { INAPP, SMS } from "../CreativesContainer/constants";
|
|
52
|
-
import {
|
|
52
|
+
import {
|
|
53
|
+
ALL, TAG, EMBEDDED, DEFAULT, FULL, LIBRARY,
|
|
54
|
+
} from "../Whatsapp/constants";
|
|
53
55
|
import CapDeviceContent from "../../v2Components/CapDeviceContent";
|
|
54
56
|
import { getCdnUrl } from "../../utils/cdnTransformation";
|
|
55
57
|
import { getCtaObject, hasAnyErrors, getSingleTab } from "./utils";
|
|
@@ -297,14 +299,13 @@ export const InApp = (props) => {
|
|
|
297
299
|
|
|
298
300
|
const templateDescErrorHandler = (value) => {
|
|
299
301
|
let errorMessage = false;
|
|
300
|
-
const { unsupportedTags, isBraceError } =
|
|
301
|
-
|
|
302
|
-
|
|
303
|
-
|
|
304
|
-
|
|
305
|
-
|
|
306
|
-
|
|
307
|
-
}) || {};
|
|
302
|
+
const { unsupportedTags, isBraceError } = validateTags({
|
|
303
|
+
content: value,
|
|
304
|
+
tagsParam: tags,
|
|
305
|
+
injectedTagsParams: injectedTags,
|
|
306
|
+
location,
|
|
307
|
+
tagModule: getDefaultTags,
|
|
308
|
+
}) || {};
|
|
308
309
|
if (value === '' && INAPP_MEDIA_TYPES.NONE) {
|
|
309
310
|
errorMessage = formatMessage(messages.emptyTemplateDescErrorMessage);
|
|
310
311
|
} else if (unsupportedTags?.length > 0) {
|
|
@@ -472,7 +473,7 @@ export const InApp = (props) => {
|
|
|
472
473
|
placeholder={formatMessage(globalMessages.templateNamePlaceholder)}
|
|
473
474
|
value={templateName}
|
|
474
475
|
size="default"
|
|
475
|
-
|
|
476
|
+
/>
|
|
476
477
|
</CapRow>
|
|
477
478
|
);
|
|
478
479
|
//create methods end
|
|
@@ -582,8 +583,7 @@ export const InApp = (props) => {
|
|
|
582
583
|
return false;
|
|
583
584
|
};
|
|
584
585
|
|
|
585
|
-
const getCtaPayload = (type) =>
|
|
586
|
-
(type === ANDROID ? ctaDataAndroid : ctaDataIos).map((cta) => {
|
|
586
|
+
const getCtaPayload = (type) => (type === ANDROID ? ctaDataAndroid : ctaDataIos).map((cta) => {
|
|
587
587
|
const { text, urlType, url } = cta;
|
|
588
588
|
return {
|
|
589
589
|
type: urlType,
|