@capillarytech/creatives-library 2.0.79 → 2.0.81
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/components/CardGrid/index.js +1 -0
- package/components/EmailPreview/assets/images/iPad.svg +10 -0
- package/components/EmailPreview/assets/images/mobile.png +0 -0
- package/components/FormBuilder/index.js +3 -2
- package/components/FormBuilder/test +1845 -0
- package/containers/CallTask/_callTask.scss +5 -0
- package/containers/CallTask/actions.js +15 -0
- package/containers/CallTask/constants.js +7 -0
- package/containers/CallTask/index.js +141 -0
- package/containers/CallTask/messages.js +21 -0
- package/containers/CallTask/reducer.js +23 -0
- package/containers/CallTask/sagas.js +11 -0
- package/containers/CallTask/selectors.js +25 -0
- package/containers/CallTask/tests/actions.test.js +18 -0
- package/containers/CallTask/tests/index.test.js +10 -0
- package/containers/CallTask/tests/reducer.test.js +9 -0
- package/containers/CallTask/tests/sagas.test.js +15 -0
- package/containers/CallTask/tests/selectors.test.js +10 -0
- package/containers/ChannelTemplates/actions.js +20 -0
- package/containers/ChannelTemplates/constants.js +8 -0
- package/containers/ChannelTemplates/index.js +48 -0
- package/containers/ChannelTemplates/messages.js +13 -0
- package/containers/ChannelTemplates/reducer.js +34 -0
- package/containers/ChannelTemplates/sagas.js +32 -0
- package/containers/ChannelTemplates/selectors.js +25 -0
- package/containers/ChannelTemplates/tests/actions.test.js +18 -0
- package/containers/ChannelTemplates/tests/index.test.js +10 -0
- package/containers/ChannelTemplates/tests/reducer.test.js +9 -0
- package/containers/ChannelTemplates/tests/sagas.test.js +15 -0
- package/containers/ChannelTemplates/tests/selectors.test.js +10 -0
- package/containers/CreativesContainer/SlideBoxContent.js +248 -0
- package/containers/CreativesContainer/SlideBoxFooter.js +38 -0
- package/containers/CreativesContainer/SlideBoxHeader.js +65 -0
- package/containers/CreativesContainer/actions.js +27 -0
- package/containers/CreativesContainer/constants.js +13 -0
- package/containers/CreativesContainer/index.js +418 -0
- package/containers/CreativesContainer/index.scss +27 -0
- package/containers/CreativesContainer/messages.js +17 -0
- package/containers/CreativesContainer/reducer.js +29 -0
- package/containers/CreativesContainer/sagas.js +11 -0
- package/containers/CreativesContainer/selectors.js +30 -0
- package/containers/CreativesContainer/tests/actions.test.js +18 -0
- package/containers/CreativesContainer/tests/index.test.js +10 -0
- package/containers/CreativesContainer/tests/reducer.test.js +9 -0
- package/containers/CreativesContainer/tests/sagas.test.js +15 -0
- package/containers/CreativesContainer/tests/selectors.test.js +10 -0
- package/containers/EmailWrapper/actions.js +15 -0
- package/containers/EmailWrapper/constants.js +7 -0
- package/containers/EmailWrapper/index.js +238 -0
- package/containers/EmailWrapper/messages.js +57 -0
- package/containers/EmailWrapper/reducer.js +23 -0
- package/containers/EmailWrapper/sagas.js +11 -0
- package/containers/EmailWrapper/selectors.js +25 -0
- package/containers/EmailWrapper/tests/actions.test.js +18 -0
- package/containers/EmailWrapper/tests/index.test.js +10 -0
- package/containers/EmailWrapper/tests/reducer.test.js +9 -0
- package/containers/EmailWrapper/tests/sagas.test.js +15 -0
- package/containers/EmailWrapper/tests/selectors.test.js +10 -0
- package/containers/Line/Create/index.js +1 -1
- package/containers/MobilePush/Create/selectors.js +1 -1
- package/containers/MobilePush/Edit/selectors.js +1 -1
- package/containers/MobilePush/commonMethods.js +249 -0
- package/containers/MobilePush/eventsMap.js +127 -0
- package/containers/MobilePush/initialSchema.js +1739 -0
- package/containers/MobilepushWrapper/_mobilepushWrapper.scss +18 -0
- package/containers/MobilepushWrapper/index.js +97 -0
- package/containers/MobilepushWrapper/messages.js +25 -0
- package/containers/MobilepushWrapper/tests/index.test.js +10 -0
- package/containers/Templates/index.js +18 -14
- package/containers/TemplatesV2/_templatesV2.scss +5 -0
- package/containers/TemplatesV2/actions.js +16 -0
- package/containers/TemplatesV2/constants.js +10 -0
- package/containers/TemplatesV2/index.js +207 -0
- package/containers/TemplatesV2/messages.js +29 -0
- package/containers/TemplatesV2/selectors.js +25 -0
- package/containers/TemplatesV2/tests/actions.test.js +18 -0
- package/containers/TemplatesV2/tests/index.test.js +10 -0
- package/containers/TemplatesV2/tests/reducer.test.js +9 -0
- package/containers/TemplatesV2/tests/sagas.test.js +15 -0
- package/containers/TemplatesV2/tests/selectors.test.js +10 -0
- package/containers/WeChat/RichmediaTemplates/Create/testschema.js +379 -0
- package/containers/WeChat/_wechat.scss +8 -0
- package/containers/WeChat/actions.js +52 -0
- package/containers/WeChat/constants.js +28 -0
- package/containers/WeChat/index.js +1635 -0
- package/containers/WeChat/messages.js +73 -0
- package/containers/WeChat/reducer.js +74 -0
- package/containers/WeChat/sagas.js +86 -0
- package/containers/WeChat/selectors.js +25 -0
- package/containers/WeChat/tests/actions.test.js +18 -0
- package/{components/SmsPreviewV2 → containers/WeChat}/tests/index.test.js +2 -2
- package/containers/WeChat/tests/reducer.test.js +9 -0
- package/containers/WeChat/tests/sagas.test.js +15 -0
- package/containers/WeChat/tests/selectors.test.js +10 -0
- package/index.js +4 -3
- package/package.json +1 -1
- package/v2Containers/MobilePush/Create/index.js +43 -9
- package/v2Containers/MobilePush/Create/messages.js +16 -0
- package/v2Containers/MobilePush/Create/selectors.js +2 -1
- package/v2Containers/MobilePush/Edit/index.js +54 -22
- package/v2Containers/MobilePush/Edit/messages.js +17 -1
- package/v2Containers/MobilePush/Edit/selectors.js +2 -1
- package/v2Containers/MobilePush/commonMethods.js +9 -7
- package/v2Containers/WeChat/MapTemplates/index.js +5 -5
- package/assets/android-message-gui-2.svg +0 -55
- package/components/SmsPreviewV2/_smsPreviewV2.scss +0 -353
- package/components/SmsPreviewV2/index.js +0 -69
- package/components/SmsPreviewV2/messages.js +0 -13
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
.mobilepush-wrapper {
|
|
2
|
+
.ant-card-body {
|
|
3
|
+
padding: unset;
|
|
4
|
+
}
|
|
5
|
+
|
|
6
|
+
.ant-radio-group.cap-radioCard-v2 {
|
|
7
|
+
.ant-radio-button-wrapper{
|
|
8
|
+
width: 258px;
|
|
9
|
+
height: 258px;
|
|
10
|
+
}
|
|
11
|
+
.radio-card-header {
|
|
12
|
+
margin-top: 8px;
|
|
13
|
+
margin-left: 16px;
|
|
14
|
+
}
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
|
|
18
|
+
}
|
|
@@ -0,0 +1,97 @@
|
|
|
1
|
+
/*
|
|
2
|
+
*
|
|
3
|
+
* MobilepushWrapper
|
|
4
|
+
*
|
|
5
|
+
*/
|
|
6
|
+
import PropTypes from 'prop-types';
|
|
7
|
+
import React from 'react';
|
|
8
|
+
import { connect } from 'react-redux';
|
|
9
|
+
import { FormattedMessage } from 'react-intl';
|
|
10
|
+
import {CapRadioCard, CapHeader} from '@capillarytech/cap-ui-library';
|
|
11
|
+
import {isEmpty} from 'lodash';
|
|
12
|
+
import MobilepushCreate from '../MobilePush/Create';
|
|
13
|
+
import WithImage from '../../assets/WithImage1';
|
|
14
|
+
import WithNoImage from '../../assets/NoImage1';
|
|
15
|
+
import messages from './messages';
|
|
16
|
+
import './_mobilepushWrapper.scss';
|
|
17
|
+
export class MobilepushWrapper extends React.Component { // eslint-disable-line react/prefer-stateless-function
|
|
18
|
+
constructor(props) {
|
|
19
|
+
super(props);
|
|
20
|
+
this.modes = [
|
|
21
|
+
|
|
22
|
+
{
|
|
23
|
+
title: <FormattedMessage {...messages.image}/>,
|
|
24
|
+
content: <WithImage height="248px" width={"248px"}/>,
|
|
25
|
+
value: 'image',
|
|
26
|
+
},
|
|
27
|
+
{
|
|
28
|
+
title: <FormattedMessage {...messages.text}/>,
|
|
29
|
+
content: <WithNoImage height="124px" width={"248px"}/>,
|
|
30
|
+
value: 'text',
|
|
31
|
+
// onClick: () => {
|
|
32
|
+
// this.emailUploader.current.click();
|
|
33
|
+
// },
|
|
34
|
+
},
|
|
35
|
+
];
|
|
36
|
+
}
|
|
37
|
+
onChange = (e) => {
|
|
38
|
+
this.props.onMobilepushModeChange( e.target.value );
|
|
39
|
+
};
|
|
40
|
+
render() {
|
|
41
|
+
const {mobilePushCreateMode, step, getFormData, setIsLoadingContent, isGetFormData, query, isFullMode} = this.props;
|
|
42
|
+
const isShowMobilepushCreate = !isEmpty(mobilePushCreateMode);
|
|
43
|
+
return (
|
|
44
|
+
<div className="mobilepush-wrapper">
|
|
45
|
+
{step === "modeSelection" ?
|
|
46
|
+
<div>
|
|
47
|
+
<CapHeader size="small" title={<FormattedMessage {...messages.createMode}/>}/>
|
|
48
|
+
<CapRadioCard
|
|
49
|
+
panes={this.modes}
|
|
50
|
+
cardHeight={"286px"}
|
|
51
|
+
onChange={this.onChange}
|
|
52
|
+
selected={mobilePushCreateMode}
|
|
53
|
+
/>
|
|
54
|
+
</div>
|
|
55
|
+
:
|
|
56
|
+
<div>
|
|
57
|
+
{isShowMobilepushCreate && <MobilepushCreate
|
|
58
|
+
getFormLibraryData={getFormData}
|
|
59
|
+
setIsLoadingContent={setIsLoadingContent}
|
|
60
|
+
location={{
|
|
61
|
+
pathname: `/mobilepush/create/${mobilePushCreateMode}`,
|
|
62
|
+
query,
|
|
63
|
+
}}
|
|
64
|
+
params={{mode: mobilePushCreateMode}}
|
|
65
|
+
isFullMode={isFullMode}
|
|
66
|
+
isGetFormData={isGetFormData}
|
|
67
|
+
route={{ name: 'mobilepush' }}
|
|
68
|
+
/>
|
|
69
|
+
|
|
70
|
+
|
|
71
|
+
}
|
|
72
|
+
</div>
|
|
73
|
+
}
|
|
74
|
+
</div>
|
|
75
|
+
);
|
|
76
|
+
}
|
|
77
|
+
}
|
|
78
|
+
|
|
79
|
+
MobilepushWrapper.propTypes = {
|
|
80
|
+
onMobilepushModeChange: PropTypes.func,
|
|
81
|
+
mobilePushCreateMode: PropTypes.string,
|
|
82
|
+
step: PropTypes.string,
|
|
83
|
+
getFormData: PropTypes.string,
|
|
84
|
+
setIsLoadingContent: PropTypes.func,
|
|
85
|
+
isGetFormData: PropTypes.bool,
|
|
86
|
+
query: PropTypes.object,
|
|
87
|
+
isFullMode: PropTypes.bool,
|
|
88
|
+
};
|
|
89
|
+
|
|
90
|
+
|
|
91
|
+
function mapDispatchToProps(dispatch) {
|
|
92
|
+
return {
|
|
93
|
+
dispatch,
|
|
94
|
+
};
|
|
95
|
+
}
|
|
96
|
+
|
|
97
|
+
export default connect(null, mapDispatchToProps)(MobilepushWrapper);
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
/*
|
|
2
|
+
* MobilepushWrapper Messages
|
|
3
|
+
*
|
|
4
|
+
* This contains all the text for the MobilepushWrapper component.
|
|
5
|
+
*/
|
|
6
|
+
import { defineMessages } from 'react-intl';
|
|
7
|
+
|
|
8
|
+
export default defineMessages({
|
|
9
|
+
header: {
|
|
10
|
+
id: 'app.containers.MobilepushWrapper.header',
|
|
11
|
+
defaultMessage: 'This is MobilepushWrapper container !',
|
|
12
|
+
},
|
|
13
|
+
image: {
|
|
14
|
+
id: 'app.containers.MobilepushWrapper.image',
|
|
15
|
+
defaultMessage: 'Image content',
|
|
16
|
+
},
|
|
17
|
+
text: {
|
|
18
|
+
id: 'app.containers.MobilepushWrapper.text',
|
|
19
|
+
defaultMessage: 'Text content',
|
|
20
|
+
},
|
|
21
|
+
createMode: {
|
|
22
|
+
id: 'app.containers.MobilepushWrapper.createMode',
|
|
23
|
+
defaultMessage: 'Which type of content you want to create?',
|
|
24
|
+
},
|
|
25
|
+
});
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
// import React from 'react';
|
|
2
|
+
// import { shallow } from 'enzyme';
|
|
3
|
+
|
|
4
|
+
// import { MobilepushWrapper } from '../index';
|
|
5
|
+
|
|
6
|
+
describe('<MobilepushWrapper />', () => {
|
|
7
|
+
it('Expect to have unit tests specified', () => {
|
|
8
|
+
expect(true).toEqual(false);
|
|
9
|
+
});
|
|
10
|
+
});
|
|
@@ -1240,6 +1240,21 @@ export class Templates extends React.Component { // eslint-disable-line react/pr
|
|
|
1240
1240
|
}
|
|
1241
1241
|
}
|
|
1242
1242
|
|
|
1243
|
+
isLoading = () => {
|
|
1244
|
+
const lineLoader = (this.props.Templates.getAllTemplatesInProgress && this.state.channel.toLowerCase() === 'line');
|
|
1245
|
+
const smsLoader = (this.props.Templates.getAllTemplatesInProgress && this.state.channel.toLowerCase() === 'sms');
|
|
1246
|
+
const wechatLoader = (((this.state.selectedAccount !== '' && this.props.Templates.getAllTemplatesInProgress) || (this.props.Templates.fetchingWeCrmAccounts)) && this.state.channel.toLowerCase() === 'wechat');
|
|
1247
|
+
const mobilePushLoader = (((this.props.Templates.getAllTemplatesInProgress) || (this.props.Templates.fetchingWeCrmAccounts)) && this.state.channel.toLowerCase() === 'mobilepush');
|
|
1248
|
+
const emailLoader = ((this.props.Templates.getAllTemplatesInProgress || this.props.Templates.sendingFile) && this.state.channel.toLowerCase() === 'email');
|
|
1249
|
+
const ebillLoader = ((this.props.Templates.getAllTemplatesInProgress || this.props.Templates.sendingFile) && this.state.channel.toLowerCase() === 'ebill');
|
|
1250
|
+
const isLoading = ((wechatLoader !== undefined) ? wechatLoader : false) ||
|
|
1251
|
+
(smsLoader !== undefined ? smsLoader : false) ||
|
|
1252
|
+
(emailLoader !== undefined ? emailLoader : false) ||
|
|
1253
|
+
(ebillLoader !== undefined ? ebillLoader : false) ||
|
|
1254
|
+
(mobilePushLoader !== undefined ? mobilePushLoader : false) ||
|
|
1255
|
+
(lineLoader !== undefined ? lineLoader : false);
|
|
1256
|
+
return isLoading;
|
|
1257
|
+
}
|
|
1243
1258
|
renderDeleteConfirmationModal = () => {
|
|
1244
1259
|
const modal =
|
|
1245
1260
|
(<Modal
|
|
@@ -1259,6 +1274,7 @@ export class Templates extends React.Component { // eslint-disable-line react/pr
|
|
|
1259
1274
|
return modal;
|
|
1260
1275
|
};
|
|
1261
1276
|
|
|
1277
|
+
|
|
1262
1278
|
renderEmailPreviewModal() {
|
|
1263
1279
|
const slideboxContent = (
|
|
1264
1280
|
<div style={{height: "75vh", width: '55vw'}}>
|
|
@@ -1276,7 +1292,6 @@ export class Templates extends React.Component { // eslint-disable-line react/pr
|
|
|
1276
1292
|
/>
|
|
1277
1293
|
);
|
|
1278
1294
|
}
|
|
1279
|
-
|
|
1280
1295
|
render() {
|
|
1281
1296
|
let pageHeaderText = '';
|
|
1282
1297
|
const moduleName = this.props.location.query.module;
|
|
@@ -1492,18 +1507,7 @@ export class Templates extends React.Component { // eslint-disable-line react/pr
|
|
|
1492
1507
|
}
|
|
1493
1508
|
}
|
|
1494
1509
|
|
|
1495
|
-
|
|
1496
|
-
const smsLoader = (this.props.Templates.getAllTemplatesInProgress && this.state.channel.toLowerCase() === 'sms');
|
|
1497
|
-
const wechatLoader = (((this.state.selectedAccount !== '' && this.props.Templates.getAllTemplatesInProgress) || (this.props.Templates.fetchingWeCrmAccounts)) && this.state.channel.toLowerCase() === 'wechat');
|
|
1498
|
-
const mobilePushLoader = (((this.props.Templates.getAllTemplatesInProgress) || (this.props.Templates.fetchingWeCrmAccounts)) && this.state.channel.toLowerCase() === 'mobilepush');
|
|
1499
|
-
const emailLoader = ((this.props.Templates.getAllTemplatesInProgress || this.props.Templates.sendingFile) && this.state.channel.toLowerCase() === 'email');
|
|
1500
|
-
const ebillLoader = ((this.props.Templates.getAllTemplatesInProgress || this.props.Templates.sendingFile) && this.state.channel.toLowerCase() === 'ebill');
|
|
1501
|
-
const isLoading = ((wechatLoader !== undefined) ? wechatLoader : false) ||
|
|
1502
|
-
(smsLoader !== undefined ? smsLoader : false) ||
|
|
1503
|
-
(emailLoader !== undefined ? emailLoader : false) ||
|
|
1504
|
-
(ebillLoader !== undefined ? ebillLoader : false) ||
|
|
1505
|
-
(mobilePushLoader !== undefined ? mobilePushLoader : false) ||
|
|
1506
|
-
(lineLoader !== undefined ? lineLoader : false);
|
|
1510
|
+
|
|
1507
1511
|
let previewHeader = this.props.intl.formatMessage(messages.preview);
|
|
1508
1512
|
// const previewHeader = (this.state.channel.toLowerCase() === 'email' ? <h3>{this.props.intl.formatMessage(messages.emailPreview)}</h3> : <h3>{this.props.intl.formatMessage(messages.ebillPreview)}</h3>);
|
|
1509
1513
|
if (this.state.channel.toLowerCase() === 'email' || this.state.channel.toLowerCase() === 'ebill') {
|
|
@@ -1538,7 +1542,7 @@ export class Templates extends React.Component { // eslint-disable-line react/pr
|
|
|
1538
1542
|
<div>
|
|
1539
1543
|
<Spin
|
|
1540
1544
|
tip={(this.props.Templates.sendingFile && (this.state.channel.toLowerCase() === 'email' || this.state.channel.toLowerCase() === 'ebill')) ? this.props.intl.formatMessage(messages.uploadingFile) : this.props.intl.formatMessage(messages.gettingAllTemplates)}
|
|
1541
|
-
spinning={isLoading}
|
|
1545
|
+
spinning={this.isLoading()}
|
|
1542
1546
|
>
|
|
1543
1547
|
<input type="file" id="filename" style={{ display: 'none'}} accept=".zip, .html, .htm" onChange={(event) => this.handleFileUpload(event, {files: event.target.files})} />
|
|
1544
1548
|
<Row>
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
|
|
2
|
+
import * as types from './constants';
|
|
3
|
+
|
|
4
|
+
export function defaultAction() {
|
|
5
|
+
return {
|
|
6
|
+
type: types.DEFAULT_ACTION,
|
|
7
|
+
};
|
|
8
|
+
}
|
|
9
|
+
|
|
10
|
+
export function getTemplates({channel, query}) {
|
|
11
|
+
return {
|
|
12
|
+
type: types.GET_TEMPLATES_REQUEST,
|
|
13
|
+
channel,
|
|
14
|
+
query,
|
|
15
|
+
};
|
|
16
|
+
}
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
/*
|
|
2
|
+
*
|
|
3
|
+
* TemplatesV2 constants
|
|
4
|
+
*
|
|
5
|
+
*/
|
|
6
|
+
|
|
7
|
+
export const DEFAULT_ACTION = 'app/TemplatesV2/DEFAULT_ACTION';
|
|
8
|
+
export const GET_TEMPLATES_REQUEST = 'app/TemplatesV2/GET_TEMPLATES_REQUEST';
|
|
9
|
+
export const GET_TEMPLATES_SUCESS = 'app/TemplatesV2/GET_TEMPLATES_SUCESS';
|
|
10
|
+
export const GET_TEMPLATES_FAILURE = 'app/TemplatesV2/GET_TEMPLATES_FAILURE';
|
|
@@ -0,0 +1,207 @@
|
|
|
1
|
+
/*
|
|
2
|
+
*
|
|
3
|
+
* TemplatesV2
|
|
4
|
+
*
|
|
5
|
+
*/
|
|
6
|
+
|
|
7
|
+
import PropTypes from 'prop-types';
|
|
8
|
+
|
|
9
|
+
import React from 'react';
|
|
10
|
+
import { connect } from 'react-redux';
|
|
11
|
+
import { injectIntl, intlShape, FormattedMessage } from 'react-intl';
|
|
12
|
+
import { createStructuredSelector } from 'reselect';
|
|
13
|
+
import { bindActionCreators } from 'redux';
|
|
14
|
+
import styled from 'styled-components';
|
|
15
|
+
import { CapTab, CapCustomCard, CapButton, CapHeader, CapSpin, CapIcon } from '@capillarytech/cap-ui-library';
|
|
16
|
+
import { find, get } from 'lodash';
|
|
17
|
+
import Helmet from 'react-helmet';
|
|
18
|
+
|
|
19
|
+
import {CAP_SPACE_24, CAP_SPACE_16} from '@capillarytech/cap-ui-library/styled/variables';
|
|
20
|
+
import { UserIsAuthenticated } from '../../utils/authWrapper';
|
|
21
|
+
import { makeSelectTemplates, makeSelectTemplatesResponse } from '../Templates/selectors';
|
|
22
|
+
import messages from './messages';
|
|
23
|
+
import * as actions from './actions';
|
|
24
|
+
import Templates from '../Templates';
|
|
25
|
+
import CallTask from '../CallTask';
|
|
26
|
+
import './_templatesV2.scss';
|
|
27
|
+
|
|
28
|
+
const {CapCustomCardList} = CapCustomCard;
|
|
29
|
+
|
|
30
|
+
const ComponentWrapper = styled.div`
|
|
31
|
+
${(props) => props.isFullMode ? `
|
|
32
|
+
max-width: 1140px;
|
|
33
|
+
margin: 0 auto;
|
|
34
|
+
width: 100%;
|
|
35
|
+
padding: ${CAP_SPACE_24} 0;
|
|
36
|
+
.ant-tabs-content{
|
|
37
|
+
margin-top: ${CAP_SPACE_16}
|
|
38
|
+
}
|
|
39
|
+
` : `.cap-tab-v2 {
|
|
40
|
+
height: calc(100vh - 118px);
|
|
41
|
+
} `}
|
|
42
|
+
|
|
43
|
+
|
|
44
|
+
`;
|
|
45
|
+
const MarginTop = styled.div`
|
|
46
|
+
${(props) => props.isFullMode ? `margin-top: ${CAP_SPACE_24}` : ``
|
|
47
|
+
}
|
|
48
|
+
`;
|
|
49
|
+
export class TemplatesV2 extends React.Component { // eslint-disable-line react/prefer-stateless-function
|
|
50
|
+
constructor(props) {
|
|
51
|
+
super(props);
|
|
52
|
+
const defaultChannel = get(this, 'props.channel') || get(this, 'props.params.channel') || 'sms';
|
|
53
|
+
const defaultPanes = [
|
|
54
|
+
{content: <div></div>, tab: 'Sms', key: 'sms'},
|
|
55
|
+
{content: <div></div>, tab: 'Email', key: 'email'},
|
|
56
|
+
// {content: this.getTemplatesComponent('wechat'), tab: 'Wechat', key: 'wechat'},
|
|
57
|
+
{content: <div></div>, tab: 'Mpush', key: 'mobilepush'},
|
|
58
|
+
];
|
|
59
|
+
if (!props.isFullMode) {
|
|
60
|
+
defaultPanes.push({content: <div></div>, tab: 'Call Task', key: 'call_task'});
|
|
61
|
+
}
|
|
62
|
+
const panes = this.setChannelContent(defaultChannel, defaultPanes);
|
|
63
|
+
this.state = {
|
|
64
|
+
selectedChannel: defaultChannel,
|
|
65
|
+
panes,
|
|
66
|
+
};
|
|
67
|
+
}
|
|
68
|
+
componentWillReceiveProps(nextProps) {
|
|
69
|
+
if (this.props.channel !== nextProps.channel) {
|
|
70
|
+
const panes = this.setChannelContent(nextProps.channel, this.state.panes);
|
|
71
|
+
this.setState({selectedChannel: nextProps.channel, panes });
|
|
72
|
+
}
|
|
73
|
+
}
|
|
74
|
+
getTemplateDataForGrid = ({templates, handlers, filterContent, channel, isLoading, loadingTip}) => {
|
|
75
|
+
const currentChannel = channel.toUpperCase();
|
|
76
|
+
const cardDataList = templates.map((template) => {
|
|
77
|
+
const templateData =
|
|
78
|
+
{
|
|
79
|
+
key: `${currentChannel}-card-${template.name}`,
|
|
80
|
+
title: <span title={template.name} >{template.name}</span>,
|
|
81
|
+
extra: [<CapIcon type="eye" onClick={() => { if (this.props.isFullMode) { handlers.handlePreviewClick(template); } else { this.props.handlePeviewTemplate(template); } }} />],
|
|
82
|
+
hoverOption: <CapButton onClick={(e) => handlers.handleEditClick(e, template._id)}>{this.props.intl.formatMessage(this.props.isFullMode ? messages.edit : messages.select)}</CapButton>,
|
|
83
|
+
};
|
|
84
|
+
if (currentChannel === "SMS") {
|
|
85
|
+
templateData.content = template.versions.base['sms-editor'];
|
|
86
|
+
} else if (currentChannel === "EMAIL") {
|
|
87
|
+
templateData.url = template.versions.base.preview_http_url;
|
|
88
|
+
}
|
|
89
|
+
return templateData;
|
|
90
|
+
});
|
|
91
|
+
return (<div>
|
|
92
|
+
{filterContent}
|
|
93
|
+
<CapSpin spinning={isLoading} tip={loadingTip}>
|
|
94
|
+
<div className="pagination-container">
|
|
95
|
+
<CapCustomCardList key={`${currentChannel}-card-list`} cardList={cardDataList} type={currentChannel} />
|
|
96
|
+
</div>
|
|
97
|
+
</CapSpin>
|
|
98
|
+
|
|
99
|
+
</div>);
|
|
100
|
+
}
|
|
101
|
+
|
|
102
|
+
getCallTaskComponent = () => <CallTask onCreateNew={this.props.createNew} onCallTaskSubmit={this.props.onCallTaskSubmit}/>
|
|
103
|
+
|
|
104
|
+
getTemplatesComponent(channel) {
|
|
105
|
+
// const templates = this.props.Templates[`${channel}Templates`];
|
|
106
|
+
let query = {};
|
|
107
|
+
if (!this.props.isFullMode) {
|
|
108
|
+
query = {type: 'embedded', module: 'library'};
|
|
109
|
+
}
|
|
110
|
+
return (channel === 'call_task' ?
|
|
111
|
+
this.getCallTaskComponent() :
|
|
112
|
+
<Templates
|
|
113
|
+
key={channel}
|
|
114
|
+
location={{pathname: `/${channel}`, search: '', query}}
|
|
115
|
+
route={{name: channel}}
|
|
116
|
+
router={this.props.router}
|
|
117
|
+
isFullMode={this.props.isFullMode}
|
|
118
|
+
createNew={this.props.createNew}
|
|
119
|
+
onSelectTemplate={(id) => this.props.onSelectTemplate(this.selectTemplate(id))}
|
|
120
|
+
renderNewCardGrid={this.getTemplateDataForGrid}
|
|
121
|
+
handlePeviewTemplate={this.props.handlePeviewTemplate}
|
|
122
|
+
/>);
|
|
123
|
+
}
|
|
124
|
+
|
|
125
|
+
setChannelContent = (selectedChannel, argsPanes) => {
|
|
126
|
+
const panes = argsPanes.map((p) => {
|
|
127
|
+
const pane = p;
|
|
128
|
+
if (pane.key === selectedChannel) {
|
|
129
|
+
let channel = selectedChannel;
|
|
130
|
+
if (channel === "mpush") {
|
|
131
|
+
channel = "mobilepush";
|
|
132
|
+
}
|
|
133
|
+
pane.content = this.getTemplatesComponent(channel);
|
|
134
|
+
return pane;
|
|
135
|
+
}
|
|
136
|
+
return {...pane, content: <div></div>};
|
|
137
|
+
});
|
|
138
|
+
return panes;
|
|
139
|
+
}
|
|
140
|
+
channelChange = (selectedChannel) => {
|
|
141
|
+
const panes = this.setChannelContent(selectedChannel, this.state.panes);
|
|
142
|
+
this.setState({panes, selectedChannel}, () => { if (!this.props.isFullMode) this.props.onChannelChange(selectedChannel); });
|
|
143
|
+
}
|
|
144
|
+
selectTemplate = (id) => find(this.props.TemplatesList, {_id: id})
|
|
145
|
+
|
|
146
|
+
isLoading() {
|
|
147
|
+
return this.props.Templates.loadingTemplates;
|
|
148
|
+
}
|
|
149
|
+
render() {
|
|
150
|
+
const {isFullMode} = this.props;
|
|
151
|
+
return (
|
|
152
|
+
<div>
|
|
153
|
+
{isFullMode && <Helmet
|
|
154
|
+
title={this.props.intl.formatMessage(messages.creatives)}
|
|
155
|
+
meta={[
|
|
156
|
+
{ name: 'description', content: this.props.intl.formatMessage(messages.creativesDesc) },
|
|
157
|
+
]}
|
|
158
|
+
/>}
|
|
159
|
+
<ComponentWrapper isFullMode={isFullMode}>
|
|
160
|
+
|
|
161
|
+
{isFullMode && <CapHeader title={<FormattedMessage {...messages.creatives}/>} description={<FormattedMessage {...messages.creativesDesc}/>}/>}
|
|
162
|
+
<MarginTop isFullMode={isFullMode}>
|
|
163
|
+
<CapTab
|
|
164
|
+
panes={this.state.panes}
|
|
165
|
+
onChange={this.channelChange}
|
|
166
|
+
activeKey={this.state.selectedChannel}
|
|
167
|
+
defaultActiveKey={this.state.selectedChannel}/>
|
|
168
|
+
</MarginTop>
|
|
169
|
+
|
|
170
|
+
|
|
171
|
+
</ComponentWrapper>
|
|
172
|
+
</div>
|
|
173
|
+
|
|
174
|
+
);
|
|
175
|
+
}
|
|
176
|
+
}
|
|
177
|
+
|
|
178
|
+
TemplatesV2.propTypes = {
|
|
179
|
+
router: PropTypes.object,
|
|
180
|
+
isFullMode: PropTypes.bool,
|
|
181
|
+
onSelectTemplate: PropTypes.func,
|
|
182
|
+
createNew: PropTypes.func,
|
|
183
|
+
channel: PropTypes.string,
|
|
184
|
+
Templates: PropTypes.object,
|
|
185
|
+
TemplatesList: PropTypes.arrayOf(PropTypes.object),
|
|
186
|
+
handlePeviewTemplate: PropTypes.func,
|
|
187
|
+
onCallTaskSubmit: PropTypes.func,
|
|
188
|
+
intl: intlShape,
|
|
189
|
+
onChannelChange: PropTypes.func,
|
|
190
|
+
};
|
|
191
|
+
|
|
192
|
+
TemplatesV2.defaultProps = {
|
|
193
|
+
isFullMode: true,
|
|
194
|
+
};
|
|
195
|
+
|
|
196
|
+
const mapStateToProps = createStructuredSelector({
|
|
197
|
+
Templates: makeSelectTemplates(),
|
|
198
|
+
TemplatesList: makeSelectTemplatesResponse(),
|
|
199
|
+
});
|
|
200
|
+
|
|
201
|
+
function mapDispatchToProps(dispatch) {
|
|
202
|
+
return {
|
|
203
|
+
actions: bindActionCreators(actions, dispatch),
|
|
204
|
+
};
|
|
205
|
+
}
|
|
206
|
+
|
|
207
|
+
export default UserIsAuthenticated(connect(mapStateToProps, mapDispatchToProps)(injectIntl(TemplatesV2)));
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
/*
|
|
2
|
+
* TemplatesV2 Messages
|
|
3
|
+
*
|
|
4
|
+
* This contains all the text for the TemplatesV2 component.
|
|
5
|
+
*/
|
|
6
|
+
import { defineMessages } from 'react-intl';
|
|
7
|
+
|
|
8
|
+
export default defineMessages({
|
|
9
|
+
header: {
|
|
10
|
+
id: 'app.containers.TemplatesV2.header',
|
|
11
|
+
defaultMessage: 'This is TemplatesV2 container !',
|
|
12
|
+
},
|
|
13
|
+
select: {
|
|
14
|
+
id: 'app.containers.TemplatesV2.select',
|
|
15
|
+
defaultMessage: 'Select',
|
|
16
|
+
},
|
|
17
|
+
edit: {
|
|
18
|
+
id: 'app.containers.TemplatesV2.edit',
|
|
19
|
+
defaultMessage: 'Edit',
|
|
20
|
+
},
|
|
21
|
+
creatives: {
|
|
22
|
+
id: 'app.containers.TemplatesV2.creatives',
|
|
23
|
+
defaultMessage: 'Creatives',
|
|
24
|
+
},
|
|
25
|
+
creativesDesc: {
|
|
26
|
+
id: 'app.containers.TemplatesV2.creativesDesc',
|
|
27
|
+
defaultMessage: 'These are pre-built templates which you could use to customize your message content.',
|
|
28
|
+
},
|
|
29
|
+
});
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
import { createSelector } from 'reselect';
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* Direct selector to the templatesV2 state domain
|
|
5
|
+
*/
|
|
6
|
+
const selectTemplatesV2Domain = () => (state) => state.get('templatesV2');
|
|
7
|
+
|
|
8
|
+
/**
|
|
9
|
+
* Other specific selectors
|
|
10
|
+
*/
|
|
11
|
+
|
|
12
|
+
|
|
13
|
+
/**
|
|
14
|
+
* Default selector used by TemplatesV2
|
|
15
|
+
*/
|
|
16
|
+
|
|
17
|
+
const makeSelectTemplatesV2 = () => createSelector(
|
|
18
|
+
selectTemplatesV2Domain(),
|
|
19
|
+
(substate) => substate.toJS()
|
|
20
|
+
);
|
|
21
|
+
|
|
22
|
+
export default makeSelectTemplatesV2;
|
|
23
|
+
export {
|
|
24
|
+
selectTemplatesV2Domain,
|
|
25
|
+
};
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
|
|
2
|
+
import {
|
|
3
|
+
defaultAction,
|
|
4
|
+
} from '../actions';
|
|
5
|
+
import {
|
|
6
|
+
DEFAULT_ACTION,
|
|
7
|
+
} from '../constants';
|
|
8
|
+
|
|
9
|
+
describe('TemplatesV2 actions', () => {
|
|
10
|
+
describe('Default Action', () => {
|
|
11
|
+
it('has a type of DEFAULT_ACTION', () => {
|
|
12
|
+
const expected = {
|
|
13
|
+
type: DEFAULT_ACTION,
|
|
14
|
+
};
|
|
15
|
+
expect(defaultAction()).toEqual(expected);
|
|
16
|
+
});
|
|
17
|
+
});
|
|
18
|
+
});
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Test sagas
|
|
3
|
+
*/
|
|
4
|
+
|
|
5
|
+
/* eslint-disable redux-saga/yield-effects */
|
|
6
|
+
// import { take, call, put, select } from 'redux-saga/effects';
|
|
7
|
+
// import { defaultSaga } from '../sagas';
|
|
8
|
+
|
|
9
|
+
// const generator = defaultSaga();
|
|
10
|
+
|
|
11
|
+
describe('defaultSaga Saga', () => {
|
|
12
|
+
it('Expect to have unit tests specified', () => {
|
|
13
|
+
expect(true).toEqual(false);
|
|
14
|
+
});
|
|
15
|
+
});
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
// import { fromJS } from 'immutable';
|
|
2
|
+
// import { makeSelectTemplatesV2Domain } from '../selectors';
|
|
3
|
+
|
|
4
|
+
// const selector = makeSelectTemplatesV2Domain();
|
|
5
|
+
|
|
6
|
+
describe('makeSelectTemplatesV2Domain', () => {
|
|
7
|
+
it('Expect to have unit tests specified', () => {
|
|
8
|
+
expect(true).toEqual(false);
|
|
9
|
+
});
|
|
10
|
+
});
|