@capillarytech/creatives-library 2.0.5 → 2.0.7

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.
@@ -164,14 +164,17 @@ class CapTagList extends React.Component { // eslint-disable-line react/prefer-s
164
164
  {
165
165
  value: "All",
166
166
  label: "All",
167
+ key: 'all',
167
168
  },
168
169
  {
169
170
  value: "Outbound",
170
171
  label: "Outbound",
172
+ key: 'outbound',
171
173
  },
172
174
  {
173
175
  value: "Loyalty",
174
176
  label: "Loyalty",
177
+ key: 'loyalty',
175
178
  },
176
179
  ];
177
180
  return (
@@ -185,7 +188,7 @@ class CapTagList extends React.Component { // eslint-disable-line react/prefer-s
185
188
  {this.props.moduleFilterEnabled ? <CapSelect getPopupContainer={(triggerNode) => triggerNode.parentNode} style={{width: '250px', marginBottom: '16px', minWidth: 'initial', display: 'inherit'}} onChange={this.props.onContextChange} defaultValue="All" options={options}>
186
189
  </CapSelect> : ''}
187
190
  <CapTree
188
- styling={{'height': '350px', 'overflow': 'auto'}}
191
+ styling={{height: '350px', overflow: 'auto'}}
189
192
  onSelect={this.handleOnSelect}
190
193
  selectedKeys={this.state.tagValue}
191
194
  expandedKeys={this.state.expandedKeys}
@@ -10,11 +10,11 @@ import { createStructuredSelector } from 'reselect';
10
10
  import _ from 'lodash';
11
11
  import moment from 'moment';
12
12
  import 'moment/locale/zh-cn';
13
+ import isEqual from 'lodash/isEqual';
13
14
  import { injectIntl, intlShape } from 'react-intl';
14
15
  import TopBar from '../../components/TopBar';
15
16
  // import 'moment/locale/en-us';
16
17
  import Sidebar from '../../components/Sidebar';
17
- import isEqual from 'lodash/isEqual';
18
18
  import { makeSelectAuthenticated, makeSelectUser } from './selectors';
19
19
  import * as actions from './actions';
20
20
  import * as locationActions from '../LanguageProvider/actions';
@@ -314,7 +314,7 @@ export class Cap extends React.Component { // eslint-disable-line react/prefer-s
314
314
  logout={this.logout}
315
315
  /> : ''}
316
316
  <div className="main">
317
- {loggedIn && type !== 'embedded' ? <div id="cap-sidebar" className={'sidebar'}>
317
+ {loggedIn && type !== 'embedded' && this.props.location.pathname !== 'templates' ? <div id="cap-sidebar" className={'sidebar'}>
318
318
  <Sidebar
319
319
  menuData={menuData}
320
320
  productMenuData={productMenuData}
@@ -0,0 +1,129 @@
1
+ import React from 'react';
2
+ import PropTypes from 'prop-types';
3
+ import styled from 'styled-components';
4
+ import TemplatesV2 from '../TemplatesV2';
5
+ import TemplatePreview from '../../components/TemplatePreview';
6
+ import SmsCreate from '../Sms/Create';
7
+ import SmsEdit from '../Sms/Edit';
8
+ import Email from '../Email';
9
+ import * as constants from './constants';
10
+ const CreativesWrapper = styled.div`
11
+ .ant-popover,
12
+ .ant-notification,
13
+ .ant-modal-wrap {
14
+ z-index: 10003;
15
+ }
16
+ `;
17
+ function SlideBoxContent(props) {
18
+ const {
19
+ slidBoxContent,
20
+ onSelectTemplate,
21
+ onPreviewTemplate,
22
+ templateData,
23
+ location,
24
+ isGetFormData,
25
+ getFormData,
26
+ messageDetails,
27
+ onCreateNew,
28
+ } = props;
29
+ const query = { type: 'embedded', module: 'library' };
30
+ const creativesLocationProps = {
31
+ pathname: `/sms/edit`,
32
+ query,
33
+ search: '',
34
+ };
35
+ let isCreateSms = false;
36
+ let isEditSms = false;
37
+ let isEditEmailWithId = false;
38
+ let isEmailEditWithContent = false;
39
+ if (templateData) {
40
+ const channel = templateData.type;
41
+ isEditSms = slidBoxContent === 'editTemplate' && channel === constants.SMS;
42
+ isCreateSms = slidBoxContent === 'createTemplate' && channel === constants.SMS;
43
+ isEditEmailWithId = slidBoxContent === 'editTemplate' && channel === constants.EMAIL && templateData._id;
44
+ isEmailEditWithContent = slidBoxContent === 'editTemplate' && channel === constants.EMAIL && !templateData._id;
45
+ }
46
+
47
+ return (
48
+ <CreativesWrapper>
49
+ {slidBoxContent === 'templates' && (
50
+ <TemplatesV2
51
+ isFullMode={false}
52
+ onSelectTemplate={onSelectTemplate}
53
+ handlePeviewTemplate={onPreviewTemplate}
54
+ location={location}
55
+ createNew={onCreateNew}
56
+ />
57
+ )}
58
+ {slidBoxContent === 'preview' && (
59
+ <TemplatePreview
60
+ content={templateData.versions.base['sms-editor']}
61
+ channel={templateData.type.toLowerCase()}
62
+ charCounterEnabled
63
+ />
64
+ )}
65
+ {isEditSms && (
66
+ <SmsEdit
67
+ location={creativesLocationProps}
68
+ route={{ name: 'sms' }}
69
+ isGetFormData={isGetFormData}
70
+ getFormSubscriptionData={getFormData}
71
+ getDefaultTags={messageDetails.type}
72
+ subscriptionTemplateDetails={templateData}
73
+ />
74
+ )}
75
+ {isCreateSms && (
76
+ <SmsCreate
77
+ location={creativesLocationProps}
78
+ route={{ name: 'sms' }}
79
+ isComponent
80
+ isGetFormData={isGetFormData}
81
+ getFormSubscriptionData={getFormData}
82
+ getDefaultTags={messageDetails.type}
83
+ />
84
+ )}
85
+ {isEditEmailWithId && (
86
+ <Email
87
+ location={{
88
+ pathname: `/email`,
89
+ query,
90
+ }}
91
+ route={{ name: 'email' }}
92
+ isGetFormData={isGetFormData}
93
+ getFormdata={getFormData}
94
+ params={{ id: templateData._id }}
95
+ templateData={templateData}
96
+ getFormSubscriptionData={getFormData}
97
+ getDefaultTags={messageDetails.type}
98
+ />
99
+ )}
100
+ {isEmailEditWithContent && (
101
+ <Email
102
+ location={{
103
+ pathname: `/email`,
104
+ query,
105
+ }}
106
+ route={{ name: 'email' }}
107
+ isGetFormData={isGetFormData}
108
+ getFormdata={getFormData}
109
+ params={{ id: templateData._id }}
110
+ templateData={templateData}
111
+ getFormSubscriptionData={getFormData}
112
+ getDefaultTags={messageDetails.type}
113
+ />
114
+ )}
115
+ </CreativesWrapper>
116
+ );
117
+ }
118
+ SlideBoxContent.propTypes = {
119
+ slidBoxContent: PropTypes.node,
120
+ onSelectTemplate: PropTypes.func,
121
+ onPreviewTemplate: PropTypes.func,
122
+ templateData: PropTypes.object,
123
+ location: PropTypes.object,
124
+ isGetFormData: PropTypes.bool,
125
+ getFormData: PropTypes.func,
126
+ messageDetails: PropTypes.object,
127
+ onCreateNew: PropTypes.func,
128
+ };
129
+ export default SlideBoxContent;
@@ -0,0 +1,31 @@
1
+ import React from 'react';
2
+ import { FormattedMessage } from 'react-intl';
3
+ import { CapButton } from '@capillarytech/cap-ui-library';
4
+ import PropTypes from 'prop-types';
5
+
6
+ function SlideBoxHeader(props) {
7
+ const { slidBoxContent, onSave, messages, onEditTemplate } = props;
8
+
9
+ return (
10
+ <div>
11
+ {(slidBoxContent === 'editTemplate' ||
12
+ slidBoxContent === 'createTemplate') && (
13
+ <CapButton onClick={onSave}>
14
+ <FormattedMessage {...messages.creativesTemplatesSave} />
15
+ </CapButton>
16
+ )}
17
+ {slidBoxContent === 'preview' && (
18
+ <CapButton onClick={onEditTemplate} type="secondary">
19
+ <FormattedMessage {...messages.creativesTemplatesEdit} />
20
+ </CapButton>
21
+ )}
22
+ </div>
23
+ );
24
+ }
25
+ SlideBoxHeader.propTypes = {
26
+ slidBoxContent: PropTypes.node,
27
+ onSave: PropTypes.func,
28
+ messages: PropTypes.object,
29
+ onEditTemplate: PropTypes.func,
30
+ };
31
+ export default SlideBoxHeader;
@@ -0,0 +1,62 @@
1
+ import React from 'react';
2
+ import styled from 'styled-components';
3
+ import { FormattedMessage } from 'react-intl';
4
+ import { CapHeader, CapIcons } from '@capillarytech/cap-ui-library';
5
+ import PropTypes from 'prop-types';
6
+
7
+ const PrefixWrapper = styled.div`
8
+ margin-right: 16px;
9
+ `;
10
+ function SlideBoxHeader(props) {
11
+ const { slidBoxContent, messages, templateData, onShowTemplates } = props;
12
+ return (
13
+ <div>
14
+ {slidBoxContent === 'templates' && (
15
+ <CapHeader
16
+ title={<FormattedMessage {...messages.creativeTemplates} />}
17
+ description={
18
+ <FormattedMessage {...messages.creativeTemplatesDesc} />
19
+ }
20
+ inline
21
+ />
22
+ )}
23
+ {slidBoxContent === 'preview' && (
24
+ <CapHeader
25
+ title={templateData.name}
26
+ prefix={
27
+ <PrefixWrapper>
28
+ <CapIcons.backIcon onClick={onShowTemplates} />
29
+ </PrefixWrapper>
30
+ }
31
+ />
32
+ )}
33
+ {slidBoxContent === 'editTemplate' && (
34
+ <CapHeader
35
+ title={<FormattedMessage {...messages.editMessageContent} />}
36
+ prefix={
37
+ <PrefixWrapper>
38
+ <CapIcons.backIcon onClick={onShowTemplates} />
39
+ </PrefixWrapper>
40
+ }
41
+ />
42
+ )}
43
+ {slidBoxContent === 'createTemplate' && (
44
+ <CapHeader
45
+ title={<FormattedMessage {...messages.createMessageContent} />}
46
+ prefix={
47
+ <PrefixWrapper>
48
+ <CapIcons.backIcon onClick={onShowTemplates} />
49
+ </PrefixWrapper>
50
+ }
51
+ />
52
+ )}
53
+ </div>
54
+ );
55
+ }
56
+ SlideBoxHeader.propTypes = {
57
+ slidBoxContent: PropTypes.node,
58
+ messages: PropTypes.object,
59
+ templateData: PropTypes.object,
60
+ onShowTemplates: PropTypes.func,
61
+ };
62
+ export default SlideBoxHeader;
@@ -0,0 +1,15 @@
1
+ /*
2
+ *
3
+ * CreativesContainer actions
4
+ *
5
+ */
6
+
7
+ import {
8
+ DEFAULT_ACTION,
9
+ } from './constants';
10
+
11
+ export function defaultAction() {
12
+ return {
13
+ type: DEFAULT_ACTION,
14
+ };
15
+ }
@@ -0,0 +1,9 @@
1
+ /*
2
+ *
3
+ * CreativesContainer constants
4
+ *
5
+ */
6
+
7
+ export const DEFAULT_ACTION = 'app/CreativesContainer/DEFAULT_ACTION';
8
+ export const EMAIL = "EMAIL";
9
+ export const SMS = "SMS";
@@ -0,0 +1,178 @@
1
+ import React from 'react';
2
+ import { PropTypes } from 'prop-types';
3
+ import {
4
+ CapSlideBox,
5
+ } from '@capillarytech/cap-ui-library';
6
+ import { injectIntl } from 'react-intl';
7
+ import classnames from 'classnames';
8
+ import {isEmpty} from 'lodash';
9
+ import SlideBoxContent from './SlideBoxContent';
10
+ import SlideBoxHeader from './SlideBoxHeader';
11
+ import SlideBoxFooter from './SlideBoxFooter';
12
+ import * as constants from './constants';
13
+ import './index.scss';
14
+
15
+
16
+ const classPrefix = 'add-creatives-section';
17
+ class Creatives extends React.Component {
18
+ constructor(props) {
19
+ super(props);
20
+ this.state = {
21
+ showSlideBox: true,
22
+ slidBoxContent: this.getSlideBocContent({mode: props.creativesMode, templateData: props.templateData}),
23
+ templateData: this.getTemplateData(props.templateData),
24
+ };
25
+ }
26
+ componentWillUnmount() {
27
+ console.log("unmounting creatives");
28
+ }
29
+
30
+
31
+ onSelectTemplate = (template) => {
32
+ this.setState({ slidBoxContent: 'editTemplate', templateData: template });
33
+ };
34
+ onPreviewTemplate = (template) => {
35
+ this.setState({ slidBoxContent: 'preview', templateData: template });
36
+ };
37
+ onEditTemplate = () => {
38
+ this.setState({ slidBoxContent: 'editTemplate', showSlideBox: true });
39
+ };
40
+ onCreateNew = () => {
41
+ this.setState({ slidBoxContent: 'createTemplate', showSlideBox: true });
42
+ };
43
+
44
+ onShowTemplates = () => {
45
+ this.setState({ slidBoxContent: 'templates', showSlideBox: true });
46
+ };
47
+ getSlideBocContent({mode, templateData}) {
48
+ let creativesMode = 'templates';
49
+ if (mode === 'create' && isEmpty(templateData)) {
50
+ creativesMode = 'templates';
51
+ } else if (mode === 'edit') {
52
+ creativesMode = 'editTemplate';
53
+ }
54
+ return creativesMode;
55
+ }
56
+ getCreativesData = (channel, template) => { //from creatives to consumers
57
+ const templateData = {channel };
58
+ if (channel === constants.SMS && template.value.base) {
59
+ templateData.messageBody = template.value.base['sms-editor'];
60
+ } else if (channel === constants.EMAIL && template.value.base) {
61
+ templateData.emailBody = template.value.base.html_content;
62
+ templateData.emailSubject = template.value.base.subject;
63
+ }
64
+ return templateData;
65
+ };
66
+ getTemplateData = (templateData) => { //from consumers to creatives
67
+ if (templateData) {
68
+ const {channel} = templateData;
69
+ let creativesTeplateData = {type: channel };
70
+ if (channel === constants.SMS) {
71
+ const formData = {
72
+ "sms-editor": templateData.messageBody,
73
+ };
74
+ creativesTeplateData = {
75
+ type: channel,
76
+ name: "Campaign message SMS content",
77
+ versions: {
78
+ base: formData,
79
+ history: [formData],
80
+ },
81
+ };
82
+ } else if (channel === constants.EMAIL) {
83
+ const formData = {
84
+ subject: templateData.emailSubject,
85
+ html_content: templateData.emailBody,
86
+ is_drag_drop: false,
87
+ lang_id: 411,
88
+ iso_code: "en",
89
+ language: "English",
90
+ };
91
+ creativesTeplateData = {
92
+ base: formData,
93
+ edit: true,
94
+ type: channel,
95
+ };
96
+ }
97
+ return creativesTeplateData;
98
+ }
99
+ return null;
100
+ }
101
+
102
+ getFormData = (template) => {
103
+ if (template.validity) {
104
+ this.setState(
105
+ {
106
+ isGetFormData: false,
107
+ },
108
+ () => {
109
+ const channel = this.state.templateData.type;
110
+ const creativesData = this.getCreativesData(channel, template);// convers data to consumer understandable format
111
+ this.props.getCreativesData(creativesData);// send data to consumer
112
+ },
113
+ );
114
+ }
115
+ };
116
+ toggleShowSlideBox = () => {
117
+ this.setState((prevState) => ({
118
+ ...prevState,
119
+ templateData: undefined,
120
+ }), this.props.handleCloseCreatives);
121
+ };
122
+ saveMessage = () => {
123
+ this.setState({ isGetFormData: true });
124
+ };
125
+ render() {
126
+ const {slidBoxContent, isGetFormData, showSlideBox} = this.state;
127
+ const { templateData } = this.state;
128
+ return (
129
+ <div className={classnames(`${classPrefix}`)}>
130
+ <CapSlideBox
131
+ header={
132
+ <SlideBoxHeader
133
+ messages={this.props.messages}
134
+ slidBoxContent={this.state.slidBoxContent}
135
+ templateData={templateData}
136
+ onShowTemplates={this.onShowTemplates}
137
+ />
138
+ }
139
+ content={
140
+ <SlideBoxContent
141
+ onSelectTemplate={this.onSelectTemplate}
142
+ onPreviewTemplate={this.onPreviewTemplate}
143
+ slidBoxContent={slidBoxContent}
144
+ templateData={templateData}
145
+ location={this.props.location}
146
+ messageDetails={this.props.messageDetails}
147
+ getFormData={this.getFormData}
148
+ onCreateNew={this.onCreateNew}
149
+ isGetFormData={isGetFormData}
150
+ />
151
+ }
152
+ footer={
153
+ <SlideBoxFooter
154
+ messages={this.props.messages}
155
+ onSave={this.saveMessage}
156
+ onEditTemplate={this.onEditTemplate}
157
+ slidBoxContent={slidBoxContent}
158
+ />
159
+ }
160
+ handleClose={this.toggleShowSlideBox}
161
+ show={showSlideBox}
162
+ size="size-l"
163
+ />
164
+ </div>
165
+ );
166
+ }
167
+ }
168
+
169
+ Creatives.propTypes = {
170
+ getCreativesData: PropTypes.func,
171
+ messages: PropTypes.object,
172
+ messageDetails: PropTypes.object,
173
+ creativesMode: PropTypes.string,
174
+ location: PropTypes.object,
175
+ handleCloseCreatives: PropTypes.func,
176
+ templateData: PropTypes.object,
177
+ };
178
+ export default injectIntl(Creatives);
@@ -0,0 +1,20 @@
1
+ @import '../../../node_modules/@capillarytech/cap-ui-library/styles/_variables.scss';
2
+
3
+ $classPrefix: add-creatives-section;
4
+
5
+ .#{$classPrefix} {
6
+ .#{$classPrefix}-footer {
7
+ position: absolute;
8
+ bottom: 0;
9
+ left: 1px;
10
+ padding: 0 12px;
11
+ display: flex;
12
+ align-items: center;
13
+ height: 48px;
14
+ border-top: 1px solid $CAP_G07;
15
+
16
+ &.with-creative {
17
+ width: 100%;
18
+ }
19
+ }
20
+ }
@@ -0,0 +1,23 @@
1
+ /*
2
+ *
3
+ * CreativesContainer reducer
4
+ *
5
+ */
6
+
7
+ import { fromJS } from 'immutable';
8
+ import {
9
+ DEFAULT_ACTION,
10
+ } from './constants';
11
+
12
+ const initialState = fromJS({});
13
+
14
+ function creativesContainerReducer(state = initialState, action) {
15
+ switch (action.type) {
16
+ case DEFAULT_ACTION:
17
+ return state;
18
+ default:
19
+ return state;
20
+ }
21
+ }
22
+
23
+ export default creativesContainerReducer;
@@ -0,0 +1,11 @@
1
+ // import { take, call, put, select } from 'redux-saga/effects';
2
+
3
+ // Individual exports for testing
4
+ export function* defaultSaga() {
5
+ // See example in containers/HomePage/sagas.js
6
+ }
7
+
8
+ // All sagas to be loaded
9
+ export default [
10
+ defaultSaga,
11
+ ];
@@ -0,0 +1,25 @@
1
+ import { createSelector } from 'reselect';
2
+
3
+ /**
4
+ * Direct selector to the creativesContainer state domain
5
+ */
6
+ const selectCreativesContainerDomain = () => (state) => state.get('creativesContainer');
7
+
8
+ /**
9
+ * Other specific selectors
10
+ */
11
+
12
+
13
+ /**
14
+ * Default selector used by CreativesContainer
15
+ */
16
+
17
+ const makeSelectCreativesContainer = () => createSelector(
18
+ selectCreativesContainerDomain(),
19
+ (substate) => substate.toJS()
20
+ );
21
+
22
+ export default makeSelectCreativesContainer;
23
+ export {
24
+ selectCreativesContainerDomain,
25
+ };
@@ -0,0 +1,18 @@
1
+
2
+ import {
3
+ defaultAction,
4
+ } from '../actions';
5
+ import {
6
+ DEFAULT_ACTION,
7
+ } from '../constants';
8
+
9
+ describe('CreativesContainer 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,10 @@
1
+ // import React from 'react';
2
+ // import { shallow } from 'enzyme';
3
+
4
+ // import { CreativesContainer } from '../index';
5
+
6
+ describe('<CreativesContainer />', () => {
7
+ it('Expect to have unit tests specified', () => {
8
+ expect(true).toEqual(true);
9
+ });
10
+ });
@@ -0,0 +1,9 @@
1
+
2
+ import { fromJS } from 'immutable';
3
+ import creativesContainerReducer from '../reducer';
4
+
5
+ describe('creativesContainerReducer', () => {
6
+ it('returns the initial state', () => {
7
+ expect(creativesContainerReducer(undefined, {})).toEqual(fromJS({}));
8
+ });
9
+ });
@@ -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(true);
14
+ });
15
+ });
@@ -0,0 +1,10 @@
1
+ // import { fromJS } from 'immutable';
2
+ // import { makeSelectCreativesContainerDomain } from '../selectors';
3
+
4
+ // const selector = makeSelectCreativesContainerDomain();
5
+
6
+ describe('makeSelectCreativesContainerDomain', () => {
7
+ it('Expect to have unit tests specified', () => {
8
+ expect(true).toEqual(true);
9
+ });
10
+ });
@@ -2007,12 +2007,14 @@ export class Email extends React.Component { // eslint-disable-line react/prefer
2007
2007
 
2008
2008
  showSubject = () => {
2009
2009
  const schema = _.cloneDeep(this.state.schema);
2010
- if (this.props.location.query.type === 'embedded' && (this.props.location.query.module === "loyalty" || this.props.location.query.module === "dvs" || this.props.location.query.module === "timeline" || this.props.location.query.module === "coupon_expiry" ||
2010
+ if (schema.standalone) {
2011
+ if (this.props.location.query.type === 'embedded' && (this.props.location.query.module === "loyalty" || this.props.location.query.module === "dvs" || this.props.location.query.module === "timeline" || this.props.location.query.module === "coupon_expiry" ||
2011
2012
  this.props.location.query.module === "library")) {
2012
- schema.standalone.sections[0].inputFields[0].style.display = "";
2013
- schema.standalone.sections[0].inputFields[0].labelStyle.display = "";
2013
+ schema.standalone.sections[0].inputFields[0].style.display = "";
2014
+ schema.standalone.sections[0].inputFields[0].labelStyle.display = "";
2015
+ }
2016
+ this.setState({schema});
2014
2017
  }
2015
- this.setState({schema});
2016
2018
  }
2017
2019
 
2018
2020
  handleOnItemClick = (isSelected, id) => {
@@ -1262,7 +1262,7 @@ export class Templates extends React.Component { // eslint-disable-line react/pr
1262
1262
  onChange={(e) => this.searchTemplate(e.target.value)}
1263
1263
  />
1264
1264
  {this.props.isComponent ? <div style={{display: "flex", justifyContent: "space-between", alignItems: 'center'}}>
1265
- <CapButton type="secondary" onClick={() => this.props.isComponent ? this.handleBlankTemplateAction() : this.createTemplate()}>{this.state.channel.toUpperCase() === 'SMS' ? this.props.intl.formatMessage(messages.createSmsActionButton) : 'Create SMS'}</CapButton>
1265
+ <CapButton type="secondary" onClick={() => this.props.isComponent ? this.handleBlankTemplateAction() : this.createTemplate()}>{ this.props.intl.formatMessage(messages.createNewActionButton) }</CapButton>
1266
1266
  </div>
1267
1267
  :
1268
1268
  <div className="action-container">
@@ -1557,7 +1557,7 @@ Templates.propTypes = {
1557
1557
  smsEditActions: PropTypes.object,
1558
1558
  ebillActions: PropTypes.object,
1559
1559
  emailActions: PropTypes.object,
1560
- TemplatesList: PropTypes.object,
1560
+ TemplatesList: PropTypes.array,
1561
1561
  Templates: PropTypes.object,
1562
1562
  route: PropTypes.object,
1563
1563
  router: PropTypes.object,
@@ -1570,6 +1570,7 @@ Templates.propTypes = {
1570
1570
  onSelectTemplate: PropTypes.func,
1571
1571
  lineActions: PropTypes.object,
1572
1572
  isComponent: PropTypes.bool,
1573
+ renderNewCardGrid: PropTypes.func,
1573
1574
  };
1574
1575
 
1575
1576
  const mapStateToProps = createStructuredSelector({
@@ -6,175 +6,175 @@
6
6
  import { defineMessages } from 'react-intl';
7
7
 
8
8
  export default defineMessages({
9
- header: {
9
+ "header": {
10
10
  id: 'app.containers.Templates.header',
11
11
  defaultMessage: 'This is Templates container !',
12
12
  },
13
- uploadedAt: {
13
+ "uploadedAt": {
14
14
  id: 'app.containers.Templates.uploadedAt',
15
15
  defaultMessage: 'Modified',
16
16
  },
17
- uploadedBy: {
17
+ "uploadedBy": {
18
18
  id: 'app.containers.Templates.uploadedBy',
19
19
  defaultMessage: 'Uploaded By',
20
20
  },
21
- mapTemplate: {
21
+ "mapTemplate": {
22
22
  id: 'app.containers.Templates.mapTemplate',
23
23
  defaultMessage: 'Map Template',
24
24
  },
25
- somethingWentWrong: {
25
+ "somethingWentWrong": {
26
26
  id: 'app.containers.Templates.somethingWentWrong',
27
27
  defaultMessage: 'Something Went Wrong!!',
28
28
  },
29
- wechatHeader: {
29
+ "wechatHeader": {
30
30
  id: 'app.containers.Templates.wechatHeader',
31
31
  defaultMessage: 'WECHAT',
32
32
  },
33
- smsHeader: {
33
+ "smsHeader": {
34
34
  id: 'app.containers.Templates.smsHeader',
35
35
  defaultMessage: 'SMS',
36
36
  },
37
- emailHeader: {
37
+ "emailHeader": {
38
38
  id: 'app.containers.Templates.emailHeader',
39
39
  defaultMessage: 'Email',
40
40
  },
41
- mobilepushHeader: {
41
+ "mobilepushHeader": {
42
42
  id: 'app.containers.Templates.mobilepushHeader',
43
43
  defaultMessage: 'Mobile Push',
44
44
  },
45
- ebillHeader: {
45
+ "ebillHeader": {
46
46
  id: 'app.containers.Templates.ebillHeader',
47
47
  defaultMessage: 'Ebill',
48
48
  },
49
- lineHeader: {
49
+ "lineHeader": {
50
50
  id: 'app.containers.Templates.lineHeader',
51
51
  defaultMessage: 'Line',
52
52
  },
53
- selectWechatHeader: {
53
+ "selectWechatHeader": {
54
54
  id: 'app.containers.Templates.selectWechatHeader',
55
55
  defaultMessage: 'Select WECHAT Template',
56
56
  },
57
- selectSmsHeader: {
57
+ "selectSmsHeader": {
58
58
  id: 'app.containers.Templates.selectSmsHeader',
59
59
  defaultMessage: 'Select SMS Template',
60
60
  },
61
- selectAccount: {
61
+ "selectAccount": {
62
62
  id: 'app.containers.Templates.selectAccount',
63
63
  defaultMessage: "Select Account",
64
64
  },
65
- gettingAllTemplates: {
65
+ "gettingAllTemplates": {
66
66
  id: 'app.containers.Templates.gettingAllTemplates',
67
67
  defaultMessage: "Getting all templates...",
68
68
  },
69
- smsChannelTemplatesHeader: {
69
+ "smsChannelTemplatesHeader": {
70
70
  id: 'app.containers.Templates.smsChannelTemplatesHeader',
71
71
  defaultMessage: "SMS Templates",
72
72
  },
73
- wechatChannelTemplatesHeader: {
73
+ "wechatChannelTemplatesHeader": {
74
74
  id: 'app.containers.Templates.wechatChannelTemplatesHeader',
75
75
  defaultMessage: "WECHAT Templates",
76
76
  },
77
- blankTemplate: {
77
+ "blankTemplate": {
78
78
  id: 'app.containers.Templates.blankTemplate',
79
79
  defaultMessage: "Blank Template",
80
80
  },
81
- selectButton: {
81
+ "selectButton": {
82
82
  id: 'app.containers.Templates.selectButton',
83
83
  defaultMessage: "Select",
84
84
  },
85
- previewButton: {
85
+ "previewButton": {
86
86
  id: 'app.containers.Templates.previewButton',
87
87
  defaultMessage: "Preview",
88
88
  },
89
- editButton: {
89
+ "editButton": {
90
90
  id: 'app.containers.Templates.editButton',
91
91
  defaultMessage: "Edit",
92
92
  },
93
- duplicateButton: {
93
+ "duplicateButton": {
94
94
  id: 'app.containers.Templates.duplicateButton',
95
95
  defaultMessage: "Duplicate",
96
96
  },
97
- deleteButton: {
97
+ "deleteButton": {
98
98
  id: 'app.containers.Templates.deleteButton',
99
99
  defaultMessage: "Delete",
100
100
  },
101
- mostRecentOption: {
101
+ "mostRecentOption": {
102
102
  id: 'app.containers.Templates.mostRecentOption',
103
103
  defaultMessage: "Most Recent",
104
104
  },
105
- alphabeticallyOption: {
105
+ "alphabeticallyOption": {
106
106
  id: 'app.containers.Templates.alphabeticallyOption',
107
107
  defaultMessage: "Alphabetically",
108
108
  },
109
- searchText: {
109
+ "searchText": {
110
110
  id: 'app.containers.Templates.searchText',
111
111
  defaultMessage: "Search",
112
112
  },
113
- noAccountMessage: {
113
+ "noAccountMessage": {
114
114
  id: 'app.containers.Templates.noAccountMessage',
115
115
  defaultMessage: "Please select an account to proceed",
116
116
  },
117
- noTemplatesMessage: {
117
+ "noTemplatesMessage": {
118
118
  id: 'app.containers.Templates.noTemplatesMessage',
119
119
  defaultMessage: "No Templates Available",
120
120
  },
121
- createSmsActionButton: {
121
+ "createSmsActionButton": {
122
122
  id: 'app.containers.Templates.createSmsActionButton',
123
123
  defaultMessage: "Create SMS",
124
124
  },
125
- createEmailActionButton: {
125
+ "createEmailActionButton": {
126
126
  id: 'app.containers.Templates.createEmailActionButton',
127
127
  defaultMessage: "Create Email",
128
128
  },
129
- sortBy: {
129
+ "sortBy": {
130
130
  id: 'app.containers.Templates.sortBy',
131
131
  defaultMessage: "Sort by",
132
132
  },
133
- unMapButton: {
133
+ "unMapButton": {
134
134
  id: 'app.containers.Templates.unMapButton',
135
135
  defaultMessage: "Unmap",
136
136
  },
137
- templateDuplicateSuccess: {
137
+ "templateDuplicateSuccess": {
138
138
  id: 'app.containers.Templates.templateDuplicateSuccess',
139
139
  defaultMessage: "Template Duplicated Successfully",
140
140
  },
141
- templateDeleteSuccess: {
141
+ "templateDeleteSuccess": {
142
142
  id: 'app.containers.Templates.templateDeleteSuccess',
143
143
  defaultMessage: "SMS Template Deleted Successfully",
144
144
  },
145
- uploadFile: {
145
+ "uploadFile": {
146
146
  id: 'app.containers.Templates.uploadFile',
147
147
  defaultMessage: "Upload File",
148
148
  },
149
- useEditor: {
149
+ "useEditor": {
150
150
  id: 'app.containers.Templates.useEditor',
151
151
  defaultMessage: "Use Editor",
152
152
  },
153
- newTemplate: {
153
+ "newTemplate": {
154
154
  id: 'app.containers.Templates.newTemplate',
155
155
  defaultMessage: "New Template",
156
156
  },
157
- uploadingFile: {
157
+ "uploadingFile": {
158
158
  id: 'app.containers.Templates.uploadingFile',
159
159
  defaultMessage: "Uploading File",
160
160
  },
161
- zipUploadFailed: {
161
+ "zipUploadFailed": {
162
162
  id: 'app.containers.Templates.zipUploadFailed',
163
163
  defaultMessage: 'Failed to Upload zip file',
164
164
  },
165
- campaigns: {
165
+ "campaigns": {
166
166
  id: 'app.containers.Templates.campaigns',
167
167
  defaultMessage: 'Campaigns',
168
168
  },
169
- creatives: {
169
+ "creatives": {
170
170
  id: 'app.containers.Templates.creatives',
171
171
  defaultMessage: 'Creatives',
172
172
  },
173
- ebillPreview: {
173
+ "ebillPreview": {
174
174
  id: 'app.containers.Templates.ebillPreview',
175
175
  defaultMessage: 'Ebill Preview',
176
176
  },
177
- emailPreview: {
177
+ "emailPreview": {
178
178
  id: 'app.containers.Templates.emailPreview',
179
179
  defaultMessage: 'Email Preview',
180
180
  },
@@ -186,48 +186,52 @@ export default defineMessages({
186
186
  id: 'app.containers.Templates.deletionFailed',
187
187
  defaultMessage: 'Template deletion failed',
188
188
  },
189
- preview: {
189
+ "preview": {
190
190
  id: 'app.containers.Templates.preview',
191
191
  defaultMessage: 'Preview',
192
192
  },
193
- invalidUploadFileError: {
193
+ "invalidUploadFileError": {
194
194
  id: 'app.containers.Templates.invalidUploadFileError',
195
195
  defaultMessage: 'File cannot be uploaded. Please select another file with valid file format.',
196
196
  },
197
- templateDeleteConfirm: {
197
+ "templateDeleteConfirm": {
198
198
  id: 'app.containers.Templates.templateDeleteConfirm',
199
199
  defaultMessage: 'Are you sure you want to delete this Template?',
200
200
  },
201
- cancelText: {
201
+ "cancelText": {
202
202
  id: 'app.containers.Templates.cancelText',
203
203
  defaultMessage: 'Cancel',
204
204
  },
205
- yesText: {
205
+ "yesText": {
206
206
  id: 'app.containers.Templates.yesText',
207
207
  defaultMessage: 'Yes',
208
208
  },
209
- templateSelection: {
209
+ "templateSelection": {
210
210
  id: 'app.containers.Templates.templateSelection',
211
211
  defaultMessage: 'Template Selection',
212
212
  },
213
- layoutSelection: {
213
+ "layoutSelection": {
214
214
  id: 'app.containers.Templates.layoutSelection',
215
215
  defaultMessage: 'Select Layout',
216
216
  },
217
- textTemplate: {
217
+ "textTemplate": {
218
218
  id: 'app.containers.Templates.textTemplate',
219
219
  defaultMessage: 'Text',
220
220
  },
221
- imageTemplate: {
221
+ "imageTemplate": {
222
222
  id: 'app.containers.Templates.imageTemplate',
223
223
  defaultMessage: 'Image',
224
224
  },
225
- selectDefaultButton: {
225
+ "selectDefaultButton": {
226
226
  id: 'app.containers.Templates.selectDefaultButton',
227
227
  defaultMessage: 'Select',
228
228
  },
229
- previewGenerateText: {
229
+ "previewGenerateText": {
230
230
  id: 'app.containers.Templates.previewGenerateText',
231
231
  defaultMessage: 'Preview is being generated...',
232
232
  },
233
+ "createNewActionButton": {
234
+ id: 'app.containers.Templates.createNewActionButton',
235
+ defaultMessage: 'Create new',
236
+ },
233
237
  });
@@ -8,7 +8,7 @@ import PropTypes from 'prop-types';
8
8
 
9
9
  import React from 'react';
10
10
  import { connect } from 'react-redux';
11
- import { injectIntl } from 'react-intl';
11
+ import { injectIntl, intlShape } from 'react-intl';
12
12
  import { createStructuredSelector } from 'reselect';
13
13
  import { bindActionCreators } from 'redux';
14
14
  import { CapTab, CapCard, CapIcons, CapButton } from '@capillarytech/cap-ui-library';
@@ -26,10 +26,10 @@ export class TemplatesV2 extends React.Component { // eslint-disable-line react/
26
26
  this.state = {
27
27
  selectedChannel: this.props.channel || 'sms',
28
28
  panes: [
29
- {content: this.getTemplatesComponent('sms'), tab: 'Sms', key: 'sms-templates'},
30
- {content: this.getTemplatesComponent('email'), tab: 'Email', key: 'email-templates'},
31
- {content: this.getTemplatesComponent('wechat'), tab: 'Wechat', key: 'wechat-templates'},
32
- {content: this.getTemplatesComponent('mobilepush'), tab: 'Mpush', key: 'mpush-templates'},
29
+ {content: this.getTemplatesComponent('sms'), tab: 'Sms', key: 'sms'},
30
+ {content: this.getTemplatesComponent('email'), tab: 'Email', key: 'email'},
31
+ {content: this.getTemplatesComponent('wechat'), tab: 'Wechat', key: 'wechat'},
32
+ {content: this.getTemplatesComponent('mobilepush'), tab: 'Mpush', key: 'mobilepush'},
33
33
  ],
34
34
  };
35
35
  }
@@ -39,7 +39,7 @@ export class TemplatesV2 extends React.Component { // eslint-disable-line react/
39
39
  {
40
40
  title: template.name,
41
41
  content: template.versions.base['sms-editor'],
42
- extra: [<View onClick={() => { this.props.isFullMode ? handlers.handlePreviewClick(template) : this.props.handlePeviewTemplate(template); }} />],
42
+ extra: [<View onClick={() => { if (this.props.isFullMode) { handlers.handlePreviewClick(template); } else { this.props.handlePeviewTemplate(template); } }} />],
43
43
  hoverOption: <CapButton onClick={(e) => handlers.handleEditClick(e, template._id)}>{this.props.intl.formatMessage(this.props.isFullMode ? messages.edit : messages.select)}</CapButton>,
44
44
  }));
45
45
  return (<div>
@@ -54,7 +54,8 @@ export class TemplatesV2 extends React.Component { // eslint-disable-line react/
54
54
  query = {type: 'embedded', module: 'library'};
55
55
  }
56
56
  return (<Templates
57
- location={{pathname: channel, search: '', query}}
57
+ key={channel}
58
+ location={{pathname: `/${channel}`, search: '', query}}
58
59
  route={{name: channel}}
59
60
  router={this.props.router}
60
61
  isComponent={!this.props.isFullMode}
@@ -74,25 +75,17 @@ export class TemplatesV2 extends React.Component { // eslint-disable-line react/
74
75
  }
75
76
  return pane;
76
77
  });
77
- this.setState({panes});
78
+ this.setState({panes, selectedChannel});
78
79
  }
79
80
  isLoading() {
80
81
  return this.props.Templates.loadingTemplates;
81
82
  }
82
83
  render() {
83
84
  return (
84
- // <CapSpin spinning={this.isLoading()}>
85
- <CapTab panes={this.state.panes} onChange={this.channelChange}/>
86
- // {this.state.previewTemplate && <PreviewSideBar
87
- // showPreview={this.state.previewOpen}
88
- // templateData={this.state.previewTemplate}
89
- // channel={this.state.selectedChannel}
90
- // handleClose={this.togglePreview}
91
- // onEditClick={this.handleEditClick}
92
- // onDuplicateClick={this.duplicateTemplate}
93
- // location={this.props.location}
94
- // />}
95
- // </CapSpin>
85
+ <div>
86
+ <CapTab panes={this.state.panes} onChange={this.channelChange} activeKey={this.state.selectedChannel} defaultActiveKey={this.state.selectedChannel}/>
87
+ </div>
88
+
96
89
  );
97
90
  }
98
91
  }
@@ -106,6 +99,7 @@ TemplatesV2.propTypes = {
106
99
  Templates: PropTypes.object,
107
100
  TemplatesList: PropTypes.arrayOf(PropTypes.object),
108
101
  handlePeviewTemplate: PropTypes.func,
102
+ intl: intlShape,
109
103
  };
110
104
 
111
105
  TemplatesV2.defaultProps = {
package/index.js CHANGED
@@ -63,7 +63,7 @@ export {default as TagListSaga} from './containers/TagList/sagas';
63
63
  export {default as TagListReducer} from './containers/TagList/reducer';
64
64
  export {default as TemplatePreview} from './components/TemplatePreview';
65
65
  export {default as EmailPreview} from './components/EmailPreview';
66
-
66
+ export {default as CreativesContainer} from './containers/CreativesContainer';
67
67
 
68
68
  export { CapContainer,
69
69
  TemplatesContainer,
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@capillarytech/creatives-library",
3
3
  "author": "meharaj",
4
- "version": "2.0.5",
4
+ "version": "2.0.7",
5
5
  "description": "Capillary creatives ui",
6
6
  "main": "./index.js",
7
7
  "module": "./index.es.js",
@@ -13,7 +13,7 @@
13
13
  "license": "LicenseRef-LICENSE",
14
14
  "dependencies": {
15
15
  "@capillarytech/cap-react-ui-library": "latest",
16
- "@capillarytech/cap-ui-library": "^1.0.33",
16
+ "@capillarytech/cap-ui-library": "^1.0.42",
17
17
  "antd": "^3.13.1",
18
18
  "axios": "^0.16.2",
19
19
  "babel-polyfill": "6.20.0",
@@ -1,34 +0,0 @@
1
- /*
2
- *
3
- * TemplatesV2 reducer
4
- *
5
- */
6
-
7
- import { fromJS } from 'immutable';
8
- import * as types from './constants';
9
-
10
- const initialState = fromJS({
11
- loadingTemplates: true,
12
- smsTemplates: [],
13
- emailTemplates: [],
14
- wechatTemplates: [],
15
- mobilepushTemplates: [],
16
- });
17
-
18
- function templatesV2Reducer(state = initialState, action) {
19
- const channelTemplates = `${action.channel}Templates`;
20
- switch (action.type) {
21
- case types.DEFAULT_ACTION:
22
- return state;
23
- case types.GET_TEMPLATES_REQUEST:
24
- return state.set('loadingTemplates', true);
25
- case types.GET_TEMPLATES_SUCESS:
26
- return state.set('loadingTemplates', false).set(channelTemplates, action.templates);
27
- case types.GET_TEMPLATES_FAILURE:
28
- return state.set('loadingTemplates', false).set('error', action.error);
29
- default:
30
- return state;
31
- }
32
- }
33
-
34
- export default templatesV2Reducer;
@@ -1,32 +0,0 @@
1
- import { take, takeLatest, call, put, cancel } from 'redux-saga/effects';
2
- import { LOCATION_CHANGE } from 'react-router-redux';
3
- import * as Api from '../../services/api';
4
-
5
-
6
- import * as types from './constants';
7
- // Individual exports for testing
8
- export function* defaultSaga() {
9
- // See example in containers/HomePage/sagas.js
10
- }
11
- function* getTemplates(action) {
12
- try {
13
- const req = {
14
- channel: action.channel,
15
- queryParams: action.query,
16
- };
17
- const res = yield call(Api.getAllTemplates, req);
18
- yield put({type: types.GET_TEMPLATES_SUCESS, templates: res.response.templates, channel: action.channel});
19
- } catch (error) {
20
- yield put({type: types.GET_TEMPLATES_FAILURE, error});
21
- }
22
- }
23
- function* getTemplatesWatcher() {
24
- const watcher = yield takeLatest(types.GET_TEMPLATES_REQUEST, getTemplates);
25
- yield take(LOCATION_CHANGE);
26
- yield cancel(watcher);
27
- }
28
- // All sagas to be loaded
29
- export default [
30
- defaultSaga,
31
- getTemplatesWatcher,
32
- ];