@capillarytech/creatives-library 2.0.47 → 2.0.49
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/components/FormBuilder/index.js +2 -1
- package/containers/CreativesContainer/SlideBoxContent.js +7 -1
- package/containers/CreativesContainer/index.js +26 -11
- package/containers/Email/index.js +8 -0
- package/containers/EmailWrapper/index.js +74 -72
- package/containers/EmailWrapper/messages.js +4 -0
- package/containers/Sms/Create/index.js +8 -0
- package/containers/Sms/Edit/index.js +8 -0
- package/package.json +1 -1
- package/components/EmailMobilePreview/index.js +0 -108
- package/components/EmailMobilePreview/index.scss +0 -66
- package/containers/TemplatesV2/reducer.js +0 -34
- package/containers/TemplatesV2/sagas.js +0 -32
|
@@ -98,6 +98,7 @@ class FormBuilder extends React.Component { // eslint-disable-line react/prefer-
|
|
|
98
98
|
|
|
99
99
|
componentWillReceiveProps(nextProps) {
|
|
100
100
|
const type = this.props.location.query.type;
|
|
101
|
+
const isLibraryModule = this.props.location.query.module === "library";
|
|
101
102
|
if (this.state.usingTabContainer && nextProps.tabCount !== this.props.tabCount) {
|
|
102
103
|
this.setState({tabCount: nextProps.tabCount});
|
|
103
104
|
}
|
|
@@ -116,7 +117,7 @@ class FormBuilder extends React.Component { // eslint-disable-line react/prefer-
|
|
|
116
117
|
// }
|
|
117
118
|
if (nextProps.isEdit) {
|
|
118
119
|
if (!_.isEqual(nextProps.formData, this.state.formData) && !_.isEmpty(nextProps.formData)) {
|
|
119
|
-
if (type === 'embedded') { //TODO: has to be checked and changed.
|
|
120
|
+
if (type === 'embedded' && !isLibraryModule) { //TODO: has to be checked and changed.
|
|
120
121
|
this.setState({checkValidation: true, formData: nextProps.formData}, () => {
|
|
121
122
|
this.validateForm();
|
|
122
123
|
});
|
|
@@ -36,9 +36,10 @@ function SlideBoxContent(props) {
|
|
|
36
36
|
cap,
|
|
37
37
|
onResetStep,
|
|
38
38
|
isFullMode,
|
|
39
|
+
setIsLoadingContent,
|
|
39
40
|
} = props;
|
|
40
41
|
const type = messageDetails.type.toLowerCase(); // type is context in get tags values : outbound | dvs | referral | loyalty | coupons
|
|
41
|
-
const query = { type: !isFullMode && 'embedded', module: isFullMode ? 'defualt' : 'library'};
|
|
42
|
+
const query = { type: !isFullMode && 'embedded', module: isFullMode ? 'defualt' : 'library', isLanguageSupport: true};
|
|
42
43
|
const creativesLocationProps = {
|
|
43
44
|
pathname: `/sms/edit`,
|
|
44
45
|
query,
|
|
@@ -91,6 +92,7 @@ function SlideBoxContent(props) {
|
|
|
91
92
|
}
|
|
92
93
|
{isEditSms && (
|
|
93
94
|
<SmsEdit
|
|
95
|
+
setIsLoadingContent={setIsLoadingContent}
|
|
94
96
|
location={creativesLocationProps}
|
|
95
97
|
isFullMode={isFullMode}
|
|
96
98
|
route={{ name: 'sms' }}
|
|
@@ -103,6 +105,7 @@ function SlideBoxContent(props) {
|
|
|
103
105
|
)}
|
|
104
106
|
{isCreateSms && (
|
|
105
107
|
<SmsCreate
|
|
108
|
+
setIsLoadingContent={setIsLoadingContent}
|
|
106
109
|
location={creativesLocationProps}
|
|
107
110
|
route={{ name: 'sms' }}
|
|
108
111
|
isComponent
|
|
@@ -114,6 +117,7 @@ function SlideBoxContent(props) {
|
|
|
114
117
|
)}
|
|
115
118
|
{isEmailCreate && (
|
|
116
119
|
<EmailWrapper
|
|
120
|
+
setIsLoadingContent={setIsLoadingContent}
|
|
117
121
|
onEmailModeChange={onEmailModeChange}
|
|
118
122
|
emailCreateMode={emailCreateMode}
|
|
119
123
|
isGetFormData={isGetFormData}
|
|
@@ -129,6 +133,7 @@ function SlideBoxContent(props) {
|
|
|
129
133
|
)}
|
|
130
134
|
{(isEditEmailWithId || isEmailEditWithContent) && (
|
|
131
135
|
<Email
|
|
136
|
+
setIsLoadingContent={setIsLoadingContent}
|
|
132
137
|
location={{
|
|
133
138
|
pathname: `/email`,
|
|
134
139
|
query,
|
|
@@ -166,5 +171,6 @@ SlideBoxContent.propTypes = {
|
|
|
166
171
|
cap: PropTypes.object,
|
|
167
172
|
onResetStep: PropTypes.func,
|
|
168
173
|
isFullMode: PropTypes.bool,
|
|
174
|
+
setIsLoadingContent: PropTypes.func,
|
|
169
175
|
};
|
|
170
176
|
export default SlideBoxContent;
|
|
@@ -27,6 +27,7 @@ class Creatives extends React.Component {
|
|
|
27
27
|
constructor(props) {
|
|
28
28
|
super(props);
|
|
29
29
|
this.state = {
|
|
30
|
+
isLoadingContent: true,
|
|
30
31
|
templateStep: 1, //modeSelection: for template name and (for email selecting upload or editor), and createTemplate to create template create based on modeSelection
|
|
31
32
|
showSlideBox: true,
|
|
32
33
|
slidBoxContent: this.getSlideBocContent({mode: props.creativesMode, templateData: props.templateData, isFullMode: props.isFullMode}),
|
|
@@ -152,16 +153,20 @@ class Creatives extends React.Component {
|
|
|
152
153
|
);
|
|
153
154
|
}
|
|
154
155
|
};
|
|
156
|
+
setIsLoadingContent = (isLoadingContent) => {
|
|
157
|
+
if (this.state.isLoadingContent !== isLoadingContent) {
|
|
158
|
+
this.setState({isLoadingContent });
|
|
159
|
+
}
|
|
160
|
+
}
|
|
155
161
|
resetStep = () => {
|
|
156
|
-
this.setState(prevState => {
|
|
162
|
+
this.setState((prevState) => {
|
|
157
163
|
let newState = {
|
|
158
164
|
templateStep: 1,
|
|
159
|
-
}
|
|
160
|
-
|
|
165
|
+
};
|
|
161
166
|
if (prevState.currentChannel.toUpperCase() === constants.EMAIL) {
|
|
162
|
-
newState= { ...newState, emailCreateMode: null };
|
|
167
|
+
newState = { ...newState, emailCreateMode: null };
|
|
163
168
|
}
|
|
164
|
-
return newState;
|
|
169
|
+
return newState;
|
|
165
170
|
});
|
|
166
171
|
}
|
|
167
172
|
handleCloseSlideBox = () => {
|
|
@@ -177,18 +182,27 @@ class Creatives extends React.Component {
|
|
|
177
182
|
shouldShowFooter = () => {
|
|
178
183
|
const {isFullMode} = this.props;
|
|
179
184
|
const {slidBoxContent, currentChannel, emailCreateMode, templateStep} = this.state;
|
|
185
|
+
const channel = currentChannel.toUpperCase();
|
|
186
|
+
const currentStep = this.creativesTemplateSteps[templateStep];
|
|
180
187
|
let showFooter = false;
|
|
181
188
|
if (!isFullMode ) {
|
|
182
|
-
const isEmailCreate = slidBoxContent === 'createTemplate' &&
|
|
189
|
+
const isEmailCreate = slidBoxContent === 'createTemplate' && channel === constants.EMAIL && currentStep !== 'createTemplateContent';
|
|
183
190
|
const isCreate = (slidBoxContent === 'editTemplate' || slidBoxContent === 'createTemplate') && !isEmailCreate;
|
|
184
191
|
showFooter = (isCreate || (isEmailCreate && emailCreateMode) || slidBoxContent === 'preview');
|
|
185
|
-
} else if (
|
|
186
|
-
const isEmailCreate = slidBoxContent === 'createTemplate' &&
|
|
192
|
+
} else if (channel === constants.EMAIL && isFullMode) {
|
|
193
|
+
const isEmailCreate = slidBoxContent === 'createTemplate' && channel === constants.EMAIL && currentStep !== 'createTemplateContent';
|
|
187
194
|
showFooter = isEmailCreate && emailCreateMode;
|
|
188
195
|
}
|
|
189
|
-
if (
|
|
196
|
+
if (channel === constants.EMAIL && emailCreateMode === "upload") {
|
|
190
197
|
showFooter = showFooter && !this.props.isUploading;
|
|
191
198
|
}
|
|
199
|
+
if (showFooter) {
|
|
200
|
+
if (slidBoxContent === "createTemplate" && ((channel === constants.EMAIL && currentStep === 'createTemplateContent') || (channel === constants.SMS && currentStep === 'modeSelection'))) {
|
|
201
|
+
showFooter = showFooter && !this.state.isLoadingContent;
|
|
202
|
+
} else if (slidBoxContent === "editTemplate" && ((channel === constants.EMAIL && currentStep === 'modeSelection') || (channel === constants.SMS && currentStep === 'modeSelection'))) {
|
|
203
|
+
showFooter = showFooter && !this.state.isLoadingContent;
|
|
204
|
+
}
|
|
205
|
+
}
|
|
192
206
|
return showFooter;
|
|
193
207
|
}
|
|
194
208
|
shouldShowDoneFooter = () => {
|
|
@@ -198,10 +212,10 @@ class Creatives extends React.Component {
|
|
|
198
212
|
const isCreate = (slidBoxContent === 'editTemplate' || slidBoxContent === 'createTemplate') && !isEmailCreate;
|
|
199
213
|
return isCreate;
|
|
200
214
|
}
|
|
201
|
-
shouldShowContinueFooter = () => { // only for email for now, has to be modified according to channel
|
|
215
|
+
shouldShowContinueFooter = () => { // only for email for now, has to be modified according to channel
|
|
202
216
|
const {slidBoxContent, templateStep, currentChannel, emailCreateMode} = this.state;
|
|
203
217
|
let isShowContinueFooter = false;
|
|
204
|
-
if (this.props.EmailLayout
|
|
218
|
+
if ((emailCreateMode === "upload" && !isEmpty(this.props.EmailLayout)) || emailCreateMode === "editor") {
|
|
205
219
|
const currentStep = this.creativesTemplateSteps[templateStep];
|
|
206
220
|
let isEmailCreate = slidBoxContent === 'createTemplate';
|
|
207
221
|
isEmailCreate = currentChannel.toUpperCase() === constants.EMAIL && ((emailCreateMode === "upload" && currentStep !== 'createTemplateContent') || ( emailCreateMode === "editor" && currentStep !== 'createTemplateContent' && currentStep !== "templateSelection"));
|
|
@@ -245,6 +259,7 @@ class Creatives extends React.Component {
|
|
|
245
259
|
onEmailNextStep={this.onEmailNextStep}
|
|
246
260
|
onResetStep={this.resetStep}
|
|
247
261
|
cap={cap}
|
|
262
|
+
setIsLoadingContent={this.setIsLoadingContent}
|
|
248
263
|
/>
|
|
249
264
|
}
|
|
250
265
|
footer={this.shouldShowFooter() &&
|
|
@@ -504,6 +504,9 @@ export class Email extends React.Component { // eslint-disable-line react/prefer
|
|
|
504
504
|
}
|
|
505
505
|
|
|
506
506
|
componentWillUnmount() {
|
|
507
|
+
if (this.props.setIsLoadingContent) {
|
|
508
|
+
this.props.setIsLoadingContent(true); // setting isLoading of CreativesContainer so that slidebox foot can be hidden till content is loaded
|
|
509
|
+
}
|
|
507
510
|
this.resetStateValue();
|
|
508
511
|
window.removeEventListener("message", this.handleFrameTasks);
|
|
509
512
|
this.props.actions.clearStoreValues();
|
|
@@ -2448,6 +2451,9 @@ export class Email extends React.Component { // eslint-disable-line react/prefer
|
|
|
2448
2451
|
// if (isLoading) {
|
|
2449
2452
|
// this.props.creativesContainerActions.hideCreativesContanerLoader();
|
|
2450
2453
|
// }
|
|
2454
|
+
if (!isLoading && this.props.setIsLoadingContent) {
|
|
2455
|
+
this.props.setIsLoadingContent(isLoading);
|
|
2456
|
+
}
|
|
2451
2457
|
return isLoading;
|
|
2452
2458
|
}
|
|
2453
2459
|
renderConfirmationModal() {
|
|
@@ -2556,6 +2562,7 @@ export class Email extends React.Component { // eslint-disable-line react/prefer
|
|
|
2556
2562
|
<Col>
|
|
2557
2563
|
{ !_.isEmpty(schema) && (this.state.formData[0] || this.state.formData["0"]) ?
|
|
2558
2564
|
<FormBuilder
|
|
2565
|
+
isFullMode={this.props.isFullMode}
|
|
2559
2566
|
schema={schema}
|
|
2560
2567
|
onSubmit={this.saveFormData}
|
|
2561
2568
|
onChange={this.onFormDataChange}
|
|
@@ -2639,6 +2646,7 @@ Email.propTypes = {
|
|
|
2639
2646
|
isLoadingMetaEntities: PropTypes.bool,
|
|
2640
2647
|
// creativesContainerActions: PropTypes.object,
|
|
2641
2648
|
isFullMode: PropTypes.bool,
|
|
2649
|
+
setIsLoadingContent: PropTypes.func,
|
|
2642
2650
|
};
|
|
2643
2651
|
|
|
2644
2652
|
const mapStateToProps = (state, props) => createStructuredSelector({
|
|
@@ -10,9 +10,9 @@ import { FormattedMessage, injectIntl, intlShape } from 'react-intl';
|
|
|
10
10
|
import { createStructuredSelector } from 'reselect';
|
|
11
11
|
import { bindActionCreators } from 'redux';
|
|
12
12
|
import _ from 'lodash';
|
|
13
|
-
import { CapRadioCard, CapHeader, CapNotification, CapInput} from '@capillarytech/cap-ui-library';
|
|
13
|
+
import { CapRadioCard, CapHeader, CapNotification, CapInput, CapUploader, CapSpin, CapButton} from '@capillarytech/cap-ui-library';
|
|
14
14
|
import { UserIsAuthenticated } from '../../utils/authWrapper';
|
|
15
|
-
import {selectEmailLayout, selectCmsTemplates, selectEdmEditor} from '../Templates/selectors';
|
|
15
|
+
import {selectEmailLayout, selectCmsTemplates, selectEdmEditor, uploadSelector} from '../Templates/selectors';
|
|
16
16
|
import * as templatesActionsCreators from '../Templates/actions';
|
|
17
17
|
import Email from '../Email';
|
|
18
18
|
import CmsTemplatesComponent from '../../components/CmsTemplatesComponent';
|
|
@@ -38,9 +38,9 @@ export class EmailWrapper extends React.Component { // eslint-disable-line react
|
|
|
38
38
|
title: <FormattedMessage {...messages.zipUpload}/>,
|
|
39
39
|
content: <FormattedMessage {...messages.zipUploadDesc}/>,
|
|
40
40
|
value: 'upload',
|
|
41
|
-
onClick: () => {
|
|
42
|
-
|
|
43
|
-
},
|
|
41
|
+
// onClick: () => {
|
|
42
|
+
// this.emailUploader.current.click();
|
|
43
|
+
// },
|
|
44
44
|
},
|
|
45
45
|
{
|
|
46
46
|
title: <FormattedMessage {...messages.useEditor}/>,
|
|
@@ -63,8 +63,6 @@ export class EmailWrapper extends React.Component { // eslint-disable-line react
|
|
|
63
63
|
} else if (step === "createTemplateContent" && !this.state.selectedCreateMode) {
|
|
64
64
|
if (emailCreateMode === 'upload' && !_.isEmpty(EmailLayout)) {
|
|
65
65
|
this.setCreateMode('upload');
|
|
66
|
-
|
|
67
|
-
//this.handleFileUpload(modeContent.e, modeContent.files);
|
|
68
66
|
} else if (emailCreateMode === "editor" && _.isEmpty(SelectedEdmDefaultTemplate)) {
|
|
69
67
|
this.handleEdmDefaultTemplateSelection(modeContent.id);
|
|
70
68
|
}
|
|
@@ -94,29 +92,28 @@ export class EmailWrapper extends React.Component { // eslint-disable-line react
|
|
|
94
92
|
};
|
|
95
93
|
CapNotification.error(message);
|
|
96
94
|
}
|
|
97
|
-
handleFileUpload = (
|
|
95
|
+
handleFileUpload = (file) => {
|
|
98
96
|
const { templatesActions, intl, showNextStep } = this.props;
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
}
|
|
102
|
-
//this.setCreateMode('upload');
|
|
103
|
-
const fileExtension = files[0].name.split('.').pop();
|
|
97
|
+
const validUpload = false;
|
|
98
|
+
const fileExtension = file.name.split('.').pop();
|
|
104
99
|
const supportedZipFormats = ['zip'];
|
|
105
|
-
//TODO: has to be changed based on props.
|
|
106
100
|
|
|
107
101
|
|
|
108
102
|
if (supportedZipFormats.indexOf(fileExtension.toLowerCase()) !== -1) {
|
|
109
|
-
templatesActions.handleZipUpload(
|
|
110
|
-
|
|
103
|
+
templatesActions.handleZipUpload(file.originFileObj, () => { //handle upload success
|
|
104
|
+
this.setState({modeContent: { file}}, showNextStep);
|
|
105
|
+
}, this.handleZipUploadError);
|
|
111
106
|
} else if (fileExtension === 'html' || fileExtension === 'htm') {
|
|
112
107
|
const reader = new FileReader();
|
|
113
108
|
reader.onload = () => {
|
|
114
109
|
const text = reader.result;
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
110
|
+
this.setState({modeContent: { file}}, () => {
|
|
111
|
+
templatesActions.handleHtmlUpload(text);
|
|
112
|
+
});
|
|
113
|
+
|
|
114
|
+
// showNextStep();
|
|
118
115
|
};
|
|
119
|
-
reader.readAsText(
|
|
116
|
+
reader.readAsText(file.originFileObj);
|
|
120
117
|
} else {
|
|
121
118
|
const message = {
|
|
122
119
|
message: intl.formatMessage(messages.invalidUploadFileError),
|
|
@@ -124,6 +121,7 @@ export class EmailWrapper extends React.Component { // eslint-disable-line react
|
|
|
124
121
|
};
|
|
125
122
|
CapNotification.error(message);
|
|
126
123
|
}
|
|
124
|
+
return validUpload;
|
|
127
125
|
};
|
|
128
126
|
|
|
129
127
|
handleEdmDefaultTemplateSelection = (id) => {
|
|
@@ -134,69 +132,70 @@ export class EmailWrapper extends React.Component { // eslint-disable-line react
|
|
|
134
132
|
this.setState({
|
|
135
133
|
selectedCreateMode: 'editor'});
|
|
136
134
|
};
|
|
137
|
-
useFileUpload = (
|
|
138
|
-
this.
|
|
139
|
-
|
|
135
|
+
useFileUpload = ({file}) => {
|
|
136
|
+
this.setState({modeContent: {}}, () => {
|
|
137
|
+
this.handleFileUpload(file);
|
|
138
|
+
});
|
|
140
139
|
}
|
|
141
140
|
useEditor = (id) => {
|
|
142
141
|
this.setState({modeContent: {id}}, this.props.showNextStep);
|
|
143
142
|
}
|
|
144
|
-
|
|
145
|
-
ev.preventDefault();
|
|
146
|
-
if (this.props.emailCreateMode === "upload" && _.isEmpty(this.state.modeContent.files)) {
|
|
147
|
-
this.props.onEmailModeChange( "" );
|
|
148
|
-
}
|
|
149
|
-
}
|
|
143
|
+
|
|
150
144
|
isShowEmailCreate = () => !_.isEmpty(this.state.selectedCreateMode) && (!_.isEmpty(this.props.EmailLayout) || this.props.SelectedEdmDefaultTemplate)
|
|
151
145
|
render() {
|
|
152
|
-
const {emailCreateMode, isGetFormData, getFormdata, type, CmsTemplates, step, cap, isFullMode} = this.props;
|
|
153
|
-
const {templateName} = this.state;
|
|
146
|
+
const {emailCreateMode, isGetFormData, getFormdata, type, CmsTemplates, step, cap, isFullMode, EmailLayout, setIsLoadingContent} = this.props;
|
|
147
|
+
const {templateName, modeContent} = this.state;
|
|
154
148
|
const isShowEmailCreate = this.isShowEmailCreate();
|
|
155
149
|
return (
|
|
156
150
|
<div>
|
|
157
|
-
<
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
151
|
+
<CapSpin spinning={emailCreateMode === "upload" ? this.props.isUploading : false} >
|
|
152
|
+
{step === "modeSelection" || (step === "templateSelection" && emailCreateMode === "upload") ?
|
|
153
|
+
<div>
|
|
154
|
+
{isFullMode &&
|
|
155
|
+
<CapInput
|
|
156
|
+
label={<FormattedMessage {...messages.creativeName}/>}
|
|
157
|
+
onChange={this.onTemplateNameChange}
|
|
158
|
+
value={templateName}
|
|
159
|
+
labelPosition="top"/>
|
|
160
|
+
}
|
|
161
|
+
<CapHeader size="small" title={<FormattedMessage {...messages.createMode}/>}/>
|
|
162
|
+
<CapRadioCard
|
|
163
|
+
panes={this.modes}
|
|
164
|
+
onChange={this.onChange}
|
|
165
|
+
selected={emailCreateMode}
|
|
166
|
+
/>
|
|
167
|
+
<div>
|
|
168
|
+
{emailCreateMode === "upload" &&
|
|
169
|
+
<div>
|
|
170
|
+
<CapUploader onChange={this.useFileUpload} accept=".zip, .html, .htm" showUploadList={false}>
|
|
171
|
+
<CapButton>Upload</CapButton>
|
|
172
|
+
</CapUploader>
|
|
173
|
+
{!_.isEmpty(EmailLayout) &&
|
|
174
|
+
<div>{_.get(modeContent, "file.name")}</div>
|
|
175
|
+
}
|
|
176
|
+
</div>
|
|
177
|
+
}
|
|
178
|
+
</div>
|
|
179
|
+
</div>
|
|
181
180
|
:
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
</div>
|
|
181
|
+
<div>
|
|
182
|
+
{isShowEmailCreate && <Email
|
|
183
|
+
setIsLoadingContent={setIsLoadingContent}
|
|
184
|
+
key="email-create-template"
|
|
185
|
+
location={this.state.routeParams}
|
|
186
|
+
route={{ name: 'email' }}
|
|
187
|
+
params={{}}
|
|
188
|
+
isGetFormData={isGetFormData}
|
|
189
|
+
getFormdata={getFormdata}
|
|
190
|
+
getFormSubscriptionData={getFormdata}
|
|
191
|
+
getDefaultTags={type}
|
|
192
|
+
defaultData={{templateName}}
|
|
193
|
+
cap={cap}
|
|
194
|
+
/>}
|
|
195
|
+
{CmsTemplates && !isShowEmailCreate && <CmsTemplatesComponent cmsTemplates={CmsTemplates} handleEdmDefaultTemplateSelection={this.useEditor}/>}
|
|
196
|
+
</div>
|
|
199
197
|
}
|
|
198
|
+
</CapSpin>
|
|
200
199
|
</div>
|
|
201
200
|
);
|
|
202
201
|
}
|
|
@@ -218,12 +217,15 @@ EmailWrapper.propTypes = {
|
|
|
218
217
|
cap: PropTypes.object,
|
|
219
218
|
onResetStep: PropTypes.func,
|
|
220
219
|
isFullMode: PropTypes.bool,
|
|
220
|
+
isUploading: PropTypes.bool,
|
|
221
|
+
setIsLoadingContent: PropTypes.func,
|
|
221
222
|
};
|
|
222
223
|
|
|
223
224
|
const mapStateToProps = createStructuredSelector({
|
|
224
225
|
EmailLayout: selectEmailLayout(),
|
|
225
226
|
CmsTemplates: selectCmsTemplates(),
|
|
226
227
|
SelectedEdmDefaultTemplate: selectEdmEditor(),
|
|
228
|
+
isUploading: uploadSelector(),
|
|
227
229
|
});
|
|
228
230
|
|
|
229
231
|
function mapDispatchToProps(dispatch) {
|
|
@@ -50,4 +50,8 @@ export default defineMessages({
|
|
|
50
50
|
id: `app.containers.EmailWrapper.invalidUploadFileDesc`,
|
|
51
51
|
defaultMessage: `Please select another file with valid file contents`,
|
|
52
52
|
},
|
|
53
|
+
upload: {
|
|
54
|
+
id: `app.containers.EmailWrapper.upload`,
|
|
55
|
+
defaultMessage: `Upload`,
|
|
56
|
+
},
|
|
53
57
|
});
|
|
@@ -175,6 +175,9 @@ export class Create extends React.Component { // eslint-disable-line react/prefe
|
|
|
175
175
|
}
|
|
176
176
|
|
|
177
177
|
componentWillUnmount() {
|
|
178
|
+
if (this.props.setIsLoadingContent) {
|
|
179
|
+
this.props.setIsLoadingContent(true); // setting isLoading of CreativesContainer so that slidebox foot can be hidden till content is loaded
|
|
180
|
+
}
|
|
178
181
|
window.removeEventListener("message", this.handleFrameTasks);
|
|
179
182
|
}
|
|
180
183
|
|
|
@@ -923,6 +926,9 @@ export class Create extends React.Component { // eslint-disable-line react/prefe
|
|
|
923
926
|
// if (isLoading && this.state.loadingStatus >= 2) {
|
|
924
927
|
// this.props.creativesContainerActions.hideCreativesContanerLoader();
|
|
925
928
|
// }
|
|
929
|
+
if (!isLoading && this.props.setIsLoadingContent) {
|
|
930
|
+
this.props.setIsLoadingContent(isLoading);
|
|
931
|
+
}
|
|
926
932
|
return isLoading;
|
|
927
933
|
}
|
|
928
934
|
render() {
|
|
@@ -947,6 +953,7 @@ export class Create extends React.Component { // eslint-disable-line react/prefe
|
|
|
947
953
|
<Row>
|
|
948
954
|
<Col>
|
|
949
955
|
<FormBuilder
|
|
956
|
+
isFullMode={this.props.isFullMode}
|
|
950
957
|
schema={schema}
|
|
951
958
|
onSubmit={this.saveFormData}
|
|
952
959
|
onChange={this.onFormDataChange}
|
|
@@ -991,6 +998,7 @@ Create.propTypes = {
|
|
|
991
998
|
// creativesContainerActions: PropTypes.object,
|
|
992
999
|
getFormSubscriptionData: PropTypes.func,
|
|
993
1000
|
isFullMode: PropTypes.bool,
|
|
1001
|
+
setIsLoadingContent: PropTypes.func,
|
|
994
1002
|
};
|
|
995
1003
|
|
|
996
1004
|
const mapStateToProps = createStructuredSelector({
|
|
@@ -191,6 +191,9 @@ export class Edit extends React.Component { // eslint-disable-line react/prefer-
|
|
|
191
191
|
}
|
|
192
192
|
|
|
193
193
|
componentWillUnmount() {
|
|
194
|
+
if (this.props.setIsLoadingContent) {
|
|
195
|
+
this.props.setIsLoadingContent(true); // setting isLoading of CreativesContainer so that slidebox foot can be hidden till content is loaded
|
|
196
|
+
}
|
|
194
197
|
window.removeEventListener("message", this.handleFrameTasks);
|
|
195
198
|
}
|
|
196
199
|
|
|
@@ -924,6 +927,9 @@ export class Edit extends React.Component { // eslint-disable-line react/prefer-
|
|
|
924
927
|
// if (isLoading && this.state.loadingStatus >= 3) {
|
|
925
928
|
// this.props.creativesContainerActions.hideCreativesContanerLoader();
|
|
926
929
|
// }
|
|
930
|
+
if (!isLoading && this.props.setIsLoadingContent) {
|
|
931
|
+
this.props.setIsLoadingContent(isLoading);
|
|
932
|
+
}
|
|
927
933
|
return isLoading;
|
|
928
934
|
}
|
|
929
935
|
render() {
|
|
@@ -950,6 +956,7 @@ export class Edit extends React.Component { // eslint-disable-line react/prefer-
|
|
|
950
956
|
<Row>
|
|
951
957
|
<Col>
|
|
952
958
|
<FormBuilder
|
|
959
|
+
isFullMode={this.props.isFullMode}
|
|
953
960
|
schema={schema}
|
|
954
961
|
onSubmit={this.saveFormData}
|
|
955
962
|
onChange={this.onFormDataChange}
|
|
@@ -996,6 +1003,7 @@ Edit.propTypes = {
|
|
|
996
1003
|
// creativesContainerActions: PropTypes.object,
|
|
997
1004
|
isFullMode: PropTypes.bool,
|
|
998
1005
|
getFormSubscriptionData: PropTypes.func,
|
|
1006
|
+
setIsLoadingContent: PropTypes.func,
|
|
999
1007
|
};
|
|
1000
1008
|
|
|
1001
1009
|
const mapStateToProps = createStructuredSelector({
|
package/package.json
CHANGED
|
@@ -1,108 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
*
|
|
3
|
-
* EmailPreviewV2
|
|
4
|
-
*
|
|
5
|
-
*/
|
|
6
|
-
|
|
7
|
-
import React from 'react';
|
|
8
|
-
// import styled from 'styled-components';
|
|
9
|
-
import PropTypes from 'prop-types';
|
|
10
|
-
import { FormattedMessage } from 'react-intl';
|
|
11
|
-
import {isEmpty} from 'lodash';
|
|
12
|
-
import { connect } from 'react-redux';
|
|
13
|
-
import { bindActionCreators } from 'redux';
|
|
14
|
-
import { createStructuredSelector } from 'reselect';
|
|
15
|
-
import { CapSpin } from '@capillarytech/cap-ui-library';
|
|
16
|
-
import moment from 'moment';
|
|
17
|
-
import messages from '../EmailPreviewV2/messages';
|
|
18
|
-
import './index.scss';
|
|
19
|
-
import mobileBody from '../../assets/mobile.png';
|
|
20
|
-
|
|
21
|
-
import {selectTemplateContent} from '../../containers/Templates/selectors';
|
|
22
|
-
import * as templateActions from '../../containers/Templates/actions';
|
|
23
|
-
|
|
24
|
-
const deviceAspectRatio = {
|
|
25
|
-
mobile: {
|
|
26
|
-
height: "500",
|
|
27
|
-
width: "300",
|
|
28
|
-
},
|
|
29
|
-
};
|
|
30
|
-
|
|
31
|
-
class EmailMobilePreview extends React.Component {
|
|
32
|
-
componentWillMount() {
|
|
33
|
-
const {templateData, templateContent} = this.props;
|
|
34
|
-
if (isEmpty(templateContent) && !isEmpty(templateData) && templateData._id) { // templateData: comes from templates list email preview
|
|
35
|
-
this.props.templateActions.getTemplateDetails(templateData._id); // templateContent: html data to be shown in iframe
|
|
36
|
-
}
|
|
37
|
-
}
|
|
38
|
-
|
|
39
|
-
getPreview = ({device, messageContainerName, templateContent}) => (
|
|
40
|
-
<div className={"shell align-center"}>
|
|
41
|
-
<img src={mobileBody} alt="capillary" width="85%" height="400px" />
|
|
42
|
-
<div className={messageContainerName}>
|
|
43
|
-
<iframe srcDoc={templateContent} {...deviceAspectRatio[device]} >
|
|
44
|
-
<p><FormattedMessage {...messages.noIframeSupport}/></p>
|
|
45
|
-
</iframe>
|
|
46
|
-
</div>
|
|
47
|
-
</div>
|
|
48
|
-
);
|
|
49
|
-
|
|
50
|
-
render() {
|
|
51
|
-
const messageContainerName = 'mobile-message-container';
|
|
52
|
-
const {currentDevice} = this.state;
|
|
53
|
-
const { templateContent } = this.props;
|
|
54
|
-
|
|
55
|
-
return (
|
|
56
|
-
<div className="email-preview-v2">
|
|
57
|
-
|
|
58
|
-
<CapSpin spinning={!templateContent}>
|
|
59
|
-
<div id="emailPreivew-container">
|
|
60
|
-
<div id="emailPreivew-content-wrapper">
|
|
61
|
-
<div id="emailPreivew-content">
|
|
62
|
-
<div className="email-preview-container">
|
|
63
|
-
<div className={"shell align-center"}>
|
|
64
|
-
<img src={mobileBody} alt="capillary" width="85%" />
|
|
65
|
-
<div className={messageContainerName}>
|
|
66
|
-
<iframe srcDoc={templateContent} {...deviceAspectRatio[currentDevice]} >
|
|
67
|
-
<p><FormattedMessage {...messages.noIframeSupport}/></p>
|
|
68
|
-
</iframe>
|
|
69
|
-
</div>
|
|
70
|
-
</div>
|
|
71
|
-
</div>
|
|
72
|
-
</div>
|
|
73
|
-
</div>
|
|
74
|
-
</div>
|
|
75
|
-
{this.props.templateData &&
|
|
76
|
-
[
|
|
77
|
-
<p className="preview-info"><FormattedMessage {...messages.lastModified} />: {moment(this.props.templateData.updatedAt).format('MM-DD-YYYY')}</p>,
|
|
78
|
-
<p style={{marginBottom: '8px'}} className="preview-info"><FormattedMessage {...messages.uploadedBy} /> : {this.props.templateData.updatedByName}</p>,
|
|
79
|
-
]
|
|
80
|
-
}
|
|
81
|
-
</CapSpin>
|
|
82
|
-
</div>
|
|
83
|
-
|
|
84
|
-
);
|
|
85
|
-
}
|
|
86
|
-
|
|
87
|
-
}
|
|
88
|
-
|
|
89
|
-
EmailMobilePreview.propTypes = {
|
|
90
|
-
templateContent: PropTypes.string,
|
|
91
|
-
templateData: PropTypes.object,
|
|
92
|
-
templateActions: PropTypes.object,
|
|
93
|
-
};
|
|
94
|
-
|
|
95
|
-
EmailMobilePreview.defaultProps = {
|
|
96
|
-
showDeviceSelection: true,
|
|
97
|
-
};
|
|
98
|
-
|
|
99
|
-
const mapStateToProps = (state, props) => createStructuredSelector({
|
|
100
|
-
templateContent: props.templateData ? selectTemplateContent() : () => props.templateContent, // when props has templateContent that means preview with content
|
|
101
|
-
});
|
|
102
|
-
function mapDispatchToProps(dispatch) {
|
|
103
|
-
return {
|
|
104
|
-
templateActions: bindActionCreators(templateActions, dispatch),
|
|
105
|
-
};
|
|
106
|
-
}
|
|
107
|
-
|
|
108
|
-
export default connect(mapStateToProps, mapDispatchToProps)(EmailMobilePreview);
|
|
@@ -1,66 +0,0 @@
|
|
|
1
|
-
$classPrefix: email-preview-v2;
|
|
2
|
-
.#{$classPrefix}{
|
|
3
|
-
#emailPreivew-container {
|
|
4
|
-
position: relative;
|
|
5
|
-
// padding: 0 24px 0 24px;
|
|
6
|
-
overflow-y: auto;
|
|
7
|
-
// font-family: 'proxima-nova';
|
|
8
|
-
overflow: hidden;
|
|
9
|
-
#emailPreivew-content-wrapper{
|
|
10
|
-
width: 100%;
|
|
11
|
-
height: 90%;
|
|
12
|
-
overflow: auto;
|
|
13
|
-
// display: table;
|
|
14
|
-
|
|
15
|
-
#emailPreivew-content {
|
|
16
|
-
.device-wrapper {
|
|
17
|
-
display: inline-flex;
|
|
18
|
-
margin-bottom: 8px;
|
|
19
|
-
margin-top: 16px;
|
|
20
|
-
.device-name {
|
|
21
|
-
padding: 6px 24px;
|
|
22
|
-
background: #E6F0FB;
|
|
23
|
-
border: 2px solid #E6F0FB;
|
|
24
|
-
font-family: "open-sans";
|
|
25
|
-
line-height: 20px;
|
|
26
|
-
font-size: 14px;
|
|
27
|
-
color: #4E92E5;
|
|
28
|
-
cursor: pointer;
|
|
29
|
-
}
|
|
30
|
-
.active {
|
|
31
|
-
background: #FFFFFF !important;
|
|
32
|
-
border: 2px solid #E6F0FB;
|
|
33
|
-
}
|
|
34
|
-
|
|
35
|
-
}
|
|
36
|
-
.email-preview-container{
|
|
37
|
-
.tablet-message-container {
|
|
38
|
-
position: absolute;
|
|
39
|
-
top: 9%;
|
|
40
|
-
left: 10%;
|
|
41
|
-
width: 100%;
|
|
42
|
-
height: 100%;
|
|
43
|
-
overflow: auto;
|
|
44
|
-
display: -webkit-box;
|
|
45
|
-
display: -ms-flexbox;
|
|
46
|
-
display: flex;
|
|
47
|
-
}
|
|
48
|
-
.mobile-message-container {
|
|
49
|
-
position: absolute;
|
|
50
|
-
top: 10.3%;
|
|
51
|
-
left: 14%;
|
|
52
|
-
overflow: auto;
|
|
53
|
-
display: -webkit-box;
|
|
54
|
-
display: -ms-flexbox;
|
|
55
|
-
display: flex;
|
|
56
|
-
}
|
|
57
|
-
}
|
|
58
|
-
padding: 0 0px 0 24px;
|
|
59
|
-
// display: table-cell;
|
|
60
|
-
// vertical-align: middle;
|
|
61
|
-
text-align: center;
|
|
62
|
-
margin-bottom: 36px;
|
|
63
|
-
}
|
|
64
|
-
}
|
|
65
|
-
}
|
|
66
|
-
}
|
|
@@ -1,34 +0,0 @@
|
|
|
1
|
-
/*
|
|
2
|
-
*
|
|
3
|
-
* TemplatesV2 reducer
|
|
4
|
-
*
|
|
5
|
-
*/
|
|
6
|
-
|
|
7
|
-
import { fromJS } from 'immutable';
|
|
8
|
-
import * as types from './constants';
|
|
9
|
-
|
|
10
|
-
const initialState = fromJS({
|
|
11
|
-
loadingTemplates: true,
|
|
12
|
-
smsTemplates: [],
|
|
13
|
-
emailTemplates: [],
|
|
14
|
-
wechatTemplates: [],
|
|
15
|
-
mobilepushTemplates: [],
|
|
16
|
-
});
|
|
17
|
-
|
|
18
|
-
function templatesV2Reducer(state = initialState, action) {
|
|
19
|
-
const channelTemplates = `${action.channel}Templates`;
|
|
20
|
-
switch (action.type) {
|
|
21
|
-
case types.DEFAULT_ACTION:
|
|
22
|
-
return state;
|
|
23
|
-
case types.GET_TEMPLATES_REQUEST:
|
|
24
|
-
return state.set('loadingTemplates', true);
|
|
25
|
-
case types.GET_TEMPLATES_SUCESS:
|
|
26
|
-
return state.set('loadingTemplates', false).set(channelTemplates, action.templates);
|
|
27
|
-
case types.GET_TEMPLATES_FAILURE:
|
|
28
|
-
return state.set('loadingTemplates', false).set('error', action.error);
|
|
29
|
-
default:
|
|
30
|
-
return state;
|
|
31
|
-
}
|
|
32
|
-
}
|
|
33
|
-
|
|
34
|
-
export default templatesV2Reducer;
|
|
@@ -1,32 +0,0 @@
|
|
|
1
|
-
import { take, takeLatest, call, put, cancel } from 'redux-saga/effects';
|
|
2
|
-
import { LOCATION_CHANGE } from 'react-router-redux';
|
|
3
|
-
import * as Api from '../../services/api';
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
import * as types from './constants';
|
|
7
|
-
// Individual exports for testing
|
|
8
|
-
export function* defaultSaga() {
|
|
9
|
-
// See example in containers/HomePage/sagas.js
|
|
10
|
-
}
|
|
11
|
-
function* getTemplates(action) {
|
|
12
|
-
try {
|
|
13
|
-
const req = {
|
|
14
|
-
channel: action.channel,
|
|
15
|
-
queryParams: action.query,
|
|
16
|
-
};
|
|
17
|
-
const res = yield call(Api.getAllTemplates, req);
|
|
18
|
-
yield put({type: types.GET_TEMPLATES_SUCESS, templates: res.response.templates, channel: action.channel});
|
|
19
|
-
} catch (error) {
|
|
20
|
-
yield put({type: types.GET_TEMPLATES_FAILURE, error});
|
|
21
|
-
}
|
|
22
|
-
}
|
|
23
|
-
function* getTemplatesWatcher() {
|
|
24
|
-
const watcher = yield takeLatest(types.GET_TEMPLATES_REQUEST, getTemplates);
|
|
25
|
-
yield take(LOCATION_CHANGE);
|
|
26
|
-
yield cancel(watcher);
|
|
27
|
-
}
|
|
28
|
-
// All sagas to be loaded
|
|
29
|
-
export default [
|
|
30
|
-
defaultSaga,
|
|
31
|
-
getTemplatesWatcher,
|
|
32
|
-
];
|