@capillarytech/creatives-library 8.0.126 → 8.0.127-alpha.1
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/index.html +3 -1
- package/package.json +1 -1
- package/services/api.js +4 -4
- 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 +272 -0
- package/utils/tests/createPayload.test.js +761 -0
- package/v2Components/CapImageUpload/index.js +59 -46
- 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/CustomerSearchSection/index.js +12 -7
- 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/v2Components/TestAndPreviewSlidebox/CustomValuesEditor.js +169 -0
- package/v2Components/TestAndPreviewSlidebox/LeftPanelContent.js +95 -0
- package/v2Components/TestAndPreviewSlidebox/PreviewSection.js +69 -0
- package/v2Components/TestAndPreviewSlidebox/SendTestMessage.js +68 -0
- package/v2Components/TestAndPreviewSlidebox/index.js +67 -246
- package/v2Components/TestAndPreviewSlidebox/tests/CustomValuesEditor.test.js +425 -0
- package/v2Components/TestAndPreviewSlidebox/tests/LeftPanelContent.test.js +400 -0
- package/v2Components/TestAndPreviewSlidebox/tests/SendTestMessage.test.js +448 -0
- package/v2Containers/CreativesContainer/SlideBoxContent.js +9 -9
- package/v2Containers/CreativesContainer/index.js +191 -136
- package/v2Containers/Email/index.js +15 -2
- package/v2Containers/InApp/constants.js +1 -0
- package/v2Containers/InApp/index.js +13 -13
- package/v2Containers/MobilePush/Create/index.js +1 -0
- package/v2Containers/MobilePush/commonMethods.js +7 -14
- package/v2Containers/MobilePushNew/actions.js +116 -0
- package/v2Containers/MobilePushNew/components/CtaButtons.js +170 -0
- package/v2Containers/MobilePushNew/components/MediaUploaders.js +754 -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 +726 -0
- package/v2Containers/MobilePushNew/index.js +2280 -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
|
@@ -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
|
|
|
@@ -83,11 +80,14 @@ const SlideBoxWrapper = styled.div`
|
|
|
83
80
|
export class Creatives extends React.Component {
|
|
84
81
|
constructor(props) {
|
|
85
82
|
super(props);
|
|
83
|
+
|
|
84
|
+
const initialSlidBoxContent = this.getSlideBoxContent({ mode: props.creativesMode, templateData: props.templateData, isFullMode: props.isFullMode });
|
|
85
|
+
|
|
86
86
|
this.state = {
|
|
87
87
|
isLoadingContent: true,
|
|
88
88
|
templateStep: 1, //modeSelection: for template name and (for email selecting upload or editor), and createTemplate to create template create based on modeSelection
|
|
89
89
|
showSlideBox: true,
|
|
90
|
-
slidBoxContent:
|
|
90
|
+
slidBoxContent: initialSlidBoxContent,
|
|
91
91
|
templateData: this.getTemplateData(props.templateData),
|
|
92
92
|
templateNameExists: props.creativesMode === 'edit', // if edit mode templateNameExists will be true, and false in create flow.
|
|
93
93
|
currentChannel: this.props.channel || 'sms',
|
|
@@ -154,28 +154,26 @@ export class Creatives extends React.Component {
|
|
|
154
154
|
const userId = parseInt(template.updatedBy, 10);
|
|
155
155
|
templateData.updatedByName = commonUtil.getUserNameById(userId, usersList);
|
|
156
156
|
this.setState({ slidBoxContent: constants.PREVIEW, templateData });
|
|
157
|
+
} else if (get(template, 'versions.base.content.zalo.previewUrl')) {
|
|
158
|
+
commonUtil.handlePreviewInNewTab(
|
|
159
|
+
template.versions.base.content.zalo.previewUrl
|
|
160
|
+
);
|
|
157
161
|
} 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
|
-
}
|
|
162
|
+
const {
|
|
163
|
+
name = "",
|
|
164
|
+
sourceAccountIdentifier = "",
|
|
165
|
+
configs: { token = "" } = {},
|
|
166
|
+
hostName = "",
|
|
167
|
+
} = get(this.props, "Templates.selectedZaloAccount", {});
|
|
168
|
+
this.props.zaloActions.getTemplateInfoById({
|
|
169
|
+
username: name,
|
|
170
|
+
oa_id: sourceAccountIdentifier,
|
|
171
|
+
token,
|
|
172
|
+
host: hostName || this.props?.hostName || this.props.Templates?.senderDetails?.hostName,
|
|
173
|
+
id: template?._id,
|
|
174
|
+
preview: true,
|
|
175
|
+
actionCallback: this.actionCallback,
|
|
176
|
+
});
|
|
179
177
|
}
|
|
180
178
|
};
|
|
181
179
|
|
|
@@ -244,38 +242,40 @@ export class Creatives extends React.Component {
|
|
|
244
242
|
this.setState({ isGetFormData: false });
|
|
245
243
|
};
|
|
246
244
|
|
|
247
|
-
mapCarouselDataToCreatives = (cards) => {
|
|
248
|
-
|
|
249
|
-
|
|
250
|
-
|
|
251
|
-
|
|
252
|
-
|
|
253
|
-
|
|
254
|
-
|
|
255
|
-
|
|
256
|
-
|
|
257
|
-
|
|
258
|
-
|
|
259
|
-
|
|
260
|
-
|
|
245
|
+
mapCarouselDataToCreatives = (cards) => cards.map((card) => {
|
|
246
|
+
const {
|
|
247
|
+
cardVarMapped, bodyTemplate, media, buttons, mediaType,
|
|
248
|
+
} = card || {};
|
|
249
|
+
const buttonData = buttons?.map((button) => {
|
|
250
|
+
const {
|
|
251
|
+
type, text, phoneNumber, url, dynamicUrlPayload,
|
|
252
|
+
} = button || {};
|
|
253
|
+
const buttonObj = { type, text };
|
|
254
|
+
if (type === PHONE_NUMBER) {
|
|
255
|
+
buttonObj.phone_number = phoneNumber;
|
|
256
|
+
}
|
|
257
|
+
if (type === URL) {
|
|
258
|
+
buttonObj.url = url;
|
|
259
|
+
if (dynamicUrlPayload) {
|
|
260
|
+
buttonObj.urlType = DYNAMIC_URL;
|
|
261
261
|
}
|
|
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
|
-
};
|
|
262
|
+
}
|
|
263
|
+
return buttonObj;
|
|
277
264
|
});
|
|
278
|
-
|
|
265
|
+
return {
|
|
266
|
+
bodyText: bodyTemplate,
|
|
267
|
+
varMap: cardVarMapped,
|
|
268
|
+
...(mediaType === IMAGE && {
|
|
269
|
+
imageUrl: media?.url,
|
|
270
|
+
}),
|
|
271
|
+
...(mediaType === VIDEO && {
|
|
272
|
+
videoUrl: media?.url,
|
|
273
|
+
videoPreviewImg: media?.previewUrl,
|
|
274
|
+
}),
|
|
275
|
+
buttons: buttonData,
|
|
276
|
+
mediaType: mediaType?.toLowerCase(),
|
|
277
|
+
};
|
|
278
|
+
})
|
|
279
279
|
|
|
280
280
|
getTemplateData = (templateData) => { //from consumers to creatives
|
|
281
281
|
const { isFullMode, messageDetails = {}, smsRegister } = this.props;
|
|
@@ -355,13 +355,33 @@ export class Creatives extends React.Component {
|
|
|
355
355
|
}
|
|
356
356
|
case constants.MOBILE_PUSH: {
|
|
357
357
|
const mode = get(templateData, 'androidContent.type') || get(templateData, 'iosContent.type') || '';
|
|
358
|
+
const androidCarouselMedia = get(templateData, 'androidContent.expandableDetails.media', []);
|
|
359
|
+
const iosCarouselMedia = get(templateData, 'iosContent.expandableDetails.media', []);
|
|
360
|
+
const androidContent = { ...(templateData?.androidContent || {}) };
|
|
361
|
+
const iosContent = { ...(templateData?.iosContent || {}) };
|
|
362
|
+
if (androidCarouselMedia?.length) {
|
|
363
|
+
androidContent.expandableDetails.carouselData = androidCarouselMedia.map((media) => ({
|
|
364
|
+
mediaType: media.type,
|
|
365
|
+
imageUrl: media.url,
|
|
366
|
+
buttons: [],
|
|
367
|
+
videoSrc: '',
|
|
368
|
+
}));
|
|
369
|
+
}
|
|
370
|
+
if (iosCarouselMedia?.length) {
|
|
371
|
+
iosContent.expandableDetails.carouselData = iosCarouselMedia.map((media) => ({
|
|
372
|
+
mediaType: media.type,
|
|
373
|
+
imageUrl: media.url,
|
|
374
|
+
buttons: [],
|
|
375
|
+
videoSrc: '',
|
|
376
|
+
}));
|
|
377
|
+
}
|
|
358
378
|
creativesTemplateData = {
|
|
359
379
|
type: channel,
|
|
360
380
|
name: templateData.messageSubject,
|
|
361
381
|
versions: {
|
|
362
382
|
base: {
|
|
363
|
-
ANDROID:
|
|
364
|
-
IOS:
|
|
383
|
+
ANDROID: androidContent,
|
|
384
|
+
IOS: iosContent,
|
|
365
385
|
},
|
|
366
386
|
},
|
|
367
387
|
definition: { accountId: templateData.accountId, mode: mode.toLowerCase() },
|
|
@@ -523,7 +543,9 @@ export class Creatives extends React.Component {
|
|
|
523
543
|
} = {},
|
|
524
544
|
} = templateData;
|
|
525
545
|
const mediaParams = {};
|
|
526
|
-
const {
|
|
546
|
+
const {
|
|
547
|
+
url = '', previewUrl = '', docParams = {}, footer = '', headerVarMapped = {}, headerTemplate = '',
|
|
548
|
+
} = whatsappMedia || {};
|
|
527
549
|
switch (mediaType) {
|
|
528
550
|
case (WHATSAPP_MEDIA_TYPES.IMAGE):
|
|
529
551
|
mediaParams.imageUrl = url;
|
|
@@ -543,7 +565,7 @@ export class Creatives extends React.Component {
|
|
|
543
565
|
break;
|
|
544
566
|
}
|
|
545
567
|
const modifiedButtons = cloneDeep(buttons)?.map((btn) => {
|
|
546
|
-
if (btn.type ===
|
|
568
|
+
if (btn.type === PHONE_NUMBER) {
|
|
547
569
|
btn.phone_number = btn.phoneNumber;
|
|
548
570
|
delete btn.phoneNumber;
|
|
549
571
|
return btn;
|
|
@@ -636,46 +658,61 @@ export class Creatives extends React.Component {
|
|
|
636
658
|
return templateData || null;
|
|
637
659
|
}
|
|
638
660
|
|
|
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(),
|
|
661
|
+
getCarouselMappedData = (carouselData = []) => carouselData.map((carousel) => {
|
|
662
|
+
const {
|
|
663
|
+
bodyText, imageUrl, videoUrl, videoPreviewImg, buttons, mediaType, cardVarMapped, bodyTemplate,
|
|
664
|
+
} = carousel || {};
|
|
665
|
+
const buttonData = buttons.map((button, index) => {
|
|
666
|
+
const {
|
|
667
|
+
type, text, phone_number, urlType, url,
|
|
668
|
+
} = button || {};
|
|
669
|
+
const buttonObj = {
|
|
670
|
+
type,
|
|
671
|
+
text,
|
|
672
|
+
index,
|
|
676
673
|
};
|
|
674
|
+
if (type === PHONE_NUMBER) {
|
|
675
|
+
buttonObj.phoneNumber = phone_number;
|
|
676
|
+
}
|
|
677
|
+
if (type === URL) {
|
|
678
|
+
buttonObj.url = url;
|
|
679
|
+
if (urlType === DYNAMIC_URL) {
|
|
680
|
+
const dynamicUrlPayload = url?.match(/{{(.*?)}}/g);
|
|
681
|
+
buttonObj.dynamicUrlPayload = dynamicUrlPayload?.length === 1 ? dynamicUrlPayload[0] : '';
|
|
682
|
+
}
|
|
683
|
+
}
|
|
684
|
+
return buttonObj;
|
|
677
685
|
});
|
|
678
|
-
|
|
686
|
+
return {
|
|
687
|
+
body: bodyText,
|
|
688
|
+
cardVarMapped,
|
|
689
|
+
bodyTemplate,
|
|
690
|
+
media: {
|
|
691
|
+
...(mediaType?.toLowerCase() === IMAGE.toLowerCase() && {
|
|
692
|
+
url: imageUrl,
|
|
693
|
+
}),
|
|
694
|
+
...(mediaType?.toLowerCase() === VIDEO.toLowerCase() && {
|
|
695
|
+
url: videoUrl,
|
|
696
|
+
previewUrl: videoPreviewImg,
|
|
697
|
+
}),
|
|
698
|
+
},
|
|
699
|
+
buttons: buttonData,
|
|
700
|
+
mediaType: mediaType?.toUpperCase(),
|
|
701
|
+
};
|
|
702
|
+
});
|
|
703
|
+
|
|
704
|
+
getMobilePushCarouselData = (expandableDetails = []) => {
|
|
705
|
+
const newExpandableDetails = {...expandableDetails};
|
|
706
|
+
newExpandableDetails.style = expandableDetails.style || 'MANUAL_CAROUSEL';
|
|
707
|
+
newExpandableDetails.message = expandableDetails.message || '';
|
|
708
|
+
newExpandableDetails.ctas = expandableDetails.ctas || [];
|
|
709
|
+
newExpandableDetails.media = expandableDetails.carouselData.map((carousel) => ({
|
|
710
|
+
url: carousel.imageUrl,
|
|
711
|
+
type: carousel?.mediaType?.toUpperCase(),
|
|
712
|
+
text: '',
|
|
713
|
+
}));
|
|
714
|
+
return newExpandableDetails;
|
|
715
|
+
}
|
|
679
716
|
|
|
680
717
|
getCreativesData = async (channel, template, templateRecords) => { //from creatives to consumers
|
|
681
718
|
let templateData = { channel };
|
|
@@ -759,6 +796,9 @@ export class Creatives extends React.Component {
|
|
|
759
796
|
if (channel !== constants.MOBILE_PUSH) {
|
|
760
797
|
androidContent.custom = custom;
|
|
761
798
|
}
|
|
799
|
+
if (channel === constants.MOBILE_PUSH && androidContent?.expandableDetails?.carouselData?.length) {
|
|
800
|
+
androidContent.expandableDetails = this.getMobilePushCarouselData({...androidContent?.expandableDetails});
|
|
801
|
+
}
|
|
762
802
|
templateData.androidContent = androidContent;
|
|
763
803
|
templateData.androidContent.type = get(channelTemplate, 'definition.mode', '').toUpperCase();
|
|
764
804
|
templateData.androidContent.deviceType = constants.ANDROID;
|
|
@@ -778,6 +818,9 @@ export class Creatives extends React.Component {
|
|
|
778
818
|
if (channel !== constants.MOBILE_PUSH) {
|
|
779
819
|
iosContent.custom = custom;
|
|
780
820
|
}
|
|
821
|
+
if (channel === constants.MOBILE_PUSH && iosContent?.expandableDetails?.carouselData?.length) {
|
|
822
|
+
iosContent.expandableDetails = this.getMobilePushCarouselData({...iosContent?.expandableDetails});
|
|
823
|
+
}
|
|
781
824
|
templateData.iosContent = iosContent;
|
|
782
825
|
templateData.iosContent.type = get(channelTemplate, 'definition.mode').toUpperCase();
|
|
783
826
|
templateData.iosContent.deviceType = constants.IOS;
|
|
@@ -947,7 +990,7 @@ export class Creatives extends React.Component {
|
|
|
947
990
|
fBContent.forEach((obj) => {
|
|
948
991
|
const data = cloneDeep(obj);
|
|
949
992
|
const {
|
|
950
|
-
subType, linkDesc, imgSrc, webSiteLink, video
|
|
993
|
+
subType, linkDesc, imgSrc, webSiteLink, video,
|
|
951
994
|
} = obj;
|
|
952
995
|
delete data.type;
|
|
953
996
|
delete data.linkDesc;
|
|
@@ -985,7 +1028,7 @@ export class Creatives extends React.Component {
|
|
|
985
1028
|
break;
|
|
986
1029
|
case constants.RCS: {
|
|
987
1030
|
if (template.value) {
|
|
988
|
-
const { name = "", versions = {}
|
|
1031
|
+
const { name = "", versions = {} } = {
|
|
989
1032
|
} = template.value || {};
|
|
990
1033
|
const {
|
|
991
1034
|
cardContent = [],
|
|
@@ -1113,7 +1156,6 @@ export class Creatives extends React.Component {
|
|
|
1113
1156
|
}
|
|
1114
1157
|
|
|
1115
1158
|
getFormData = (template) => {
|
|
1116
|
-
|
|
1117
1159
|
if (template.validity) {
|
|
1118
1160
|
this.setState(
|
|
1119
1161
|
{
|
|
@@ -1131,7 +1173,7 @@ export class Creatives extends React.Component {
|
|
|
1131
1173
|
);
|
|
1132
1174
|
}
|
|
1133
1175
|
}
|
|
1134
|
-
|
|
1176
|
+
|
|
1135
1177
|
processCentralCommsMetaId = (channel, creativesData) => {
|
|
1136
1178
|
// Create the payload for the centralcommnsmetaId API call
|
|
1137
1179
|
const { isLoyaltyModule = false, loyaltyMetaData = {} } = this.props;
|
|
@@ -1222,13 +1264,16 @@ export class Creatives extends React.Component {
|
|
|
1222
1264
|
|
|
1223
1265
|
shouldShowFooter = () => {
|
|
1224
1266
|
const { isFullMode } = this.props;
|
|
1225
|
-
const {
|
|
1267
|
+
const {
|
|
1268
|
+
slidBoxContent, currentChannel, emailCreateMode, templateNameExists, templateStep, mobilePushCreateMode, weChatTemplateType, templateData,
|
|
1269
|
+
} = this.state;
|
|
1226
1270
|
const channel = currentChannel.toUpperCase();
|
|
1227
1271
|
const currentStep = this.creativesTemplateSteps[templateStep];
|
|
1228
1272
|
let showFooter = false;
|
|
1229
1273
|
showFooter = isFullMode && slidBoxContent === "preview";
|
|
1230
1274
|
const isMobilepush = channel === constants.MOBILE_PUSH;
|
|
1231
|
-
|
|
1275
|
+
|
|
1276
|
+
|
|
1232
1277
|
if (!isFullMode) {
|
|
1233
1278
|
const isEmailCreate = slidBoxContent === 'createTemplate' && channel === constants.EMAIL && currentStep !== 'createTemplateContent';
|
|
1234
1279
|
const isCreate = (slidBoxContent === 'editTemplate' || slidBoxContent === 'createTemplate') && !isEmailCreate;
|
|
@@ -1250,15 +1295,15 @@ export class Creatives extends React.Component {
|
|
|
1250
1295
|
if (slidBoxContent === "editTemplate" && ((channel === constants.EMAIL && currentStep === 'modeSelection'))) {
|
|
1251
1296
|
showFooter = true;
|
|
1252
1297
|
}
|
|
1253
|
-
if (channel === constants.MOBILE_PUSH
|
|
1254
|
-
((slidBoxContent === 'createTemplate' && !isEmpty(mobilePushCreateMode))
|
|
1255
|
-
|| (slidBoxContent === 'editTemplate' && currentStep === 'modeSelection')) &&
|
|
1298
|
+
if (channel === constants.MOBILE_PUSH
|
|
1299
|
+
&& ((slidBoxContent === 'createTemplate' && !isEmpty(mobilePushCreateMode))
|
|
1300
|
+
|| (slidBoxContent === 'editTemplate' && (currentStep === 'modeSelection' || isFullMode))) &&
|
|
1256
1301
|
templateNameExists) {
|
|
1257
1302
|
showFooter = true;
|
|
1258
1303
|
}
|
|
1259
1304
|
|
|
1260
|
-
if (channel === constants.WECHAT
|
|
1261
|
-
((slidBoxContent === 'createTemplate' && !isEmpty(weChatTemplateType))
|
|
1305
|
+
if (channel === constants.WECHAT
|
|
1306
|
+
&& ((slidBoxContent === 'createTemplate' && !isEmpty(weChatTemplateType))
|
|
1262
1307
|
|| (slidBoxContent === 'editTemplate' && currentStep === 'modeSelection'))) {
|
|
1263
1308
|
showFooter = true;
|
|
1264
1309
|
}
|
|
@@ -1267,9 +1312,9 @@ export class Creatives extends React.Component {
|
|
|
1267
1312
|
if (slidBoxContent === "createTemplate" && ((channel === constants.EMAIL && currentStep === 'createTemplateContent') ||
|
|
1268
1313
|
([constants.SMS, constants.WECHAT].includes(channel) && currentStep === 'modeSelection'))) {
|
|
1269
1314
|
showFooter = showFooter && !this.state.isLoadingContent;
|
|
1270
|
-
} else if (slidBoxContent === "editTemplate"
|
|
1271
|
-
([constants.SMS, constants.WECHAT, constants.EMAIL].includes(channel)
|
|
1272
|
-
currentStep === 'modeSelection')) {
|
|
1315
|
+
} else if (slidBoxContent === "editTemplate"
|
|
1316
|
+
&& ([constants.SMS, constants.WECHAT, constants.EMAIL].includes(channel)
|
|
1317
|
+
&& currentStep === 'modeSelection')) {
|
|
1273
1318
|
showFooter = showFooter && !this.state.isLoadingContent;
|
|
1274
1319
|
}
|
|
1275
1320
|
}
|
|
@@ -1278,6 +1323,8 @@ export class Creatives extends React.Component {
|
|
|
1278
1323
|
if ([constants.LINE, constants.VIBER, constants.FACEBOOK].includes(channel) || isLineViberChannel) {
|
|
1279
1324
|
showFooter = false;
|
|
1280
1325
|
}
|
|
1326
|
+
|
|
1327
|
+
|
|
1281
1328
|
return showFooter;
|
|
1282
1329
|
}
|
|
1283
1330
|
|
|
@@ -1290,13 +1337,21 @@ export class Creatives extends React.Component {
|
|
|
1290
1337
|
let showDone = false;
|
|
1291
1338
|
const channelName = !isFullMode && templateData ? templateData.type : currentChannel;
|
|
1292
1339
|
const channel = channelName?.toUpperCase();
|
|
1340
|
+
|
|
1341
|
+
|
|
1293
1342
|
if (channel === constants.EMAIL || channel === constants.SMS) {
|
|
1294
1343
|
const isEmailCreate = slidBoxContent === 'createTemplate' && channel === constants.EMAIL && currentStep !== 'createTemplateContent';
|
|
1295
1344
|
showDone = (slidBoxContent === 'editTemplate' || slidBoxContent === 'createTemplate') && !isEmailCreate;
|
|
1296
1345
|
} else if ([constants.WECHAT, constants.MOBILE_PUSH].includes(channel)) {
|
|
1297
1346
|
showDone = currentStep === "createTemplateContent" || slidBoxContent === "editTemplate";
|
|
1347
|
+
|
|
1348
|
+
// Additional condition for MobilePush edit in full mode
|
|
1349
|
+
if (channel === constants.MOBILE_PUSH && slidBoxContent === "editTemplate" && isFullMode) {
|
|
1350
|
+
showDone = true;
|
|
1351
|
+
}
|
|
1298
1352
|
}
|
|
1299
1353
|
|
|
1354
|
+
|
|
1300
1355
|
return showDone;
|
|
1301
1356
|
}
|
|
1302
1357
|
|
|
@@ -1356,7 +1411,9 @@ export class Creatives extends React.Component {
|
|
|
1356
1411
|
}
|
|
1357
1412
|
|
|
1358
1413
|
shouldShowContinueFooter = () => { // only for email for now, has to be modified according to channel
|
|
1359
|
-
const {
|
|
1414
|
+
const {
|
|
1415
|
+
slidBoxContent, templateStep, currentChannel, emailCreateMode, mobilePushCreateMode, inAppCreateMode, weChatTemplateType,
|
|
1416
|
+
} = this.state;
|
|
1360
1417
|
let isShowContinueFooter = false;
|
|
1361
1418
|
const currentStep = this.creativesTemplateSteps[templateStep];
|
|
1362
1419
|
const channel = currentChannel.toUpperCase();
|
|
@@ -1439,17 +1496,16 @@ export class Creatives extends React.Component {
|
|
|
1439
1496
|
loyaltyMetaData = {},
|
|
1440
1497
|
} = this.props;
|
|
1441
1498
|
const mapTemplateCreate =
|
|
1442
|
-
slidBoxContent === "createTemplate"
|
|
1443
|
-
weChatTemplateType === MAP_TEMPLATE
|
|
1444
|
-
templateStep !== "modeSelection";
|
|
1445
|
-
const slideBoxWrapperMargin =
|
|
1446
|
-
|
|
1447
|
-
|
|
1448
|
-
|
|
1449
|
-
|
|
1450
|
-
|
|
1451
|
-
|
|
1452
|
-
: 0;
|
|
1499
|
+
slidBoxContent === "createTemplate"
|
|
1500
|
+
&& weChatTemplateType === MAP_TEMPLATE
|
|
1501
|
+
&& templateStep !== "modeSelection";
|
|
1502
|
+
const slideBoxWrapperMargin = (get(liquidErrorMessage, 'STANDARD_ERROR_MSG.length', 0) > 0 && get(liquidErrorMessage, 'LIQUID_ERROR_MSG.length', 0) > 0)
|
|
1503
|
+
? CAP_SPACE_64
|
|
1504
|
+
: get(liquidErrorMessage, 'LIQUID_ERROR_MSG.length', 0) > 0
|
|
1505
|
+
? CAP_SPACE_56
|
|
1506
|
+
: get(liquidErrorMessage, 'STANDARD_ERROR_MSG.length', 0) > 0
|
|
1507
|
+
? CAP_SPACE_32
|
|
1508
|
+
: 0;
|
|
1453
1509
|
/* TODO: Instead of passing down same props separately to each component down, write common function to these props and pass it accordingly */
|
|
1454
1510
|
return (
|
|
1455
1511
|
<SlideBoxWrapper slideBoxWrapperMargin={slideBoxWrapperMargin} className={classnames(`${classPrefix} ${isFullMode ? 'creatives-full-mode' : 'creatives-library-mode'} ${mapTemplateCreate ? 'map-template-create' : ''}`)}>
|
|
@@ -1577,7 +1633,6 @@ export class Creatives extends React.Component {
|
|
|
1577
1633
|
) : isLiquidValidationError && (
|
|
1578
1634
|
<CapRow className="template-footer-width">
|
|
1579
1635
|
{(() => {
|
|
1580
|
-
|
|
1581
1636
|
const errorsToShow = get(liquidErrorMessage, constants.LIQUID_ERROR_MSG, []);
|
|
1582
1637
|
const standardErrorsToShow = get(liquidErrorMessage, constants.STANDARD_ERROR_MSG, []);
|
|
1583
1638
|
return <ErrorInfoNote currentTab={activeFormBuilderTab?.toUpperCase()} errorMessages={{LIQUID_ERROR_MSG: errorsToShow, STANDARD_ERROR_MSG: standardErrorsToShow}} />;
|
|
@@ -1647,7 +1702,7 @@ function mapDispatchToProps(dispatch) {
|
|
|
1647
1702
|
const withConnect = connect(mapStatesToProps, mapDispatchToProps);
|
|
1648
1703
|
const withReducer = injectReducer({ key: 'creativesContainer', reducer: creativesContainerReducer });
|
|
1649
1704
|
const withSaga = injectSaga({ key: 'cap', saga: capSagaForFetchSchemaForEntity });
|
|
1650
|
-
const withLiquidSaga = injectSaga({ key: 'liquid', saga: capSagaLiquidEntity
|
|
1705
|
+
const withLiquidSaga = injectSaga({ key: 'liquid', saga: capSagaLiquidEntity, mode: DAEMON });
|
|
1651
1706
|
const withDefaultTempSaga = injectSaga({ key: 'creativesContainer', saga: v2TemplateSagaWatchGetDefaultBeeTemplates });
|
|
1652
1707
|
|
|
1653
|
-
export default compose(withSaga,withLiquidSaga, withDefaultTempSaga, withReducer, withConnect)(injectIntl(Creatives));
|
|
1708
|
+
export default compose(withSaga, withLiquidSaga, withDefaultTempSaga, withReducer, withConnect)(injectIntl(Creatives));
|
|
@@ -820,6 +820,18 @@ export class Email extends React.Component { // eslint-disable-line react/prefer
|
|
|
820
820
|
// return response;
|
|
821
821
|
}
|
|
822
822
|
|
|
823
|
+
getTemplateContent = () => {
|
|
824
|
+
const { formData, currentTab } = this.state;
|
|
825
|
+
const currentTabData = formData[currentTab - 1];
|
|
826
|
+
const activeTab = currentTabData?.activeTab;
|
|
827
|
+
|
|
828
|
+
if (currentTabData && activeTab && currentTabData[activeTab]) {
|
|
829
|
+
return currentTabData[activeTab]['template-content'] || '';
|
|
830
|
+
}
|
|
831
|
+
|
|
832
|
+
return '';
|
|
833
|
+
}
|
|
834
|
+
|
|
823
835
|
setFormValidity = (isFormValid) => {
|
|
824
836
|
this.setState({isFormValid});
|
|
825
837
|
}
|
|
@@ -2661,7 +2673,7 @@ export class Email extends React.Component { // eslint-disable-line react/prefer
|
|
|
2661
2673
|
formData,
|
|
2662
2674
|
};
|
|
2663
2675
|
}, () => {
|
|
2664
|
-
this.setState({
|
|
2676
|
+
!this.props.showTestAndPreviewSlidebox && this.setState({
|
|
2665
2677
|
startValidation: true,
|
|
2666
2678
|
});
|
|
2667
2679
|
});
|
|
@@ -2774,7 +2786,8 @@ export class Email extends React.Component { // eslint-disable-line react/prefer
|
|
|
2774
2786
|
show={showTestAndPreviewSlidebox}
|
|
2775
2787
|
onClose={handleCloseTestAndPreview}
|
|
2776
2788
|
formData={this.state.formData}
|
|
2777
|
-
|
|
2789
|
+
beeInstance={this.beeInstance}
|
|
2790
|
+
content={this.getTemplateContent()}
|
|
2778
2791
|
currentChannel={EMAIL}
|
|
2779
2792
|
/>
|
|
2780
2793
|
</div>
|
|
@@ -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,
|
|
@@ -239,6 +239,7 @@ export class Create extends React.Component { // eslint-disable-line react/prefe
|
|
|
239
239
|
onLinkTypeChange = (eventTriggered, formData, field) => {
|
|
240
240
|
let schema = cloneDeep(this.state.schema);
|
|
241
241
|
const inputFields = get(schema, `containers[0].panes[${this.state.currentTab - 1}].sections[0].childSections[0].childSections[0].inputFields`);
|
|
242
|
+
|
|
242
243
|
forEach(inputFields, (inputField, fieldIndex) => {
|
|
243
244
|
if (inputField) {
|
|
244
245
|
forEach(inputField.cols, (col) => {
|