@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.
- package/containers/Cap/index.js +1 -2
- package/containers/Email/index.js +20 -22
- package/containers/Sms/Create/index.js +5 -4
- package/containers/Sms/Edit/index.js +5 -4
- package/containers/WeChat/MapTemplates/index.js +7 -4
- package/package.json +2 -2
- package/v2Components/FormBuilder/index.js +14 -12
- package/v2Components/NavigationBar/index.js +2 -2
- package/v2Components/TopBar/index.js +2 -1
- package/v2Containers/Assets/Gallery/index.js +4 -4
- package/v2Containers/Cap/constants.js +1 -1
- package/v2Containers/Cap/index.js +3 -2
- package/v2Containers/CreativesContainer/SlideBoxContent.js +4 -0
- package/v2Containers/CreativesContainer/SlideBoxHeader.js +9 -8
- package/v2Containers/CreativesContainer/index.js +39 -23
- package/v2Containers/CreativesContainer/messages.js +1 -1
- package/v2Containers/Email/index.js +19 -16
- package/v2Containers/Email/sagas.js +7 -4
- package/v2Containers/EmailWrapper/index.js +3 -1
- package/v2Containers/Sms/Create/_smsCreate.scss +0 -44
- package/v2Containers/Sms/Create/index.js +16 -14
- package/v2Containers/Sms/Edit/index.js +33 -31
- package/v2Containers/Sms/initialSchema.js +17 -17
- package/v2Containers/Templates/index.js +21 -22
package/containers/Cap/index.js
CHANGED
|
@@ -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
|
-
|
|
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
|
-
|
|
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
|
|
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
|
|
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
|
-
|
|
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
|
|
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
|
|
2576
|
-
delete
|
|
2577
|
-
|
|
2578
|
-
|
|
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
|
-
|
|
2580
|
+
newSchema.standalone.sections.push(_.cloneDeep(schema.standalone.sections[0]));
|
|
2582
2581
|
}
|
|
2583
2582
|
|
|
2584
|
-
_.forEach(
|
|
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
|
-
|
|
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
|
|
739
|
-
myField.
|
|
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
|
|
1241
|
-
myField.
|
|
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
|
|
1040
|
-
|
|
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.
|
|
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.
|
|
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
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
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() !==
|
|
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: [
|
|
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 (
|
|
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=
|
|
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 = '/
|
|
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,
|
|
21
|
-
const
|
|
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' && !
|
|
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
|
-
{
|
|
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}
|
|
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
|
-
{!
|
|
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
|
-
{!
|
|
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
|
-
|
|
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
|
-
|
|
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 {
|
|
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
|
-
|
|
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() &&
|
|
@@ -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
|
-
|
|
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
|
-
|
|
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.
|
|
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
|
-
//
|
|
2314
|
-
|
|
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.
|
|
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 =
|
|
141
|
-
|
|
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 =
|
|
213
|
-
|
|
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.
|
|
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
|
-
|
|
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
|
|
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 =
|
|
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 {
|
|
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 =
|
|
165
|
-
|
|
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 =
|
|
177
|
-
|
|
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 =
|
|
232
|
-
|
|
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.
|
|
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
|
-
|
|
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
|
|
897
|
-
|
|
898
|
-
|
|
899
|
-
|
|
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(
|
|
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
|
-
<
|
|
936
|
-
{/*<
|
|
937
|
-
<
|
|
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
|
-
</
|
|
944
|
-
</
|
|
945
|
-
<
|
|
946
|
-
<
|
|
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
|
-
</
|
|
973
|
-
</
|
|
974
|
-
</
|
|
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
|
-
|
|
240
|
-
|
|
238
|
+
// {
|
|
239
|
+
// id: "discard-button",
|
|
240
|
+
// metaType: "submit-button",
|
|
241
241
|
|
|
242
|
-
|
|
243
|
-
|
|
244
|
-
|
|
245
|
-
|
|
246
|
-
|
|
247
|
-
|
|
248
|
-
|
|
249
|
-
|
|
250
|
-
|
|
251
|
-
|
|
252
|
-
|
|
253
|
-
|
|
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 =
|
|
263
|
-
|
|
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 =
|
|
270
|
-
|
|
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 =
|
|
277
|
-
|
|
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 =
|
|
284
|
-
|
|
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 =
|
|
291
|
-
|
|
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 =
|
|
309
|
-
|
|
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
|
-
|
|
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 =
|
|
665
|
-
|
|
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
|
-
|
|
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 =
|
|
971
|
-
|
|
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}
|