@capillarytech/creatives-library 8.0.126 → 8.0.127-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/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 +193 -134
- 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,9 +15,10 @@ 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 {
|
|
@@ -44,20 +46,19 @@ import {
|
|
|
44
46
|
import { IMAGE, VIDEO } from '../Facebook/Advertisement/constant';
|
|
45
47
|
import { CREATIVE } from '../Facebook/constants';
|
|
46
48
|
import { LOYALTY } from '../App/constants';
|
|
47
|
-
import {
|
|
48
|
-
|
|
49
|
+
import {
|
|
50
|
+
WHATSAPP_STATUSES, WHATSAPP_MEDIA_TYPES, PHONE_NUMBER, URL,
|
|
51
|
+
} from '../Whatsapp/constants';
|
|
52
|
+
import SlideBoxHeader from './SlideBoxHeader';
|
|
53
|
+
import SlideBoxFooter from './SlideBoxFooter';
|
|
54
|
+
import SlideBoxContent from './SlideBoxContent';
|
|
49
55
|
import { updateImagesInHtml } from '../../utils/cdnTransformation';
|
|
50
|
-
|
|
56
|
+
|
|
51
57
|
import injectReducer from '../../utils/injectReducer';
|
|
52
58
|
import injectSaga from '../../utils/injectSaga';
|
|
53
59
|
import creativesContainerReducer from './reducer';
|
|
54
|
-
import {
|
|
55
|
-
import { capSagaForFetchSchemaForEntity,capSagaLiquidEntity } from '../Cap/sagas';
|
|
60
|
+
import { capSagaForFetchSchemaForEntity, capSagaLiquidEntity } from '../Cap/sagas';
|
|
56
61
|
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
62
|
import { DYNAMIC_URL } from '../../v2Components/CapWhatsappCTA/constants';
|
|
62
63
|
import ErrorInfoNote from '../../v2Components/ErrorInfoNote';
|
|
63
64
|
|
|
@@ -83,11 +84,14 @@ const SlideBoxWrapper = styled.div`
|
|
|
83
84
|
export class Creatives extends React.Component {
|
|
84
85
|
constructor(props) {
|
|
85
86
|
super(props);
|
|
87
|
+
|
|
88
|
+
const initialSlidBoxContent = this.getSlideBoxContent({ mode: props.creativesMode, templateData: props.templateData, isFullMode: props.isFullMode });
|
|
89
|
+
|
|
86
90
|
this.state = {
|
|
87
91
|
isLoadingContent: true,
|
|
88
92
|
templateStep: 1, //modeSelection: for template name and (for email selecting upload or editor), and createTemplate to create template create based on modeSelection
|
|
89
93
|
showSlideBox: true,
|
|
90
|
-
slidBoxContent:
|
|
94
|
+
slidBoxContent: initialSlidBoxContent,
|
|
91
95
|
templateData: this.getTemplateData(props.templateData),
|
|
92
96
|
templateNameExists: props.creativesMode === 'edit', // if edit mode templateNameExists will be true, and false in create flow.
|
|
93
97
|
currentChannel: this.props.channel || 'sms',
|
|
@@ -154,28 +158,26 @@ export class Creatives extends React.Component {
|
|
|
154
158
|
const userId = parseInt(template.updatedBy, 10);
|
|
155
159
|
templateData.updatedByName = commonUtil.getUserNameById(userId, usersList);
|
|
156
160
|
this.setState({ slidBoxContent: constants.PREVIEW, templateData });
|
|
161
|
+
} else if (get(template, 'versions.base.content.zalo.previewUrl')) {
|
|
162
|
+
commonUtil.handlePreviewInNewTab(
|
|
163
|
+
template.versions.base.content.zalo.previewUrl
|
|
164
|
+
);
|
|
157
165
|
} 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
|
-
}
|
|
166
|
+
const {
|
|
167
|
+
name = "",
|
|
168
|
+
sourceAccountIdentifier = "",
|
|
169
|
+
configs: { token = "" } = {},
|
|
170
|
+
hostName = "",
|
|
171
|
+
} = get(this.props, "Templates.selectedZaloAccount", {});
|
|
172
|
+
this.props.zaloActions.getTemplateInfoById({
|
|
173
|
+
username: name,
|
|
174
|
+
oa_id: sourceAccountIdentifier,
|
|
175
|
+
token,
|
|
176
|
+
host: hostName || this.props?.hostName || this.props.Templates?.senderDetails?.hostName,
|
|
177
|
+
id: template?._id,
|
|
178
|
+
preview: true,
|
|
179
|
+
actionCallback: this.actionCallback,
|
|
180
|
+
});
|
|
179
181
|
}
|
|
180
182
|
};
|
|
181
183
|
|
|
@@ -244,38 +246,40 @@ export class Creatives extends React.Component {
|
|
|
244
246
|
this.setState({ isGetFormData: false });
|
|
245
247
|
};
|
|
246
248
|
|
|
247
|
-
mapCarouselDataToCreatives = (cards) => {
|
|
248
|
-
|
|
249
|
-
|
|
250
|
-
|
|
251
|
-
|
|
252
|
-
|
|
253
|
-
|
|
254
|
-
|
|
255
|
-
|
|
256
|
-
|
|
257
|
-
|
|
258
|
-
|
|
259
|
-
|
|
260
|
-
|
|
249
|
+
mapCarouselDataToCreatives = (cards) => cards.map((card) => {
|
|
250
|
+
const {
|
|
251
|
+
cardVarMapped, bodyTemplate, media, buttons, mediaType,
|
|
252
|
+
} = card || {};
|
|
253
|
+
const buttonData = buttons?.map((button) => {
|
|
254
|
+
const {
|
|
255
|
+
type, text, phoneNumber, url, dynamicUrlPayload,
|
|
256
|
+
} = button || {};
|
|
257
|
+
const buttonObj = { type, text };
|
|
258
|
+
if (type === PHONE_NUMBER) {
|
|
259
|
+
buttonObj.phone_number = phoneNumber;
|
|
260
|
+
}
|
|
261
|
+
if (type === URL) {
|
|
262
|
+
buttonObj.url = url;
|
|
263
|
+
if (dynamicUrlPayload) {
|
|
264
|
+
buttonObj.urlType = DYNAMIC_URL;
|
|
261
265
|
}
|
|
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
|
-
};
|
|
266
|
+
}
|
|
267
|
+
return buttonObj;
|
|
277
268
|
});
|
|
278
|
-
|
|
269
|
+
return {
|
|
270
|
+
bodyText: bodyTemplate,
|
|
271
|
+
varMap: cardVarMapped,
|
|
272
|
+
...(mediaType === IMAGE && {
|
|
273
|
+
imageUrl: media?.url,
|
|
274
|
+
}),
|
|
275
|
+
...(mediaType === VIDEO && {
|
|
276
|
+
videoUrl: media?.url,
|
|
277
|
+
videoPreviewImg: media?.previewUrl,
|
|
278
|
+
}),
|
|
279
|
+
buttons: buttonData,
|
|
280
|
+
mediaType: mediaType?.toLowerCase(),
|
|
281
|
+
};
|
|
282
|
+
})
|
|
279
283
|
|
|
280
284
|
getTemplateData = (templateData) => { //from consumers to creatives
|
|
281
285
|
const { isFullMode, messageDetails = {}, smsRegister } = this.props;
|
|
@@ -355,13 +359,33 @@ export class Creatives extends React.Component {
|
|
|
355
359
|
}
|
|
356
360
|
case constants.MOBILE_PUSH: {
|
|
357
361
|
const mode = get(templateData, 'androidContent.type') || get(templateData, 'iosContent.type') || '';
|
|
362
|
+
const androidCarouselMedia = get(templateData, 'androidContent.expandableDetails.media', []);
|
|
363
|
+
const iosCarouselMedia = get(templateData, 'iosContent.expandableDetails.media', []);
|
|
364
|
+
const androidContent = { ...(templateData?.androidContent || {}) };
|
|
365
|
+
const iosContent = { ...(templateData?.iosContent || {}) };
|
|
366
|
+
if (androidCarouselMedia?.length) {
|
|
367
|
+
androidContent.expandableDetails.carouselData = androidCarouselMedia.map((media) => ({
|
|
368
|
+
mediaType: media.type,
|
|
369
|
+
imageUrl: media.url,
|
|
370
|
+
buttons: [],
|
|
371
|
+
videoSrc: '',
|
|
372
|
+
}));
|
|
373
|
+
}
|
|
374
|
+
if (iosCarouselMedia?.length) {
|
|
375
|
+
iosContent.expandableDetails.carouselData = iosCarouselMedia.map((media) => ({
|
|
376
|
+
mediaType: media.type,
|
|
377
|
+
imageUrl: media.url,
|
|
378
|
+
buttons: [],
|
|
379
|
+
videoSrc: '',
|
|
380
|
+
}));
|
|
381
|
+
}
|
|
358
382
|
creativesTemplateData = {
|
|
359
383
|
type: channel,
|
|
360
384
|
name: templateData.messageSubject,
|
|
361
385
|
versions: {
|
|
362
386
|
base: {
|
|
363
|
-
ANDROID:
|
|
364
|
-
IOS:
|
|
387
|
+
ANDROID: androidContent,
|
|
388
|
+
IOS: iosContent,
|
|
365
389
|
},
|
|
366
390
|
},
|
|
367
391
|
definition: { accountId: templateData.accountId, mode: mode.toLowerCase() },
|
|
@@ -523,7 +547,9 @@ export class Creatives extends React.Component {
|
|
|
523
547
|
} = {},
|
|
524
548
|
} = templateData;
|
|
525
549
|
const mediaParams = {};
|
|
526
|
-
const {
|
|
550
|
+
const {
|
|
551
|
+
url = '', previewUrl = '', docParams = {}, footer = '', headerVarMapped = {}, headerTemplate = '',
|
|
552
|
+
} = whatsappMedia || {};
|
|
527
553
|
switch (mediaType) {
|
|
528
554
|
case (WHATSAPP_MEDIA_TYPES.IMAGE):
|
|
529
555
|
mediaParams.imageUrl = url;
|
|
@@ -543,7 +569,7 @@ export class Creatives extends React.Component {
|
|
|
543
569
|
break;
|
|
544
570
|
}
|
|
545
571
|
const modifiedButtons = cloneDeep(buttons)?.map((btn) => {
|
|
546
|
-
if (btn.type ===
|
|
572
|
+
if (btn.type === PHONE_NUMBER) {
|
|
547
573
|
btn.phone_number = btn.phoneNumber;
|
|
548
574
|
delete btn.phoneNumber;
|
|
549
575
|
return btn;
|
|
@@ -636,46 +662,61 @@ export class Creatives extends React.Component {
|
|
|
636
662
|
return templateData || null;
|
|
637
663
|
}
|
|
638
664
|
|
|
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(),
|
|
665
|
+
getCarouselMappedData = (carouselData = []) => carouselData.map((carousel) => {
|
|
666
|
+
const {
|
|
667
|
+
bodyText, imageUrl, videoUrl, videoPreviewImg, buttons, mediaType, cardVarMapped, bodyTemplate,
|
|
668
|
+
} = carousel || {};
|
|
669
|
+
const buttonData = buttons.map((button, index) => {
|
|
670
|
+
const {
|
|
671
|
+
type, text, phone_number, urlType, url,
|
|
672
|
+
} = button || {};
|
|
673
|
+
const buttonObj = {
|
|
674
|
+
type,
|
|
675
|
+
text,
|
|
676
|
+
index,
|
|
676
677
|
};
|
|
678
|
+
if (type === PHONE_NUMBER) {
|
|
679
|
+
buttonObj.phoneNumber = phone_number;
|
|
680
|
+
}
|
|
681
|
+
if (type === URL) {
|
|
682
|
+
buttonObj.url = url;
|
|
683
|
+
if (urlType === DYNAMIC_URL) {
|
|
684
|
+
const dynamicUrlPayload = url?.match(/{{(.*?)}}/g);
|
|
685
|
+
buttonObj.dynamicUrlPayload = dynamicUrlPayload?.length === 1 ? dynamicUrlPayload[0] : '';
|
|
686
|
+
}
|
|
687
|
+
}
|
|
688
|
+
return buttonObj;
|
|
677
689
|
});
|
|
678
|
-
|
|
690
|
+
return {
|
|
691
|
+
body: bodyText,
|
|
692
|
+
cardVarMapped,
|
|
693
|
+
bodyTemplate,
|
|
694
|
+
media: {
|
|
695
|
+
...(mediaType?.toLowerCase() === IMAGE.toLowerCase() && {
|
|
696
|
+
url: imageUrl,
|
|
697
|
+
}),
|
|
698
|
+
...(mediaType?.toLowerCase() === VIDEO.toLowerCase() && {
|
|
699
|
+
url: videoUrl,
|
|
700
|
+
previewUrl: videoPreviewImg,
|
|
701
|
+
}),
|
|
702
|
+
},
|
|
703
|
+
buttons: buttonData,
|
|
704
|
+
mediaType: mediaType?.toUpperCase(),
|
|
705
|
+
};
|
|
706
|
+
});
|
|
707
|
+
|
|
708
|
+
getMobilePushCarouselData = (expandableDetails = []) => {
|
|
709
|
+
const newExpandableDetails = {...expandableDetails};
|
|
710
|
+
newExpandableDetails.style = expandableDetails.style || 'MANUAL_CAROUSEL';
|
|
711
|
+
newExpandableDetails.message = expandableDetails.message || '';
|
|
712
|
+
newExpandableDetails.ctas = expandableDetails.ctas || [];
|
|
713
|
+
newExpandableDetails.media = expandableDetails.carouselData.map((carousel) => ({
|
|
714
|
+
url: carousel.imageUrl,
|
|
715
|
+
type: carousel?.mediaType?.toUpperCase(),
|
|
716
|
+
text: '',
|
|
717
|
+
}));
|
|
718
|
+
return newExpandableDetails;
|
|
719
|
+
}
|
|
679
720
|
|
|
680
721
|
getCreativesData = async (channel, template, templateRecords) => { //from creatives to consumers
|
|
681
722
|
let templateData = { channel };
|
|
@@ -759,6 +800,9 @@ export class Creatives extends React.Component {
|
|
|
759
800
|
if (channel !== constants.MOBILE_PUSH) {
|
|
760
801
|
androidContent.custom = custom;
|
|
761
802
|
}
|
|
803
|
+
if (channel === constants.MOBILE_PUSH && androidContent?.expandableDetails?.carouselData?.length) {
|
|
804
|
+
androidContent.expandableDetails = this.getMobilePushCarouselData({...androidContent?.expandableDetails});
|
|
805
|
+
}
|
|
762
806
|
templateData.androidContent = androidContent;
|
|
763
807
|
templateData.androidContent.type = get(channelTemplate, 'definition.mode', '').toUpperCase();
|
|
764
808
|
templateData.androidContent.deviceType = constants.ANDROID;
|
|
@@ -778,6 +822,9 @@ export class Creatives extends React.Component {
|
|
|
778
822
|
if (channel !== constants.MOBILE_PUSH) {
|
|
779
823
|
iosContent.custom = custom;
|
|
780
824
|
}
|
|
825
|
+
if (channel === constants.MOBILE_PUSH && iosContent?.expandableDetails?.carouselData?.length) {
|
|
826
|
+
iosContent.expandableDetails = this.getMobilePushCarouselData({...iosContent?.expandableDetails});
|
|
827
|
+
}
|
|
781
828
|
templateData.iosContent = iosContent;
|
|
782
829
|
templateData.iosContent.type = get(channelTemplate, 'definition.mode').toUpperCase();
|
|
783
830
|
templateData.iosContent.deviceType = constants.IOS;
|
|
@@ -947,7 +994,7 @@ export class Creatives extends React.Component {
|
|
|
947
994
|
fBContent.forEach((obj) => {
|
|
948
995
|
const data = cloneDeep(obj);
|
|
949
996
|
const {
|
|
950
|
-
subType, linkDesc, imgSrc, webSiteLink, video
|
|
997
|
+
subType, linkDesc, imgSrc, webSiteLink, video,
|
|
951
998
|
} = obj;
|
|
952
999
|
delete data.type;
|
|
953
1000
|
delete data.linkDesc;
|
|
@@ -985,7 +1032,7 @@ export class Creatives extends React.Component {
|
|
|
985
1032
|
break;
|
|
986
1033
|
case constants.RCS: {
|
|
987
1034
|
if (template.value) {
|
|
988
|
-
const { name = "", versions = {}
|
|
1035
|
+
const { name = "", versions = {} } = {
|
|
989
1036
|
} = template.value || {};
|
|
990
1037
|
const {
|
|
991
1038
|
cardContent = [],
|
|
@@ -1113,7 +1160,6 @@ export class Creatives extends React.Component {
|
|
|
1113
1160
|
}
|
|
1114
1161
|
|
|
1115
1162
|
getFormData = (template) => {
|
|
1116
|
-
|
|
1117
1163
|
if (template.validity) {
|
|
1118
1164
|
this.setState(
|
|
1119
1165
|
{
|
|
@@ -1131,7 +1177,7 @@ export class Creatives extends React.Component {
|
|
|
1131
1177
|
);
|
|
1132
1178
|
}
|
|
1133
1179
|
}
|
|
1134
|
-
|
|
1180
|
+
|
|
1135
1181
|
processCentralCommsMetaId = (channel, creativesData) => {
|
|
1136
1182
|
// Create the payload for the centralcommnsmetaId API call
|
|
1137
1183
|
const { isLoyaltyModule = false, loyaltyMetaData = {} } = this.props;
|
|
@@ -1222,13 +1268,16 @@ export class Creatives extends React.Component {
|
|
|
1222
1268
|
|
|
1223
1269
|
shouldShowFooter = () => {
|
|
1224
1270
|
const { isFullMode } = this.props;
|
|
1225
|
-
const {
|
|
1271
|
+
const {
|
|
1272
|
+
slidBoxContent, currentChannel, emailCreateMode, templateNameExists, templateStep, mobilePushCreateMode, weChatTemplateType, templateData,
|
|
1273
|
+
} = this.state;
|
|
1226
1274
|
const channel = currentChannel.toUpperCase();
|
|
1227
1275
|
const currentStep = this.creativesTemplateSteps[templateStep];
|
|
1228
1276
|
let showFooter = false;
|
|
1229
1277
|
showFooter = isFullMode && slidBoxContent === "preview";
|
|
1230
1278
|
const isMobilepush = channel === constants.MOBILE_PUSH;
|
|
1231
|
-
|
|
1279
|
+
|
|
1280
|
+
|
|
1232
1281
|
if (!isFullMode) {
|
|
1233
1282
|
const isEmailCreate = slidBoxContent === 'createTemplate' && channel === constants.EMAIL && currentStep !== 'createTemplateContent';
|
|
1234
1283
|
const isCreate = (slidBoxContent === 'editTemplate' || slidBoxContent === 'createTemplate') && !isEmailCreate;
|
|
@@ -1250,15 +1299,15 @@ export class Creatives extends React.Component {
|
|
|
1250
1299
|
if (slidBoxContent === "editTemplate" && ((channel === constants.EMAIL && currentStep === 'modeSelection'))) {
|
|
1251
1300
|
showFooter = true;
|
|
1252
1301
|
}
|
|
1253
|
-
if (channel === constants.MOBILE_PUSH
|
|
1254
|
-
((slidBoxContent === 'createTemplate' && !isEmpty(mobilePushCreateMode))
|
|
1255
|
-
|| (slidBoxContent === 'editTemplate' && currentStep === 'modeSelection')) &&
|
|
1302
|
+
if (channel === constants.MOBILE_PUSH
|
|
1303
|
+
&& ((slidBoxContent === 'createTemplate' && !isEmpty(mobilePushCreateMode))
|
|
1304
|
+
|| (slidBoxContent === 'editTemplate' && (currentStep === 'modeSelection' || isFullMode))) &&
|
|
1256
1305
|
templateNameExists) {
|
|
1257
1306
|
showFooter = true;
|
|
1258
1307
|
}
|
|
1259
1308
|
|
|
1260
|
-
if (channel === constants.WECHAT
|
|
1261
|
-
((slidBoxContent === 'createTemplate' && !isEmpty(weChatTemplateType))
|
|
1309
|
+
if (channel === constants.WECHAT
|
|
1310
|
+
&& ((slidBoxContent === 'createTemplate' && !isEmpty(weChatTemplateType))
|
|
1262
1311
|
|| (slidBoxContent === 'editTemplate' && currentStep === 'modeSelection'))) {
|
|
1263
1312
|
showFooter = true;
|
|
1264
1313
|
}
|
|
@@ -1267,9 +1316,9 @@ export class Creatives extends React.Component {
|
|
|
1267
1316
|
if (slidBoxContent === "createTemplate" && ((channel === constants.EMAIL && currentStep === 'createTemplateContent') ||
|
|
1268
1317
|
([constants.SMS, constants.WECHAT].includes(channel) && currentStep === 'modeSelection'))) {
|
|
1269
1318
|
showFooter = showFooter && !this.state.isLoadingContent;
|
|
1270
|
-
} else if (slidBoxContent === "editTemplate"
|
|
1271
|
-
([constants.SMS, constants.WECHAT, constants.EMAIL].includes(channel)
|
|
1272
|
-
currentStep === 'modeSelection')) {
|
|
1319
|
+
} else if (slidBoxContent === "editTemplate"
|
|
1320
|
+
&& ([constants.SMS, constants.WECHAT, constants.EMAIL].includes(channel)
|
|
1321
|
+
&& currentStep === 'modeSelection')) {
|
|
1273
1322
|
showFooter = showFooter && !this.state.isLoadingContent;
|
|
1274
1323
|
}
|
|
1275
1324
|
}
|
|
@@ -1278,6 +1327,8 @@ export class Creatives extends React.Component {
|
|
|
1278
1327
|
if ([constants.LINE, constants.VIBER, constants.FACEBOOK].includes(channel) || isLineViberChannel) {
|
|
1279
1328
|
showFooter = false;
|
|
1280
1329
|
}
|
|
1330
|
+
|
|
1331
|
+
|
|
1281
1332
|
return showFooter;
|
|
1282
1333
|
}
|
|
1283
1334
|
|
|
@@ -1290,13 +1341,21 @@ export class Creatives extends React.Component {
|
|
|
1290
1341
|
let showDone = false;
|
|
1291
1342
|
const channelName = !isFullMode && templateData ? templateData.type : currentChannel;
|
|
1292
1343
|
const channel = channelName?.toUpperCase();
|
|
1344
|
+
|
|
1345
|
+
|
|
1293
1346
|
if (channel === constants.EMAIL || channel === constants.SMS) {
|
|
1294
1347
|
const isEmailCreate = slidBoxContent === 'createTemplate' && channel === constants.EMAIL && currentStep !== 'createTemplateContent';
|
|
1295
1348
|
showDone = (slidBoxContent === 'editTemplate' || slidBoxContent === 'createTemplate') && !isEmailCreate;
|
|
1296
1349
|
} else if ([constants.WECHAT, constants.MOBILE_PUSH].includes(channel)) {
|
|
1297
1350
|
showDone = currentStep === "createTemplateContent" || slidBoxContent === "editTemplate";
|
|
1351
|
+
|
|
1352
|
+
// Additional condition for MobilePush edit in full mode
|
|
1353
|
+
if (channel === constants.MOBILE_PUSH && slidBoxContent === "editTemplate" && isFullMode) {
|
|
1354
|
+
showDone = true;
|
|
1355
|
+
}
|
|
1298
1356
|
}
|
|
1299
1357
|
|
|
1358
|
+
|
|
1300
1359
|
return showDone;
|
|
1301
1360
|
}
|
|
1302
1361
|
|
|
@@ -1356,7 +1415,9 @@ export class Creatives extends React.Component {
|
|
|
1356
1415
|
}
|
|
1357
1416
|
|
|
1358
1417
|
shouldShowContinueFooter = () => { // only for email for now, has to be modified according to channel
|
|
1359
|
-
const {
|
|
1418
|
+
const {
|
|
1419
|
+
slidBoxContent, templateStep, currentChannel, emailCreateMode, mobilePushCreateMode, inAppCreateMode, weChatTemplateType,
|
|
1420
|
+
} = this.state;
|
|
1360
1421
|
let isShowContinueFooter = false;
|
|
1361
1422
|
const currentStep = this.creativesTemplateSteps[templateStep];
|
|
1362
1423
|
const channel = currentChannel.toUpperCase();
|
|
@@ -1439,17 +1500,16 @@ export class Creatives extends React.Component {
|
|
|
1439
1500
|
loyaltyMetaData = {},
|
|
1440
1501
|
} = this.props;
|
|
1441
1502
|
const mapTemplateCreate =
|
|
1442
|
-
slidBoxContent === "createTemplate"
|
|
1443
|
-
weChatTemplateType === MAP_TEMPLATE
|
|
1444
|
-
templateStep !== "modeSelection";
|
|
1445
|
-
const slideBoxWrapperMargin =
|
|
1446
|
-
|
|
1447
|
-
|
|
1448
|
-
|
|
1449
|
-
|
|
1450
|
-
|
|
1451
|
-
|
|
1452
|
-
: 0;
|
|
1503
|
+
slidBoxContent === "createTemplate"
|
|
1504
|
+
&& weChatTemplateType === MAP_TEMPLATE
|
|
1505
|
+
&& templateStep !== "modeSelection";
|
|
1506
|
+
const slideBoxWrapperMargin = (get(liquidErrorMessage, 'STANDARD_ERROR_MSG.length', 0) > 0 && get(liquidErrorMessage, 'LIQUID_ERROR_MSG.length', 0) > 0)
|
|
1507
|
+
? CAP_SPACE_64
|
|
1508
|
+
: get(liquidErrorMessage, 'LIQUID_ERROR_MSG.length', 0) > 0
|
|
1509
|
+
? CAP_SPACE_56
|
|
1510
|
+
: get(liquidErrorMessage, 'STANDARD_ERROR_MSG.length', 0) > 0
|
|
1511
|
+
? CAP_SPACE_32
|
|
1512
|
+
: 0;
|
|
1453
1513
|
/* TODO: Instead of passing down same props separately to each component down, write common function to these props and pass it accordingly */
|
|
1454
1514
|
return (
|
|
1455
1515
|
<SlideBoxWrapper slideBoxWrapperMargin={slideBoxWrapperMargin} className={classnames(`${classPrefix} ${isFullMode ? 'creatives-full-mode' : 'creatives-library-mode'} ${mapTemplateCreate ? 'map-template-create' : ''}`)}>
|
|
@@ -1577,7 +1637,6 @@ export class Creatives extends React.Component {
|
|
|
1577
1637
|
) : isLiquidValidationError && (
|
|
1578
1638
|
<CapRow className="template-footer-width">
|
|
1579
1639
|
{(() => {
|
|
1580
|
-
|
|
1581
1640
|
const errorsToShow = get(liquidErrorMessage, constants.LIQUID_ERROR_MSG, []);
|
|
1582
1641
|
const standardErrorsToShow = get(liquidErrorMessage, constants.STANDARD_ERROR_MSG, []);
|
|
1583
1642
|
return <ErrorInfoNote currentTab={activeFormBuilderTab?.toUpperCase()} errorMessages={{LIQUID_ERROR_MSG: errorsToShow, STANDARD_ERROR_MSG: standardErrorsToShow}} />;
|
|
@@ -1647,7 +1706,7 @@ function mapDispatchToProps(dispatch) {
|
|
|
1647
1706
|
const withConnect = connect(mapStatesToProps, mapDispatchToProps);
|
|
1648
1707
|
const withReducer = injectReducer({ key: 'creativesContainer', reducer: creativesContainerReducer });
|
|
1649
1708
|
const withSaga = injectSaga({ key: 'cap', saga: capSagaForFetchSchemaForEntity });
|
|
1650
|
-
const withLiquidSaga = injectSaga({ key: 'liquid', saga: capSagaLiquidEntity
|
|
1709
|
+
const withLiquidSaga = injectSaga({ key: 'liquid', saga: capSagaLiquidEntity, mode: DAEMON });
|
|
1651
1710
|
const withDefaultTempSaga = injectSaga({ key: 'creativesContainer', saga: v2TemplateSagaWatchGetDefaultBeeTemplates });
|
|
1652
1711
|
|
|
1653
|
-
export default compose(withSaga,withLiquidSaga, withDefaultTempSaga, withReducer, withConnect)(injectIntl(Creatives));
|
|
1712
|
+
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) => {
|
|
@@ -248,20 +248,13 @@ function getLinkTypeFields({inputFieldsArgs, fieldIndex, deepLinkOptions, formDa
|
|
|
248
248
|
}
|
|
249
249
|
|
|
250
250
|
function getContent(obj) {
|
|
251
|
-
const {
|
|
252
|
-
|
|
253
|
-
|
|
254
|
-
|
|
255
|
-
|
|
256
|
-
|
|
257
|
-
|
|
258
|
-
IOS: {
|
|
259
|
-
title: iosTitle,
|
|
260
|
-
message: iosMessage
|
|
261
|
-
} = {}
|
|
262
|
-
} = {}
|
|
263
|
-
} = {}
|
|
264
|
-
} = obj;
|
|
251
|
+
const base = obj?.versions?.base || {};
|
|
252
|
+
const android = base.ANDROID || {};
|
|
253
|
+
const ios = base.IOS || {};
|
|
254
|
+
const androidTitle = android.title || '';
|
|
255
|
+
const androidMessage = android.message || '';
|
|
256
|
+
const iosTitle = ios.title || '';
|
|
257
|
+
const iosMessage = ios.message || '';
|
|
265
258
|
return `${androidTitle} ${androidMessage} ${iosTitle} ${iosMessage}`;
|
|
266
259
|
}
|
|
267
260
|
export {
|