@capillarytech/creatives-library 6.10.4 → 6.10.6
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/package.json +1 -1
- package/reducers.js +2 -0
- package/routes.js +4 -0
- package/services/api.js +6 -0
- package/translations/en.json +17 -0
- package/translations/zh.json +17 -0
- package/v2Components/FormBuilder/index.js +2 -3
- package/v2Containers/BeeEditor/actions.js +12 -0
- package/v2Containers/BeeEditor/constants.js +5 -0
- package/v2Containers/BeeEditor/index.js +329 -0
- package/v2Containers/BeeEditor/index.scss +6 -0
- package/v2Containers/BeeEditor/messages.js +67 -0
- package/v2Containers/BeeEditor/reducer.js +25 -0
- package/v2Containers/BeeEditor/sagas.js +33 -0
- package/v2Containers/BeeEditor/selectors.js +17 -0
- package/v2Containers/BeeEditor/tests/index.test.js +10 -0
- package/v2Containers/CreativesContainer/index.js +3 -3
- package/v2Containers/Email/index.js +1 -1
package/package.json
CHANGED
package/reducers.js
CHANGED
|
@@ -8,6 +8,7 @@ import { fromJS } from 'immutable';
|
|
|
8
8
|
import { LOCATION_CHANGE } from 'react-router-redux';
|
|
9
9
|
|
|
10
10
|
import languageProviderReducer from 'v2Containers/LanguageProvider/reducer';
|
|
11
|
+
import beeEditorReducer from 'v2Containers/BeeEditor/reducer';
|
|
11
12
|
import capReducer from 'containers/Cap/reducer';
|
|
12
13
|
import appReducer from 'containers/App/reducer';
|
|
13
14
|
import createSmsReducer from 'containers/Sms/Create/reducer';
|
|
@@ -60,6 +61,7 @@ export default function createReducer(asyncReducers) {
|
|
|
60
61
|
tagList: tagsReducer,
|
|
61
62
|
email: emailReducer,
|
|
62
63
|
ebill: ebillReducer,
|
|
64
|
+
beeEditor: beeEditorReducer,
|
|
63
65
|
...asyncReducers,
|
|
64
66
|
});
|
|
65
67
|
}
|
package/routes.js
CHANGED
|
@@ -12,6 +12,7 @@ import * as emailSagas from 'containers/Email/sagas';
|
|
|
12
12
|
import * as templateSagas from 'containers/Templates/sagas';
|
|
13
13
|
import * as lineSagas from 'containers/Line/Create/sagas';
|
|
14
14
|
import * as languageSaga from './v2Containers/LanguageProvider/sagas';
|
|
15
|
+
|
|
15
16
|
import {updateCharCount} from './utils/smsCharCountV2';
|
|
16
17
|
const errorLoading = (err) => {
|
|
17
18
|
console.error('Dynamic page loading failed', err); // eslint-disable-line no-console
|
|
@@ -614,6 +615,7 @@ export default function createRoutes(store) {
|
|
|
614
615
|
import('v2Containers/Sms/Edit/sagas'),
|
|
615
616
|
import('v2Containers/Email/reducer'),
|
|
616
617
|
import('v2Containers/Email/sagas'),
|
|
618
|
+
import('v2Containers/BeeEditor/sagas'),
|
|
617
619
|
import('v2Containers/CallTask/reducer'),
|
|
618
620
|
import('v2Containers/CallTask/sagas'),
|
|
619
621
|
import('v2Containers/MobilePush/Create/sagas'),
|
|
@@ -642,6 +644,7 @@ export default function createRoutes(store) {
|
|
|
642
644
|
creativesContainerReducer,
|
|
643
645
|
smsCreateReducer, smsCreateSaga, smsEditReducer, smsEditSaga,
|
|
644
646
|
emailReducer, emailSaga,
|
|
647
|
+
BeeEditorSaga,
|
|
645
648
|
callTaskReducer, callTaskSagas,
|
|
646
649
|
mpushCreateSagas, mpushCreateReducer,
|
|
647
650
|
mpushEditSagas, mpushEditReducer,
|
|
@@ -673,6 +676,7 @@ export default function createRoutes(store) {
|
|
|
673
676
|
injectSagas(smsCreateSaga.default);
|
|
674
677
|
injectSagas(smsEditSaga.default);
|
|
675
678
|
injectSagas(emailSaga.default);
|
|
679
|
+
injectSagas(BeeEditorSaga.default);
|
|
676
680
|
injectSagas(callTaskSagas.default);
|
|
677
681
|
injectSagas(mpushCreateSagas.default);
|
|
678
682
|
injectSagas(mpushEditSagas.default);
|
package/services/api.js
CHANGED
|
@@ -386,3 +386,9 @@ export const getMarketingObjectives = (channel) =>
|
|
|
386
386
|
|
|
387
387
|
export const getAllLineStickers = () =>
|
|
388
388
|
request(`${API_ENDPOINT}/meta/sticker`, getAPICallObject('GET'));
|
|
389
|
+
|
|
390
|
+
|
|
391
|
+
export const createCustomRow = (data) => {
|
|
392
|
+
const url = `${API_ENDPOINT}/cms/saveRows`;
|
|
393
|
+
return request(url, getAPICallObject('POST', data));
|
|
394
|
+
};
|
package/translations/en.json
CHANGED
|
@@ -86,6 +86,21 @@
|
|
|
86
86
|
"creatives.components.WechatRichmediaTemplatePreview.header": "This is the WechatRichmediaTemplatePreview component !",
|
|
87
87
|
"creatives.components.WechatRichmediaTemplatePreview.reply": "Reply",
|
|
88
88
|
"creatives.components.WechatRichmediaTemplatePreview.select": "Select",
|
|
89
|
+
"creatives.componentsV2.BeeEditor.addLabel": "Add label",
|
|
90
|
+
"creatives.componentsV2.BeeEditor.cancel": "Cancel",
|
|
91
|
+
"creatives.componentsV2.BeeEditor.cta": "CTA",
|
|
92
|
+
"creatives.componentsV2.BeeEditor.customRows": "Custom rows",
|
|
93
|
+
"creatives.componentsV2.BeeEditor.footer": "Footer",
|
|
94
|
+
"creatives.componentsV2.BeeEditor.header": "Header",
|
|
95
|
+
"creatives.componentsV2.BeeEditor.others": "Others",
|
|
96
|
+
"creatives.componentsV2.BeeEditor.rowName": "Row name",
|
|
97
|
+
"creatives.componentsV2.BeeEditor.rowPlaceHolder": "Enter Row name",
|
|
98
|
+
"creatives.componentsV2.BeeEditor.save": "Save",
|
|
99
|
+
"creatives.componentsV2.BeeEditor.select": "Select",
|
|
100
|
+
"creatives.componentsV2.BeeEditor.selectCategoyPlaceholder": "Select category",
|
|
101
|
+
"creatives.componentsV2.BeeEditor.socialPlatform": "Social platform",
|
|
102
|
+
"creatives.componentsV2.BeeEditor.tagPlaceHolder": "Enter tags",
|
|
103
|
+
"creatives.componentsV2.BeeEditor.tags": "Tags (optional)",
|
|
89
104
|
"creatives.componentsV2.BreadCrumbs.header": "This is the BreadCrumbs component !",
|
|
90
105
|
"creatives.componentsV2.CallTaskPreview.header": "This is the CallTaskPreview component !",
|
|
91
106
|
"creatives.componentsV2.CapTagList.Cancel": "Cancel",
|
|
@@ -1452,8 +1467,10 @@
|
|
|
1452
1467
|
"creatives.containersV2.Templates.creativesTemplatesSave": "Done",
|
|
1453
1468
|
"creatives.containersV2.Templates.deleteButton": "Delete",
|
|
1454
1469
|
"creatives.containersV2.Templates.deletedSuccssfully": "Template deleted successfully",
|
|
1470
|
+
"creatives.containersV2.Templates.deletingTemplate": "Deleting template...",
|
|
1455
1471
|
"creatives.containersV2.Templates.deletionFailed": "Template deletion failed",
|
|
1456
1472
|
"creatives.containersV2.Templates.duplicateButton": "Duplicate",
|
|
1473
|
+
"creatives.containersV2.Templates.duplicatingTemplate": "Duplicating template...",
|
|
1457
1474
|
"creatives.containersV2.Templates.ebillHeader": "Ebill",
|
|
1458
1475
|
"creatives.containersV2.Templates.ebillPreview": "Ebill preview",
|
|
1459
1476
|
"creatives.containersV2.Templates.editButton": "Edit",
|
package/translations/zh.json
CHANGED
|
@@ -86,6 +86,21 @@
|
|
|
86
86
|
"creatives.components.WechatRichmediaTemplatePreview.header": "",
|
|
87
87
|
"creatives.components.WechatRichmediaTemplatePreview.reply": "",
|
|
88
88
|
"creatives.components.WechatRichmediaTemplatePreview.select": "",
|
|
89
|
+
"creatives.componentsV2.BeeEditor.addLabel": "",
|
|
90
|
+
"creatives.componentsV2.BeeEditor.cancel": "",
|
|
91
|
+
"creatives.componentsV2.BeeEditor.cta": "",
|
|
92
|
+
"creatives.componentsV2.BeeEditor.customRows": "",
|
|
93
|
+
"creatives.componentsV2.BeeEditor.footer": "",
|
|
94
|
+
"creatives.componentsV2.BeeEditor.header": "",
|
|
95
|
+
"creatives.componentsV2.BeeEditor.others": "",
|
|
96
|
+
"creatives.componentsV2.BeeEditor.rowName": "",
|
|
97
|
+
"creatives.componentsV2.BeeEditor.rowPlaceHolder": "",
|
|
98
|
+
"creatives.componentsV2.BeeEditor.save": "",
|
|
99
|
+
"creatives.componentsV2.BeeEditor.select": "",
|
|
100
|
+
"creatives.componentsV2.BeeEditor.selectCategoyPlaceholder": "",
|
|
101
|
+
"creatives.componentsV2.BeeEditor.socialPlatform": "",
|
|
102
|
+
"creatives.componentsV2.BeeEditor.tagPlaceHolder": "",
|
|
103
|
+
"creatives.componentsV2.BeeEditor.tags": "",
|
|
89
104
|
"creatives.componentsV2.BreadCrumbs.header": "",
|
|
90
105
|
"creatives.componentsV2.CallTaskPreview.header": "",
|
|
91
106
|
"creatives.componentsV2.CapTagList.Cancel": "",
|
|
@@ -1452,8 +1467,10 @@
|
|
|
1452
1467
|
"creatives.containersV2.Templates.creativesTemplatesSave": "",
|
|
1453
1468
|
"creatives.containersV2.Templates.deleteButton": "",
|
|
1454
1469
|
"creatives.containersV2.Templates.deletedSuccssfully": "",
|
|
1470
|
+
"creatives.containersV2.Templates.deletingTemplate": "",
|
|
1455
1471
|
"creatives.containersV2.Templates.deletionFailed": "",
|
|
1456
1472
|
"creatives.containersV2.Templates.duplicateButton": "",
|
|
1473
|
+
"creatives.containersV2.Templates.duplicatingTemplate": "",
|
|
1457
1474
|
"creatives.containersV2.Templates.ebillHeader": "",
|
|
1458
1475
|
"creatives.containersV2.Templates.ebillPreview": "",
|
|
1459
1476
|
"creatives.containersV2.Templates.editButton": "",
|
|
@@ -21,7 +21,7 @@ import SlideBox from '../SlideBox';
|
|
|
21
21
|
import CardGrid from '../CardGrid';
|
|
22
22
|
import CKEditor from "../Ckeditor/";
|
|
23
23
|
import EDMEditor from "../Edmeditor";
|
|
24
|
-
import BeeEditor from '
|
|
24
|
+
import BeeEditor from '../../v2Containers/BeeEditor';
|
|
25
25
|
import CustomPopOver from '../CustomPopOver';
|
|
26
26
|
import messages from './messages';
|
|
27
27
|
import './_formBuilder.scss';
|
|
@@ -3330,9 +3330,8 @@ class FormBuilder extends React.Component { // eslint-disable-line react/prefer-
|
|
|
3330
3330
|
if (columns.length) {
|
|
3331
3331
|
fields.push(row);
|
|
3332
3332
|
}
|
|
3333
|
-
|
|
3334
3333
|
});
|
|
3335
|
-
if(!this.props.isEmailLoading && this.props.schema.channel.toUpperCase() === 'EMAIL' && !fields.length) {
|
|
3334
|
+
if (!this.props.isEmailLoading && this.props.schema.channel.toUpperCase() === 'EMAIL' && !fields.length) {
|
|
3336
3335
|
return (
|
|
3337
3336
|
<div style={{ textAlign: 'center' }}>
|
|
3338
3337
|
<CapSpin spinning />
|
|
@@ -0,0 +1,5 @@
|
|
|
1
|
+
const prefix = 'APP/V2CONTAINER/BEEEDITOR';
|
|
2
|
+
export const CREATE_CUSTOM_ROW_REQUEST = `${prefix}/CREATE_CUSTOM_ROW_REQUEST`;
|
|
3
|
+
export const CREATE_CUSTOM_ROW_SUCCESS = `${prefix}/CREATE_CUSTOM_ROW_SUCCESS`;
|
|
4
|
+
export const CREATE_CUSTOM_ROW_FAILURE = `${prefix}/CREATE_CUSTOM_ROW_FAILURE`;
|
|
5
|
+
|
|
@@ -0,0 +1,329 @@
|
|
|
1
|
+
/**
|
|
2
|
+
*
|
|
3
|
+
* Beeeditor
|
|
4
|
+
*
|
|
5
|
+
*/
|
|
6
|
+
import React, { useEffect, useState, useRef, useCallback } from 'react';
|
|
7
|
+
import PropTypes from 'prop-types';
|
|
8
|
+
import { injectIntl, intlShape, FormattedMessage } from 'react-intl';
|
|
9
|
+
import { connect } from 'react-redux';
|
|
10
|
+
import TagList from '../TagList';
|
|
11
|
+
import { bindActionCreators } from 'redux';
|
|
12
|
+
import { createStructuredSelector } from 'reselect';
|
|
13
|
+
import makeSelectBEE from './selectors';
|
|
14
|
+
import { UserIsAuthenticated } from '../../utils/authWrapper';
|
|
15
|
+
import config from '../../config/app';
|
|
16
|
+
import { loadItem } from 'services/localStorageApi';
|
|
17
|
+
import './index.scss';
|
|
18
|
+
import {
|
|
19
|
+
CapModal,
|
|
20
|
+
CapButton,
|
|
21
|
+
CapInput,
|
|
22
|
+
CapSelect,
|
|
23
|
+
CapSpin,
|
|
24
|
+
CapNotification,
|
|
25
|
+
}
|
|
26
|
+
from '@capillarytech/cap-ui-library';
|
|
27
|
+
import messages from './messages';
|
|
28
|
+
import * as beeActions from './actions';
|
|
29
|
+
function BeeEditor(props) {
|
|
30
|
+
const {
|
|
31
|
+
uid,
|
|
32
|
+
beeJson,
|
|
33
|
+
tokenData,
|
|
34
|
+
id,
|
|
35
|
+
location = {},
|
|
36
|
+
moduleFilterEnabled,
|
|
37
|
+
label,
|
|
38
|
+
className,
|
|
39
|
+
userLocale,
|
|
40
|
+
selectedOfferDetails,
|
|
41
|
+
tags,
|
|
42
|
+
injectedTags,
|
|
43
|
+
saveBeeInstance,
|
|
44
|
+
saveBeeData,
|
|
45
|
+
intl,
|
|
46
|
+
onContextChange,
|
|
47
|
+
actions,
|
|
48
|
+
BEESelect,
|
|
49
|
+
} = props;
|
|
50
|
+
const { saveRowRequest } = BEESelect;
|
|
51
|
+
const {formatMessage} = intl;
|
|
52
|
+
const UNSUBSCRIBE = 'unsubscribe';
|
|
53
|
+
let beePluginInstance = null;
|
|
54
|
+
const categoryOptions = [{key: 'cta', value: 'cta', label: formatMessage(messages.cta)},
|
|
55
|
+
{key: 'footer', value: 'footer', label: formatMessage(messages.footer)},
|
|
56
|
+
{key: 'header', value: 'header', label: formatMessage(messages.header)},
|
|
57
|
+
{key: 'sp', value: 'sp', label: formatMessage(messages.socialPlatform)},
|
|
58
|
+
{key: 'others', value: 'others', label: formatMessage(messages.others)},
|
|
59
|
+
];
|
|
60
|
+
const [visibleTaglist, setVisibleTaglist] = useState(false);
|
|
61
|
+
const [showRowMetaModal, setRowMetaModal] = useState(false);
|
|
62
|
+
const [selectedTag, setSelectedTag] = useState({});
|
|
63
|
+
const [rowMetaInfo, setRowMetaInfo] = useState({});
|
|
64
|
+
const [rowName, setRowName] = useState('');
|
|
65
|
+
const [rowCategory, setRowCategory] = useState('');
|
|
66
|
+
let API_ENDPOINT = config.development.api_endpoint;
|
|
67
|
+
if (process.env.NODE_ENV === 'production') {
|
|
68
|
+
API_ENDPOINT = `${window.location.origin}${config.production.api_endpoint}`;
|
|
69
|
+
}
|
|
70
|
+
const savedCallback = useRef();
|
|
71
|
+
const filteredTags = (tags || []).filter((obj) => obj.definition.value !== UNSUBSCRIBE);
|
|
72
|
+
let intervalTimer;
|
|
73
|
+
|
|
74
|
+
const DEFAULT_LOCALE = 'en';
|
|
75
|
+
const MAPPED_LOCALE = {
|
|
76
|
+
'en': 'en',
|
|
77
|
+
'zh-cn': 'zh',
|
|
78
|
+
'zh': 'zh',
|
|
79
|
+
};
|
|
80
|
+
const user = localStorage.getItem('user');
|
|
81
|
+
let locale = 'en';
|
|
82
|
+
if (user && JSON.parse(user).lang) {
|
|
83
|
+
locale = JSON.parse(user).lang;
|
|
84
|
+
}
|
|
85
|
+
const defaultFormattedUrl = locale !== DEFAULT_LOCALE && ['zh-cn', 'zh'].includes(locale)
|
|
86
|
+
? `${API_ENDPOINT}/common/getBEECustomLangunage?langid=${MAPPED_LOCALE[locale]}`
|
|
87
|
+
: "";
|
|
88
|
+
useEffect(() => {
|
|
89
|
+
savedCallback.current = Object.keys(selectedTag).length > 0 ? selectedTag : rowMetaInfo;
|
|
90
|
+
}, [selectedTag, rowMetaInfo]);
|
|
91
|
+
|
|
92
|
+
const getExternalContentURLs = () => {
|
|
93
|
+
const externalContentURLs = categoryOptions.map((obj) => ({name: obj.label, value: `${API_ENDPOINT}/common/getCustomRows?category=${obj.value}&orgid=${loadItem('orgID')}`}));
|
|
94
|
+
return externalContentURLs;
|
|
95
|
+
};
|
|
96
|
+
useEffect(() => {
|
|
97
|
+
const beeConfig = {
|
|
98
|
+
uid,
|
|
99
|
+
container: 'bee-plugin-container',
|
|
100
|
+
translationsUrl: defaultFormattedUrl,
|
|
101
|
+
rowsConfiguration: {
|
|
102
|
+
emptyRows: true,
|
|
103
|
+
defaultRows: true,
|
|
104
|
+
externalContentURLs: getExternalContentURLs(),
|
|
105
|
+
},
|
|
106
|
+
contentDialog: {
|
|
107
|
+
specialLinks: {
|
|
108
|
+
label: UNSUBSCRIBE,
|
|
109
|
+
handler(resolve) {
|
|
110
|
+
resolve({
|
|
111
|
+
type: 'custom',
|
|
112
|
+
label: UNSUBSCRIBE,
|
|
113
|
+
link: `{{${UNSUBSCRIBE}}}`,
|
|
114
|
+
});
|
|
115
|
+
},
|
|
116
|
+
},
|
|
117
|
+
mergeTags: {
|
|
118
|
+
label: formatMessage(messages.addLabel),
|
|
119
|
+
handler: async (resolve, reject) => {
|
|
120
|
+
// this will open tag modal
|
|
121
|
+
await setVisibleTaglist(true);
|
|
122
|
+
// until tag modal will not open promise will not execute
|
|
123
|
+
// once tag modal is opened it will start 2 sec interval to wait use has selected any tag or cancel the tag selection
|
|
124
|
+
const promise = new Promise((resolveP) => {
|
|
125
|
+
intervalTimer = setInterval(() => {
|
|
126
|
+
// this will execute, if user cancel the tag selection
|
|
127
|
+
if ((savedCallback.current || {}).close === true) {
|
|
128
|
+
reject();
|
|
129
|
+
clearInterval(intervalTimer);
|
|
130
|
+
return;
|
|
131
|
+
}
|
|
132
|
+
// this block is checking use has selected any tag or not
|
|
133
|
+
if (Object.keys(savedCallback.current || {}).length > 0) {
|
|
134
|
+
resolveP(savedCallback.current);
|
|
135
|
+
setSelectedTag({});
|
|
136
|
+
clearInterval(intervalTimer);
|
|
137
|
+
}
|
|
138
|
+
}, 2000);
|
|
139
|
+
});
|
|
140
|
+
// once prmise will resolve , pass the resolve data to handler to show tags in bee edior
|
|
141
|
+
const result = await promise;
|
|
142
|
+
resolve(result);
|
|
143
|
+
},
|
|
144
|
+
},
|
|
145
|
+
saveRow: {
|
|
146
|
+
handler: async (resolve, reject) => {
|
|
147
|
+
await setRowMetaModal(true);
|
|
148
|
+
const promise = new Promise((resolveP) => {
|
|
149
|
+
intervalTimer = setInterval(() => {
|
|
150
|
+
if ((savedCallback.current || {}).close === true) {
|
|
151
|
+
reject();
|
|
152
|
+
clearInterval(intervalTimer);
|
|
153
|
+
setRowMetaInfo({});
|
|
154
|
+
setRowName('');
|
|
155
|
+
setRowCategory('');
|
|
156
|
+
return;
|
|
157
|
+
}
|
|
158
|
+
if (Object.keys(savedCallback.current || {}).length > 0) {
|
|
159
|
+
resolveP(savedCallback.current);
|
|
160
|
+
}
|
|
161
|
+
}, 2000);
|
|
162
|
+
});
|
|
163
|
+
const result = await promise;
|
|
164
|
+
resolve(result); // "done!"
|
|
165
|
+
setRowMetaInfo({});
|
|
166
|
+
setRowName('');
|
|
167
|
+
setRowCategory('');
|
|
168
|
+
clearInterval(intervalTimer);
|
|
169
|
+
},
|
|
170
|
+
},
|
|
171
|
+
},
|
|
172
|
+
onSave: (jsonFile, htmlFile) => {
|
|
173
|
+
saveBeeData(jsonFile, htmlFile);
|
|
174
|
+
},
|
|
175
|
+
onSaveRow: (rowJSON) => {
|
|
176
|
+
actions.createCustomRow(JSON.parse(rowJSON), callbackSaveRow);
|
|
177
|
+
},
|
|
178
|
+
};
|
|
179
|
+
window.BeePlugin.create(tokenData, beeConfig, (instance) => {
|
|
180
|
+
beePluginInstance = instance;
|
|
181
|
+
const parseJson = JSON.parse(beeJson);
|
|
182
|
+
beePluginInstance.start(parseJson);
|
|
183
|
+
saveBeeInstance(beePluginInstance);
|
|
184
|
+
});
|
|
185
|
+
return () => clearInterval(intervalTimer);
|
|
186
|
+
}, []);
|
|
187
|
+
const callbackSaveRow = (status, errorMsg) => {
|
|
188
|
+
if (status === 'success') {
|
|
189
|
+
CapNotification.success({message: formatMessage(messages.rowCreationSuccessMgs), key: 'create-custom-row-success'});
|
|
190
|
+
} else {
|
|
191
|
+
CapNotification.error({message: errorMsg || formatMessage(messages.rowCreationFailureMgs), key: 'create-custom-row-failure'});
|
|
192
|
+
}
|
|
193
|
+
};
|
|
194
|
+
|
|
195
|
+
const onTagSelect = (result) => {
|
|
196
|
+
const msg = {
|
|
197
|
+
name: result,
|
|
198
|
+
value: `{{${result}}}`,
|
|
199
|
+
};
|
|
200
|
+
setSelectedTag(msg);
|
|
201
|
+
setVisibleTaglist(false);
|
|
202
|
+
};
|
|
203
|
+
|
|
204
|
+
const onCancelTagList = () => {
|
|
205
|
+
setVisibleTaglist(false);
|
|
206
|
+
setSelectedTag({close: true});
|
|
207
|
+
};
|
|
208
|
+
|
|
209
|
+
const onCustomRowCancel = () => {
|
|
210
|
+
setRowMetaModal(false);
|
|
211
|
+
setRowCategory('');
|
|
212
|
+
setRowName('');
|
|
213
|
+
setRowMetaInfo({close: true});
|
|
214
|
+
};
|
|
215
|
+
|
|
216
|
+
const onCustomRowSave = () => {
|
|
217
|
+
const rowInfo = {};
|
|
218
|
+
if (rowCategory !== '') {
|
|
219
|
+
rowInfo.category = rowCategory;
|
|
220
|
+
}
|
|
221
|
+
setRowMetaInfo({
|
|
222
|
+
name: rowName,
|
|
223
|
+
...rowInfo,
|
|
224
|
+
});
|
|
225
|
+
setRowMetaModal(false);
|
|
226
|
+
setRowCategory('');
|
|
227
|
+
setRowName('');
|
|
228
|
+
};
|
|
229
|
+
|
|
230
|
+
const isDisableSave = () => rowName === '' || rowCategory === '';
|
|
231
|
+
|
|
232
|
+
const onRowChange = useCallback((e) => {
|
|
233
|
+
setRowName(e.target.value);
|
|
234
|
+
});
|
|
235
|
+
const onChangeCategoy = (e) => {
|
|
236
|
+
setRowCategory(e);
|
|
237
|
+
};
|
|
238
|
+
const contentSection = <>
|
|
239
|
+
<CapInput
|
|
240
|
+
label={<FormattedMessage {...messages.rowName} />}
|
|
241
|
+
placeholder={formatMessage(messages.rowPlaceHolder)}
|
|
242
|
+
onChange={onRowChange}
|
|
243
|
+
value={rowName}
|
|
244
|
+
maxLength={50}
|
|
245
|
+
style={{ width: 324, paddingBottom: 21 }}
|
|
246
|
+
/>
|
|
247
|
+
<CapSelect
|
|
248
|
+
label="Category"
|
|
249
|
+
style={{ width: 324, paddingBottom: 24}}
|
|
250
|
+
options={categoryOptions}
|
|
251
|
+
value={rowCategory || undefined}
|
|
252
|
+
placeholder={<FormattedMessage {...messages.selectCategoyPlaceholder} />}
|
|
253
|
+
onChange={onChangeCategoy}
|
|
254
|
+
/>
|
|
255
|
+
|
|
256
|
+
</>;
|
|
257
|
+
return (
|
|
258
|
+
<CapSpin spinning={saveRowRequest || false}>
|
|
259
|
+
<div id="bee-plugin-container" style={{ height: '500px'}}>
|
|
260
|
+
</div>
|
|
261
|
+
<TagList
|
|
262
|
+
moduleFilterEnabled={moduleFilterEnabled}
|
|
263
|
+
label={label}
|
|
264
|
+
onTagSelect={onTagSelect}
|
|
265
|
+
location={location}
|
|
266
|
+
tags={filteredTags}
|
|
267
|
+
injectedTags={injectedTags}
|
|
268
|
+
className={className}
|
|
269
|
+
id={id}
|
|
270
|
+
userLocale={userLocale}
|
|
271
|
+
selectedOfferDetails={selectedOfferDetails}
|
|
272
|
+
visibleTaglist={visibleTaglist}
|
|
273
|
+
hidePopover
|
|
274
|
+
modalProps={{
|
|
275
|
+
onCancel: onCancelTagList,
|
|
276
|
+
style: { left: 135, top: 250 },
|
|
277
|
+
className: "bee-editor-tag-list",
|
|
278
|
+
}}
|
|
279
|
+
onContextChange={onContextChange}
|
|
280
|
+
/>
|
|
281
|
+
<CapModal
|
|
282
|
+
className="custom-row-modal"
|
|
283
|
+
visible={showRowMetaModal}
|
|
284
|
+
onCancel={onCustomRowCancel}
|
|
285
|
+
title={formatMessage(messages.customRows)}
|
|
286
|
+
style={{width: 372, height: 296, left: 135, top: 300}}
|
|
287
|
+
footer={[
|
|
288
|
+
<CapButton key="submit" type="primary" id="delete-version" onClick={onCustomRowSave} disabled={isDisableSave()}>
|
|
289
|
+
{formatMessage(messages.done)}
|
|
290
|
+
</CapButton>,
|
|
291
|
+
]}
|
|
292
|
+
>
|
|
293
|
+
{contentSection}
|
|
294
|
+
</CapModal>
|
|
295
|
+
</CapSpin>
|
|
296
|
+
);
|
|
297
|
+
}
|
|
298
|
+
|
|
299
|
+
BeeEditor.propTypes = {
|
|
300
|
+
beeJson: PropTypes.object.isRequired,
|
|
301
|
+
tokenData: PropTypes.object.isRequired,
|
|
302
|
+
uid: PropTypes.string.isRequired,
|
|
303
|
+
intl: intlShape.isRequired,
|
|
304
|
+
actions: PropTypes.object.isRequired,
|
|
305
|
+
BEESelect: PropTypes.object,
|
|
306
|
+
id: PropTypes.string,
|
|
307
|
+
location: PropTypes.object,
|
|
308
|
+
moduleFilterEnabled: PropTypes.bool,
|
|
309
|
+
label: PropTypes.string,
|
|
310
|
+
className: PropTypes.string,
|
|
311
|
+
tags: PropTypes.array,
|
|
312
|
+
saveBeeData: PropTypes.func,
|
|
313
|
+
saveBeeInstance: PropTypes.func,
|
|
314
|
+
injectedTags: PropTypes.object,
|
|
315
|
+
onContextChange: PropTypes.func,
|
|
316
|
+
userLocale: PropTypes.string,
|
|
317
|
+
};
|
|
318
|
+
|
|
319
|
+
const mapStateToProps = () => createStructuredSelector({
|
|
320
|
+
BEESelect: makeSelectBEE(),
|
|
321
|
+
});
|
|
322
|
+
|
|
323
|
+
function mapDispatchToProps(dispatch) {
|
|
324
|
+
return {
|
|
325
|
+
actions: bindActionCreators(beeActions, dispatch),
|
|
326
|
+
};
|
|
327
|
+
}
|
|
328
|
+
|
|
329
|
+
export default UserIsAuthenticated(connect(mapStateToProps, mapDispatchToProps)(injectIntl(BeeEditor)));
|
|
@@ -0,0 +1,67 @@
|
|
|
1
|
+
/*
|
|
2
|
+
* BeeEditor Messages
|
|
3
|
+
*
|
|
4
|
+
* This contains all the text for the BeeEditor component.
|
|
5
|
+
*/
|
|
6
|
+
import { defineMessages } from 'react-intl';
|
|
7
|
+
|
|
8
|
+
const prefix = 'creatives.containersV2.BeeEditor';
|
|
9
|
+
|
|
10
|
+
export default defineMessages({
|
|
11
|
+
done: {
|
|
12
|
+
id: `${prefix}.done`,
|
|
13
|
+
defaultMessage: 'Done',
|
|
14
|
+
},
|
|
15
|
+
rowPlaceHolder: {
|
|
16
|
+
id: `${prefix}.rowPlaceHolder`,
|
|
17
|
+
defaultMessage: 'Enter Row name',
|
|
18
|
+
},
|
|
19
|
+
rowName: {
|
|
20
|
+
id: `${prefix}.rowName`,
|
|
21
|
+
defaultMessage: 'Row name',
|
|
22
|
+
},
|
|
23
|
+
select: {
|
|
24
|
+
id: `${prefix}.select`,
|
|
25
|
+
defaultMessage: 'Select',
|
|
26
|
+
},
|
|
27
|
+
customRows: {
|
|
28
|
+
id: `${prefix}.customRows`,
|
|
29
|
+
defaultMessage: 'Create new row',
|
|
30
|
+
},
|
|
31
|
+
selectCategoyPlaceholder: {
|
|
32
|
+
id: `${prefix}.selectCategoyPlaceholder`,
|
|
33
|
+
defaultMessage: 'Select category',
|
|
34
|
+
},
|
|
35
|
+
addLabel: {
|
|
36
|
+
id: `${prefix}.addLabel`,
|
|
37
|
+
defaultMessage: 'Add label',
|
|
38
|
+
},
|
|
39
|
+
cta: {
|
|
40
|
+
id: `${prefix}.cta`,
|
|
41
|
+
defaultMessage: 'CTA',
|
|
42
|
+
},
|
|
43
|
+
header: {
|
|
44
|
+
id: `${prefix}.header`,
|
|
45
|
+
defaultMessage: 'Header',
|
|
46
|
+
},
|
|
47
|
+
footer: {
|
|
48
|
+
id: `${prefix}.footer`,
|
|
49
|
+
defaultMessage: 'Footer',
|
|
50
|
+
},
|
|
51
|
+
others: {
|
|
52
|
+
id: `${prefix}.others`,
|
|
53
|
+
defaultMessage: 'Others',
|
|
54
|
+
},
|
|
55
|
+
socialPlatform: {
|
|
56
|
+
id: `${prefix}.socialPlatform`,
|
|
57
|
+
defaultMessage: 'Social platform',
|
|
58
|
+
},
|
|
59
|
+
rowCreationSuccessMgs: {
|
|
60
|
+
id: `${prefix}.rowCreationSuccessMgs`,
|
|
61
|
+
defaultMessage: 'Row created successfully',
|
|
62
|
+
},
|
|
63
|
+
rowCreationFailureMgs: {
|
|
64
|
+
id: `${prefix}.rowCreationFailureMgs`,
|
|
65
|
+
defaultMessage: 'Error in row creation',
|
|
66
|
+
},
|
|
67
|
+
});
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
import { fromJS } from 'immutable';
|
|
2
|
+
import {
|
|
3
|
+
CREATE_CUSTOM_ROW_REQUEST,
|
|
4
|
+
CREATE_CUSTOM_ROW_SUCCESS,
|
|
5
|
+
CREATE_CUSTOM_ROW_FAILURE,
|
|
6
|
+
} from './constants';
|
|
7
|
+
|
|
8
|
+
const initialState = fromJS({
|
|
9
|
+
saveRowRequest: false,
|
|
10
|
+
});
|
|
11
|
+
|
|
12
|
+
function beeEditorReducer(state = initialState, action) {
|
|
13
|
+
switch (action.type) {
|
|
14
|
+
case CREATE_CUSTOM_ROW_REQUEST:
|
|
15
|
+
return state.set('saveRowRequest', true);
|
|
16
|
+
case CREATE_CUSTOM_ROW_SUCCESS:
|
|
17
|
+
return state.set('saveRowRequest', false);
|
|
18
|
+
case CREATE_CUSTOM_ROW_FAILURE:
|
|
19
|
+
return state.set('saveRowRequest', false);
|
|
20
|
+
default:
|
|
21
|
+
return state;
|
|
22
|
+
}
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
export default beeEditorReducer;
|
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
import { take, cancel, call, put, takeLatest } from 'redux-saga/effects';
|
|
2
|
+
import { LOCATION_CHANGE } from 'react-router-redux';
|
|
3
|
+
import * as Api from '../../services/api';
|
|
4
|
+
import * as types from './constants';
|
|
5
|
+
|
|
6
|
+
export function* createCustomRow({data, callback}) {
|
|
7
|
+
let errorMsg;
|
|
8
|
+
try {
|
|
9
|
+
const result = yield call(Api.createCustomRow, data);
|
|
10
|
+
const code = result.status ? result.status.code : '';
|
|
11
|
+
if (!result.success || code === 500) {
|
|
12
|
+
errorMsg = result.message;
|
|
13
|
+
yield put({ type: types.CREATE_CUSTOM_ROW_FAILURE, errorMsg });
|
|
14
|
+
callback('failed', code !== 500 ? errorMsg : '');
|
|
15
|
+
} else {
|
|
16
|
+
yield put({ type: types.CREATE_CUSTOM_ROW_SUCCESS, data: result.response, statusCode: code, errorMsg });
|
|
17
|
+
callback('success');
|
|
18
|
+
}
|
|
19
|
+
} catch (error) {
|
|
20
|
+
yield put({ type: types.CREATE_CUSTOM_ROW_FAILURE, error, errorMsg });
|
|
21
|
+
}
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
function* watchCreateCustomRow() {
|
|
25
|
+
const watcher = yield takeLatest(types.CREATE_CUSTOM_ROW_REQUEST, createCustomRow);
|
|
26
|
+
yield take(LOCATION_CHANGE);
|
|
27
|
+
yield cancel(watcher);
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
// All sagas to be loaded
|
|
31
|
+
export default [
|
|
32
|
+
watchCreateCustomRow,
|
|
33
|
+
];
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
import { createSelector } from 'reselect';
|
|
2
|
+
import { fromJS } from 'immutable';
|
|
3
|
+
/**
|
|
4
|
+
* Direct selector to the email state domain
|
|
5
|
+
*/
|
|
6
|
+
const selectBEEDomain = () => (state) => state.get('beeEditor');
|
|
7
|
+
|
|
8
|
+
/**
|
|
9
|
+
* Default selector used by beeEditor
|
|
10
|
+
*/
|
|
11
|
+
|
|
12
|
+
const makeSelectBEE = () => createSelector(
|
|
13
|
+
selectBEEDomain(),
|
|
14
|
+
(substate = fromJS({})) => substate.toJS()
|
|
15
|
+
);
|
|
16
|
+
|
|
17
|
+
export default makeSelectBEE;
|
|
@@ -318,10 +318,10 @@ class Creatives extends React.Component {
|
|
|
318
318
|
if (template.value) {
|
|
319
319
|
const { versions } = template.value;
|
|
320
320
|
const { Templates, templateData: templateDataProps } = this.props;
|
|
321
|
-
const { accountDetails: selectedAccountDetails } = templateDataProps || {};
|
|
321
|
+
const { accountDetails: selectedAccountDetails, accountId: selectedAccountId } = templateDataProps || {};
|
|
322
322
|
const selectedLineAccount = Templates && Templates.selectedLineAccount;
|
|
323
|
-
const accountDetails = !!selectedLineAccount ? JSON.stringify(selectedLineAccount) :
|
|
324
|
-
const accountId = !!selectedLineAccount ? selectedLineAccount.id : '';
|
|
323
|
+
const accountDetails = selectedAccountDetails || (!!selectedLineAccount ? JSON.stringify(selectedLineAccount) : '');
|
|
324
|
+
const accountId = selectedAccountId || (!!selectedLineAccount ? selectedLineAccount.id : '');
|
|
325
325
|
templateData = {
|
|
326
326
|
channel,
|
|
327
327
|
accountId,
|
|
@@ -696,10 +696,10 @@ export class Email extends React.Component { // eslint-disable-line react/prefer
|
|
|
696
696
|
getValidationData = () => {
|
|
697
697
|
const that = this;
|
|
698
698
|
let id = _.get(this.props, 'Email.templateDetails._id', '') || _.get(this.props, 'Templates.BEETemplate._id', '');
|
|
699
|
+
const formData = _.cloneDeep(this.state.formData);
|
|
699
700
|
if (!id) {
|
|
700
701
|
id = _.get(formData, `base[${formData.base.activeTab}].id`, '');
|
|
701
702
|
}
|
|
702
|
-
const formData = _.cloneDeep(this.state.formData);
|
|
703
703
|
if (!this.props.Email.fetchingCmsData) {
|
|
704
704
|
// checking wheather getCmsData in progress or not cuz getValidationData gets called multiple times from handleEdmSave
|
|
705
705
|
_.forEach(formData, (val, index) => {
|