@capillarytech/creatives-library 2.0.89 → 2.0.91

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.
Files changed (51) hide show
  1. package/assets/android-message-gui-2.svg +55 -0
  2. package/components/CallTaskPreview/_callTaskPreview.scss +17 -0
  3. package/components/CallTaskPreview/images/Footer.png +0 -0
  4. package/components/CallTaskPreview/images/Header.png +0 -0
  5. package/components/CallTaskPreview/index.js +37 -0
  6. package/components/CallTaskPreview/messages.js +13 -0
  7. package/components/CallTaskPreview/tests/index.test.js +15 -0
  8. package/components/CmsTemplatesComponent/index.js +33 -0
  9. package/components/CmsTemplatesComponent/messages.js +17 -0
  10. package/components/CmsTemplatesComponent/tests/index.test.js +10 -0
  11. package/components/EmailMobilePreview/index.js +129 -0
  12. package/components/EmailMobilePreview/index.scss +55 -0
  13. package/components/EmailPreviewV2/_emailPreviewV2.scss +69 -0
  14. package/components/EmailPreviewV2/index.js +132 -0
  15. package/components/EmailPreviewV2/messages.js +41 -0
  16. package/components/EmailPreviewV2/tests/index.test.js +10 -0
  17. package/components/MobilePushPreviewV2/index.js +120 -0
  18. package/components/MobilePushPreviewV2/messages.js +13 -0
  19. package/components/MobilePushPreviewV2/tests/index.test.js +10 -0
  20. package/components/NewCallTask/_newCallTask.scss +9 -0
  21. package/components/NewCallTask/index.js +152 -0
  22. package/components/NewCallTask/messages.js +29 -0
  23. package/components/NewCallTask/tests/index.test.js +10 -0
  24. package/components/SmsPreviewV2/_smsPreviewV2.scss +353 -0
  25. package/components/SmsPreviewV2/index.js +69 -0
  26. package/components/SmsPreviewV2/messages.js +13 -0
  27. package/components/SmsPreviewV2/tests/index.test.js +10 -0
  28. package/containers/Cap/index.js +1 -2
  29. package/containers/Email/index.js +20 -22
  30. package/containers/Sms/Create/index.js +5 -4
  31. package/containers/Sms/Edit/index.js +5 -4
  32. package/containers/WeChat/MapTemplates/index.js +7 -4
  33. package/package.json +2 -2
  34. package/v2Components/FormBuilder/index.js +25 -15
  35. package/v2Components/NavigationBar/index.js +2 -2
  36. package/v2Components/TopBar/index.js +2 -1
  37. package/v2Containers/Assets/Gallery/index.js +4 -4
  38. package/v2Containers/Cap/constants.js +1 -1
  39. package/v2Containers/Cap/index.js +3 -2
  40. package/v2Containers/CreativesContainer/SlideBoxContent.js +4 -0
  41. package/v2Containers/CreativesContainer/SlideBoxHeader.js +9 -8
  42. package/v2Containers/CreativesContainer/index.js +39 -23
  43. package/v2Containers/CreativesContainer/messages.js +1 -1
  44. package/v2Containers/Email/index.js +19 -16
  45. package/v2Containers/Email/sagas.js +7 -4
  46. package/v2Containers/EmailWrapper/index.js +3 -1
  47. package/v2Containers/Sms/Create/_smsCreate.scss +0 -44
  48. package/v2Containers/Sms/Create/index.js +16 -14
  49. package/v2Containers/Sms/Edit/index.js +33 -31
  50. package/v2Containers/Sms/initialSchema.js +17 -17
  51. package/v2Containers/Templates/index.js +21 -22
@@ -0,0 +1,69 @@
1
+ /**
2
+ *
3
+ * SmsPreviewV2
4
+ *
5
+ */
6
+
7
+ import React from 'react';
8
+ // import styled from 'styled-components';
9
+
10
+ import { FormattedMessage } from 'react-intl';
11
+ import messages from './messages';
12
+ import {CapColumn, CapRow, CapHeading} from '@capillarytech/cap-ui-library';
13
+ import androidPhoneImage from '../../assets/android-message-gui-2.svg';
14
+
15
+ class SmsPreviewV2 extends React.Component { // eslint-disable-line react/prefer-stateless-function
16
+ render() {
17
+ let content = [this.props.content];
18
+ const channel = this.props.channel;
19
+ let smsDetails = {};
20
+ if (this.props.content && this.props.charCounterEnabled) {
21
+ smsDetails = updateCharCount(this.props.content, this.props.unicodeEnabled);
22
+ content = [];
23
+ for (let i = 0, limit = 0; i < smsDetails.parts; i += 1, limit += smsDetails.chars_sms) {
24
+ content.push(smsDetails.char_list.slice(limit, smsDetails.chars_sms * (i + 1)));
25
+ }
26
+ if (document.getElementById("msg_count") && this.props.showCount) {
27
+ document.getElementById("msg_count").val = smsDetails.parts;
28
+ }
29
+ }
30
+ const type = this.props.location && this.props.location.query.type ? this.props.location.query.type : '';
31
+ return (
32
+ <CapRow>
33
+ {this.props.showCount && <CapColumn span={16}>
34
+ {channel && channel.toLowerCase() === 'sms' && <CapHeading type="h3">
35
+ <FormattedMessage {...messages.charactersTotal} values={{smsCount: smsDetails.parts, charCount: smsDetails.chars_used}}/>
36
+ {smsDetails.unicode &&
37
+ <FormattedMessage {...messages.smsFormatType}/>
38
+ }
39
+ </CapHeading>}
40
+ </CapColumn>}
41
+ <CapColumn span={this.props.showCount ? 8 : 24}>
42
+ <div className={`preview-container ${type === 'embedded' ? 'embedded-preview' : ''}`}>
43
+ { channel && channel.toLowerCase() === 'sms' &&
44
+ <div className="shell align-center" id="sms-preview">
45
+ <img className="preview-image sms" src={smsBody} alt="Preview is being generated"/>
46
+ <div className="msgContainer sms">
47
+ <img className="sms-icon" src={smsIcon} alt="Sms icon" />
48
+ <div className={"message-pop sms"}>
49
+ {content && content.length && content.map((msg, index) =>
50
+ <CapColumn key={`"message-pop-content-${index}`} className="message-pop-item align-left" style={{ background: '#3F51B5', color: '#ffffff'}}>
51
+ {msg}
52
+ </CapColumn>)
53
+ }
54
+ </div>
55
+ </div>
56
+ </div>
57
+ }
58
+ </div>
59
+ </CapColumn>
60
+ </CapRow>
61
+ );
62
+ }
63
+ }
64
+
65
+ SmsPreviewV2.propTypes = {
66
+
67
+ };
68
+
69
+ export default SmsPreviewV2;
@@ -0,0 +1,13 @@
1
+ /*
2
+ * SmsPreviewV2 Messages
3
+ *
4
+ * This contains all the text for the SmsPreviewV2 component.
5
+ */
6
+ import { defineMessages } from 'react-intl';
7
+
8
+ export default defineMessages({
9
+ header: {
10
+ id: 'app.components.SmsPreviewV2.header',
11
+ defaultMessage: 'This is the SmsPreviewV2 component !',
12
+ },
13
+ });
@@ -0,0 +1,10 @@
1
+ // import React from 'react';
2
+ // import { shallow } from 'enzyme';
3
+
4
+ // import SmsPreviewV2 from '../index';
5
+
6
+ describe('<SmsPreviewV2 />', () => {
7
+ it('Expect to have unit tests specified', () => {
8
+ expect(true).toEqual(false);
9
+ });
10
+ });
@@ -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.89",
4
+ "version": "2.0.91",
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;
@@ -1234,15 +1236,23 @@ class FormBuilder extends React.Component { // eslint-disable-line react/prefer-
1234
1236
 
1235
1237
  initializeStandAloneSections(schema, formDataObj, ifError) {
1236
1238
  let formData = _.cloneDeep(formDataObj);
1239
+ const channel = _.get(this, "props.schema.channel");
1240
+ let isContainer = false;
1241
+ let index = -1;
1242
+ if (channel && channel.toUpperCase() === SMS) {
1243
+ // sms v2 scema does not have any containers section the input ant preview fields are in stand alon section and v1 FormBuilder did not have valiation support for stand alone input fields
1244
+ isContainer = true;
1245
+ index = 0;
1246
+ }
1237
1247
  if (schema.standalone) {
1238
1248
  _.forEach(schema.standalone.sections, (section) => {
1239
1249
  if (section) {
1240
1250
  if (section.type === 'multicols') {
1241
- formData = this.initializeMultiColSection(section, formData, false, -1, ifError);
1251
+ formData = this.initializeMultiColSection(section, formData, isContainer, index, ifError);
1242
1252
  } else if (section.type === 'col-label') {
1243
- formData = this.initializeColLabelSection(section, formData, false, -1, ifError);
1253
+ formData = this.initializeColLabelSection(section, formData, isContainer, index, ifError);
1244
1254
  } else if (section.type === 'parent') {
1245
- formData = this.initializeParentSection(section, formData, false, -1, ifError);
1255
+ formData = this.initializeParentSection(section, formData, isContainer, index, ifError);
1246
1256
  }
1247
1257
  }
1248
1258
  });
@@ -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;