@capillarytech/creatives-library 3.1.46 → 3.1.49
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/Cap/index.js +1 -4
- package/package.json +1 -1
- package/translations/en.json +77 -60
- package/translations/zh.json +77 -60
- package/v2Components/NavigationBar/index.js +11 -17
- package/v2Components/NavigationBar/messages.js +28 -0
- package/v2Components/TopBar/index.js +3 -0
- package/v2Components/TopBar/messages.js +8 -0
- package/v2Containers/Assets/Gallery/index.js +11 -5
- package/v2Containers/Cap/index.js +0 -1
- package/v2Containers/Email/messages.js +8 -0
- package/v2Containers/LanguageProvider/constants.js +0 -1
- package/v2Containers/LanguageProvider/reducer.js +1 -7
- package/v2Containers/Templates/_templates.scss +9 -1
- package/v2Containers/Templates/index.js +66 -53
- package/v2Containers/WeChat/RichmediaTemplates/Create/_createRichmedia.scss +10 -0
- package/v2Containers/WeChat/RichmediaTemplates/Create/actions.js +9 -0
- package/v2Containers/WeChat/RichmediaTemplates/Create/constants.js +3 -0
- package/v2Containers/WeChat/RichmediaTemplates/Create/index.js +143 -1
- package/v2Containers/WeChat/RichmediaTemplates/Create/messages.js +16 -0
- package/v2Containers/WeChat/RichmediaTemplates/Create/reducer.js +24 -1
- package/v2Containers/WeChat/RichmediaTemplates/Create/sagas.js +45 -0
- package/v2Containers/WeChat/RichmediaTemplates/Edit/constants.js +4 -0
- package/v2Containers/WeChat/RichmediaTemplates/Edit/index.js +8 -1
- package/v2Containers/WeChat/Wrapper/_wrapper.scss +9 -1
|
@@ -7,21 +7,15 @@
|
|
|
7
7
|
import { fromJS } from 'immutable';
|
|
8
8
|
|
|
9
9
|
import * as types from './constants';
|
|
10
|
-
import {
|
|
11
|
-
DEFAULT_LOCALE,
|
|
12
|
-
} from '../Cap/constants'; // eslint-disable-line
|
|
13
10
|
|
|
14
11
|
const initialState = fromJS({
|
|
15
|
-
locale: DEFAULT_LOCALE,
|
|
12
|
+
locale: types.DEFAULT_LOCALE,
|
|
16
13
|
messages: {},
|
|
17
14
|
localeLoading: false,
|
|
18
15
|
});
|
|
19
16
|
|
|
20
17
|
function languageProviderReducer(state = initialState, action) {
|
|
21
18
|
switch (action.type) {
|
|
22
|
-
case types.CHANGE_LOCALE:
|
|
23
|
-
return state
|
|
24
|
-
.set('locale', action.locale);
|
|
25
19
|
case types.GET_LOCIZ_MESSAGE_REQUEST:
|
|
26
20
|
return state.set('localeLoading', true);
|
|
27
21
|
case types.GET_LOCIZ_MESSAGE_SUCCESS:
|
|
@@ -1,4 +1,6 @@
|
|
|
1
|
-
|
|
1
|
+
@import '~@capillarytech/cap-ui-library/styles/_variables.scss';
|
|
2
|
+
|
|
3
|
+
.ant-tabs-content{
|
|
2
4
|
margin-top: 16px;
|
|
3
5
|
.ant-tabs-tabpane-active{
|
|
4
6
|
padding: unset;
|
|
@@ -16,6 +18,12 @@
|
|
|
16
18
|
}
|
|
17
19
|
}
|
|
18
20
|
|
|
21
|
+
.ant-radio-group.#{cap-radioCard-v2} {
|
|
22
|
+
.ant-radio-button-wrapper {
|
|
23
|
+
border: 1px solid $CAP_G07;
|
|
24
|
+
}
|
|
25
|
+
}
|
|
26
|
+
|
|
19
27
|
.card-title {
|
|
20
28
|
line-height: 24px;
|
|
21
29
|
font-size: 14px;
|
|
@@ -54,6 +54,7 @@ import { MOBILE_PUSH, WECHAT, SMS, EMAIL, EBILL, LINE } from '../CreativesContai
|
|
|
54
54
|
import emailIllustration from '../Assets/images/emailIllustration.svg';
|
|
55
55
|
import smsIllustration from '../Assets/images/smsIllustration.svg';
|
|
56
56
|
import pushIllustration from '../Assets/images/pushIllustration.svg';
|
|
57
|
+
import { CAP_SPACE_16 } from '@capillarytech/cap-ui-library/styled/variables';
|
|
57
58
|
|
|
58
59
|
|
|
59
60
|
const {CapCustomCardList} = CapCustomCard;
|
|
@@ -67,6 +68,7 @@ const InlineDiv = styled.div`
|
|
|
67
68
|
}
|
|
68
69
|
`;
|
|
69
70
|
const ACCOUNT_SELECTION_MODE = "accountSelectionMode";
|
|
71
|
+
const ACCOUNT_CHANGE_MODE = 'accountChangeMode';
|
|
70
72
|
const TEMPLATES_MODE = "templatesMode";
|
|
71
73
|
const WECHAT_FILTERS = {
|
|
72
74
|
ALL: 'all',
|
|
@@ -1525,6 +1527,7 @@ export class Templates extends React.Component { // eslint-disable-line react/pr
|
|
|
1525
1527
|
|
|
1526
1528
|
renderAccountSelection = () => {
|
|
1527
1529
|
const accountOptions = [];
|
|
1530
|
+
const { selectedAccount } = this.state;
|
|
1528
1531
|
let { channel = '' } = this.state;
|
|
1529
1532
|
channel = channel.toUpperCase();
|
|
1530
1533
|
const { Templates: templates = {}, location = {} } = this.props;
|
|
@@ -1569,8 +1572,8 @@ export class Templates extends React.Component { // eslint-disable-line react/pr
|
|
|
1569
1572
|
});
|
|
1570
1573
|
}
|
|
1571
1574
|
return (<CapSpin spinning={fetchingWeCrmAccounts}>
|
|
1572
|
-
{isEmpty(weCrmAccounts) && !fetchingWeCrmAccounts ? <FormattedMessage {...messages.noAccountsPresentWeChat} /> :
|
|
1573
|
-
<div style={{overflowX: "auto"}}>
|
|
1575
|
+
{isEmpty(weCrmAccounts) && !fetchingWeCrmAccounts ? <FormattedMessage {...(channel === WECHAT ? messages.noAccountsPresentWeChat : messages.noAccountsPresent)} /> :
|
|
1576
|
+
<div style={{ overflowX: "auto", paddingBottom: CAP_SPACE_16 }}>
|
|
1574
1577
|
<CapHeader
|
|
1575
1578
|
title={isMobilePushChannel ? this.props.intl.formatMessage(messages.mobilepushAccount) : this.props.intl.formatMessage(messages.wechatAccount)}
|
|
1576
1579
|
description={this.props.intl.formatMessage(messages.chooseAccount)}
|
|
@@ -1584,7 +1587,9 @@ export class Templates extends React.Component { // eslint-disable-line react/pr
|
|
|
1584
1587
|
cardHeight="48px"
|
|
1585
1588
|
cardWidth="276px"
|
|
1586
1589
|
size="small"
|
|
1587
|
-
|
|
1590
|
+
defaultValue={selectedAccount}
|
|
1591
|
+
selected={selectedAccount}
|
|
1592
|
+
/>
|
|
1588
1593
|
</div>
|
|
1589
1594
|
}
|
|
1590
1595
|
</CapSpin>);
|
|
@@ -1594,18 +1599,23 @@ export class Templates extends React.Component { // eslint-disable-line react/pr
|
|
|
1594
1599
|
this.setState({activeMode: ACCOUNT_SELECTION_MODE});
|
|
1595
1600
|
}
|
|
1596
1601
|
|
|
1602
|
+
setAccountChangeMode = () => {
|
|
1603
|
+
this.setState({activeMode: ACCOUNT_CHANGE_MODE});
|
|
1604
|
+
}
|
|
1605
|
+
|
|
1597
1606
|
setTemplatesMode = () => {
|
|
1598
1607
|
this.setState({activeMode: TEMPLATES_MODE});
|
|
1599
1608
|
}
|
|
1600
1609
|
|
|
1601
1610
|
showAccountName = () => {
|
|
1602
|
-
const { selectedAccount, channel } = this.state;
|
|
1611
|
+
const { activeMode, selectedAccount, channel } = this.state;
|
|
1603
1612
|
const { Templates: templates = {}} = this.props;
|
|
1604
1613
|
const { weCrmAccounts = []} = templates;
|
|
1605
1614
|
const isMobilePushChannel = channel === MOBILE_PUSH;
|
|
1606
|
-
return (
|
|
1615
|
+
return (activeMode !== ACCOUNT_CHANGE_MODE &&
|
|
1616
|
+
<CapHeader
|
|
1607
1617
|
title={<CapHeading type="h4">{isMobilePushChannel ? this.props.intl.formatMessage(messages.mobilepushAccount) : this.props.intl.formatMessage(messages.wechatAccount)}</CapHeading>}
|
|
1608
|
-
description={<><CapHeading type="h3">{selectedAccount} {weCrmAccounts.length > 1 && <CapLink onClick={this.
|
|
1618
|
+
description={<><CapHeading type="h3">{selectedAccount} {weCrmAccounts.length > 1 && <CapLink onClick={this.setAccountChangeMode} style={{display: 'inline-block', position: 'relative', top: '3px'}} fontWeight="regular" fontSize="14px" title="change"/>} </CapHeading></>}
|
|
1609
1619
|
size="regular"
|
|
1610
1620
|
/>);
|
|
1611
1621
|
}
|
|
@@ -1691,63 +1701,66 @@ export class Templates extends React.Component { // eslint-disable-line react/pr
|
|
|
1691
1701
|
const {route} = this.props;
|
|
1692
1702
|
const loadingTip = (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);
|
|
1693
1703
|
return (
|
|
1694
|
-
|
|
1695
|
-
|
|
1704
|
+
<>
|
|
1705
|
+
{activeMode === ACCOUNT_CHANGE_MODE && this.renderAccountSelection()}
|
|
1706
|
+
<div className={`creatives-templates-list ${this.props.isFullMode ? 'full-mode' : 'library-mode'}`}>
|
|
1707
|
+
<input type="file" id="filename" style={{ display: 'none'}} accept=".zip, .html, .htm" onChange={(event) => this.handleFileUpload(event, {files: event.target.files})} />
|
|
1696
1708
|
|
|
1697
1709
|
|
|
1698
|
-
|
|
1699
|
-
|
|
1700
|
-
|
|
1701
|
-
|
|
1702
|
-
|
|
1710
|
+
<CapRow>
|
|
1711
|
+
<Pagination onPageChange={templates.length ? this.onPaginationChange : () => {}} paginationSelector="pagination-container">
|
|
1712
|
+
{this.getTemplateDataForGrid({isLoading, loadingTip, channel: this.state.channel, templates: this.props.TemplatesList, filterContent, handlers: {handlePreviewClick: this.handlePreviewClick, handleEditClick: this.handleEditClick}})}
|
|
1713
|
+
</Pagination>
|
|
1714
|
+
{(((this.state.selectedAccount !== '' && !isEmpty(this.props.Templates.selectedWeChatAccount) && this.state.channel.toLowerCase() === 'wechat') || this.state.channel.toLowerCase() !== 'wechat') && isEmpty(this.props.TemplatesList)) && !this.props.Templates.getAllTemplatesInProgress && !isEmpty(this.state.searchText) &&
|
|
1703
1715
|
<div style={{ height: '65vh', textAlign: 'center', lineHeight: '65vh'}}>
|
|
1704
1716
|
<CapHeading type="h6">{this.props.intl.formatMessage(messages.noTemplatesFound)}</CapHeading>
|
|
1705
1717
|
</div>}
|
|
1706
|
-
|
|
1707
|
-
|
|
1708
|
-
|
|
1709
|
-
|
|
1710
|
-
|
|
1711
|
-
|
|
1712
|
-
|
|
1713
|
-
|
|
1714
|
-
|
|
1715
|
-
|
|
1716
|
-
|
|
1717
|
-
|
|
1718
|
-
|
|
1719
|
-
|
|
1720
|
-
|
|
1721
|
-
|
|
1718
|
+
</CapRow>
|
|
1719
|
+
|
|
1720
|
+
|
|
1721
|
+
<CapRow>
|
|
1722
|
+
{!isEmpty(creativesParams.mode) && isFullMode && //creatives container for fullmode
|
|
1723
|
+
<CreativesContainer
|
|
1724
|
+
key={creativesParams.mode}
|
|
1725
|
+
messageDetails={{type: "default"}}
|
|
1726
|
+
creativesMode={creativesParams.mode}
|
|
1727
|
+
messages={messages}
|
|
1728
|
+
isFullMode={isFullMode}
|
|
1729
|
+
templateData={creativesParams}
|
|
1730
|
+
getCreativesData={() => { this.onCreateComplete(true); }}
|
|
1731
|
+
channel={route.name.toUpperCase()}
|
|
1732
|
+
handleCloseCreatives={this.onCreateComplete}
|
|
1733
|
+
selectedWeChatAccount={get(this.props, 'Templates.selectedWeChatAccount', {})}
|
|
1722
1734
|
/>
|
|
1723
1735
|
}
|
|
1724
|
-
|
|
1725
|
-
|
|
1726
|
-
|
|
1727
|
-
|
|
1728
|
-
|
|
1729
|
-
|
|
1730
|
-
|
|
1731
|
-
|
|
1732
|
-
|
|
1733
|
-
|
|
1734
|
-
|
|
1735
|
-
|
|
1736
|
-
|
|
1736
|
+
</CapRow>
|
|
1737
|
+
<CapRow>
|
|
1738
|
+
|
|
1739
|
+
{(this.state.channel.toLowerCase() === 'ebill' || this.state.channel.toLowerCase() === 'email') && htmlPreviewContent && <EmailPreview
|
|
1740
|
+
header={previewHeader}
|
|
1741
|
+
content={htmlPreviewContent}
|
|
1742
|
+
show={this.state.showHtmlPreview}
|
|
1743
|
+
device={this.state.device}
|
|
1744
|
+
handleClose={this.toggleEmailPreview}
|
|
1745
|
+
changePreviewDevice={this.changePreviewDevice}
|
|
1746
|
+
versions={get(this.state, 'previewTemplate.versions', {})}
|
|
1747
|
+
lastModified={this.state.previewTemplate ? this.state.previewTemplate.updatedAt : ''}
|
|
1748
|
+
updatedByName={commonUtil.getUserNameById(parseInt(this.state.previewTemplate.updatedBy, 10), commonUtil.getMergedUserList(this.props.Templates.userList))}
|
|
1737
1749
|
/>}
|
|
1738
|
-
|
|
1739
|
-
|
|
1740
|
-
|
|
1741
|
-
|
|
1742
|
-
|
|
1743
|
-
|
|
1744
|
-
|
|
1745
|
-
|
|
1750
|
+
<CapSlideBox
|
|
1751
|
+
header={(<h3>{this.props.intl.formatMessage(messages.layoutSelection)}</h3>)}
|
|
1752
|
+
width={60}
|
|
1753
|
+
content={cmsTemplateSelectionContent}
|
|
1754
|
+
show={this.state.showEdmEmailTemplates}
|
|
1755
|
+
handleClose={this.toggleEdmEmailTemplateSelection}
|
|
1756
|
+
loadingText={"Loading EDM Templates"}
|
|
1757
|
+
isLoading={this.props.Templates.getCmsTemplatesInProgress}
|
|
1746
1758
|
/>
|
|
1747
|
-
|
|
1748
|
-
|
|
1759
|
+
{this.renderDeleteConfirmationModal()}
|
|
1760
|
+
</CapRow>
|
|
1749
1761
|
|
|
1750
|
-
|
|
1762
|
+
</div>
|
|
1763
|
+
</>
|
|
1751
1764
|
);
|
|
1752
1765
|
}
|
|
1753
1766
|
|
|
@@ -59,6 +59,16 @@
|
|
|
59
59
|
border-bottom-left-radius: 4px;
|
|
60
60
|
border-bottom-right-radius: 4px;
|
|
61
61
|
}
|
|
62
|
+
|
|
63
|
+
.existing-template-title-card {
|
|
64
|
+
padding: 12px;
|
|
65
|
+
background-color: white;
|
|
66
|
+
height: 44px;
|
|
67
|
+
width: 244px;
|
|
68
|
+
border-bottom-left-radius: 4px;
|
|
69
|
+
border-bottom-right-radius: 4px;
|
|
70
|
+
}
|
|
71
|
+
|
|
62
72
|
.custom-image {
|
|
63
73
|
position: relative;
|
|
64
74
|
.name-container {
|
|
@@ -10,6 +10,15 @@ export function defaultAction() {
|
|
|
10
10
|
type: types.DEFAULT_ACTION,
|
|
11
11
|
};
|
|
12
12
|
}
|
|
13
|
+
|
|
14
|
+
export function getAllTemplates(channel, queryParams) {
|
|
15
|
+
return {
|
|
16
|
+
type: types.GET_ALL_TEMPLATES_REQUEST,
|
|
17
|
+
channel,
|
|
18
|
+
queryParams,
|
|
19
|
+
};
|
|
20
|
+
}
|
|
21
|
+
|
|
13
22
|
export function uploadAsset(file, assetType, fileParams, mode, wechatParams, contentId, uploadId) {
|
|
14
23
|
return {
|
|
15
24
|
type: types.UPLOAD_ASSET_REQUEST,
|
|
@@ -13,3 +13,6 @@ export const SAVE_TEMPLATE_REQUEST = 'app/v2Containers/Wechat/RichmediaTemplates
|
|
|
13
13
|
export const SAVE_TEMPLATE_SUCCESS = 'app/v2Containers/Wechat/RichmediaTemplates/Create/SAVE_TEMPLATE_SUCCESS';
|
|
14
14
|
export const SAVE_TEMPLATE_FAILURE = 'app/v2Containers/Wechat/RichmediaTemplates/Create/SAVE_TEMPLATE_FAILURE';
|
|
15
15
|
export const CLEAR_CONTENT_ASSET = 'app/v2Containers/Wechat/RichmediaTemplates/Create/CLEAR_CONTENT_ASSET';
|
|
16
|
+
export const GET_ALL_TEMPLATES_REQUEST = 'app/v2Containers/Wechat/RichmediaTemplates/Create/GET_ALL_TEMPLATES_REQUEST';
|
|
17
|
+
export const GET_ALL_TEMPLATES_SUCCESS = 'app/v2Containers/Wechat/RichmediaTemplates/Create/GET_ALL_TEMPLATES_SUCCESS';
|
|
18
|
+
export const GET_ALL_TEMPLATES_FAILURE = 'app/v2Containers/Wechat/RichmediaTemplates/Create/GET_ALL_TEMPLATES_FAILURE';
|
|
@@ -17,7 +17,7 @@ import cloneDeep from 'lodash/cloneDeep';
|
|
|
17
17
|
import forEach from 'lodash/forEach';
|
|
18
18
|
import isEqual from 'lodash/isEqual';
|
|
19
19
|
import get from 'lodash/get';
|
|
20
|
-
import { CapRow, CapColumn, CapButton, CapCard, CapSpin, CapInput, CapHeading, CapDivider, CapIcon, CapLink, CapLabel, CapNotification } from '@capillarytech/cap-ui-library';
|
|
20
|
+
import { CapRow, CapColumn, CapButton, CapCard, CapSpin, CapInput, CapHeading, CapDivider, CapIcon, CapLink, CapLabel, CapNotification, CapSlideBox } from '@capillarytech/cap-ui-library';
|
|
21
21
|
import makeSelectCreate, {makeSelectTemplates, getAssetDetails, getContentAssetDetails} from './selectors';
|
|
22
22
|
import * as actions from './actions';
|
|
23
23
|
import richmediaschema from './richmediaschema';
|
|
@@ -26,6 +26,8 @@ import messages from './messages';
|
|
|
26
26
|
import FormBuilder from '../../../../v2Components/FormBuilder';
|
|
27
27
|
import WechatRichmediaTemplatePreview from '../../../../v2Components/TemplatePreview/WechatRichmediaTemplatePreview';
|
|
28
28
|
import noImage from '../../../../assets/noImage.png';
|
|
29
|
+
import Pagination from '../../../../v2Components/Pagination';
|
|
30
|
+
import { CAP_SPACE_08, CAP_SPACE_12, CAP_SPACE_20, CAP_SPACE_16 } from '@capillarytech/cap-ui-library/styled/variables';
|
|
29
31
|
|
|
30
32
|
export class Create extends React.Component { // eslint-disable-line react/prefer-stateless-function
|
|
31
33
|
constructor(props) {
|
|
@@ -102,6 +104,13 @@ export class Create extends React.Component { // eslint-disable-line react/prefe
|
|
|
102
104
|
type: 'confirm',
|
|
103
105
|
id: 'template-back-confirm-modal',
|
|
104
106
|
},
|
|
107
|
+
showExistingTemplates: false,
|
|
108
|
+
existingTemplatesPageNo: 1,
|
|
109
|
+
existingTemplatesPageLimit: 25,
|
|
110
|
+
sortBy: 'Most Recent',
|
|
111
|
+
searchText: '',
|
|
112
|
+
pagination: true,
|
|
113
|
+
scrollDebounce: true,
|
|
105
114
|
};
|
|
106
115
|
this.onFormDataChange = this.onFormDataChange.bind(this);
|
|
107
116
|
this.cancelHandler = this.cancelHandler.bind(this);
|
|
@@ -836,6 +845,126 @@ export class Create extends React.Component { // eslint-disable-line react/prefe
|
|
|
836
845
|
});
|
|
837
846
|
return true;
|
|
838
847
|
}
|
|
848
|
+
|
|
849
|
+
onChooseExistingTemplate = (template, e) => {
|
|
850
|
+
e.stopPropagation();
|
|
851
|
+
const content = get(template, 'versions.base.mediaList[0]', {});
|
|
852
|
+
let postCommentsValue = 'No one';
|
|
853
|
+
const templateData = cloneDeep(this.state.templateData);
|
|
854
|
+
|
|
855
|
+
if (content.only_fans_can_comment && content.need_open_comment) {
|
|
856
|
+
postCommentsValue = 'Only followers';
|
|
857
|
+
} else if (content.need_open_comment) {
|
|
858
|
+
postCommentsValue = 'Anyone';
|
|
859
|
+
}
|
|
860
|
+
|
|
861
|
+
templateData[this.state.currentContentId] = {
|
|
862
|
+
formData: {
|
|
863
|
+
'title-value': content.title,
|
|
864
|
+
'author-value': content.author,
|
|
865
|
+
'cover-abstract-value': content.digest,
|
|
866
|
+
'content-value': content.content,
|
|
867
|
+
'source-link-value': content.content_source_url,
|
|
868
|
+
'post-comments-value': postCommentsValue,
|
|
869
|
+
'show-cover-pic-value': content.show_cover_pic,
|
|
870
|
+
},
|
|
871
|
+
imageUrl: content.image_url,
|
|
872
|
+
mediaId: content.thumb_media_id,
|
|
873
|
+
};
|
|
874
|
+
this.setState({ templateData });
|
|
875
|
+
this.onCloseExistingTemplatesSlideBox();
|
|
876
|
+
}
|
|
877
|
+
|
|
878
|
+
getExistingTemplates = () => {
|
|
879
|
+
const { searchText, sortBy, existingTemplatesPageNo, existingTemplatesPageLimit } = this.state;
|
|
880
|
+
const { selectedWeChatAccount } = this.props.Templates;
|
|
881
|
+
|
|
882
|
+
this.setState({showExistingTemplates: true});
|
|
883
|
+
const queryParams = {
|
|
884
|
+
name: searchText || '',
|
|
885
|
+
sortBy: sortBy,
|
|
886
|
+
wecrmId: selectedWeChatAccount.configs.wecrm_app_id,
|
|
887
|
+
wecrmToken: selectedWeChatAccount.configs.wecrm_token,
|
|
888
|
+
originalId: selectedWeChatAccount.sourceAccountIdentifier,
|
|
889
|
+
page: existingTemplatesPageNo,
|
|
890
|
+
perPage: existingTemplatesPageLimit,
|
|
891
|
+
};
|
|
892
|
+
this.props.actions.getAllTemplates('wechat', queryParams);
|
|
893
|
+
}
|
|
894
|
+
|
|
895
|
+
searchTemplate = (data) => {
|
|
896
|
+
this.setState({searchText: data}, () => {
|
|
897
|
+
this.getExistingTemplates();
|
|
898
|
+
});
|
|
899
|
+
}
|
|
900
|
+
|
|
901
|
+
onPaginationChange = () => {
|
|
902
|
+
if (this.props.Create.pagination && this.state.scrollDebounce) {
|
|
903
|
+
this.setState((prevState) => ({
|
|
904
|
+
existingTemplatesPageNo: prevState.existingTemplatesPageNo + 1,
|
|
905
|
+
scrollDebounce: false,
|
|
906
|
+
}),
|
|
907
|
+
() => {
|
|
908
|
+
this.getExistingTemplates();
|
|
909
|
+
setTimeout(() => {
|
|
910
|
+
this.setState({ scrollDebounce: true })
|
|
911
|
+
}, 500);
|
|
912
|
+
});
|
|
913
|
+
}
|
|
914
|
+
}
|
|
915
|
+
|
|
916
|
+
existingTemplatesContent = () => {
|
|
917
|
+
const { getAllTemplatesInProgress, templates = [] } = this.props.Create;
|
|
918
|
+
return (
|
|
919
|
+
<CapSpin style={{textAlign: "center"}} spinning={getAllTemplatesInProgress}>
|
|
920
|
+
<CapInput.Search
|
|
921
|
+
className="search-text"
|
|
922
|
+
style={{ width: '100%', marginBottom: CAP_SPACE_16 }}
|
|
923
|
+
placeholder={this.props.intl.formatMessage(messages.searchText)}
|
|
924
|
+
value={this.state.searchText}
|
|
925
|
+
onChange={(e) => this.searchTemplate(e.target.value)}
|
|
926
|
+
onClear={() => this.searchTemplate('')}
|
|
927
|
+
/>
|
|
928
|
+
<Pagination style={{ height: 'calc(100vh - 150px)', overflowY: 'auto' }} onPageChange={templates.length && this.onPaginationChange}>
|
|
929
|
+
{ templates.map((template) => (
|
|
930
|
+
<CapCard
|
|
931
|
+
key={template._id}
|
|
932
|
+
bordered={false}
|
|
933
|
+
bodyStyle={{
|
|
934
|
+
padding: 0,
|
|
935
|
+
borderRadius: '4px',
|
|
936
|
+
width: '276px',
|
|
937
|
+
border: '16px solid #f4f5f7',
|
|
938
|
+
}}
|
|
939
|
+
onClick={(e) => this.onChooseExistingTemplate(template, e)}
|
|
940
|
+
style={{ paddingBottom: CAP_SPACE_12 }}
|
|
941
|
+
>
|
|
942
|
+
<div>
|
|
943
|
+
<div className="custom-image">
|
|
944
|
+
<img alt="" width="244px" height="136px" src={template.versions.base.mediaList[0].image_url} />
|
|
945
|
+
</div>
|
|
946
|
+
<div className="existing-template-title-card">
|
|
947
|
+
<CapHeading type="h5" className="overflow-wrap-fields">{template.name || "Title"}</CapHeading>
|
|
948
|
+
</div>
|
|
949
|
+
</div>
|
|
950
|
+
</CapCard>
|
|
951
|
+
))
|
|
952
|
+
}
|
|
953
|
+
</Pagination>
|
|
954
|
+
</CapSpin>
|
|
955
|
+
);
|
|
956
|
+
}
|
|
957
|
+
|
|
958
|
+
onCloseExistingTemplatesSlideBox = () => {
|
|
959
|
+
this.setState({
|
|
960
|
+
showExistingTemplates: false,
|
|
961
|
+
existingTemplatesPageNo: 1,
|
|
962
|
+
existingTemplatesPageLimit: 25,
|
|
963
|
+
searchText: '',
|
|
964
|
+
pagination: true,
|
|
965
|
+
});
|
|
966
|
+
}
|
|
967
|
+
|
|
839
968
|
updateContentData = () => {
|
|
840
969
|
this.state.editorInstanse.insertHtml(`<img src='${this.props.ContentImageData.metaInfo.wechatUrl}' alt='Capillary Image'>`);
|
|
841
970
|
this.props.actions.clearContentImageStore();
|
|
@@ -846,6 +975,7 @@ export class Create extends React.Component { // eslint-disable-line react/prefe
|
|
|
846
975
|
<>
|
|
847
976
|
<div style={{width: '292px'}}><CapDivider /></div>
|
|
848
977
|
<CapHeading type="h5" style={{marginBottom: '8px'}}>{this.props.intl.formatMessage(messages.addRichMediaContent)}</CapHeading>
|
|
978
|
+
<CapButton type="dashed" onClick={this.getExistingTemplates} prefix={<CapIcon size="s" type="media" />} style={{backgroundColor: 'white', width: '142px', marginRight: CAP_SPACE_08, paddingLeft: CAP_SPACE_12}}>{this.props.intl.formatMessage(messages.existingMedia)}</CapButton>
|
|
849
979
|
<CapButton type="dashed" onClick={this.menuOnClickEvent} prefix={<CapIcon size="s" type="add-media" />} style={{backgroundColor: 'white'}}>{this.props.intl.formatMessage(messages.newMedia)}</CapButton>
|
|
850
980
|
</>
|
|
851
981
|
);
|
|
@@ -902,6 +1032,7 @@ export class Create extends React.Component { // eslint-disable-line react/prefe
|
|
|
902
1032
|
const schema = this.returnCurrentSchema();
|
|
903
1033
|
const formData = this.returnCurrentFormData();
|
|
904
1034
|
const { isIframe } = this.state;
|
|
1035
|
+
const { intl } = this.props;
|
|
905
1036
|
this.updateImageData();
|
|
906
1037
|
if (this.props.ContentImageData && this.props.ContentImageData.metaInfo && this.props.ContentImageData.metaInfo.wechatUrl) {
|
|
907
1038
|
this.updateContentData();
|
|
@@ -956,6 +1087,17 @@ export class Create extends React.Component { // eslint-disable-line react/prefe
|
|
|
956
1087
|
</CapRow>
|
|
957
1088
|
</div>
|
|
958
1089
|
</div>
|
|
1090
|
+
<CapSlideBox
|
|
1091
|
+
header={(
|
|
1092
|
+
<CapHeading type="h3">
|
|
1093
|
+
{intl.formatMessage(messages.existingMediaHeader)}
|
|
1094
|
+
</CapHeading>
|
|
1095
|
+
)}
|
|
1096
|
+
content={this.existingTemplatesContent()}
|
|
1097
|
+
show={this.state.showExistingTemplates}
|
|
1098
|
+
handleClose={this.onCloseExistingTemplatesSlideBox}
|
|
1099
|
+
size="size-s"
|
|
1100
|
+
/>
|
|
959
1101
|
</CapSpin>
|
|
960
1102
|
</div>
|
|
961
1103
|
);
|
|
@@ -199,6 +199,10 @@ export default defineMessages({
|
|
|
199
199
|
id: `${scope}.templateNameExists`,
|
|
200
200
|
defaultMessage: 'Template with the same name exists. Please try another template name.',
|
|
201
201
|
},
|
|
202
|
+
'Template name already exists': {
|
|
203
|
+
id: 'creatives.containersV2.richMedia.create.templateNameAlreadyExists',
|
|
204
|
+
defaultMessage: 'Template name already exists',
|
|
205
|
+
},
|
|
202
206
|
'Template name cannot be blank!': {
|
|
203
207
|
id: `${scope}.templateNameBlank`,
|
|
204
208
|
defaultMessage: 'Template name cannot be blank',
|
|
@@ -247,4 +251,16 @@ export default defineMessages({
|
|
|
247
251
|
id: `${scope}.nameOfTemplate`,
|
|
248
252
|
defaultMessage: 'Name of the template',
|
|
249
253
|
},
|
|
254
|
+
'existingMedia': {
|
|
255
|
+
id: `${scope}.existingMedia`,
|
|
256
|
+
defaultMessage: 'Existing media',
|
|
257
|
+
},
|
|
258
|
+
'existingMediaHeader': {
|
|
259
|
+
id: `${scope}.existingMediaHeader`,
|
|
260
|
+
defaultMessage: 'Rich media templates',
|
|
261
|
+
},
|
|
262
|
+
'searchText': {
|
|
263
|
+
id: `${scope}.searchText`,
|
|
264
|
+
defaultMessage: 'Search Templates',
|
|
265
|
+
},
|
|
250
266
|
});
|
|
@@ -5,9 +5,13 @@
|
|
|
5
5
|
*/
|
|
6
6
|
|
|
7
7
|
import { fromJS } from 'immutable';
|
|
8
|
+
import unionBy from 'lodash/unionBy';
|
|
8
9
|
import * as types from './constants';
|
|
9
10
|
|
|
10
|
-
const initialState = fromJS({
|
|
11
|
+
const initialState = fromJS({
|
|
12
|
+
getAllTemplatesInProgress: false,
|
|
13
|
+
templates: [],
|
|
14
|
+
});
|
|
11
15
|
|
|
12
16
|
function createReducer(state = initialState, action) {
|
|
13
17
|
switch (action.type) {
|
|
@@ -52,6 +56,25 @@ function createReducer(state = initialState, action) {
|
|
|
52
56
|
return state
|
|
53
57
|
.set('saveTemplateSuccess', false)
|
|
54
58
|
.set('savingTemplate', false);
|
|
59
|
+
case types.GET_ALL_TEMPLATES_REQUEST:
|
|
60
|
+
return state
|
|
61
|
+
.set('getAllTemplatesInProgress', true).set('templateError', {});
|
|
62
|
+
case types.GET_ALL_TEMPLATES_SUCCESS:
|
|
63
|
+
const { data, isReset } = action;
|
|
64
|
+
if (isReset) {
|
|
65
|
+
return state
|
|
66
|
+
.set('getAllTemplatesInProgress', false)
|
|
67
|
+
.set('pagination', true)
|
|
68
|
+
.set('templates', data ? data.templates : [])
|
|
69
|
+
.set('isSearch', data ? data.search : false);
|
|
70
|
+
}
|
|
71
|
+
return state
|
|
72
|
+
.set('getAllTemplatesInProgress', false)
|
|
73
|
+
.set('pagination', data ? Boolean(data.templates.length) : true)
|
|
74
|
+
.set('templates', data ? unionBy(state.get('templates'), data.templates, '_id') : state.get('templates'))
|
|
75
|
+
.set('isSearch', data ? data.search : false);
|
|
76
|
+
case types.GET_ALL_TEMPLATES_FAILURE:
|
|
77
|
+
return state.set('getAllTemplatesInProgress', false).set('templateError', action.error);
|
|
55
78
|
default:
|
|
56
79
|
return state;
|
|
57
80
|
}
|
|
@@ -1,5 +1,7 @@
|
|
|
1
1
|
import { take, cancel, call, put, takeLatest } from 'redux-saga/effects';
|
|
2
2
|
import { LOCATION_CHANGE } from 'react-router-redux';
|
|
3
|
+
import orderBy from 'lodash/orderBy';
|
|
4
|
+
import moment from 'moment';
|
|
3
5
|
import * as Api from '../../../../services/api';
|
|
4
6
|
import * as types from './constants';
|
|
5
7
|
// import testschema from './testschema';
|
|
@@ -33,6 +35,48 @@ export function* saveTemplate({template, callback}) {
|
|
|
33
35
|
yield put({ type: types.SAVE_TEMPLATE_FAILURE, error });
|
|
34
36
|
}
|
|
35
37
|
}
|
|
38
|
+
|
|
39
|
+
export function* getAllTemplates(action) {
|
|
40
|
+
try {
|
|
41
|
+
const result = yield call(Api.getAllTemplates, action);
|
|
42
|
+
const channelTemplates = {
|
|
43
|
+
templates: result.response.richmedia,
|
|
44
|
+
};
|
|
45
|
+
if (
|
|
46
|
+
action.channel === 'wechat' &&
|
|
47
|
+
action.queryParams &&
|
|
48
|
+
action.queryParams.sortBy
|
|
49
|
+
) {
|
|
50
|
+
if (action.queryParams.sortBy.toLocaleLowerCase() === ("Most Recent").toLocaleLowerCase()) {
|
|
51
|
+
channelTemplates.templates = orderBy(channelTemplates.templates, (template) => moment(template.updatedAt), ['desc']);
|
|
52
|
+
// channelTemplates.templates.sort((a, b) => {
|
|
53
|
+
// const dateA = new Date(a.updatedAt);
|
|
54
|
+
// const dateB = new Date(b.updatedAt);
|
|
55
|
+
// return dateB - dateA;
|
|
56
|
+
// });
|
|
57
|
+
} else if (action.queryParams.sortBy.toLocaleLowerCase() === ("Alphabetically").toLocaleLowerCase()) {
|
|
58
|
+
channelTemplates.templates.sort((a, b) => b.name - a.name);
|
|
59
|
+
}
|
|
60
|
+
}
|
|
61
|
+
yield put({
|
|
62
|
+
type: types.GET_ALL_TEMPLATES_SUCCESS,
|
|
63
|
+
data: channelTemplates,
|
|
64
|
+
isReset: action.queryParams.page === 1,
|
|
65
|
+
});
|
|
66
|
+
} catch (error) {
|
|
67
|
+
yield put({
|
|
68
|
+
type: types.GET_ALL_TEMPLATES_FAILURE,
|
|
69
|
+
error,
|
|
70
|
+
});
|
|
71
|
+
}
|
|
72
|
+
}
|
|
73
|
+
|
|
74
|
+
function* watchGetAllTemplates() {
|
|
75
|
+
const watcher = yield takeLatest(types.GET_ALL_TEMPLATES_REQUEST, getAllTemplates);
|
|
76
|
+
yield take(LOCATION_CHANGE);
|
|
77
|
+
yield cancel(watcher);
|
|
78
|
+
}
|
|
79
|
+
|
|
36
80
|
function* watchUploadAsset() {
|
|
37
81
|
const watcher = yield takeLatest(types.UPLOAD_ASSET_REQUEST, uploadAsset);
|
|
38
82
|
yield take(LOCATION_CHANGE);
|
|
@@ -48,4 +92,5 @@ export default [
|
|
|
48
92
|
defaultSaga,
|
|
49
93
|
watchUploadAsset,
|
|
50
94
|
watchSaveTemplate,
|
|
95
|
+
watchGetAllTemplates,
|
|
51
96
|
];
|
|
@@ -8,3 +8,7 @@ export const DEFAULT_ACTION = 'app/Edit/DEFAULT_ACTION';
|
|
|
8
8
|
export const GET_TEMPLATE_DETAILS_REQUEST = 'app/v2Containers/WeChat/RichmediaTemplates/Edit/GET_TEMPLATE_DETAILS_REQUEST';
|
|
9
9
|
export const GET_TEMPLATE_DETAILS_SUCCESS = 'app/v2Containers/WeChat/RichmediaTemplates/Edit/GET_TEMPLATE_DETAILS_SUCCESS';
|
|
10
10
|
export const GET_TEMPLATE_DETAILS_FAILURE = 'app/v2Containers/WeChat/RichmediaTemplates/Edit/GET_TEMPLATE_DETAILS_FAILURE';
|
|
11
|
+
|
|
12
|
+
export const NO_ONE = 'No one';
|
|
13
|
+
export const ONLY_FOLLOWERS = 'Only followers';
|
|
14
|
+
export const ANYONE = 'Anyone';
|
|
@@ -15,6 +15,7 @@ import { CapSpin } from '@capillarytech/cap-ui-library';
|
|
|
15
15
|
import { createStructuredSelector } from 'reselect';
|
|
16
16
|
import makeSelectEdit, { makeSelectTemplates } from './selectors';
|
|
17
17
|
import * as actions from './actions';
|
|
18
|
+
import { NO_ONE, ONLY_FOLLOWERS, ANYONE } from './constants';
|
|
18
19
|
import Create from '../Create';
|
|
19
20
|
import { getCommonProps } from '../../helper';
|
|
20
21
|
|
|
@@ -39,12 +40,18 @@ export class Edit extends React.PureComponent { // eslint-disable-line react/pre
|
|
|
39
40
|
if (!_.isEmpty(templateDetails)) {
|
|
40
41
|
_.forEach(templateDetails.versions.base.mediaList, (content) => {
|
|
41
42
|
const formData = {};
|
|
43
|
+
let postCommentsValue = NO_ONE;
|
|
44
|
+
if (content.only_fans_can_comment && content.need_open_comment) {
|
|
45
|
+
postCommentsValue = ONLY_FOLLOWERS;
|
|
46
|
+
} else if (content.need_open_comment) {
|
|
47
|
+
postCommentsValue = ANYONE;
|
|
48
|
+
}
|
|
42
49
|
formData['title-value'] = content.title;
|
|
43
50
|
formData['author-value'] = content.author;
|
|
44
51
|
formData['cover-abstract-value'] = content.digest;
|
|
45
52
|
formData['content-value'] = content.content;
|
|
46
53
|
formData['source-link-value'] = content.content_source_url;
|
|
47
|
-
formData['post-comments-value'] =
|
|
54
|
+
formData['post-comments-value'] = postCommentsValue;
|
|
48
55
|
formData['show-cover-pic-value'] = content.show_cover_pic;
|
|
49
56
|
templateData[contentId] = {
|
|
50
57
|
formData,
|
|
@@ -1,5 +1,13 @@
|
|
|
1
|
+
@import '~@capillarytech/cap-ui-library/styles/_variables.scss';
|
|
2
|
+
|
|
1
3
|
.template-image {
|
|
2
4
|
margin: 0 -1.142rem;
|
|
3
5
|
height: 274px;
|
|
4
6
|
width: 370px;
|
|
5
|
-
}
|
|
7
|
+
}
|
|
8
|
+
|
|
9
|
+
.ant-radio-group.#{cap-radioCard-v2} {
|
|
10
|
+
.ant-radio-button-wrapper {
|
|
11
|
+
border: 1px solid $CAP_G07;
|
|
12
|
+
}
|
|
13
|
+
}
|