@capillarytech/creatives-library 2.0.90 → 2.0.92

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.
@@ -10,7 +10,6 @@ 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';
14
13
  import { injectIntl, intlShape } from 'react-intl';
15
14
  import TopBar from '../../components/TopBar';
16
15
  // import 'moment/locale/en-us';
@@ -151,7 +150,7 @@ export class Cap extends React.Component { // eslint-disable-line react/prefer-s
151
150
  const { user: userData } = props.Global;
152
151
  const userName = userData.attributes.USERNAME;
153
152
  const userEmail = userData.attributes.EMAIL;
154
- const orgObj = find(userData.proxyOrgList, {orgID: props.Global.orgID});
153
+ const orgObj = _.find(userData.proxyOrgList, {orgID: props.Global.orgID});
155
154
  const gtmData = {
156
155
  orgId: props.Global.orgID,
157
156
  orgName: orgObj && orgObj.orgName,
@@ -1258,7 +1258,7 @@ export class Email extends React.Component { // eslint-disable-line react/prefer
1258
1258
  const formData = _.cloneDeep(this.state.formData);
1259
1259
 
1260
1260
  const tabIndex = this.state.currentTab + 1;
1261
- const schema = (this.props.location.query.type === 'embedded') ? this.removeStandAlone() : _.cloneDeep(this.state.schema);
1261
+ const schema = (this.props.location.query.type === 'embedded') ? this.removeStandAlone(this.state.schema) : _.cloneDeep(this.state.schema);
1262
1262
  const containers = _.cloneDeep(schema.containers.slice());
1263
1263
  let tabKey = "";
1264
1264
  let currentTab = _.cloneDeep(this.state.currentTab);
@@ -2472,18 +2472,16 @@ export class Email extends React.Component { // eslint-disable-line react/prefer
2472
2472
  });
2473
2473
  return data;
2474
2474
  }
2475
-
2476
2475
  injectEvents = (schema) => {
2477
2476
  const type = this.props.location.query.type;
2478
- console.log('now injecting events');
2479
- const temp = schema;
2477
+ let temp = _.cloneDeep(schema);
2480
2478
  temp.standalone.sections = this.injectSections(temp.standalone.sections);
2481
2479
  _.forEach(temp.containers, (container) => {
2482
2480
  let tempContainer = container;
2483
2481
  tempContainer = this.injectContainer(tempContainer);
2484
2482
  return tempContainer;
2485
2483
  });
2486
- console.log("Lang Test ", this.props.location.query.isLanguageSupport, (this.props.location.query.isLanguageSupport === false));
2484
+
2487
2485
  // if (type !== "embedded" || (type === "embedded" && (this.props.location.query.isLanguageSupport === "false" || (this.props.location.query.isLanguageSupport === undefined || this.props.location.query.isLanguageSupport === "true")))) {
2488
2486
  const ifLangSupported = this.props.location.query.isLanguageSupport === "true" || type !== "embedded";
2489
2487
  _.forEach(temp.containers, (container) => {
@@ -2518,14 +2516,18 @@ export class Email extends React.Component { // eslint-disable-line react/prefer
2518
2516
  }
2519
2517
  if (containerInputFieldCol.id === 'add-language-button' && !ifLangSupported) {
2520
2518
  const newContainerInputFieldCol = containerInputFieldCol;
2521
- newContainerInputFieldCol.colStyle.display = "none";
2519
+ if (newContainerInputFieldCol.colStyle.display !== "none") {
2520
+ newContainerInputFieldCol.colStyle.display = "none";
2521
+ }
2522
2522
  hideLang = true;
2523
2523
  } else if (containerInputFieldCol.id === 'add-language-button') {
2524
2524
  hideLang = true;
2525
2525
  }
2526
2526
  if (containerInputFieldCol.id === "mark-final-version-label") {
2527
2527
  const newContainerInputFieldCol = containerInputFieldCol;
2528
- newContainerInputFieldCol.colStyle.display = "none";
2528
+ if (newContainerInputFieldCol.colStyle.display !== "none") {
2529
+ newContainerInputFieldCol.colStyle.display = "none";
2530
+ }
2529
2531
  }
2530
2532
  // if (containerInputFieldCol.id === "tab-options-popover") {
2531
2533
  // const newContainerInputFieldCol = containerInputFieldCol;
@@ -2542,11 +2544,8 @@ export class Email extends React.Component { // eslint-disable-line react/prefer
2542
2544
  }
2543
2545
  });
2544
2546
  //}
2545
- console.log('final injected schema', schema);
2546
- this.setState({schema, isSchemaChanged: true}, () => {
2547
- if (type === 'embedded') {
2548
- this.removeStandAlone();
2549
- }
2547
+ temp = type === 'embedded' ? this.removeStandAlone(temp) : temp;
2548
+ this.setState({schema: temp, isSchemaChanged: true, loadingStatus: this.state.loadingStatus + 1}, () => {
2550
2549
  if (type === 'embedded' && (this.props.route.name === 'EmailView' || (this.props.location.query.module && (this.props.location.query.module.toLowerCase() === 'loyalty' || this.props.location.query.module.toLowerCase() === 'dvs' || this.props.location.query.module.toLowerCase() === 'coupon_expiry' || this.props.location.query.module.toLowerCase() === 'timeline')))) {
2551
2550
  if ((this.props.route.name === "EmailEdit" || this.props.route.name === "EmailCreate") && (this.props.location.query.module === "dvs" || this.props.location.query.module.toLowerCase() === 'coupon_expiry')) {
2552
2551
  return;
@@ -2557,7 +2556,7 @@ export class Email extends React.Component { // eslint-disable-line react/prefer
2557
2556
  parent.postMessage(JSON.stringify(response), '*');
2558
2557
  }
2559
2558
  });
2560
- return schema;
2559
+ return temp;
2561
2560
  }
2562
2561
 
2563
2562
  handleOnTagsContextChange = (data) => {
@@ -2571,17 +2570,17 @@ export class Email extends React.Component { // eslint-disable-line react/prefer
2571
2570
  this.props.globalActions.fetchSchemaForEntity(query);
2572
2571
  }
2573
2572
 
2574
- removeStandAlone() {
2575
- const schema = _.cloneDeep(this.state.schema);
2576
- delete schema.standalone;
2577
- schema.standalone = {};
2578
- schema.standalone.sections = [];
2573
+ removeStandAlone(schema) {
2574
+ const newSchema = _.cloneDeep(schema);
2575
+ delete newSchema.standalone;
2576
+ newSchema.standalone = {};
2577
+ newSchema.standalone.sections = [];
2579
2578
  if (this.props.location.query.type === 'embedded' && (this.props.location.query.module === "loyalty" || this.props.location.query.module === "dvs" || this.props.location.query.module === "coupon_expiry" || this.props.location.query.module === "timeline" ||
2580
2579
  this.props.location.query.module === "library")) {
2581
- schema.standalone.sections.push(_.cloneDeep(this.state.schema.standalone.sections[0]));
2580
+ newSchema.standalone.sections.push(_.cloneDeep(schema.standalone.sections[0]));
2582
2581
  }
2583
2582
 
2584
- _.forEach(schema.containers, (container) => {
2583
+ _.forEach(newSchema.containers, (container) => {
2585
2584
  const temp = container;
2586
2585
  if (temp.type === 'tabs') {
2587
2586
  // temp.tabBarExtraContent = {};
@@ -2617,8 +2616,7 @@ export class Email extends React.Component { // eslint-disable-line react/prefer
2617
2616
  temp.panes.push(basePane);
2618
2617
  }
2619
2618
  });
2620
- this.setState({ schema, isSchemaChanged: true });
2621
- return schema;
2619
+ return newSchema;
2622
2620
  }
2623
2621
 
2624
2622
  startTemplateCreation(data) {
@@ -196,7 +196,7 @@ export class Create extends React.Component { // eslint-disable-line react/prefe
196
196
  onTagSelect(data, currentTab) {
197
197
  console.log('parent data tag', data, currentTab);
198
198
  const editorId = currentTab > 1 ? `sms-editor${currentTab}` : 'sms-editor';
199
- this.insertAtCursor(document.getElementById(editorId), `{{${data}}}`);
199
+ this.insertAtCursor(document.getElementById(editorId), `{{${data}}}`, currentTab);
200
200
  document.getElementById(editorId).focus();
201
201
  }
202
202
 
@@ -717,7 +717,7 @@ export class Create extends React.Component { // eslint-disable-line react/prefe
717
717
  return false;
718
718
  }
719
719
 
720
- insertAtCursor(field, myValue) {
720
+ insertAtCursor(field, myValue, currentTab) {
721
721
  //IE support
722
722
  const myField = field;
723
723
  if (document.selection) {
@@ -735,8 +735,9 @@ export class Create extends React.Component { // eslint-disable-line react/prefe
735
735
  } else {
736
736
  myField.value += myValue;
737
737
  }
738
- const event = new Event('input', { bubbles: true });
739
- myField.dispatchEvent(event);
738
+ const formData = _.cloneDeep(this.state.formData);
739
+ formData[currentTab - 1][field.id] = myField.value;
740
+ this.setState({formData});
740
741
  }
741
742
 
742
743
  startTemplateCreation(data) {
@@ -198,7 +198,7 @@ export class Edit extends React.Component { // eslint-disable-line react/prefer-
198
198
  onTagSelect(data, currentTab) {
199
199
  console.log('parent data tag', data, currentTab);
200
200
  const editorId = currentTab > 1 ? `sms-editor${currentTab}` : 'sms-editor';
201
- this.insertAtCursor(document.getElementById(editorId), `{{${data}}}`);
201
+ this.insertAtCursor(document.getElementById(editorId), `{{${data}}}`, currentTab);
202
202
  document.getElementById(editorId).focus();
203
203
  }
204
204
 
@@ -1219,7 +1219,7 @@ export class Edit extends React.Component { // eslint-disable-line react/prefer-
1219
1219
  }
1220
1220
  }
1221
1221
 
1222
- insertAtCursor(field, myValue) {
1222
+ insertAtCursor(field, myValue, currentTab) {
1223
1223
  //IE support
1224
1224
  const myField = field;
1225
1225
  if (document.selection) {
@@ -1237,8 +1237,9 @@ export class Edit extends React.Component { // eslint-disable-line react/prefer-
1237
1237
  } else {
1238
1238
  myField.value += myValue;
1239
1239
  }
1240
- const event = new Event('input', { bubbles: true });
1241
- myField.dispatchEvent(event);
1240
+ const formData = _.cloneDeep(this.state.formData);
1241
+ formData[currentTab - 1][field.id] = myField.value;
1242
+ this.setState({formData});
1242
1243
  }
1243
1244
 
1244
1245
  handleFrameTasks = (e) => {
@@ -425,7 +425,7 @@ export class MapTemplates extends React.Component { // eslint-disable-line react
425
425
 
426
426
  onTagSelect(data, currentTab, value) {
427
427
  const editorId = (value.id).replace('tagList', 'template');
428
- this.insertAtCursor(document.getElementById(editorId), `{{${data}}}`);
428
+ this.insertAtCursor(document.getElementById(editorId), `{{${data}}}`, currentTab);
429
429
  document.getElementById(editorId).focus();
430
430
  }
431
431
 
@@ -1018,7 +1018,7 @@ export class MapTemplates extends React.Component { // eslint-disable-line react
1018
1018
  parent.postMessage(JSON.stringify(response), '*');
1019
1019
  }
1020
1020
 
1021
- insertAtCursor(field, myValue) {
1021
+ insertAtCursor(field, myValue, currentTab) {
1022
1022
  //IE support
1023
1023
  const myField = field;
1024
1024
  if (document.selection) {
@@ -1036,8 +1036,11 @@ export class MapTemplates extends React.Component { // eslint-disable-line react
1036
1036
  } else {
1037
1037
  myField.value += myValue;
1038
1038
  }
1039
- const event = new Event('input', { bubbles: true });
1040
- myField.dispatchEvent(event);
1039
+ const formData = _.cloneDeep(this.state.formData);
1040
+ if (currentTab) {
1041
+ formData[currentTab - 1][field.id] = myField.value;
1042
+ }
1043
+ this.setState({formData});
1041
1044
  }
1042
1045
 
1043
1046
  internalUrlChecked() {
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@capillarytech/creatives-library",
3
3
  "author": "meharaj",
4
- "version": "2.0.90",
4
+ "version": "2.0.92",
5
5
  "description": "Capillary creatives ui",
6
6
  "main": "./index.js",
7
7
  "module": "./index.es.js",
@@ -12,7 +12,7 @@
12
12
  },
13
13
  "license": "LicenseRef-LICENSE",
14
14
  "dependencies": {
15
- "@capillarytech/cap-ui-library": "^1.0.168",
15
+ "@capillarytech/cap-ui-library": "^1.0.170",
16
16
  "antd": "3.19.6",
17
17
  "axios": "^0.16.2",
18
18
  "babel-polyfill": "6.20.0",
@@ -111,13 +111,14 @@ class FormBuilder extends React.Component { // eslint-disable-line react/prefer-
111
111
  }
112
112
  if (nextProps.startValidation && nextProps.startValidation !== false && this.props.startValidation !== nextProps.startValidation) {
113
113
  this.setState({checkValidation: true});
114
- const ifValid = this.validateForm(null, null, null, true);
115
-
116
- if (ifValid) {
117
- this.saveForm(true);
118
- } else {
119
- this.props.stopValidation();
120
- }
114
+ this.validateForm(null, null, null, true, () => {
115
+ //triggering the saveFormData or onSubmit when validation sets isFormValid to TRUE
116
+ if (this.state.isFormValid) {
117
+ this.saveForm(true);
118
+ } else {
119
+ this.props.stopValidation();
120
+ }
121
+ });
121
122
  }
122
123
  // if (nextProps.saveForm && this.props.saveForm !== nextProps.saveForm) {
123
124
  // this.saveForm(saveForm);
@@ -433,7 +434,7 @@ class FormBuilder extends React.Component { // eslint-disable-line react/prefer-
433
434
  return isPresent;
434
435
  }
435
436
  /* eslint-disable */
436
- validateForm(tags, injectedTags, isSave, showMessages) {
437
+ validateForm(tags, injectedTags, isSave, showMessages, onValidationComplete) {
437
438
  const channel = _.get(this, "props.schema.channel");
438
439
  let isValid = true;
439
440
  const type = (this.props.location && this.props.location.query.type) ? this.props.location.query.type : 'full';
@@ -441,9 +442,6 @@ class FormBuilder extends React.Component { // eslint-disable-line react/prefer-
441
442
  let errorData = _.cloneDeep(this.state.errorData);
442
443
  const stateFormData = _.cloneDeep(this.state.formData);
443
444
  if (channel && channel.toUpperCase() === SMS) {
444
- if(!this.errorFieldsPresent(errorData, SMS)){
445
- errorData = this.initializeEditErrorData(stateFormData, 1, true);
446
- }
447
445
  for (let count = 0; count < this.state.tabCount; count += 1) {
448
446
  if (_.isEmpty(errorData[count])) {
449
447
  return;
@@ -933,7 +931,11 @@ class FormBuilder extends React.Component { // eslint-disable-line react/prefer-
933
931
  // errorData['template-name'] = false;
934
932
  // }
935
933
  }
936
- this.setState({isFormValid : isValid, errorData});
934
+ this.setState({isFormValid : isValid, errorData}, () => {
935
+ if (onValidationComplete) {
936
+ onValidationComplete();
937
+ }
938
+ });
937
939
 
938
940
  this.props.onFormValidityChange(isValid, errorData);
939
941
  return isValid;
@@ -12,7 +12,7 @@ import { loadItem } from 'services/localStorageApi';
12
12
  import { intlShape, injectIntl } from 'react-intl';
13
13
  import TopBar from '../TopBar';
14
14
  import messages from './messages';
15
-
15
+ const PRODUCT_MASTERS = 'masters';
16
16
  const EMBEDDED = 'embedded';
17
17
 
18
18
  const CapWrapper = styled.div`
@@ -108,7 +108,7 @@ class NavigationBar extends React.Component {
108
108
  const productsList = [];
109
109
  if (currentOrgDetails) {
110
110
  forEach(currentOrgDetails.module_details, (module) => {
111
- if (module.name.toLowerCase() !== 'masters') {
111
+ if (module.name.toLowerCase() !== PRODUCT_MASTERS) {
112
112
  productsList.push({
113
113
  value: module.name.toLowerCase(),
114
114
  url: module.url,
@@ -5,6 +5,7 @@ import { CAP_SPACE_24 } from '@capillarytech/cap-ui-library/styled/variables';
5
5
  import { intlShape, injectIntl } from 'react-intl';
6
6
  import messages from './messages';
7
7
  const drawerPlacement = 'left';
8
+ const DEFAULT_MODULE = 'creatives';
8
9
 
9
10
  const TopBar = (props) => {
10
11
  const {
@@ -45,7 +46,7 @@ const TopBar = (props) => {
45
46
  }}
46
47
  menuProps={{
47
48
  items: topbarMenuData,
48
- defaultSelectedKeys: ['creatives'],
49
+ defaultSelectedKeys: [DEFAULT_MODULE],
49
50
  onMenuItemClick: handleTopbarMenuChange,
50
51
  }}
51
52
  dropdownMenuProps={dropdownMenuProps}
@@ -227,7 +227,7 @@ export class Gallery extends React.Component { // eslint-disable-line react/pref
227
227
  e.preventDefault();
228
228
  const _URL = window.URL || window.webkitURL;
229
229
  //const file = files[0];
230
- for (let file in files) {
230
+ for (const file in files) {
231
231
  const img = new Image();
232
232
  const that = this;
233
233
  img.src = _URL.createObjectURL(files[file]);
@@ -386,13 +386,13 @@ export class Gallery extends React.Component { // eslint-disable-line react/pref
386
386
  const filterContent = (
387
387
  <div className="action-container" style={{ display: 'inline-flex', width: '100%'}}>
388
388
  <div style={{ marginTop: '8px', width: '50%'}}>
389
- <CapInput
389
+ <CapInput.Search
390
390
  className="search-text"
391
391
  style={{width: '210px'}}
392
- placeholder="Search"
393
- prefix={<i className="material-icons" style={{color: '#707070', fontSize: '16px'}}>search</i>}
392
+ placeholder={this.props.intl.formatMessage(messages.search)}
394
393
  value={this.state.searchText}
395
394
  onChange={(e) => this.searchAsset(e.target.value)}
395
+ onClear={() => this.searchAsset('')}
396
396
  />
397
397
  </div>
398
398
  <div style={{ textAlign: 'right', marginTop: '16px', width: '50%'}}>
@@ -28,7 +28,7 @@ export const GET_TOPBAR_MENU_DATA_SUCCESS = 'creatives/cap/GET_TOPBAR_MENU_DATA_
28
28
  export const GET_TOPBAR_MENU_DATA_FAILURE = 'creatives/cap/GET_TOPBAR_MENU_DATA_FAILURE';
29
29
  export const CLEAR_TOPBAR_MENU_DATA = 'creatives/cap/CLEAR_TOPBAR_MENU_DATA';
30
30
 
31
- export const CAMPAIGN_SETTINGS_URL = '/campaign/settings/message?from="/creatives/ui/v2/"';
31
+ export const CAMPAIGN_SETTINGS_URL = '/creatives/settings/message';
32
32
  export const BRAND_SETTINGS_URL = '/org/index';
33
33
  export const PROFILE_SETTINGS_URL = '/org/users/NewProfile';
34
34
  export const HELP_URL = 'https://support.capillarytech.com';
@@ -118,7 +118,7 @@ export class Cap extends React.Component { // eslint-disable-line react/prefer-s
118
118
  const { user: userData } = props.Global;
119
119
  const userName = userData.attributes.USERNAME;
120
120
  const userEmail = userData.attributes.EMAIL;
121
- const orgObj = find(userData.proxyOrgList, {orgID: props.Global.orgID});
121
+ const orgObj = _.find(userData.proxyOrgList, {orgID: props.Global.orgID});
122
122
  const gtmData = {
123
123
  orgId: props.Global.orgID,
124
124
  orgName: orgObj && orgObj.orgName,
@@ -184,7 +184,8 @@ export class Cap extends React.Component { // eslint-disable-line react/prefer-s
184
184
  topbarMenuData={topbarMenuDataOptions}
185
185
  location={location}
186
186
  /> : ''}
187
- <div className="main">
187
+ <div className="main" style={{minHeight: 'calc(100vh - 74px', position: 'relative', top: '74px'}}>
188
+
188
189
  <div className="main-content">
189
190
  {React.Children.toArray(this.props.children)}
190
191
  </div>
@@ -47,6 +47,7 @@ function SlideBoxContent(props) {
47
47
  onCallTaskSubmit,
48
48
  setIsLoadingContent,
49
49
  showTemplateName,
50
+ onValidationFail,
50
51
  } = props;
51
52
  const type = messageDetails.type.toLowerCase(); // type is context in get tags values : outbound | dvs | referral | loyalty | coupons
52
53
  const query = { type: !isFullMode && 'embedded', module: isFullMode ? 'defualt' : 'library'};
@@ -171,6 +172,7 @@ function SlideBoxContent(props) {
171
172
  cap={cap}
172
173
  onResetStep={onResetStep}
173
174
  showTemplateName={showTemplateName}
175
+ onValidationFail={onValidationFail}
174
176
  />
175
177
  )}
176
178
  {(isEditEmailWithId || isEmailEditWithContent) && (
@@ -191,6 +193,7 @@ function SlideBoxContent(props) {
191
193
  isFullMode={isFullMode}
192
194
  cap={cap}
193
195
  showTemplateName={showTemplateName}
196
+ onValidationFail={onValidationFail}
194
197
  />
195
198
  )}
196
199
  {isEditMPush &&
@@ -260,5 +263,6 @@ SlideBoxContent.propTypes = {
260
263
  onMobilepushModeChange: PropTypes.func,
261
264
  mobilePushCreateMode: PropTypes.string,
262
265
  showTemplateName: PropTypes.func,
266
+ onValidationFail: PropTypes.func,
263
267
  };
264
268
  export default SlideBoxContent;
@@ -17,11 +17,11 @@ function getChannelLabel(channel) {
17
17
  return labels[channel.toLowerCase()];
18
18
  }
19
19
  function SlideBoxHeader(props) {
20
- const { slidBoxContent, templateData, onShowTemplates, creativesMode, isFullMode, showPrefix, showTemplateName, channel } = props;
21
- const TemplateName = isFullMode && showTemplateName;
20
+ const { slidBoxContent, templateData, onShowTemplates, creativesMode, isFullMode, showPrefix, shouldShowTemplateName, channel, templateNameRenderProp } = props;
21
+ const showTemplateNameHeader = isFullMode && shouldShowTemplateName;
22
22
  return (
23
23
  <div key="creatives-container-slidebox-header-content">
24
- {slidBoxContent === 'templates' && !TemplateName && (
24
+ {slidBoxContent === 'templates' && !showTemplateNameHeader && (
25
25
  <CapHeader
26
26
  title={<FormattedMessage {...messages.creativeTemplates} />}
27
27
  description={
@@ -29,12 +29,12 @@ function SlideBoxHeader(props) {
29
29
  }
30
30
  />
31
31
  )}
32
- {TemplateName && <TemplateName/>}
32
+ {showTemplateNameHeader && templateNameRenderProp()}
33
33
  {slidBoxContent === 'preview' && (
34
34
  <CapHeader
35
35
  title={templateData.name}
36
36
  description={<CapLabel type="label3">
37
- <FormattedMessage {...messages.lastUpdated}/>{moment(templateData.updatedAt).format('DD MMM YYYY')} <FormattedMessage {...messages.by}/>{templateData.updatedByName}
37
+ <FormattedMessage {...messages.lastUpdated} values={{date: moment(templateData.updatedAt).format('DD MMM YYYY'), user: templateData.updatedByName}}/>
38
38
  </CapLabel>}
39
39
  prefix={!isFullMode &&
40
40
  <PrefixWrapper>
@@ -43,7 +43,7 @@ function SlideBoxHeader(props) {
43
43
  }
44
44
  />
45
45
  )}
46
- {!TemplateName && slidBoxContent === 'editTemplate' && (
46
+ {!showTemplateNameHeader && slidBoxContent === 'editTemplate' && (
47
47
  <CapHeader
48
48
  title={<FormattedMessage {...messages.editMessageContent} />}
49
49
  prefix={creativesMode !== 'edit' && !isFullMode && showPrefix &&
@@ -53,7 +53,7 @@ function SlideBoxHeader(props) {
53
53
  }
54
54
  />
55
55
  )}
56
- {!TemplateName && slidBoxContent === 'createTemplate' && (
56
+ {!showTemplateNameHeader && slidBoxContent === 'createTemplate' && (
57
57
  <CapHeader
58
58
  title={<FormattedMessage {...messages.createMessageContent} values={{channel: getChannelLabel(channel)}}/>}
59
59
  prefix={!isFullMode && showPrefix &&
@@ -73,7 +73,8 @@ SlideBoxHeader.propTypes = {
73
73
  creativesMode: PropTypes.string,
74
74
  isFullMode: PropTypes.bool,
75
75
  showPrefix: PropTypes.bool,
76
- showTemplateName: PropTypes.func,
77
76
  channel: PropTypes.string,
77
+ shouldShowTemplateName: PropTypes.bool,
78
+ templateNameRenderProp: PropTypes.func,
78
79
  };
79
80
  export default SlideBoxHeader;
@@ -279,6 +279,9 @@ class Creatives extends React.Component {
279
279
  saveMessage = () => {
280
280
  this.setState({ isGetFormData: true });
281
281
  };
282
+ onValidationFail = () => {
283
+ this.setState({ isGetFormData: false });
284
+ }
282
285
  discardMessage = () => {
283
286
  this.setState({ isDiscardMessage: true });
284
287
  }
@@ -342,34 +345,35 @@ class Creatives extends React.Component {
342
345
 
343
346
  return showDone;
344
347
  }
348
+ templateNameComponentHeader = ({formData, onFormDataChange, name}) => (
349
+ <CapHeader
350
+ inline
351
+ title={name}
352
+ description={<CapLink
353
+ title={<FormattedMessage {...messages.creativesTemplatesEditName}/>}
354
+ onClick={() => { this.setState({isEditName: true}, () => { this.showTemplateName({formData, onFormDataChange}); }); }}/>
355
+ }/>)
356
+ templateNameComponentInput = ({formData, onFormDataChange, name}) => (<CapInput
357
+
358
+ value={name}
359
+ suffix={<span/>}
360
+ onBlur={() => { this.setState({isEditName: false}, () => { this.showTemplateName({formData, onFormDataChange}); }); }}
361
+ onChange={(ev) => {
362
+ const value = ev.currentTarget.value;
363
+ const newFormData = {...formData, 'template-name': value};
364
+ onFormDataChange(newFormData);
365
+ }}
366
+ />)
345
367
  showTemplateName = ({formData, onFormDataChange}) => { //gets called from email/index after template data is fetched
346
368
  const {slidBoxContent, currentChannel, isEditName} = this.state;
347
369
  const channel = currentChannel.toUpperCase();
348
370
  if ((channel === constants.EMAIL || channel === constants.MOBILE_PUSH) && (slidBoxContent === 'editTemplate' || slidBoxContent === 'createTemplate')) {
349
371
  const name = get(formData, 'template-name');
372
+ this.templateContainerDetails = {formData, onFormDataChange};
350
373
  if (name && !isEditName) {
351
- const TemplateNameComponent = () => (
352
- <CapHeader
353
- inline
354
- title={name}
355
- description={<CapLink
356
- title={<FormattedMessage {...messages.creativesTemplatesEditName}/>}
357
- onClick={() => { this.setState({isEditName: true}, () => { this.showTemplateName({formData, onFormDataChange}); }); }}/>
358
- }/>);
359
- this.setState({templateNameComponent: TemplateNameComponent});
374
+ this.setState({showTemplateNameComponentEdit: false});
360
375
  } else if (isEditName) {
361
- const TemplateNameComponent = () => (<CapInput
362
- key="cap-input-template-name"
363
- value={name}
364
- suffix={<span/>}
365
- onBlur={() => { this.setState({isEditName: false}, () => { this.showTemplateName({formData, onFormDataChange}); }); }}
366
- onChange={(ev) => {
367
- const value = ev.currentTarget.value;
368
- const newFormData = {...formData, 'template-name': value};
369
- onFormDataChange(newFormData);
370
- }}
371
- />);
372
- this.setState({templateNameComponent: TemplateNameComponent});
376
+ this.setState({showTemplateNameComponentEdit: true});
373
377
  }
374
378
  }
375
379
  }
@@ -390,8 +394,18 @@ class Creatives extends React.Component {
390
394
 
391
395
  return isShowContinueFooter;
392
396
  }
397
+ templateNameRenderProp = () => {
398
+ const {showTemplateNameComponentEdit, currentChannel, slidBoxContent} = this.state;
399
+ const {templateContainerDetails} = this;
400
+ const {formData, onFormDataChange} = templateContainerDetails;
401
+ const channel = currentChannel.toUpperCase();
402
+ if ((channel === constants.EMAIL || channel === constants.MOBILE_PUSH) && (slidBoxContent === 'editTemplate' || slidBoxContent === 'createTemplate')) {
403
+ const name = get(formData, 'template-name');
404
+ return showTemplateNameComponentEdit ? this.templateNameComponentInput({formData, onFormDataChange, name}) : this.templateNameComponentHeader({formData, onFormDataChange, name});
405
+ }
406
+ }
393
407
  render() {
394
- const {templateNameComponent, slidBoxContent, isGetFormData, showSlideBox, templateData, currentChannel, emailCreateMode, templateStep, isLoadingContent, mobilePushCreateMode, isDiscardMessage} = this.state;
408
+ const {slidBoxContent, isGetFormData, showSlideBox, templateData, currentChannel, emailCreateMode, templateStep, isLoadingContent, mobilePushCreateMode, isDiscardMessage} = this.state;
395
409
  const {isFullMode, creativesMode, cap, isUploading} = this.props;
396
410
  return (
397
411
  <SlideBoxWrapper className={classnames(`${classPrefix} ${isFullMode ? 'creatives-full-mode' : 'creatives-library-mode'}`)}>
@@ -407,7 +421,8 @@ class Creatives extends React.Component {
407
421
  creativesMode={creativesMode}
408
422
  isFullMode={isFullMode}
409
423
  isLoadingContent={isLoadingContent}
410
- showTemplateName={templateNameComponent}
424
+ shouldShowTemplateName={this.templateContainerDetails}
425
+ templateNameRenderProp={this.templateNameRenderProp}
411
426
  showPrefix={!isUploading} // not show back button when email template is being uploaded
412
427
  />
413
428
  }
@@ -440,6 +455,7 @@ class Creatives extends React.Component {
440
455
  onMobilepushModeChange={this.onMobilepushModeChange}
441
456
  mobilePushCreateMode={mobilePushCreateMode}
442
457
  showTemplateName={this.showTemplateName}
458
+ onValidationFail={this.onValidationFail}
443
459
  />
444
460
  }
445
461
  footer={this.shouldShowFooter() &&
@@ -16,7 +16,7 @@ export default defineMessages({
16
16
  },
17
17
  "lastUpdated": {
18
18
  id: 'app.containers.Creatives.lastUpdated',
19
- defaultMessage: 'Last updated:',
19
+ defaultMessage: 'Last updated: {date} by {user}',
20
20
  },
21
21
  "by": {
22
22
  id: 'app.containers.Creatives.by',
@@ -11,7 +11,7 @@ import { connect } from 'react-redux';
11
11
  import { bindActionCreators } from 'redux';
12
12
  import { Row, Col, Popover, Modal } from 'antd';
13
13
  import { injectIntl, intlShape, FormattedMessage } from 'react-intl';
14
- import { CapButton, CapInput, CapSpin, CapSlideBox, CapCustomCard } from '@capillarytech/cap-ui-library';
14
+ import { CapButton, CapInput, CapSpin, CapSlideBox, CapCustomCard, CapNotification } from '@capillarytech/cap-ui-library';
15
15
  import { createStructuredSelector } from 'reselect';
16
16
  import _ from 'lodash';
17
17
  import moment from "moment";
@@ -216,6 +216,11 @@ export class Email extends React.Component { // eslint-disable-line react/prefer
216
216
  // if (this.props.location.query.type === 'embedded') {
217
217
  // this.showNext();
218
218
  // }
219
+ const {isFullMode, isGetFormData} = nextProps;
220
+ if (isFullMode && isGetFormData && !_.isEqual(isGetFormData, this.props.isGetFormData)) {
221
+ //when create button is clicked in full mode
222
+ this.startValidation(true);
223
+ }
219
224
  if (this.state.languageDataSet && nextProps.Templates.selectedEmailLayout && nextProps.Templates.selectedEmailLayout !== '' && !_.isEqual(this.props.Templates.selectedEmailLayout, nextProps.Templates.selectedEmailLayout )) {
220
225
  this.setNewLanguageContent(nextProps.Templates.selectedEmailLayout);
221
226
  }
@@ -632,7 +637,7 @@ export class Email extends React.Component { // eslint-disable-line react/prefer
632
637
  } else {
633
638
  message = getMessageObject('success', this.props.intl.formatMessage(messages.emailCreateSuccess), true);
634
639
  }
635
- this.props.globalActions.addMessageToQueue(message);
640
+ CapNotification.success({message});
636
641
  const module = this.props.location.query.module ? this.props.location.query.module : 'default';
637
642
  const type = this.props.location.query.type;
638
643
  const isLanguageSupport = this.props.location.query.isLanguageSupport || false;
@@ -944,13 +949,18 @@ export class Email extends React.Component { // eslint-disable-line react/prefer
944
949
  shouldStartValidation = () => {
945
950
  this.setState((prevState) => ({ cmsDataCount: prevState.cmsDataCount + 1}), () => {
946
951
  if (this.state.targetSaveCount === this.state.cmsDataCount) {
947
- this.setState({startValidation: true});
952
+ //gets called when org is edm editor enabled, whenever the edm data get saved
953
+ this.startValidation(this.props.isGetFormData);
948
954
  }
949
955
  });
950
956
  }
951
-
957
+ startValidation = (shouldSave) => {
958
+ if (!this.state.startValidation && shouldSave) {
959
+ this.setState({startValidation: true});
960
+ }
961
+ }
952
962
  stopValidation = () => {
953
- this.setState({startValidation: false});
963
+ this.setState({startValidation: false}, this.props.onValidationFail);
954
964
  }
955
965
  saveValidationData = () => {
956
966
  let saveCount = 0;
@@ -965,7 +975,7 @@ export class Email extends React.Component { // eslint-disable-line react/prefer
965
975
  }
966
976
  });
967
977
  if (saveCount === 0) {
968
- this.setState({startValidation: true});
978
+ this.startValidation();
969
979
  return;
970
980
  }
971
981
  this.setState({targetSaveCount: saveCount, mode: "save", saveCount: 0, cmsDataCount: 0}, () => {
@@ -2310,16 +2320,8 @@ export class Email extends React.Component { // eslint-disable-line react/prefer
2310
2320
  }
2311
2321
 
2312
2322
  saveFormData = (passedData) => {
2313
- //Logic to save in db etc
2314
- // const isValidated = this.validateFormData(formData);
2315
- //
2316
- // if (!isValidated) {
2317
- // return;
2318
- // }
2319
- //if (!this.state.startValidation) {
2320
- // this.saveValidationData();
2321
- // return;
2322
- //}
2323
+ //saveFormData gets called only when validation result is true
2324
+
2323
2325
 
2324
2326
  if (this.state.gettingFormData && !this.props.isFullMode) {
2325
2327
  const response = {
@@ -2682,6 +2684,7 @@ Email.propTypes = {
2682
2684
  injectedTags: PropTypes.object,
2683
2685
  defaultData: PropTypes.object,
2684
2686
  showTemplateName: PropTypes.func,
2687
+ onValidationFail: PropTypes.func,
2685
2688
  };
2686
2689
 
2687
2690
  const mapStateToProps = (state, props) => createStructuredSelector({
@@ -1,18 +1,21 @@
1
1
  import { take, cancel, call, put, takeLatest, takeEvery } from 'redux-saga/effects';
2
2
  import { LOCATION_CHANGE } from 'react-router-redux';
3
+ import {CapNotification} from '@capillarytech/cap-ui-library';
3
4
  import * as Api from '../../services/api';
4
5
  import * as types from './constants';
5
6
 
6
-
7
7
  export function* createTemplate(template) {
8
8
  let errorMsg;
9
9
  try {
10
10
  const result = yield call(Api.createEmailTemplate, template);
11
- if (result.message || result.status.code === 500) {
11
+ if (result.status.code === 500) {
12
12
  errorMsg = result.message;
13
+ CapNotification.error({message: errorMsg, key: 'create-email-template-error'});
14
+ yield put({ type: types.CREATE_TEMPLATE_FAILURE, errorMsg });
15
+ } else {
16
+ yield put({ type: types.CREATE_TEMPLATE_SUCCESS, data: result.response, statusCode: result.status ? result.status.code : '', errorMsg });
17
+ yield template.onCreateTemplateComplete(result.response);
13
18
  }
14
- yield put({ type: types.CREATE_TEMPLATE_SUCCESS, data: result.response, statusCode: result.status ? result.status.code : '', errorMsg });
15
- yield template.onCreateTemplateComplete(result.response);
16
19
  } catch (error) {
17
20
  yield put({ type: types.CREATE_TEMPLATE_FAILURE, error, errorMsg });
18
21
  }
@@ -158,7 +158,7 @@ export class EmailWrapper extends React.Component { // eslint-disable-line react
158
158
 
159
159
  isShowEmailCreate = () => !_.isEmpty(this.state.selectedCreateMode) && (!_.isEmpty(this.props.EmailLayout) || this.props.SelectedEdmDefaultTemplate)
160
160
  render() {
161
- const {showTemplateName, emailCreateMode, isGetFormData, getFormdata, type, CmsTemplates, step, cap, isFullMode, EmailLayout, setIsLoadingContent} = this.props;
161
+ const {showTemplateName, emailCreateMode, isGetFormData, getFormdata, type, CmsTemplates, step, cap, isFullMode, EmailLayout, setIsLoadingContent, onValidationFail} = this.props;
162
162
  const {templateName, modeContent} = this.state;
163
163
  const isShowEmailCreate = this.isShowEmailCreate();
164
164
  return (
@@ -211,6 +211,7 @@ export class EmailWrapper extends React.Component { // eslint-disable-line react
211
211
  defaultData={{'template-name': templateName}}
212
212
  cap={cap}
213
213
  showTemplateName={showTemplateName}
214
+ onValidationFail={onValidationFail}
214
215
  />}
215
216
  {CmsTemplates && !isShowEmailCreate && <CmsTemplatesComponent cmsTemplates={CmsTemplates} handleEdmDefaultTemplateSelection={this.useEditor}/>}
216
217
  </div>
@@ -240,6 +241,7 @@ EmailWrapper.propTypes = {
240
241
  isUploading: PropTypes.bool,
241
242
  setIsLoadingContent: PropTypes.func,
242
243
  showTemplateName: PropTypes.func,
244
+ onValidationFail: PropTypes.func,
243
245
  };
244
246
 
245
247
  const mapStateToProps = createStructuredSelector({
@@ -12,47 +12,3 @@
12
12
  }
13
13
  }
14
14
 
15
- .ant-breadcrumb{
16
- color: #707070;
17
- font-family: open-sans;
18
- line-height: 16px;
19
- font-size: 12px;
20
- padding-left: 8px;
21
- }
22
- .ant-checkbox{
23
- vertical-align: middle !important;
24
- }
25
-
26
- #template-name.ant-input{
27
- font-size: 20px !important;
28
- // font-family: proxima-nova, sans-serif;
29
- font-style: normal;
30
- font-weight: 600;
31
- }
32
- .ant-tabs-bar{
33
- margin-bottom: 0 !important;
34
- display: flex;
35
- align-items: center;
36
- flex-direction: row-reverse;
37
- justify-content: flex-end;
38
- }
39
- .ant-tabs-tabpane{
40
- border: 1px solid #d9d9d9;
41
- border-top: none;
42
- margin-top: -0.2%;
43
- min-height: calc(70vh);
44
- }
45
-
46
- .ant-tabs-extra-content{
47
- flex: 1;
48
- align-self: flex-end;
49
- }
50
-
51
- .version-popover {
52
- line-height: 24px;
53
- cursor: pointer;
54
- }
55
-
56
- .version-popover:hover{
57
- background-color: #ecf6fd;
58
- }
@@ -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 { CapRow, CapColumn, CapSpin } from '@capillarytech/cap-ui-library';
11
+ import { CapRow, CapColumn, CapSpin, CapNotification } from '@capillarytech/cap-ui-library';
12
12
  import { injectIntl, intlShape } from 'react-intl';
13
13
  import { createStructuredSelector } from 'reselect';
14
14
  import _ from 'lodash';
@@ -25,6 +25,7 @@ import {checkUnicode, updateCharCount} from '../../../utils/smsCharCountV2';
25
25
  import * as globalActions from '../../Cap/actions';
26
26
  import {getMessageObject} from '../../../utils/messageUtils';
27
27
  import * as creativesContainerActions from '../../CreativesContainer/actions';
28
+ import {SMS} from '../../CreativesContainer/constants';
28
29
  // import callNativeEvent from '../../../utils/callNativeEvent';
29
30
  import {showError} from '../commonMethods';
30
31
  export class Create extends React.Component { // eslint-disable-line react/prefer-stateless-function
@@ -137,8 +138,8 @@ export class Create extends React.Component { // eslint-disable-line react/prefe
137
138
  this.startValidation();
138
139
  }
139
140
  if (nextProps.Create.createTemplateError && !_.isEqual(nextProps.Create.createTemplateError, this.props.Create.createTemplateError)) {
140
- const message = getMessageObject('error', (nextProps.Create.createTemplateErrorMessage && nextProps.Create.createTemplateErrorMessage !== '') ? nextProps.Create.createTemplateErrorMessage : this.props.intl.formatMessage(messages.somethingWentWrong), true);
141
- this.props.globalActions.addMessageToQueue(message);
141
+ const message = (nextProps.Create.createTemplateErrorMessage && nextProps.Create.createTemplateErrorMessage !== '') ? nextProps.Create.createTemplateErrorMessage : this.props.intl.formatMessage(messages.somethingWentWrong);
142
+ CapNotification.error({key: 'createTemplateError', message });
142
143
  }
143
144
  if (nextProps.metaEntities && nextProps.metaEntities.layouts && nextProps.metaEntities.layouts.length > 0 && _.isEmpty(this.state.schema)) {
144
145
  this.injectEvents(nextProps.metaEntities.layouts[0].definition);
@@ -209,8 +210,8 @@ export class Create extends React.Component { // eslint-disable-line react/prefe
209
210
  currentTab: 1,
210
211
  editData: {},
211
212
  });
212
- const message = getMessageObject('success', 'SMS Template Created Successfully', true);
213
- this.props.globalActions.addMessageToQueue(message);
213
+ const message = 'SMS Template Created Successfully';
214
+ CapNotification.success({key: 'createMessageSuccess', message});
214
215
  const module = this.props.location.query.module ? this.props.location.query.module : 'default';
215
216
  const type = this.props.location.query.type;
216
217
  if (this.props.isFullMode) {
@@ -279,7 +280,7 @@ export class Create extends React.Component { // eslint-disable-line react/prefe
279
280
  cancelTemplate: this.cancelTemplate,
280
281
  },
281
282
  "save-button": {
282
- saveFormData: this.saveFormData,
283
+ saveFormData: this.validateAndSaveFormData,
283
284
  },
284
285
  "sms-editor": {
285
286
  onChange: this.onTemplateContentChange,
@@ -879,20 +880,21 @@ export class Create extends React.Component { // eslint-disable-line react/prefe
879
880
  this.setState({showModal: false});
880
881
  }
881
882
 
882
- saveFormData(formData) {
883
+ validateAndSaveFormData = () => {
884
+ this.setState({startValidation: true});
885
+ }
886
+ stopValidation = () => {
887
+ this.setState({startValidation: false});
888
+ }
889
+ saveFormData() {
883
890
  //Logic to save in db etc
884
- const validatedFormData = this.getFormData();
885
-
886
- if (!validatedFormData.validity) {
887
- return;
888
- }
889
-
891
+ const formData = _.cloneDeep(this.state.formData);
890
892
  const obj = {};
891
893
  obj.versions = {
892
894
  base: {},
893
895
  history: [],
894
896
  };
895
- obj.type = validatedFormData.type;
897
+ obj.type = SMS;
896
898
  for (let index = 0; index < this.state.tabCount; index += 1 ) {
897
899
  obj.versions.history.push(formData[index]);
898
900
  // if (formData[index])
@@ -9,7 +9,7 @@ import PropTypes from 'prop-types';
9
9
 
10
10
  import React from 'react';
11
11
  import { connect } from 'react-redux';
12
- import { Row, Col, Spin } from 'antd';
12
+ import { CapRow, CapColumn, CapSpinner, CapNotification } from '@capillarytech/cap-ui-library';
13
13
  import { injectIntl, intlShape } from 'react-intl';
14
14
  import { createStructuredSelector } from 'reselect';
15
15
  import _ from 'lodash';
@@ -161,8 +161,8 @@ export class Edit extends React.Component { // eslint-disable-line react/prefer-
161
161
  currentTab: 1,
162
162
  editData: {},
163
163
  });
164
- const message = getMessageObject('success', 'SMS Template Edited Successfully', true);
165
- this.props.globalActions.addMessageToQueue(message);
164
+ const message = 'SMS Template Edited Successfully';
165
+ CapNotification.success({key: 'messageCreateSuccess', message });
166
166
  this.props.actions.clearEditResponse();
167
167
  const module = this.props.location.query.module ? this.props.location.query.module : 'default';
168
168
  const type = this.props.location.query.type;
@@ -173,8 +173,8 @@ export class Edit extends React.Component { // eslint-disable-line react/prefer-
173
173
  }
174
174
 
175
175
  if (nextProps.Edit.editTemplateError && !_.isEqual(nextProps.Edit.editTemplateError, this.props.Edit.editTemplateError)) {
176
- const message = getMessageObject('error', (nextProps.Edit.editTemplateErrorMessage && nextProps.Edit.editTemplateErrorMessage !== '') ? nextProps.Edit.editTemplateErrorMessage : this.props.intl.formatMessage(messages.somethingWentWrong), true);
177
- this.props.globalActions.addMessageToQueue(message);
176
+ const message = (nextProps.Edit.editTemplateErrorMessage && nextProps.Edit.editTemplateErrorMessage !== '') ? nextProps.Edit.editTemplateErrorMessage : this.props.intl.formatMessage(messages.somethingWentWrong);
177
+ CapNotification.error({key: 'templateEditFailed', message});
178
178
  }
179
179
  }
180
180
 
@@ -228,8 +228,8 @@ export class Edit extends React.Component { // eslint-disable-line react/prefer-
228
228
  currentTab: 1,
229
229
  editData: {},
230
230
  });
231
- const message = getMessageObject('success', 'SMS Template Edited Successfully', true);
232
- this.props.globalActions.addMessageToQueue(message);
231
+ const message = 'SMS Template Edited Successfully';
232
+ CapNotification.success({key: 'editTemplateSuccess', message});
233
233
  this.props.actions.clearEditResponse();
234
234
  const module = this.props.location.query.module ? this.props.location.query.module : 'default';
235
235
  const type = this.props.location.query.type;
@@ -351,7 +351,7 @@ export class Edit extends React.Component { // eslint-disable-line react/prefer-
351
351
  cancelTemplate: this.cancelTemplate,
352
352
  },
353
353
  "save-button": {
354
- saveFormData: this.saveFormData,
354
+ saveFormData: this.validateAndSaveFormData,
355
355
  },
356
356
  "sms-editor": {
357
357
  onChange: this.onTemplateContentChange,
@@ -889,22 +889,22 @@ export class Edit extends React.Component { // eslint-disable-line react/prefer-
889
889
  handleCancelModal = () => {
890
890
  this.setState({showModal: false});
891
891
  }
892
-
893
- saveFormData(formData) {
892
+ validateAndSaveFormData = () => {
893
+ this.setState({startValidation: true});
894
+ }
895
+ stopValidation = () => {
896
+ this.setState({startValidation: false});
897
+ }
898
+ saveFormData() {
894
899
  //Logic to save in db etc
900
+ //saveFormData gets called only when validation result is true
895
901
 
896
- const obj = _.cloneDeep(this.state.editData);
897
- obj.versions = {
898
- base: {},
899
- history: [],
900
- };
901
- for (let index = 0; index < this.state.tabCount; index += 1 ) {
902
- obj.versions.history.push(formData[index]);
903
- }
904
- obj.name = formData['template-name'];
905
- obj.versions.base = formData.base;
902
+ const editData = _.cloneDeep(this.state.editData);
903
+ const formData = _.cloneDeep(this.state.formData);
904
+ editData.name = formData['template-name'];
905
+ editData.versions.base = formData.base;
906
906
 
907
- this.props.actions.editTemplate(obj, this.onUpdateTemplateComplete);
907
+ this.props.actions.editTemplate(editData, this.onUpdateTemplateComplete);
908
908
  }
909
909
  isSmsLoading = () => {
910
910
  //let {isLoading} = this.props;
@@ -932,18 +932,18 @@ export class Edit extends React.Component { // eslint-disable-line react/prefer-
932
932
  }
933
933
  return (
934
934
  <div className="sms-email-container">
935
- <Spin tip={tipText} spinning={spinning}>
936
- {/*<Row style={{marginBottom: '16px', marginLeft: '-40px'}}>
937
- <Col offset={1}>
935
+ <CapSpinner tip={tipText} spinning={spinning}>
936
+ {/*<CapRow style={{marginBottom: '16px', marginLeft: '-40px'}}>
937
+ <CapColumn offset={1}>
938
938
  <Breadcrumb>
939
939
  <Breadcrumb.Item>Campaigns</Breadcrumb.Item>
940
940
  <Breadcrumb.Item>Creatives</Breadcrumb.Item>
941
941
  <Breadcrumb.Item>SMS</Breadcrumb.Item>
942
942
  </Breadcrumb>
943
- </Col>
944
- </Row>*/}
945
- <Row>
946
- <Col>
943
+ </CapColumn>
944
+ </CapRow>*/}
945
+ <CapRow>
946
+ <CapColumn>
947
947
  <FormBuilder
948
948
  isFullMode={this.props.isFullMode}
949
949
  refs={this.componentRefs}
@@ -968,10 +968,12 @@ export class Edit extends React.Component { // eslint-disable-line react/prefer-
968
968
  onContextChange={this.handleOnTagsContextChange}
969
969
  handleCancelModal={this.handleCancelModal}
970
970
  router={this.props.router}
971
+ startValidation={this.state.startValidation}
972
+ stopValidation={this.stopValidation}
971
973
  />
972
- </Col>
973
- </Row>
974
- </Spin>
974
+ </CapColumn>
975
+ </CapRow>
976
+ </CapSpinner>
975
977
  </div>
976
978
  );
977
979
  }
@@ -235,24 +235,24 @@ export const response = {
235
235
  "saveFormData",
236
236
  ],
237
237
  },
238
- {
239
- id: "discard-button",
240
- metaType: "submit-button",
238
+ // {
239
+ // id: "discard-button",
240
+ // metaType: "submit-button",
241
241
 
242
- type: "button",
243
- buttonType: "secondary",
244
- value: "Discard changes",
245
- customComponent: false,
246
- standalone: true,
247
- styling: "semantic",
248
- order: 3,
249
- fluid: true,
250
- submitAction: "discardValues",
251
- onlyDisplay: true,
252
- supportedEvents: [
253
- "discardValues",
254
- ],
255
- },
242
+ // type: "button",
243
+ // buttonType: "secondary",
244
+ // value: "Discard changes",
245
+ // customComponent: false,
246
+ // standalone: true,
247
+ // styling: "semantic",
248
+ // order: 3,
249
+ // fluid: true,
250
+ // submitAction: "discardValues",
251
+ // onlyDisplay: true,
252
+ // supportedEvents: [
253
+ // "discardValues",
254
+ // ],
255
+ // },
256
256
 
257
257
 
258
258
  ],
@@ -15,7 +15,7 @@ import moment from "moment";
15
15
  import _ from 'lodash';
16
16
  import { bindActionCreators } from 'redux';
17
17
  import { Modal} from 'antd';
18
- import {CapMenu, CapDropdown, CapButton, CapInput, CapIcon, CapSelect, CapPopover, CapSpin, CapCustomCard, CapRow, CapSlideBox, CapLink, CapHeading} from '@capillarytech/cap-ui-library';
18
+ import {CapMenu, CapDropdown, CapButton, CapInput, CapIcon, CapSelect, CapPopover, CapSpin, CapCustomCard, CapRow, CapSlideBox, CapLink, CapHeading, CapNotification} from '@capillarytech/cap-ui-library';
19
19
  import { makeSelectTemplates, makeSelectTemplatesResponse } from './selectors';
20
20
  import { makeSelectCreate as makeSelectCreateSms} from '../Sms/Create/selectors';
21
21
  import { makeSelectCreate as makeSelectCreateMobilePush } from '../MobilePush/Create/selectors';
@@ -38,7 +38,6 @@ import config from '../../config/app';
38
38
  import './_templates.scss';
39
39
  import * as globalActions from '../Cap/actions';
40
40
  import { makeSelectAuthenticated } from '../Cap/selectors';
41
- import {getMessageObject} from '../../utils/messageUtils';
42
41
  import * as commonUtil from '../../utils/common';
43
42
  import Pagination from '../../v2Components/Pagination';
44
43
  import EmailPreview from '../../v2Components/EmailPreview';
@@ -259,36 +258,36 @@ export class Templates extends React.Component { // eslint-disable-line react/pr
259
258
  if (this.state.channel.toLowerCase() === "mobilepush" && !_.isEmpty(nextProps.Templates.selectedWeChatAccount)) {
260
259
  params.accountId = nextProps.Templates.selectedWeChatAccount.id;
261
260
  }
262
- const message = getMessageObject('success', `${this.state.channel} ${this.props.intl.formatMessage(messages.templateDuplicateSuccess)}`, true);
263
- this.props.globalActions.addMessageToQueue(message);
261
+ const message = `${this.state.channel} ${this.props.intl.formatMessage(messages.templateDuplicateSuccess)}`;
262
+ CapNotification.success({key: 'duplicateSuccess', message});
264
263
  this.getAllTemplates({params});
265
264
  this.props.mobilepushActions.clearCreateResponse();
266
265
  }
267
266
 
268
267
  if (this.state.channel.toLowerCase() === "ebill" && nextProps.CreateEbill && nextProps.CreateEbill.createResponse && nextProps.CreateEbill.createResponse.templateId && nextProps.CreateEbill.createResponse.templateId !== '') {
269
- const message = getMessageObject('success', `${this.state.channel} ${this.props.intl.formatMessage(messages.templateDuplicateSuccess)}`, true);
270
- this.props.globalActions.addMessageToQueue(message);
268
+ const message = `${this.state.channel} ${this.props.intl.formatMessage(messages.templateDuplicateSuccess)}`;
269
+ CapNotification.success({key: 'duplicateSucess', message});
271
270
  this.getAllTemplates({params, resetPage: true});
272
271
  this.props.ebillActions.clearStoreValues();
273
272
  }
274
273
 
275
274
  if (this.state.channel.toLowerCase() === "email" && nextProps.EmailCreate && nextProps.EmailCreate.duplicateResponse && nextProps.EmailCreate.duplicateResponse.templateId && nextProps.EmailCreate.duplicateResponse.templateId !== '') {
276
- const message = getMessageObject('success', `${this.state.channel} ${this.props.intl.formatMessage(messages.templateDuplicateSuccess)}`, true);
277
- this.props.globalActions.addMessageToQueue(message);
275
+ const message = `${this.state.channel} ${this.props.intl.formatMessage(messages.templateDuplicateSuccess)}`;
276
+ CapNotification.success({key: 'duplicateSucess', message});
278
277
  this.getAllTemplates({params, resetPage: true});
279
278
  this.props.emailActions.clearStoreValues();
280
279
  }
281
280
 
282
281
  if (this.state.channel.toLowerCase() === "line" && nextProps.Line && nextProps.Line.response && nextProps.Line.response.templateId && nextProps.Line.response.templateId !== '') {
283
- const message = getMessageObject('success', `${this.state.channel} ${this.props.intl.formatMessage(messages.templateDuplicateSuccess)}`, true);
284
- this.props.globalActions.addMessageToQueue(message);
282
+ const message = `${this.state.channel} ${this.props.intl.formatMessage(messages.templateDuplicateSuccess)}`;
283
+ CapNotification.success({key: 'duplicateSuccess', message});
285
284
  this.getAllTemplates({params, resetPage: true});
286
285
  this.props.lineActions.clearCreateResponse();
287
286
  }
288
287
 
289
288
  if (nextProps.Create && this.props.Create && nextProps.Create.createTemplateError && !_.isEqual(nextProps.Create.createTemplateError, this.props.Create.createTemplateError)) {
290
- const message = getMessageObject('error', this.props.intl.formatMessage(messages.somethingWentWrong), true);
291
- this.props.globalActions.addMessageToQueue(message);
289
+ const message = this.props.intl.formatMessage(messages.somethingWentWrong);
290
+ CapNotification.error({key: 'somethingWrong', message});
292
291
  if (this.state.channel.toLowerCase() === "sms") {
293
292
  this.props.smsActions.clearCreateResponse();
294
293
  } else if (this.state.channel.toLowerCase() === "mobilepush") {
@@ -305,8 +304,8 @@ export class Templates extends React.Component { // eslint-disable-line react/pr
305
304
  }
306
305
  if (!nextProps.Templates.deleteTemplateInProgress && !_.isEqual(nextProps.Templates.deleteTemplateInProgress, this.props.Templates.deleteTemplateInProgress) &&
307
306
  nextProps.Templates.deleteResponse) {
308
- const message = getMessageObject('success', `${this.state.channel.toUpperCase()} ${this.props.intl.formatMessage(messages['Template deleted successfully'])}`, true);
309
- nextProps.globalActions.addMessageToQueue(message);
307
+ const message = `${this.state.channel.toUpperCase()} ${this.props.intl.formatMessage(messages['Template deleted successfully'])}`;
308
+ CapNotification.success({key: 'deleteSucess', message});
310
309
  this.getAllTemplates({params, resetPage: true});
311
310
  }
312
311
 
@@ -330,8 +329,7 @@ export class Templates extends React.Component { // eslint-disable-line react/pr
330
329
  if (nextProps.Templates.errorMessage && nextProps.Templates.errorMessage !== "") {
331
330
  errorMessage = nextProps.Templates.errorMessage;
332
331
  }
333
- const message = getMessageObject('error', errorMessage, true);
334
- nextProps.globalActions.addMessageToQueue(message);
332
+ CapNotification.error({key: 'uploadError', message: errorMessage});
335
333
  }
336
334
 
337
335
  if (!_.isEmpty(nextProps.Templates.templateDetails) && !_.isEqual(nextProps.Templates.templateDetails, this.props.Templates.templateDetails)) {
@@ -661,8 +659,8 @@ export class Templates extends React.Component { // eslint-disable-line react/pr
661
659
  };
662
660
  reader.readAsText(files[0]);
663
661
  } else {
664
- const message = getMessageObject('error', this.props.intl.formatMessage(messages.invalidUploadFileError), true);
665
- this.props.globalActions.addMessageToQueue(message);
662
+ const message = this.props.intl.formatMessage(messages.invalidUploadFileError);
663
+ CapNotification.error({key: 'uploadError', message});
666
664
  }
667
665
  };
668
666
 
@@ -867,8 +865,7 @@ export class Templates extends React.Component { // eslint-disable-line react/pr
867
865
  type = this.props.location.query.type;
868
866
  if (this.props.Templates && this.props.Templates.selectedWeChatAccount && this.props.Templates.selectedWeChatAccount.configs && (_.isEmpty(this.props.Templates.selectedWeChatAccount.configs.wechat_app_id) || _.isEmpty(this.props.Templates.selectedWeChatAccount.configs.wechat_app_secret))) {
869
867
  const errorMessage = this.props.intl.formatMessage(messages.wechatAccountNotConfigured);
870
- const message = getMessageObject('error', errorMessage, true);
871
- this.props.globalActions.addMessageToQueue(message);
868
+ CapNotification.error({key: 'wechatError', message: errorMessage});
872
869
  } else {
873
870
  this.props.router.push({
874
871
  pathname: `/wechat/richmedia/create`,
@@ -967,8 +964,9 @@ export class Templates extends React.Component { // eslint-disable-line react/pr
967
964
  if (this.state.channel.toLowerCase() === "sms") {
968
965
  this.props.smsActions.createTemplate(duplicateObj, (response) => {
969
966
  if (response && response.templateId) {
970
- const message = getMessageObject('success', `${this.state.channel} ${this.props.intl.formatMessage(messages.templateDuplicateSuccess)}`, true);
971
- this.props.globalActions.addMessageToQueue(message);
967
+ const message = `${this.state.channel} ${this.props.intl.formatMessage(messages.templateDuplicateSuccess)}`;
968
+ CapNotification.success({key: 'duplicateSucess', message});
969
+
972
970
  this.getAllTemplates({params, resetPage: true});
973
971
  this.props.smsActions.clearCreateResponse();
974
972
  }
@@ -1570,6 +1568,7 @@ export class Templates extends React.Component { // eslint-disable-line react/pr
1570
1568
  value={this.state.searchText}
1571
1569
  onChange={(e) => this.searchTemplate(e.target.value)}
1572
1570
  disabled={this.checkSearchDisabled()}
1571
+ onClear={() => this.searchTemplate('')}
1573
1572
  />
1574
1573
  <div style={{display: "flex", justifyContent: "space-between", alignItems: 'center'}}>
1575
1574
  {(this.props.location.query.type === 'embedded' ) ? pageHeaderDvs : pageHeader}