@capillarytech/creatives-library 2.0.34 → 2.0.35

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.
@@ -8,7 +8,7 @@ import PropTypes from 'prop-types';
8
8
 
9
9
  import React from 'react';
10
10
  import moment from "moment";
11
- import { CapButton } from '@capillarytech/cap-react-ui-library';
11
+ import { CapButton } from '@capillarytech/cap-ui-library';
12
12
  // import styled from 'styled-components';
13
13
 
14
14
  import { FormattedMessage } from 'react-intl';
@@ -10,7 +10,7 @@ import React from 'react';
10
10
  import _ from 'lodash';
11
11
  import { injectIntl, intlShape} from 'react-intl';
12
12
  // import styled from 'styled-components';
13
- import {CapColumn} from '@capillarytech/cap-react-ui-library'
13
+ import {CapColumn} from '@capillarytech/cap-ui-library'
14
14
  import './_templatePreview.scss';
15
15
  import * as charCount from '../../utils/smsCharCount';
16
16
  import {updateCharCount} from '../../utils/smsCharCountV2';
@@ -14,7 +14,7 @@ import { FormattedMessage, injectIntl, intlShape } from 'react-intl';
14
14
  import { createStructuredSelector } from 'reselect';
15
15
  import moment from "moment";
16
16
  import _ from "lodash";
17
- import { CapInput, CapButton } from '@capillarytech/cap-react-ui-library';
17
+ import { CapInput, CapButton } from '@capillarytech/cap-ui-library';
18
18
  import { Spin, Popover, Select } from 'antd';
19
19
  import makeSelectGallery from './selectors';
20
20
  import messages from './messages';
@@ -35,9 +35,10 @@ function SlideBoxContent(props) {
35
35
  onEmailNextStep,
36
36
  cap,
37
37
  onResetStep,
38
+ isFullMode,
38
39
  } = props;
39
40
  const type = messageDetails.type.toLowerCase(); // type is context in get tags values : outbound | dvs | referral | loyalty | coupons
40
- const query = { type: 'embedded', module: 'library' };
41
+ const query = { type: !isFullMode && 'embedded', module: isFullMode ? 'defualt' : 'library', isLanguageSupport: true };
41
42
  const creativesLocationProps = {
42
43
  pathname: `/sms/edit`,
43
44
  query,
@@ -62,9 +63,9 @@ function SlideBoxContent(props) {
62
63
 
63
64
  return (
64
65
  <CreativesWrapper>
65
- {slidBoxContent === 'templates' && (
66
+ {!isFullMode && slidBoxContent === 'templates' && (
66
67
  <TemplatesV2
67
- isFullMode={false}
68
+ isFullMode={isFullMode}
68
69
  onSelectTemplate={onSelectTemplate}
69
70
  handlePeviewTemplate={onPreviewTemplate}
70
71
  location={location}
@@ -117,7 +118,7 @@ function SlideBoxContent(props) {
117
118
  type={type}
118
119
  step={templateStep}
119
120
  showNextStep={onEmailNextStep}
120
- isFullMode={false}
121
+ isFullMode={isFullMode}
121
122
  cap={cap}
122
123
  onResetStep={onResetStep}
123
124
  />
@@ -159,5 +160,6 @@ SlideBoxContent.propTypes = {
159
160
  onEmailNextStep: PropTypes.func,
160
161
  cap: PropTypes.object,
161
162
  onResetStep: PropTypes.func,
163
+ isFullMode: PropTypes.bool,
162
164
  };
163
165
  export default SlideBoxContent;
@@ -8,7 +8,7 @@ const PrefixWrapper = styled.div`
8
8
  margin-right: 16px;
9
9
  `;
10
10
  function SlideBoxHeader(props) {
11
- const { slidBoxContent, messages, templateData, onShowTemplates, creativesMode } = props;
11
+ const { slidBoxContent, messages, templateData, onShowTemplates, creativesMode, isFullMode } = props;
12
12
  return (
13
13
  <div>
14
14
  {slidBoxContent === 'templates' && (
@@ -33,7 +33,7 @@ function SlideBoxHeader(props) {
33
33
  {slidBoxContent === 'editTemplate' && (
34
34
  <CapHeader
35
35
  title={<FormattedMessage {...messages.editMessageContent} />}
36
- prefix={creativesMode !== 'edit' &&
36
+ prefix={creativesMode !== 'edit' && !isFullMode &&
37
37
  <PrefixWrapper>
38
38
  <CapIcons.backIcon onClick={onShowTemplates} />
39
39
  </PrefixWrapper>
@@ -43,7 +43,7 @@ function SlideBoxHeader(props) {
43
43
  {slidBoxContent === 'createTemplate' && (
44
44
  <CapHeader
45
45
  title={<FormattedMessage {...messages.createMessageContent} />}
46
- prefix={
46
+ prefix={!isFullMode &&
47
47
  <PrefixWrapper>
48
48
  <CapIcons.backIcon onClick={onShowTemplates} />
49
49
  </PrefixWrapper>
@@ -59,5 +59,6 @@ SlideBoxHeader.propTypes = {
59
59
  templateData: PropTypes.object,
60
60
  onShowTemplates: PropTypes.func,
61
61
  creativesMode: PropTypes.string,
62
+ isFullMode: PropTypes.bool,
62
63
  };
63
64
  export default SlideBoxHeader;
@@ -6,6 +6,8 @@
6
6
 
7
7
  import {
8
8
  DEFAULT_ACTION,
9
+ HIDE_CONTAINER_LOADER,
10
+ SHOW_CONTANER_LOADER,
9
11
  } from './constants';
10
12
 
11
13
  export function defaultAction() {
@@ -13,3 +15,13 @@ export function defaultAction() {
13
15
  type: DEFAULT_ACTION,
14
16
  };
15
17
  }
18
+ export function showCreativesContainerLoader() {
19
+ return {
20
+ type: SHOW_CONTANER_LOADER,
21
+ };
22
+ }
23
+ export function hideCreativesContanerLoader() {
24
+ return {
25
+ type: HIDE_CONTAINER_LOADER,
26
+ };
27
+ }
@@ -7,3 +7,5 @@
7
7
  export const DEFAULT_ACTION = 'app/CreativesContainer/DEFAULT_ACTION';
8
8
  export const EMAIL = "EMAIL";
9
9
  export const SMS = "SMS";
10
+ export const SHOW_CONTANER_LOADER = "app/CreativesContainer/SHOW_CONTANER_LOADER";
11
+ export const HIDE_CONTAINER_LOADER = "app/CreativesContainer/HIDE_CONTAINER_LOADER";
@@ -7,7 +7,9 @@ import { injectIntl } from 'react-intl';
7
7
  import classnames from 'classnames';
8
8
  import {isEmpty} from 'lodash';
9
9
  import { connect } from 'react-redux';
10
+ import { createStructuredSelector } from 'reselect';
10
11
  import { bindActionCreators } from 'redux';
12
+ import * as actions from './actions';
11
13
  import SlideBoxContent from './SlideBoxContent';
12
14
  import SlideBoxHeader from './SlideBoxHeader';
13
15
  import SlideBoxFooter from './SlideBoxFooter';
@@ -15,6 +17,7 @@ import * as constants from './constants';
15
17
  import './index.scss';
16
18
  import * as templateActions from '../Templates/actions';
17
19
  import * as globalActions from '../Cap/actions';
20
+ import {isLoading as isLoadingSelector} from './selectors';
18
21
 
19
22
  const classPrefix = 'add-creatives-section';
20
23
  class Creatives extends React.Component {
@@ -156,9 +159,9 @@ class Creatives extends React.Component {
156
159
 
157
160
  render() {
158
161
  const {slidBoxContent, isGetFormData, showSlideBox, templateData, currentChannel, emailCreateMode, templateStep} = this.state;
159
- const {isFullMode, creativesMode, cap} = this.props;
162
+ const {isFullMode, creativesMode, cap, isLoading} = this.props;
160
163
  return (
161
- <div className={classnames(`${classPrefix}`)}>
164
+ <div className={classnames(`${classPrefix} ${isFullMode ? 'creatives-full-mode' : 'creatives-library-mode'}`)}>
162
165
  <CapSlideBox
163
166
  header={
164
167
  <SlideBoxHeader
@@ -167,6 +170,7 @@ class Creatives extends React.Component {
167
170
  templateData={templateData}
168
171
  onShowTemplates={this.onShowTemplates}
169
172
  creativesMode={creativesMode}
173
+ isFullMode={isFullMode}
170
174
  />
171
175
  }
172
176
  content={
@@ -193,7 +197,7 @@ class Creatives extends React.Component {
193
197
  cap={cap}
194
198
  />
195
199
  }
196
- footer={
200
+ footer={!isFullMode && !isLoading &&
197
201
  <SlideBoxFooter
198
202
  messages={this.props.messages}
199
203
  onSave={this.saveMessage}
@@ -227,11 +231,16 @@ Creatives.propTypes = {
227
231
  templateActions: PropTypes.object,
228
232
  globalActions: PropTypes.object,
229
233
  cap: PropTypes.object,
234
+ isLoading: PropTypes.bool,
230
235
  };
236
+ const mapStatesToProps = () => createStructuredSelector({
237
+ isLoading: isLoadingSelector(),
238
+ });
231
239
  function mapDispatchToProps(dispatch) {
232
240
  return {
233
241
  templateActions: bindActionCreators(templateActions, dispatch),
234
242
  globalActions: bindActionCreators(globalActions, dispatch),
243
+ actions: bindActionCreators(actions, dispatch),
235
244
  };
236
245
  }
237
- export default connect(null, mapDispatchToProps)(injectIntl(Creatives));
246
+ export default connect(mapStatesToProps, mapDispatchToProps)(injectIntl(Creatives));
@@ -7,14 +7,20 @@
7
7
  import { fromJS } from 'immutable';
8
8
  import {
9
9
  DEFAULT_ACTION,
10
+ SHOW_CONTANER_LOADER,
11
+ HIDE_CONTAINER_LOADER,
10
12
  } from './constants';
11
13
 
12
- const initialState = fromJS({});
14
+ const initialState = fromJS({containerLoader: true});
13
15
 
14
16
  function creativesContainerReducer(state = initialState, action) {
15
17
  switch (action.type) {
16
18
  case DEFAULT_ACTION:
17
19
  return state;
20
+ case SHOW_CONTANER_LOADER:
21
+ return state.set('containerLoader', true);
22
+ case HIDE_CONTAINER_LOADER:
23
+ return state.set('containerLoader', false);
18
24
  default:
19
25
  return state;
20
26
  }
@@ -18,8 +18,13 @@ const makeSelectCreativesContainer = () => createSelector(
18
18
  selectCreativesContainerDomain(),
19
19
  (substate) => substate.toJS()
20
20
  );
21
+ const isLoading = () => createSelector(
22
+ makeSelectCreativesContainer(),
23
+ (substate) => substate.containerLoader
24
+ );
21
25
 
22
26
  export default makeSelectCreativesContainer;
23
27
  export {
24
28
  selectCreativesContainerDomain,
29
+ isLoading,
25
30
  };
@@ -9,9 +9,9 @@ import PropTypes from 'prop-types';
9
9
  import React from 'react';
10
10
  import { connect } from 'react-redux';
11
11
  import { bindActionCreators } from 'redux';
12
- import { Row, Col, Spin, Popover, Modal, Select } from 'antd';
12
+ import { Row, Col, Popover, Modal, Select } from 'antd';
13
13
  import { injectIntl, intlShape, FormattedMessage } from 'react-intl';
14
- import { CapButton, CapInput } from '@capillarytech/cap-react-ui-library';
14
+ import { CapButton, CapInput, CapSpin } from '@capillarytech/cap-ui-library';
15
15
  import { createStructuredSelector } from 'reselect';
16
16
  import _ from 'lodash';
17
17
  import moment from "moment";
@@ -31,6 +31,7 @@ import EmailPreview from '../../components/EmailPreview';
31
31
  import ImagePreview from '../../components/ImagePreview';
32
32
  import CardGrid from '../../components/CardGrid';
33
33
  import Pagination from '../../components/Pagination';
34
+ import * as creativesContainerActions from '../CreativesContainer/actions';
34
35
 
35
36
  export class Email extends React.Component { // eslint-disable-line react/prefer-stateless-function
36
37
  constructor(props) {
@@ -595,17 +596,31 @@ export class Email extends React.Component { // eslint-disable-line react/prefer
595
596
  const isEdmSupport = (this.props.location.query.isEdmSupport !== "false") || false;
596
597
 
597
598
  if (isDragDrop && isEdmSupport) {
598
- const msg = {
599
- action: "InsertToCursor",
600
- content: `{{${data}}}`,
601
- };
599
+ let msg = {};
600
+ if (data === "unsubscribe") {
601
+ const anchor = `<a href='{{${data}}}'>${data}</a>`;
602
+ msg = {
603
+ action: "InsertToCursor",
604
+ content: `${anchor}`,
605
+ };
606
+ } else {
607
+ msg = {
608
+ action: "InsertToCursor",
609
+ content: `{{${data}}}`,
610
+ };
611
+ }
602
612
  const msgString = JSON.stringify(msg);
603
613
  const langId = formData[this.state.currentTab - 1].activeTab;
604
614
  const langIndex = formData[this.state.currentTab - 1].selectedLanguages.indexOf(langId);
605
615
  const win = document.getElementById(`edmeditor${(langIndex + 1) > 1 ? (langIndex + 1) : ''}`).contentWindow;
606
616
  win.postMessage(msgString, '*');
607
617
  } else {
608
- this.state.editorInstanse.insertHtml(`{{${data}}}`);
618
+ if (data === "unsubscribe") {
619
+ const anchor = `<a href='{{${data}}}'>${data}</a>`;
620
+ this.state.editorInstanse.insertHtml(`${anchor}`);
621
+ } else {
622
+ this.state.editorInstanse.insertHtml(`{{${data}}}`);
623
+ }
609
624
  //this.resetCkEditorInstance(currentTab, formData, true, data);
610
625
  }
611
626
  }
@@ -2306,7 +2321,7 @@ export class Email extends React.Component { // eslint-disable-line react/prefer
2306
2321
  this.props.getFormSubscriptionData(response);
2307
2322
  }
2308
2323
  parent.postMessage(JSON.stringify(response), "*");
2309
- this.setState({gettingFormData: false, startValidation: false});
2324
+ this.setState({gettingFormData: false, startValidation: false, loading: true});
2310
2325
  return;
2311
2326
  }
2312
2327
  const formData = _.cloneDeep(passedData);
@@ -2438,6 +2453,9 @@ export class Email extends React.Component { // eslint-disable-line react/prefer
2438
2453
  if (!isLoading) {
2439
2454
  isLoading = this.state.loadingStatus < 2;
2440
2455
  }
2456
+ if (isLoading) {
2457
+ this.props.creativesContainerActions.hideCreativesContanerLoader();
2458
+ }
2441
2459
  return isLoading;
2442
2460
  }
2443
2461
  renderConfirmationModal() {
@@ -2540,24 +2558,10 @@ export class Email extends React.Component { // eslint-disable-line react/prefer
2540
2558
  <div className="email-container">
2541
2559
 
2542
2560
  {/* <PageHeader pageHeading={pageHeading} /> */}
2543
- <Spin tip={loaderText} spinning={isLoading}>
2561
+ <CapSpin tip={loaderText} spinning={isLoading}>
2544
2562
 
2545
2563
  <Row>
2546
2564
  <Col>
2547
- {/* <input type="file" id="filename" style={{ display: 'none'}} accept="text/html" onChange={(event) => this.openFile(event)} /><br/> */}
2548
- {/* <CKEditor
2549
- content={this.state.content}
2550
- config={{}}
2551
- events={this.state.events}
2552
- /> */}
2553
- {/* { (!this.props.Email.fetchingCmsSettings && !this.props.Email.fetchingCmsSettingsError &&
2554
- !_.isEmpty(this.props.Email.CmsSettings) && this.props.Email.CmsSettings.url) ?
2555
- <EDMEditor
2556
- content={'Hello World'}
2557
- getEditorInstanse={this.getEditorInstanse}
2558
- edmSrc={this.props.Email.CmsSettings.url}
2559
- /> : ''
2560
- } */}
2561
2565
  { !_.isEmpty(schema) && (this.state.formData[0] || this.state.formData["0"]) ?
2562
2566
  <FormBuilder
2563
2567
  schema={schema}
@@ -2600,7 +2604,7 @@ export class Email extends React.Component { // eslint-disable-line react/prefer
2600
2604
  /> : ''}
2601
2605
  </Col>
2602
2606
  </Row>
2603
- </Spin>
2607
+ </CapSpin>
2604
2608
  {!_.isEmpty(this.state.formData[(this.state.currentTab - 1)]) && <EmailPreview
2605
2609
  header={previewHeader}
2606
2610
  content={this.state.formData[(this.state.currentTab - 1)][this.state.formData[(this.state.currentTab - 1)].activeTab] ? this.state.formData[(this.state.currentTab - 1)][this.state.formData[(this.state.currentTab - 1)].activeTab][`template-content`] : ''}
@@ -2641,6 +2645,7 @@ Email.propTypes = {
2641
2645
  getDefaultTags: PropTypes.string,
2642
2646
  currentOrgDetails: PropTypes.object,
2643
2647
  isLoadingMetaEntities: PropTypes.bool,
2648
+ creativesContainerActions: PropTypes.object,
2644
2649
  };
2645
2650
 
2646
2651
  const mapStateToProps = (state, props) => createStructuredSelector({
@@ -2656,6 +2661,7 @@ function mapDispatchToProps(dispatch) {
2656
2661
  actions: bindActionCreators(actions, dispatch),
2657
2662
  globalActions: bindActionCreators(globalActions, dispatch),
2658
2663
  templatesActions: bindActionCreators(templatesActions, dispatch),
2664
+ creativesContainerActions: bindActionCreators(creativesContainerActions, dispatch),
2659
2665
  };
2660
2666
  }
2661
2667
 
@@ -10,7 +10,7 @@ import { FormattedMessage, injectIntl, intlShape } from 'react-intl';
10
10
  import { createStructuredSelector } from 'reselect';
11
11
  import { bindActionCreators } from 'redux';
12
12
  import _ from 'lodash';
13
- import { CapRadioCard, CapHeader, CapNotification} from '@capillarytech/cap-ui-library';
13
+ import { CapRadioCard, CapHeader, CapNotification, CapInput} from '@capillarytech/cap-ui-library';
14
14
  import { UserIsAuthenticated } from '../../utils/authWrapper';
15
15
  import {selectEmailLayout, selectCmsTemplates, selectEdmEditor} from '../Templates/selectors';
16
16
  import * as templatesActionsCreators from '../Templates/actions';
@@ -127,7 +127,7 @@ export class EmailWrapper extends React.Component { // eslint-disable-line react
127
127
 
128
128
  isShowEmailCreate = () => !_.isEmpty(this.state.selectedCreateMode) && (!_.isEmpty(this.props.EmailLayout) || this.props.SelectedEdmDefaultTemplate)
129
129
  render() {
130
- const {emailCreateMode, isGetFormData, getFormdata, type, CmsTemplates, step, cap} = this.props;
130
+ const {emailCreateMode, isGetFormData, getFormdata, type, CmsTemplates, step, cap, isFullMode} = this.props;
131
131
  const {templateName} = this.state;
132
132
  const isShowEmailCreate = this.isShowEmailCreate();
133
133
  return (
@@ -136,11 +136,11 @@ export class EmailWrapper extends React.Component { // eslint-disable-line react
136
136
 
137
137
  {step === "modeSelection" || (step === "templateSelection" && emailCreateMode === "upload") ?
138
138
  <div>
139
- {/* <CapInput
139
+ {isFullMode && <CapInput
140
140
  label={<FormattedMessage {...messages.creativeName}/>}
141
141
  onChange={this.onTemplateNameChange}
142
142
  value={templateName}
143
- labelPosition="top"/> */}
143
+ labelPosition="top"/>}
144
144
  <CapHeader size="small" title={<FormattedMessage {...messages.createMode}/>}/>
145
145
  <CapRadioCard
146
146
  panes={this.modes}
@@ -187,6 +187,7 @@ EmailWrapper.propTypes = {
187
187
  intl: intlShape,
188
188
  cap: PropTypes.object,
189
189
  onResetStep: PropTypes.func,
190
+ isFullMode: PropTypes.bool,
190
191
  };
191
192
 
192
193
  const mapStateToProps = createStructuredSelector({
@@ -1,7 +1,7 @@
1
1
  import PropTypes from 'prop-types';
2
2
  import React from 'react';
3
3
  import { Form, Icon } from 'antd';
4
- import { CapInput, CapButton } from '@capillarytech/cap-react-ui-library';
4
+ import { CapInput, CapButton } from '@capillarytech/cap-ui-library';
5
5
  const FormItem = Form.Item;
6
6
 
7
7
  class NormalLoginForm extends React.Component {