@capillarytech/creatives-library 8.0.123 → 8.0.125-alpha.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/containers/App/constants.js +1 -0
- package/package.json +1 -1
- package/services/api.js +1 -1
- package/tests/integration/TemplateCreation/TemplateCreation.integration.test.js +8 -3
- package/tests/integration/TemplateCreation/api-response.js +5 -0
- package/tests/integration/TemplateCreation/msw-handler.js +42 -63
- package/utils/common.js +7 -0
- package/utils/commonUtils.js +2 -6
- package/utils/createPayload.js +240 -0
- package/utils/tests/createPayload.test.js +761 -0
- package/v2Components/CapDeviceContent/index.js +1 -0
- package/v2Components/CapImageUpload/index.js +51 -45
- package/v2Components/CapInAppCTA/index.js +1 -0
- package/v2Components/CapMpushCTA/constants.js +25 -0
- package/v2Components/CapMpushCTA/index.js +332 -0
- package/v2Components/CapMpushCTA/index.scss +95 -0
- package/v2Components/CapMpushCTA/messages.js +89 -0
- package/v2Components/CapTagList/index.js +177 -120
- package/v2Components/CapVideoUpload/constants.js +3 -0
- package/v2Components/CapVideoUpload/index.js +167 -110
- package/v2Components/CapVideoUpload/messages.js +16 -0
- package/v2Components/Carousel/index.js +15 -13
- package/v2Components/ErrorInfoNote/style.scss +1 -0
- package/v2Components/MobilePushPreviewV2/index.js +37 -5
- package/v2Components/TemplatePreview/_templatePreview.scss +114 -72
- package/v2Components/TemplatePreview/assets/images/Android _ With date and time.svg +29 -0
- package/v2Components/TemplatePreview/assets/images/android.svg +9 -0
- package/v2Components/TemplatePreview/assets/images/iOS _ With date and time.svg +26 -0
- package/v2Components/TemplatePreview/assets/images/ios.svg +9 -0
- package/v2Components/TemplatePreview/index.js +178 -50
- package/v2Components/TemplatePreview/messages.js +4 -0
- package/v2Containers/CreativesContainer/SlideBoxContent.js +7 -8
- package/v2Containers/CreativesContainer/index.js +194 -138
- package/v2Containers/InApp/constants.js +1 -1
- package/v2Containers/InApp/index.js +13 -13
- package/v2Containers/MobilePush/Create/index.js +1 -0
- package/v2Containers/MobilePushNew/actions.js +116 -0
- package/v2Containers/MobilePushNew/components/CtaButtons.js +170 -0
- package/v2Containers/MobilePushNew/components/MediaUploaders.js +686 -0
- package/v2Containers/MobilePushNew/components/PlatformContentFields.js +279 -0
- package/v2Containers/MobilePushNew/components/index.js +5 -0
- package/v2Containers/MobilePushNew/components/tests/CtaButtons.test.js +779 -0
- package/v2Containers/MobilePushNew/components/tests/MediaUploaders.test.js +2114 -0
- package/v2Containers/MobilePushNew/components/tests/PlatformContentFields.test.js +343 -0
- package/v2Containers/MobilePushNew/constants.js +115 -0
- package/v2Containers/MobilePushNew/hooks/tests/usePlatformSync.test.js +1299 -0
- package/v2Containers/MobilePushNew/hooks/tests/useUpload.test.js +1223 -0
- package/v2Containers/MobilePushNew/hooks/usePlatformSync.js +246 -0
- package/v2Containers/MobilePushNew/hooks/useUpload.js +709 -0
- package/v2Containers/MobilePushNew/index.js +1937 -0
- package/v2Containers/MobilePushNew/index.scss +308 -0
- package/v2Containers/MobilePushNew/messages.js +226 -0
- package/v2Containers/MobilePushNew/reducer.js +160 -0
- package/v2Containers/MobilePushNew/sagas.js +198 -0
- package/v2Containers/MobilePushNew/selectors.js +55 -0
- package/v2Containers/MobilePushNew/tests/reducer.test.js +741 -0
- package/v2Containers/MobilePushNew/tests/sagas.test.js +863 -0
- package/v2Containers/MobilePushNew/tests/selectors.test.js +425 -0
- package/v2Containers/MobilePushNew/tests/utils.test.js +322 -0
- package/v2Containers/MobilePushNew/utils.js +33 -0
- package/v2Containers/Rcs/tests/__snapshots__/index.test.js.snap +5 -5
- package/v2Containers/TagList/index.js +56 -10
- package/v2Containers/Templates/_templates.scss +101 -1
- package/v2Containers/Templates/index.js +147 -35
- package/v2Containers/Templates/messages.js +8 -0
- package/v2Containers/Templates/sagas.js +2 -0
- package/v2Containers/Whatsapp/constants.js +1 -0
|
@@ -90,4 +90,8 @@ export default defineMessages({
|
|
|
90
90
|
id: `creatives.componentsV2.TemplatePreview.addToCart`,
|
|
91
91
|
defaultMessage: 'Add to cart',
|
|
92
92
|
},
|
|
93
|
+
videoNotSupported: {
|
|
94
|
+
id: 'creatives.componentsV2.TemplatePreview.videoNotSupported',
|
|
95
|
+
defaultMessage: 'Your browser does not support the video tag.',
|
|
96
|
+
},
|
|
93
97
|
});
|
|
@@ -7,17 +7,14 @@ import cloneDeep from 'lodash/cloneDeep';
|
|
|
7
7
|
import TemplatesV2 from '../TemplatesV2';
|
|
8
8
|
import TemplatePreview from '../../v2Components/TemplatePreview';
|
|
9
9
|
import SmsWrapper from '../SmsWrapper';
|
|
10
|
-
// import SmsEdit from '../Sms/Edit';
|
|
11
10
|
import Email from '../Email';
|
|
12
11
|
import EmailWrapper from '../EmailWrapper';
|
|
13
|
-
import MobilepushWrapper from '../MobilepushWrapper';
|
|
14
12
|
import EmailPreviewV2 from '../../v2Components/EmailPreviewV2';
|
|
15
13
|
import MobilePushPreview from '../../v2Components/MobilePushPreviewV2';
|
|
16
14
|
import WechatWrapper from '../WeChat/Wrapper';
|
|
17
15
|
import Facebook from '../Facebook';
|
|
18
16
|
import { RICH_MEDIA, MAP_TEMPLATE, CREATE } from '../WeChat/Wrapper/constants';
|
|
19
17
|
import CallTask from '../CallTask';
|
|
20
|
-
import MobliPushEdit from '../MobilePush/Edit';
|
|
21
18
|
import * as constants from './constants';
|
|
22
19
|
import LineContainer from '../Line/Container';
|
|
23
20
|
import FTP from '../FTP';
|
|
@@ -28,6 +25,7 @@ import Rcs from '../Rcs';
|
|
|
28
25
|
import { getWhatsappContent } from '../Whatsapp/utils';
|
|
29
26
|
import * as commonUtil from '../../utils/common';
|
|
30
27
|
import Zalo from '../Zalo';
|
|
28
|
+
import MobilePushNew from '../MobilePushNew';
|
|
31
29
|
const CreativesWrapper = styled.div`
|
|
32
30
|
.ant-popover,
|
|
33
31
|
.ant-notification,
|
|
@@ -476,9 +474,6 @@ export function SlideBoxContent(props) {
|
|
|
476
474
|
forwardedTags={forwardedTags}
|
|
477
475
|
/>
|
|
478
476
|
)}
|
|
479
|
-
{isMpushPreview &&
|
|
480
|
-
<MobilePushPreview templateData={templateData} channel={channel}/>
|
|
481
|
-
}
|
|
482
477
|
{
|
|
483
478
|
(currentChannel === constants.WECHAT && !!slidBoxContent) && <WechatWrapper
|
|
484
479
|
mode={slidBoxContent}
|
|
@@ -657,7 +652,7 @@ export function SlideBoxContent(props) {
|
|
|
657
652
|
/>
|
|
658
653
|
)}
|
|
659
654
|
{isEditMPush &&
|
|
660
|
-
<
|
|
655
|
+
<MobilePushNew
|
|
661
656
|
getFormLibraryData={getFormData}
|
|
662
657
|
setIsLoadingContent={setIsLoadingContent}
|
|
663
658
|
location={{
|
|
@@ -684,7 +679,7 @@ export function SlideBoxContent(props) {
|
|
|
684
679
|
/>
|
|
685
680
|
}
|
|
686
681
|
{isCreateMPush &&
|
|
687
|
-
<
|
|
682
|
+
<MobilePushNew
|
|
688
683
|
key="creatives-mobilepush-wrapper"
|
|
689
684
|
date={new Date().getMilliseconds()}
|
|
690
685
|
setIsLoadingContent={setIsLoadingContent}
|
|
@@ -692,8 +687,11 @@ export function SlideBoxContent(props) {
|
|
|
692
687
|
mobilePushCreateMode={mobilePushCreateMode}
|
|
693
688
|
isGetFormData={isGetFormData}
|
|
694
689
|
getFormData={getFormData}
|
|
690
|
+
location={location}
|
|
691
|
+
getDefaultTags={type}
|
|
695
692
|
templateData={templateData}
|
|
696
693
|
type={type}
|
|
694
|
+
handleClose={handleClose}
|
|
697
695
|
step={templateStep}
|
|
698
696
|
showNextStep={onCreateNextStep}
|
|
699
697
|
isFullMode={isFullMode}
|
|
@@ -711,6 +709,7 @@ export function SlideBoxContent(props) {
|
|
|
711
709
|
onTestContentClicked={onTestContentClicked}
|
|
712
710
|
eventContextTags={eventContextTags}
|
|
713
711
|
showLiquidErrorInFooter={showLiquidErrorInFooter}
|
|
712
|
+
onCreateComplete={onCreateComplete}
|
|
714
713
|
/>
|
|
715
714
|
}
|
|
716
715
|
{
|
|
@@ -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,17 +15,15 @@ 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
|
-
import SlideBoxHeader from './SlideBoxHeader';
|
|
27
|
-
import SlideBoxFooter from './SlideBoxFooter';
|
|
28
27
|
import * as constants from './constants';
|
|
29
28
|
import * as commonUtil from '../../utils/common';
|
|
30
29
|
import { gtmPush } from '../../utils/gtmTrackers';
|
|
@@ -43,20 +42,19 @@ import {
|
|
|
43
42
|
import { IMAGE, VIDEO } from '../Facebook/Advertisement/constant';
|
|
44
43
|
import { CREATIVE } from '../Facebook/constants';
|
|
45
44
|
import { LOYALTY } from '../App/constants';
|
|
46
|
-
import {
|
|
47
|
-
|
|
45
|
+
import {
|
|
46
|
+
WHATSAPP_STATUSES, WHATSAPP_MEDIA_TYPES, PHONE_NUMBER, URL,
|
|
47
|
+
} from '../Whatsapp/constants';
|
|
48
|
+
import SlideBoxHeader from './SlideBoxHeader';
|
|
49
|
+
import SlideBoxFooter from './SlideBoxFooter';
|
|
50
|
+
import SlideBoxContent from './SlideBoxContent';
|
|
48
51
|
import { updateImagesInHtml } from '../../utils/cdnTransformation';
|
|
49
|
-
|
|
52
|
+
|
|
50
53
|
import injectReducer from '../../utils/injectReducer';
|
|
51
54
|
import injectSaga from '../../utils/injectSaga';
|
|
52
55
|
import creativesContainerReducer from './reducer';
|
|
53
|
-
import {
|
|
54
|
-
import { capSagaForFetchSchemaForEntity,capSagaLiquidEntity } from '../Cap/sagas';
|
|
56
|
+
import { capSagaForFetchSchemaForEntity, capSagaLiquidEntity } from '../Cap/sagas';
|
|
55
57
|
import { v2TemplateSagaWatchGetDefaultBeeTemplates } from '../Templates/sagas';
|
|
56
|
-
import {
|
|
57
|
-
CAP_SPACE_32, CAP_SPACE_56, CAP_SPACE_64,
|
|
58
|
-
} from '@capillarytech/cap-ui-library/styled/variables';
|
|
59
|
-
import { DAEMON } from '@capillarytech/vulcan-react-sdk/utils/sagaInjectorTypes';
|
|
60
58
|
import { DYNAMIC_URL } from '../../v2Components/CapWhatsappCTA/constants';
|
|
61
59
|
import ErrorInfoNote from '../../v2Components/ErrorInfoNote';
|
|
62
60
|
|
|
@@ -82,11 +80,14 @@ const SlideBoxWrapper = styled.div`
|
|
|
82
80
|
export class Creatives extends React.Component {
|
|
83
81
|
constructor(props) {
|
|
84
82
|
super(props);
|
|
83
|
+
|
|
84
|
+
const initialSlidBoxContent = this.getSlideBoxContent({ mode: props.creativesMode, templateData: props.templateData, isFullMode: props.isFullMode });
|
|
85
|
+
|
|
85
86
|
this.state = {
|
|
86
87
|
isLoadingContent: true,
|
|
87
88
|
templateStep: 1, //modeSelection: for template name and (for email selecting upload or editor), and createTemplate to create template create based on modeSelection
|
|
88
89
|
showSlideBox: true,
|
|
89
|
-
slidBoxContent:
|
|
90
|
+
slidBoxContent: initialSlidBoxContent,
|
|
90
91
|
templateData: this.getTemplateData(props.templateData),
|
|
91
92
|
templateNameExists: props.creativesMode === 'edit', // if edit mode templateNameExists will be true, and false in create flow.
|
|
92
93
|
currentChannel: this.props.channel || 'sms',
|
|
@@ -151,28 +152,26 @@ export class Creatives extends React.Component {
|
|
|
151
152
|
const userId = parseInt(template.updatedBy, 10);
|
|
152
153
|
templateData.updatedByName = commonUtil.getUserNameById(userId, usersList);
|
|
153
154
|
this.setState({ slidBoxContent: constants.PREVIEW, templateData });
|
|
155
|
+
} else if (get(template, 'versions.base.content.zalo.previewUrl')) {
|
|
156
|
+
commonUtil.handlePreviewInNewTab(
|
|
157
|
+
template.versions.base.content.zalo.previewUrl
|
|
158
|
+
);
|
|
154
159
|
} else {
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
host: hostName || this.props?.hostName || this.props.Templates?.senderDetails?.hostName,
|
|
171
|
-
id: template?._id,
|
|
172
|
-
preview: true,
|
|
173
|
-
actionCallback: this.actionCallback,
|
|
174
|
-
});
|
|
175
|
-
}
|
|
160
|
+
const {
|
|
161
|
+
name = "",
|
|
162
|
+
sourceAccountIdentifier = "",
|
|
163
|
+
configs: { token = "" } = {},
|
|
164
|
+
hostName = "",
|
|
165
|
+
} = get(this.props, "Templates.selectedZaloAccount", {});
|
|
166
|
+
this.props.zaloActions.getTemplateInfoById({
|
|
167
|
+
username: name,
|
|
168
|
+
oa_id: sourceAccountIdentifier,
|
|
169
|
+
token,
|
|
170
|
+
host: hostName || this.props?.hostName || this.props.Templates?.senderDetails?.hostName,
|
|
171
|
+
id: template?._id,
|
|
172
|
+
preview: true,
|
|
173
|
+
actionCallback: this.actionCallback,
|
|
174
|
+
});
|
|
176
175
|
}
|
|
177
176
|
};
|
|
178
177
|
|
|
@@ -241,38 +240,40 @@ export class Creatives extends React.Component {
|
|
|
241
240
|
this.setState({ isGetFormData: false });
|
|
242
241
|
};
|
|
243
242
|
|
|
244
|
-
mapCarouselDataToCreatives = (cards) => {
|
|
245
|
-
|
|
246
|
-
|
|
247
|
-
|
|
248
|
-
|
|
249
|
-
|
|
250
|
-
|
|
251
|
-
|
|
252
|
-
|
|
253
|
-
|
|
254
|
-
|
|
255
|
-
|
|
256
|
-
|
|
257
|
-
|
|
243
|
+
mapCarouselDataToCreatives = (cards) => cards.map((card) => {
|
|
244
|
+
const {
|
|
245
|
+
cardVarMapped, bodyTemplate, media, buttons, mediaType,
|
|
246
|
+
} = card || {};
|
|
247
|
+
const buttonData = buttons?.map((button) => {
|
|
248
|
+
const {
|
|
249
|
+
type, text, phoneNumber, url, dynamicUrlPayload,
|
|
250
|
+
} = button || {};
|
|
251
|
+
const buttonObj = { type, text };
|
|
252
|
+
if (type === PHONE_NUMBER) {
|
|
253
|
+
buttonObj.phone_number = phoneNumber;
|
|
254
|
+
}
|
|
255
|
+
if (type === URL) {
|
|
256
|
+
buttonObj.url = url;
|
|
257
|
+
if (dynamicUrlPayload) {
|
|
258
|
+
buttonObj.urlType = DYNAMIC_URL;
|
|
258
259
|
}
|
|
259
|
-
|
|
260
|
-
|
|
261
|
-
return {
|
|
262
|
-
bodyText: bodyTemplate,
|
|
263
|
-
varMap: cardVarMapped,
|
|
264
|
-
...(mediaType === IMAGE && {
|
|
265
|
-
imageUrl: media?.url,
|
|
266
|
-
}),
|
|
267
|
-
...(mediaType === VIDEO && {
|
|
268
|
-
videoUrl: media?.url,
|
|
269
|
-
videoPreviewImg: media?.previewUrl,
|
|
270
|
-
}),
|
|
271
|
-
buttons: buttonData,
|
|
272
|
-
mediaType: mediaType?.toLowerCase(),
|
|
273
|
-
};
|
|
260
|
+
}
|
|
261
|
+
return buttonObj;
|
|
274
262
|
});
|
|
275
|
-
|
|
263
|
+
return {
|
|
264
|
+
bodyText: bodyTemplate,
|
|
265
|
+
varMap: cardVarMapped,
|
|
266
|
+
...(mediaType === IMAGE && {
|
|
267
|
+
imageUrl: media?.url,
|
|
268
|
+
}),
|
|
269
|
+
...(mediaType === VIDEO && {
|
|
270
|
+
videoUrl: media?.url,
|
|
271
|
+
videoPreviewImg: media?.previewUrl,
|
|
272
|
+
}),
|
|
273
|
+
buttons: buttonData,
|
|
274
|
+
mediaType: mediaType?.toLowerCase(),
|
|
275
|
+
};
|
|
276
|
+
})
|
|
276
277
|
|
|
277
278
|
getTemplateData = (templateData) => { //from consumers to creatives
|
|
278
279
|
const { isFullMode, messageDetails = {}, smsRegister } = this.props;
|
|
@@ -352,13 +353,33 @@ export class Creatives extends React.Component {
|
|
|
352
353
|
}
|
|
353
354
|
case constants.MOBILE_PUSH: {
|
|
354
355
|
const mode = get(templateData, 'androidContent.type') || get(templateData, 'iosContent.type') || '';
|
|
356
|
+
const androidCarouselMedia = get(templateData, 'androidContent.expandableDetails.media', []);
|
|
357
|
+
const iosCarouselMedia = get(templateData, 'iosContent.expandableDetails.media', []);
|
|
358
|
+
const androidContent = { ...(templateData?.androidContent || {}) };
|
|
359
|
+
const iosContent = { ...(templateData?.iosContent || {}) };
|
|
360
|
+
if (androidCarouselMedia?.length) {
|
|
361
|
+
androidContent.expandableDetails.carouselData = androidCarouselMedia.map((media) => ({
|
|
362
|
+
mediaType: media.type,
|
|
363
|
+
imageUrl: media.url,
|
|
364
|
+
buttons: [],
|
|
365
|
+
videoSrc: '',
|
|
366
|
+
}));
|
|
367
|
+
}
|
|
368
|
+
if (iosCarouselMedia?.length) {
|
|
369
|
+
iosContent.expandableDetails.carouselData = iosCarouselMedia.map((media) => ({
|
|
370
|
+
mediaType: media.type,
|
|
371
|
+
imageUrl: media.url,
|
|
372
|
+
buttons: [],
|
|
373
|
+
videoSrc: '',
|
|
374
|
+
}));
|
|
375
|
+
}
|
|
355
376
|
creativesTemplateData = {
|
|
356
377
|
type: channel,
|
|
357
378
|
name: templateData.messageSubject,
|
|
358
379
|
versions: {
|
|
359
380
|
base: {
|
|
360
|
-
ANDROID:
|
|
361
|
-
IOS:
|
|
381
|
+
ANDROID: androidContent,
|
|
382
|
+
IOS: iosContent,
|
|
362
383
|
},
|
|
363
384
|
},
|
|
364
385
|
definition: { accountId: templateData.accountId, mode: mode.toLowerCase() },
|
|
@@ -520,7 +541,9 @@ export class Creatives extends React.Component {
|
|
|
520
541
|
} = {},
|
|
521
542
|
} = templateData;
|
|
522
543
|
const mediaParams = {};
|
|
523
|
-
const {
|
|
544
|
+
const {
|
|
545
|
+
url = '', previewUrl = '', docParams = {}, footer = '', headerVarMapped = {}, headerTemplate = '',
|
|
546
|
+
} = whatsappMedia || {};
|
|
524
547
|
switch (mediaType) {
|
|
525
548
|
case (WHATSAPP_MEDIA_TYPES.IMAGE):
|
|
526
549
|
mediaParams.imageUrl = url;
|
|
@@ -540,7 +563,7 @@ export class Creatives extends React.Component {
|
|
|
540
563
|
break;
|
|
541
564
|
}
|
|
542
565
|
const modifiedButtons = cloneDeep(buttons)?.map((btn) => {
|
|
543
|
-
if (btn.type ===
|
|
566
|
+
if (btn.type === PHONE_NUMBER) {
|
|
544
567
|
btn.phone_number = btn.phoneNumber;
|
|
545
568
|
delete btn.phoneNumber;
|
|
546
569
|
return btn;
|
|
@@ -633,46 +656,61 @@ export class Creatives extends React.Component {
|
|
|
633
656
|
return templateData || null;
|
|
634
657
|
}
|
|
635
658
|
|
|
636
|
-
getCarouselMappedData = (carouselData = []) => {
|
|
637
|
-
|
|
638
|
-
|
|
639
|
-
|
|
640
|
-
|
|
641
|
-
|
|
642
|
-
|
|
643
|
-
|
|
644
|
-
|
|
645
|
-
|
|
646
|
-
|
|
647
|
-
|
|
648
|
-
}
|
|
649
|
-
if (type === URL) {
|
|
650
|
-
buttonObj.url = url;
|
|
651
|
-
if (urlType === DYNAMIC_URL) {
|
|
652
|
-
const dynamicUrlPayload = url?.match(/{{(.*?)}}/g);
|
|
653
|
-
buttonObj.dynamicUrlPayload = dynamicUrlPayload?.length === 1 ? dynamicUrlPayload[0] : '';
|
|
654
|
-
}
|
|
655
|
-
}
|
|
656
|
-
return buttonObj;
|
|
657
|
-
});
|
|
658
|
-
return {
|
|
659
|
-
body: bodyText,
|
|
660
|
-
cardVarMapped,
|
|
661
|
-
bodyTemplate,
|
|
662
|
-
media: {
|
|
663
|
-
...(mediaType?.toLowerCase() === IMAGE.toLowerCase() && {
|
|
664
|
-
url: imageUrl,
|
|
665
|
-
}),
|
|
666
|
-
...(mediaType?.toLowerCase() === VIDEO.toLowerCase() && {
|
|
667
|
-
url: videoUrl,
|
|
668
|
-
previewUrl: videoPreviewImg,
|
|
669
|
-
}),
|
|
670
|
-
},
|
|
671
|
-
buttons: buttonData,
|
|
672
|
-
mediaType: mediaType?.toUpperCase(),
|
|
659
|
+
getCarouselMappedData = (carouselData = []) => carouselData.map((carousel) => {
|
|
660
|
+
const {
|
|
661
|
+
bodyText, imageUrl, videoUrl, videoPreviewImg, buttons, mediaType, cardVarMapped, bodyTemplate,
|
|
662
|
+
} = carousel || {};
|
|
663
|
+
const buttonData = buttons.map((button, index) => {
|
|
664
|
+
const {
|
|
665
|
+
type, text, phone_number, urlType, url,
|
|
666
|
+
} = button || {};
|
|
667
|
+
const buttonObj = {
|
|
668
|
+
type,
|
|
669
|
+
text,
|
|
670
|
+
index,
|
|
673
671
|
};
|
|
672
|
+
if (type === PHONE_NUMBER) {
|
|
673
|
+
buttonObj.phoneNumber = phone_number;
|
|
674
|
+
}
|
|
675
|
+
if (type === URL) {
|
|
676
|
+
buttonObj.url = url;
|
|
677
|
+
if (urlType === DYNAMIC_URL) {
|
|
678
|
+
const dynamicUrlPayload = url?.match(/{{(.*?)}}/g);
|
|
679
|
+
buttonObj.dynamicUrlPayload = dynamicUrlPayload?.length === 1 ? dynamicUrlPayload[0] : '';
|
|
680
|
+
}
|
|
681
|
+
}
|
|
682
|
+
return buttonObj;
|
|
674
683
|
});
|
|
675
|
-
|
|
684
|
+
return {
|
|
685
|
+
body: bodyText,
|
|
686
|
+
cardVarMapped,
|
|
687
|
+
bodyTemplate,
|
|
688
|
+
media: {
|
|
689
|
+
...(mediaType?.toLowerCase() === IMAGE.toLowerCase() && {
|
|
690
|
+
url: imageUrl,
|
|
691
|
+
}),
|
|
692
|
+
...(mediaType?.toLowerCase() === VIDEO.toLowerCase() && {
|
|
693
|
+
url: videoUrl,
|
|
694
|
+
previewUrl: videoPreviewImg,
|
|
695
|
+
}),
|
|
696
|
+
},
|
|
697
|
+
buttons: buttonData,
|
|
698
|
+
mediaType: mediaType?.toUpperCase(),
|
|
699
|
+
};
|
|
700
|
+
});
|
|
701
|
+
|
|
702
|
+
getMobilePushCarouselData = (expandableDetails = []) => {
|
|
703
|
+
const newExpandableDetails = {...expandableDetails};
|
|
704
|
+
newExpandableDetails.style = expandableDetails.style || 'MANUAL_CAROUSEL';
|
|
705
|
+
newExpandableDetails.message = expandableDetails.message || '';
|
|
706
|
+
newExpandableDetails.ctas = expandableDetails.ctas || [];
|
|
707
|
+
newExpandableDetails.media = expandableDetails.carouselData.map((carousel) => ({
|
|
708
|
+
url: carousel.imageUrl,
|
|
709
|
+
type: carousel?.mediaType?.toUpperCase(),
|
|
710
|
+
text: '',
|
|
711
|
+
}));
|
|
712
|
+
return newExpandableDetails;
|
|
713
|
+
}
|
|
676
714
|
|
|
677
715
|
getCreativesData = async (channel, template, templateRecords) => { //from creatives to consumers
|
|
678
716
|
let templateData = { channel };
|
|
@@ -756,6 +794,9 @@ export class Creatives extends React.Component {
|
|
|
756
794
|
if (channel !== constants.MOBILE_PUSH) {
|
|
757
795
|
androidContent.custom = custom;
|
|
758
796
|
}
|
|
797
|
+
if (channel === constants.MOBILE_PUSH && androidContent?.expandableDetails?.carouselData?.length) {
|
|
798
|
+
androidContent.expandableDetails = this.getMobilePushCarouselData({...androidContent?.expandableDetails});
|
|
799
|
+
}
|
|
759
800
|
templateData.androidContent = androidContent;
|
|
760
801
|
templateData.androidContent.type = get(channelTemplate, 'definition.mode', '').toUpperCase();
|
|
761
802
|
templateData.androidContent.deviceType = constants.ANDROID;
|
|
@@ -775,6 +816,9 @@ export class Creatives extends React.Component {
|
|
|
775
816
|
if (channel !== constants.MOBILE_PUSH) {
|
|
776
817
|
iosContent.custom = custom;
|
|
777
818
|
}
|
|
819
|
+
if (channel === constants.MOBILE_PUSH && iosContent?.expandableDetails?.carouselData?.length) {
|
|
820
|
+
iosContent.expandableDetails = this.getMobilePushCarouselData({...iosContent?.expandableDetails});
|
|
821
|
+
}
|
|
778
822
|
templateData.iosContent = iosContent;
|
|
779
823
|
templateData.iosContent.type = get(channelTemplate, 'definition.mode').toUpperCase();
|
|
780
824
|
templateData.iosContent.deviceType = constants.IOS;
|
|
@@ -944,7 +988,7 @@ export class Creatives extends React.Component {
|
|
|
944
988
|
fBContent.forEach((obj) => {
|
|
945
989
|
const data = cloneDeep(obj);
|
|
946
990
|
const {
|
|
947
|
-
subType, linkDesc, imgSrc, webSiteLink, video
|
|
991
|
+
subType, linkDesc, imgSrc, webSiteLink, video,
|
|
948
992
|
} = obj;
|
|
949
993
|
delete data.type;
|
|
950
994
|
delete data.linkDesc;
|
|
@@ -982,7 +1026,7 @@ export class Creatives extends React.Component {
|
|
|
982
1026
|
break;
|
|
983
1027
|
case constants.RCS: {
|
|
984
1028
|
if (template.value) {
|
|
985
|
-
const { name = "", versions = {}
|
|
1029
|
+
const { name = "", versions = {} } = {
|
|
986
1030
|
} = template.value || {};
|
|
987
1031
|
const {
|
|
988
1032
|
cardContent = [],
|
|
@@ -1110,7 +1154,6 @@ export class Creatives extends React.Component {
|
|
|
1110
1154
|
}
|
|
1111
1155
|
|
|
1112
1156
|
getFormData = (template) => {
|
|
1113
|
-
|
|
1114
1157
|
if (template.validity) {
|
|
1115
1158
|
this.setState(
|
|
1116
1159
|
{
|
|
@@ -1128,7 +1171,7 @@ export class Creatives extends React.Component {
|
|
|
1128
1171
|
);
|
|
1129
1172
|
}
|
|
1130
1173
|
}
|
|
1131
|
-
|
|
1174
|
+
|
|
1132
1175
|
processCentralCommsMetaId = (channel, creativesData) => {
|
|
1133
1176
|
// Create the payload for the centralcommnsmetaId API call
|
|
1134
1177
|
const { isLoyaltyModule = false, loyaltyMetaData = {} } = this.props;
|
|
@@ -1209,13 +1252,16 @@ export class Creatives extends React.Component {
|
|
|
1209
1252
|
|
|
1210
1253
|
shouldShowFooter = () => {
|
|
1211
1254
|
const { isFullMode } = this.props;
|
|
1212
|
-
const {
|
|
1255
|
+
const {
|
|
1256
|
+
slidBoxContent, currentChannel, emailCreateMode, templateNameExists, templateStep, mobilePushCreateMode, weChatTemplateType, templateData,
|
|
1257
|
+
} = this.state;
|
|
1213
1258
|
const channel = currentChannel.toUpperCase();
|
|
1214
1259
|
const currentStep = this.creativesTemplateSteps[templateStep];
|
|
1215
1260
|
let showFooter = false;
|
|
1216
1261
|
showFooter = isFullMode && slidBoxContent === "preview";
|
|
1217
1262
|
const isMobilepush = channel === constants.MOBILE_PUSH;
|
|
1218
|
-
|
|
1263
|
+
|
|
1264
|
+
|
|
1219
1265
|
if (!isFullMode) {
|
|
1220
1266
|
const isEmailCreate = slidBoxContent === 'createTemplate' && channel === constants.EMAIL && currentStep !== 'createTemplateContent';
|
|
1221
1267
|
const isCreate = (slidBoxContent === 'editTemplate' || slidBoxContent === 'createTemplate') && !isEmailCreate;
|
|
@@ -1237,15 +1283,15 @@ export class Creatives extends React.Component {
|
|
|
1237
1283
|
if (slidBoxContent === "editTemplate" && ((channel === constants.EMAIL && currentStep === 'modeSelection'))) {
|
|
1238
1284
|
showFooter = true;
|
|
1239
1285
|
}
|
|
1240
|
-
if (channel === constants.MOBILE_PUSH
|
|
1241
|
-
((slidBoxContent === 'createTemplate' && !isEmpty(mobilePushCreateMode))
|
|
1242
|
-
|| (slidBoxContent === 'editTemplate' && currentStep === 'modeSelection')) &&
|
|
1286
|
+
if (channel === constants.MOBILE_PUSH
|
|
1287
|
+
&& ((slidBoxContent === 'createTemplate' && !isEmpty(mobilePushCreateMode))
|
|
1288
|
+
|| (slidBoxContent === 'editTemplate' && (currentStep === 'modeSelection' || isFullMode))) &&
|
|
1243
1289
|
templateNameExists) {
|
|
1244
1290
|
showFooter = true;
|
|
1245
1291
|
}
|
|
1246
1292
|
|
|
1247
|
-
if (channel === constants.WECHAT
|
|
1248
|
-
((slidBoxContent === 'createTemplate' && !isEmpty(weChatTemplateType))
|
|
1293
|
+
if (channel === constants.WECHAT
|
|
1294
|
+
&& ((slidBoxContent === 'createTemplate' && !isEmpty(weChatTemplateType))
|
|
1249
1295
|
|| (slidBoxContent === 'editTemplate' && currentStep === 'modeSelection'))) {
|
|
1250
1296
|
showFooter = true;
|
|
1251
1297
|
}
|
|
@@ -1254,9 +1300,9 @@ export class Creatives extends React.Component {
|
|
|
1254
1300
|
if (slidBoxContent === "createTemplate" && ((channel === constants.EMAIL && currentStep === 'createTemplateContent') ||
|
|
1255
1301
|
([constants.SMS, constants.WECHAT].includes(channel) && currentStep === 'modeSelection'))) {
|
|
1256
1302
|
showFooter = showFooter && !this.state.isLoadingContent;
|
|
1257
|
-
} else if (slidBoxContent === "editTemplate"
|
|
1258
|
-
([constants.SMS, constants.WECHAT, constants.EMAIL].includes(channel)
|
|
1259
|
-
currentStep === 'modeSelection')) {
|
|
1303
|
+
} else if (slidBoxContent === "editTemplate"
|
|
1304
|
+
&& ([constants.SMS, constants.WECHAT, constants.EMAIL].includes(channel)
|
|
1305
|
+
&& currentStep === 'modeSelection')) {
|
|
1260
1306
|
showFooter = showFooter && !this.state.isLoadingContent;
|
|
1261
1307
|
}
|
|
1262
1308
|
}
|
|
@@ -1265,6 +1311,8 @@ export class Creatives extends React.Component {
|
|
|
1265
1311
|
if ([constants.LINE, constants.VIBER, constants.FACEBOOK].includes(channel) || isLineViberChannel) {
|
|
1266
1312
|
showFooter = false;
|
|
1267
1313
|
}
|
|
1314
|
+
|
|
1315
|
+
|
|
1268
1316
|
return showFooter;
|
|
1269
1317
|
}
|
|
1270
1318
|
|
|
@@ -1277,13 +1325,21 @@ export class Creatives extends React.Component {
|
|
|
1277
1325
|
let showDone = false;
|
|
1278
1326
|
const channelName = !isFullMode && templateData ? templateData.type : currentChannel;
|
|
1279
1327
|
const channel = channelName && channelName.toUpperCase();
|
|
1328
|
+
|
|
1329
|
+
|
|
1280
1330
|
if (channel === constants.EMAIL || channel === constants.SMS) {
|
|
1281
1331
|
const isEmailCreate = slidBoxContent === 'createTemplate' && channel === constants.EMAIL && currentStep !== 'createTemplateContent';
|
|
1282
1332
|
showDone = (slidBoxContent === 'editTemplate' || slidBoxContent === 'createTemplate') && !isEmailCreate;
|
|
1283
1333
|
} else if ([constants.WECHAT, constants.MOBILE_PUSH].includes(channel)) {
|
|
1284
1334
|
showDone = currentStep === "createTemplateContent" || slidBoxContent === "editTemplate";
|
|
1335
|
+
|
|
1336
|
+
// Additional condition for MobilePush edit in full mode
|
|
1337
|
+
if (channel === constants.MOBILE_PUSH && slidBoxContent === "editTemplate" && isFullMode) {
|
|
1338
|
+
showDone = true;
|
|
1339
|
+
}
|
|
1285
1340
|
}
|
|
1286
1341
|
|
|
1342
|
+
|
|
1287
1343
|
return showDone;
|
|
1288
1344
|
}
|
|
1289
1345
|
|
|
@@ -1343,7 +1399,9 @@ export class Creatives extends React.Component {
|
|
|
1343
1399
|
}
|
|
1344
1400
|
|
|
1345
1401
|
shouldShowContinueFooter = () => { // only for email for now, has to be modified according to channel
|
|
1346
|
-
const {
|
|
1402
|
+
const {
|
|
1403
|
+
slidBoxContent, templateStep, currentChannel, emailCreateMode, mobilePushCreateMode, inAppCreateMode, weChatTemplateType,
|
|
1404
|
+
} = this.state;
|
|
1347
1405
|
let isShowContinueFooter = false;
|
|
1348
1406
|
const currentStep = this.creativesTemplateSteps[templateStep];
|
|
1349
1407
|
const channel = currentChannel.toUpperCase();
|
|
@@ -1425,17 +1483,16 @@ export class Creatives extends React.Component {
|
|
|
1425
1483
|
loyaltyMetaData = {},
|
|
1426
1484
|
} = this.props;
|
|
1427
1485
|
const mapTemplateCreate =
|
|
1428
|
-
slidBoxContent === "createTemplate"
|
|
1429
|
-
weChatTemplateType === MAP_TEMPLATE
|
|
1430
|
-
templateStep !== "modeSelection";
|
|
1431
|
-
const slideBoxWrapperMargin =
|
|
1432
|
-
|
|
1433
|
-
|
|
1434
|
-
|
|
1435
|
-
|
|
1436
|
-
|
|
1437
|
-
|
|
1438
|
-
: 0;
|
|
1486
|
+
slidBoxContent === "createTemplate"
|
|
1487
|
+
&& weChatTemplateType === MAP_TEMPLATE
|
|
1488
|
+
&& templateStep !== "modeSelection";
|
|
1489
|
+
const slideBoxWrapperMargin = (get(liquidErrorMessage, 'STANDARD_ERROR_MSG.length', 0) > 0 && get(liquidErrorMessage, 'LIQUID_ERROR_MSG.length', 0) > 0)
|
|
1490
|
+
? CAP_SPACE_64
|
|
1491
|
+
: get(liquidErrorMessage, 'LIQUID_ERROR_MSG.length', 0) > 0
|
|
1492
|
+
? CAP_SPACE_56
|
|
1493
|
+
: get(liquidErrorMessage, 'STANDARD_ERROR_MSG.length', 0) > 0
|
|
1494
|
+
? CAP_SPACE_32
|
|
1495
|
+
: 0;
|
|
1439
1496
|
/* TODO: Instead of passing down same props separately to each component down, write common function to these props and pass it accordingly */
|
|
1440
1497
|
return (
|
|
1441
1498
|
<SlideBoxWrapper slideBoxWrapperMargin={slideBoxWrapperMargin} className={classnames(`${classPrefix} ${isFullMode ? 'creatives-full-mode' : 'creatives-library-mode'} ${mapTemplateCreate ? 'map-template-create' : ''}`)}>
|
|
@@ -1555,7 +1612,6 @@ export class Creatives extends React.Component {
|
|
|
1555
1612
|
) : isLiquidValidationError && (
|
|
1556
1613
|
<CapRow className="template-footer-width">
|
|
1557
1614
|
{(() => {
|
|
1558
|
-
|
|
1559
1615
|
const errorsToShow = get(liquidErrorMessage, constants.LIQUID_ERROR_MSG, []);
|
|
1560
1616
|
const standardErrorsToShow = get(liquidErrorMessage, constants.STANDARD_ERROR_MSG, []);
|
|
1561
1617
|
return <ErrorInfoNote currentTab={activeFormBuilderTab?.toUpperCase()} errorMessages={{LIQUID_ERROR_MSG: errorsToShow, STANDARD_ERROR_MSG: standardErrorsToShow}} />;
|
|
@@ -1566,7 +1622,7 @@ export class Creatives extends React.Component {
|
|
|
1566
1622
|
show={showSlideBox}
|
|
1567
1623
|
size="size-xl"
|
|
1568
1624
|
/>
|
|
1569
|
-
|
|
1625
|
+
|
|
1570
1626
|
</SlideBoxWrapper>
|
|
1571
1627
|
);
|
|
1572
1628
|
}
|
|
@@ -1626,7 +1682,7 @@ function mapDispatchToProps(dispatch) {
|
|
|
1626
1682
|
const withConnect = connect(mapStatesToProps, mapDispatchToProps);
|
|
1627
1683
|
const withReducer = injectReducer({ key: 'creativesContainer', reducer: creativesContainerReducer });
|
|
1628
1684
|
const withSaga = injectSaga({ key: 'cap', saga: capSagaForFetchSchemaForEntity });
|
|
1629
|
-
const withLiquidSaga = injectSaga({ key: 'liquid', saga: capSagaLiquidEntity
|
|
1685
|
+
const withLiquidSaga = injectSaga({ key: 'liquid', saga: capSagaLiquidEntity, mode: DAEMON });
|
|
1630
1686
|
const withDefaultTempSaga = injectSaga({ key: 'creativesContainer', saga: v2TemplateSagaWatchGetDefaultBeeTemplates });
|
|
1631
1687
|
|
|
1632
|
-
export default compose(withSaga,withLiquidSaga, withDefaultTempSaga, withReducer, withConnect)(injectIntl(Creatives));
|
|
1688
|
+
export default compose(withSaga, withLiquidSaga, withDefaultTempSaga, withReducer, withConnect)(injectIntl(Creatives));
|
|
@@ -49,6 +49,7 @@ export const INAPP_BUTTON_TYPES = {
|
|
|
49
49
|
};
|
|
50
50
|
|
|
51
51
|
export const DEEP_LINK = 'DEEP_LINK';
|
|
52
|
+
export const EXTERNAL_LINK = 'EXTERNAL_LINK';
|
|
52
53
|
|
|
53
54
|
export const INITIAL_CTA_DATA = [
|
|
54
55
|
{
|
|
@@ -131,7 +132,6 @@ export const BUTTON_RADIO_OPTIONS = [
|
|
|
131
132
|
</div>
|
|
132
133
|
</>
|
|
133
134
|
),
|
|
134
|
-
disabled: true,
|
|
135
135
|
},
|
|
136
136
|
];
|
|
137
137
|
|