seperating components into multiple files
This commit is contained in:
committed by
pavel-mailpoet
parent
ddbabcfcb5
commit
8603e2a96a
15
assets/js/src/common/loading.jsx
Normal file
15
assets/js/src/common/loading.jsx
Normal file
@@ -0,0 +1,15 @@
|
||||
import React from 'react';
|
||||
|
||||
class Loading extends React.Component {
|
||||
componentWillMount() {
|
||||
MailPoet.Modal.loading(true);
|
||||
}
|
||||
componentWillUnmount() {
|
||||
MailPoet.Modal.loading(false);
|
||||
}
|
||||
render() {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
export default Loading;
|
@@ -4,6 +4,10 @@ import MailPoet from 'mailpoet';
|
||||
import { confirmAlert } from 'react-confirm-alert';
|
||||
import Breadcrumb from 'newsletters/breadcrumb.jsx';
|
||||
import HelpTooltip from 'help-tooltip.jsx';
|
||||
import Loading from 'common/loading.jsx';
|
||||
import Tabs from 'newsletters/templates/tabs.jsx';
|
||||
import TemplateBox from 'newsletters/templates/template_box.jsx';
|
||||
import ImportTemplate from 'newsletters/templates/import_template.jsx';
|
||||
|
||||
const getEditorUrl = id => `admin.php?page=mailpoet-newsletter-editor&id=${id}`;
|
||||
|
||||
@@ -38,272 +42,6 @@ const templatesCategories = [
|
||||
},
|
||||
];
|
||||
|
||||
class Loading extends React.Component {
|
||||
componentWillMount() {
|
||||
MailPoet.Modal.loading(true);
|
||||
}
|
||||
componentWillUnmount() {
|
||||
MailPoet.Modal.loading(false);
|
||||
}
|
||||
render() {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
const Tabs = ({ tabs, selected, select }) => (
|
||||
<div className="wp-filter hide-if-no-js">
|
||||
<ul className="filter-links">
|
||||
{tabs.map(({ name, label }) => (
|
||||
<li key={name}><a
|
||||
href="javascript:"
|
||||
className={selected === name ? 'current' : ''}
|
||||
onClick={() => select(name)}
|
||||
> {label}
|
||||
</a></li>
|
||||
))}
|
||||
</ul>
|
||||
</div>
|
||||
);
|
||||
|
||||
/**
|
||||
* props = {
|
||||
* index, id, newsletterId, name, description, thumbnail, readonly,
|
||||
* beforeDelete, afterDelete, beforeSelect, afterSelect
|
||||
* }
|
||||
*/
|
||||
class TemplateBox extends React.Component {
|
||||
onDelete() {
|
||||
const { id, name, beforeDelete, afterDelete } = this.props;
|
||||
const onConfirm = () => {
|
||||
beforeDelete();
|
||||
MailPoet.Ajax.post({
|
||||
api_version: window.mailpoet_api_version,
|
||||
endpoint: 'newsletterTemplates',
|
||||
action: 'delete',
|
||||
data: {
|
||||
id: id,
|
||||
},
|
||||
}).done(() => {
|
||||
afterDelete(true, id);
|
||||
}).fail((response) => {
|
||||
if (response.errors.length > 0) {
|
||||
MailPoet.Notice.error(
|
||||
response.errors.map(error => error.message),
|
||||
{ scroll: true }
|
||||
);
|
||||
}
|
||||
afterDelete(false);
|
||||
});
|
||||
};
|
||||
confirmAlert({
|
||||
title: MailPoet.I18n.t('confirmTitle'),
|
||||
message: MailPoet.I18n.t('confirmTemplateDeletion').replace('%$1s', name),
|
||||
confirmLabel: MailPoet.I18n.t('confirmLabel'),
|
||||
cancelLabel: MailPoet.I18n.t('cancelLabel'),
|
||||
onConfirm: onConfirm,
|
||||
onCancel: () => {},
|
||||
});
|
||||
}
|
||||
|
||||
onPreview() {
|
||||
MailPoet.Modal.popup({
|
||||
title: this.props.name,
|
||||
template: '<div class="mailpoet_boxes_preview" style="background-color: {{ body.globalStyles.body.backgroundColor }}"><img src="{{ thumbnail }}" /></div>',
|
||||
data: this.props,
|
||||
});
|
||||
}
|
||||
|
||||
onSelect() {
|
||||
const { newsletterId, name, beforeSelect } = this.props;
|
||||
let body = this.props.body;
|
||||
|
||||
if (!_.isUndefined(body)) {
|
||||
body = JSON.stringify(body);
|
||||
}
|
||||
|
||||
beforeSelect();
|
||||
|
||||
MailPoet.trackEvent('Emails > Template selected', {
|
||||
'MailPoet Free version': window.mailpoet_version,
|
||||
'Email name': name,
|
||||
});
|
||||
|
||||
MailPoet.Ajax.post({
|
||||
api_version: window.mailpoet_api_version,
|
||||
endpoint: 'newsletters',
|
||||
action: 'save',
|
||||
data: {
|
||||
id: newsletterId,
|
||||
body: body,
|
||||
},
|
||||
}).done((response) => {
|
||||
afterSelect(true, response.data.id);
|
||||
}).fail((response) => {
|
||||
if (response.errors.length > 0) {
|
||||
MailPoet.Notice.error(
|
||||
response.errors.map(error => error.message),
|
||||
{ scroll: true }
|
||||
);
|
||||
}
|
||||
afterSelect(false);
|
||||
});
|
||||
}
|
||||
|
||||
render() {
|
||||
const { index, name, thumbnail, description, readonly } = this.props;
|
||||
const onDelete = this.onDelete.bind(this);
|
||||
const onPreview = this.onPreview.bind(this);
|
||||
const onSelect = this.onSelect.bind(this);
|
||||
|
||||
const deleteLink = (
|
||||
<div className="mailpoet_delete">
|
||||
<a href="javascript:;" onClick={onDelete}>{MailPoet.I18n.t('delete')}</a>
|
||||
</div>
|
||||
);
|
||||
|
||||
let preview = '';
|
||||
if (typeof thumbnail === 'string' && thumbnail.length > 0) {
|
||||
preview = (
|
||||
<a href="javascript:;" onClick={onPreview}>
|
||||
<img src={thumbnail} />
|
||||
<div className="mailpoet_overlay"></div>
|
||||
</a>
|
||||
);
|
||||
}
|
||||
|
||||
return (
|
||||
<li>
|
||||
<div className="mailpoet_thumbnail">
|
||||
{ preview }
|
||||
</div>
|
||||
|
||||
<div className="mailpoet_description">
|
||||
<h3>{ name }</h3>
|
||||
<p>{ description }</p>
|
||||
</div>
|
||||
|
||||
<div className="mailpoet_actions">
|
||||
<a
|
||||
className="button button-secondary"
|
||||
onClick={onPreview}
|
||||
>{MailPoet.I18n.t('preview')}</a>
|
||||
|
||||
<a
|
||||
className="button button-primary"
|
||||
data-automation-id={`select_template_${index}`}
|
||||
onClick={onSelect}
|
||||
> {MailPoet.I18n.t('select')} </a>
|
||||
</div>
|
||||
{ readonly === '1' ? false : deleteLink }
|
||||
</li>
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* props = {beforeImport, afterImport}
|
||||
*/
|
||||
class ImportTemplate extends React.Component {
|
||||
|
||||
saveTemplate(saveTemplate) {
|
||||
const template = saveTemplate;
|
||||
const {beforeImport, afterImport} = this.props;
|
||||
|
||||
// Stringify to enable transmission of primitive non-string value types
|
||||
if (!_.isUndefined(template.body)) {
|
||||
template.body = JSON.stringify(template.body);
|
||||
}
|
||||
|
||||
try {
|
||||
template.categories = JSON.parse(template.categories);
|
||||
} catch (err) {
|
||||
template.categories = [];
|
||||
}
|
||||
|
||||
if (template.categories.indexOf('saved') === -1) {
|
||||
template.categories.push('saved');
|
||||
}
|
||||
|
||||
if (
|
||||
template.categories.indexOf('standard') === -1 &&
|
||||
template.categories.indexOf('welcome') === -1 &&
|
||||
template.categories.indexOf('notification') === -1
|
||||
) {
|
||||
template.categories.push('standard');
|
||||
}
|
||||
|
||||
template.categories = JSON.stringify(template.categories);
|
||||
|
||||
|
||||
beforeImport();
|
||||
MailPoet.Ajax.post({
|
||||
api_version: window.mailpoet_api_version,
|
||||
endpoint: 'newsletterTemplates',
|
||||
action: 'save',
|
||||
data: template,
|
||||
}).done((response) => {
|
||||
afterImport(true, response.data);
|
||||
}).fail((response) => {
|
||||
if (response.errors.length > 0) {
|
||||
MailPoet.Notice.error(
|
||||
response.errors.map(error => error.message),
|
||||
{ scroll: true }
|
||||
);
|
||||
}
|
||||
afterImport(false);
|
||||
});
|
||||
}
|
||||
|
||||
handleSubmit(e) {
|
||||
e.preventDefault();
|
||||
|
||||
if (_.size(this.refs.templateFile.files) <= 0) {
|
||||
return false;
|
||||
}
|
||||
|
||||
const file = _.first(this.refs.templateFile.files);
|
||||
const reader = new FileReader();
|
||||
|
||||
reader.onload = (evt) => {
|
||||
try {
|
||||
this.saveTemplate(JSON.parse(evt.target.result));
|
||||
MailPoet.trackEvent('Emails > Template imported', {
|
||||
'MailPoet Free version': window.mailpoet_version,
|
||||
});
|
||||
} catch (err) {
|
||||
MailPoet.Notice.error(MailPoet.I18n.t('templateFileMalformedError'));
|
||||
}
|
||||
};
|
||||
|
||||
reader.readAsText(file);
|
||||
return true;
|
||||
}
|
||||
render() {
|
||||
const handleSubmit = this.handleSubmit.bind(this);
|
||||
return (
|
||||
<div>
|
||||
<h2>
|
||||
{MailPoet.I18n.t('importTemplateTitle')}
|
||||
<HelpTooltip
|
||||
tooltip={MailPoet.I18n.t('helpTooltipTemplateUpload')}
|
||||
place="right"
|
||||
className="tooltip-help-import-template"
|
||||
/>
|
||||
</h2>
|
||||
<form onSubmit={handleSubmit}>
|
||||
<input type="file" placeholder={MailPoet.I18n.t('selectJsonFileToUpload')} ref="templateFile" />
|
||||
<p className="submit">
|
||||
<input
|
||||
className="button button-primary"
|
||||
type="submit"
|
||||
value={MailPoet.I18n.t('upload')} />
|
||||
</p>
|
||||
</form>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
class NewsletterTemplates extends React.Component {
|
||||
constructor(props) {
|
||||
super(props);
|
||||
|
110
assets/js/src/newsletters/templates/import_template.jsx
Normal file
110
assets/js/src/newsletters/templates/import_template.jsx
Normal file
@@ -0,0 +1,110 @@
|
||||
import React from 'react';
|
||||
import _ from 'underscore';
|
||||
import MailPoet from 'mailpoet';
|
||||
import HelpTooltip from 'help-tooltip.jsx';
|
||||
|
||||
/**
|
||||
* props = {beforeImport, afterImport}
|
||||
*/
|
||||
class ImportTemplate extends React.Component {
|
||||
|
||||
saveTemplate(saveTemplate) {
|
||||
const template = saveTemplate;
|
||||
const {beforeImport, afterImport} = this.props;
|
||||
|
||||
// Stringify to enable transmission of primitive non-string value types
|
||||
if (!_.isUndefined(template.body)) {
|
||||
template.body = JSON.stringify(template.body);
|
||||
}
|
||||
|
||||
try {
|
||||
template.categories = JSON.parse(template.categories);
|
||||
} catch (err) {
|
||||
template.categories = [];
|
||||
}
|
||||
|
||||
if (template.categories.indexOf('saved') === -1) {
|
||||
template.categories.push('saved');
|
||||
}
|
||||
|
||||
if (
|
||||
template.categories.indexOf('standard') === -1 &&
|
||||
template.categories.indexOf('welcome') === -1 &&
|
||||
template.categories.indexOf('notification') === -1
|
||||
) {
|
||||
template.categories.push('standard');
|
||||
}
|
||||
|
||||
template.categories = JSON.stringify(template.categories);
|
||||
|
||||
|
||||
beforeImport();
|
||||
MailPoet.Ajax.post({
|
||||
api_version: window.mailpoet_api_version,
|
||||
endpoint: 'newsletterTemplates',
|
||||
action: 'save',
|
||||
data: template,
|
||||
}).done((response) => {
|
||||
afterImport(true, response.data);
|
||||
}).fail((response) => {
|
||||
if (response.errors.length > 0) {
|
||||
MailPoet.Notice.error(
|
||||
response.errors.map(error => error.message),
|
||||
{ scroll: true }
|
||||
);
|
||||
}
|
||||
afterImport(false);
|
||||
});
|
||||
}
|
||||
|
||||
handleSubmit(e) {
|
||||
e.preventDefault();
|
||||
|
||||
if (_.size(this.refs.templateFile.files) <= 0) {
|
||||
return false;
|
||||
}
|
||||
|
||||
const file = _.first(this.refs.templateFile.files);
|
||||
const reader = new FileReader();
|
||||
|
||||
reader.onload = (evt) => {
|
||||
try {
|
||||
this.saveTemplate(JSON.parse(evt.target.result));
|
||||
MailPoet.trackEvent('Emails > Template imported', {
|
||||
'MailPoet Free version': window.mailpoet_version,
|
||||
});
|
||||
} catch (err) {
|
||||
MailPoet.Notice.error(MailPoet.I18n.t('templateFileMalformedError'));
|
||||
}
|
||||
};
|
||||
|
||||
reader.readAsText(file);
|
||||
return true;
|
||||
}
|
||||
render() {
|
||||
const handleSubmit = this.handleSubmit.bind(this);
|
||||
return (
|
||||
<div>
|
||||
<h2>
|
||||
{MailPoet.I18n.t('importTemplateTitle')}
|
||||
<HelpTooltip
|
||||
tooltip={MailPoet.I18n.t('helpTooltipTemplateUpload')}
|
||||
place="right"
|
||||
className="tooltip-help-import-template"
|
||||
/>
|
||||
</h2>
|
||||
<form onSubmit={handleSubmit}>
|
||||
<input type="file" placeholder={MailPoet.I18n.t('selectJsonFileToUpload')} ref="templateFile" />
|
||||
<p className="submit">
|
||||
<input
|
||||
className="button button-primary"
|
||||
type="submit"
|
||||
value={MailPoet.I18n.t('upload')} />
|
||||
</p>
|
||||
</form>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
export default ImportTemplate;
|
18
assets/js/src/newsletters/templates/tabs.jsx
Normal file
18
assets/js/src/newsletters/templates/tabs.jsx
Normal file
@@ -0,0 +1,18 @@
|
||||
import React from 'react';
|
||||
|
||||
const Tabs = ({ tabs, selected, select }) => (
|
||||
<div className="wp-filter hide-if-no-js">
|
||||
<ul className="filter-links">
|
||||
{tabs.map(({ name, label }) => (
|
||||
<li key={name}><a
|
||||
href="javascript:"
|
||||
className={selected === name ? 'current' : ''}
|
||||
onClick={() => select(name)}
|
||||
> {label}
|
||||
</a></li>
|
||||
))}
|
||||
</ul>
|
||||
</div>
|
||||
);
|
||||
|
||||
export default Tabs;
|
140
assets/js/src/newsletters/templates/template_box.jsx
Normal file
140
assets/js/src/newsletters/templates/template_box.jsx
Normal file
@@ -0,0 +1,140 @@
|
||||
import React from 'react';
|
||||
import MailPoet from 'mailpoet';
|
||||
import { confirmAlert } from 'react-confirm-alert';
|
||||
|
||||
/**
|
||||
* props = {
|
||||
* index, id, newsletterId, name, description, thumbnail, readonly,
|
||||
* beforeDelete, afterDelete, beforeSelect, afterSelect
|
||||
* }
|
||||
*/
|
||||
class TemplateBox extends React.Component {
|
||||
onDelete() {
|
||||
const { id, name, beforeDelete, afterDelete } = this.props;
|
||||
const onConfirm = () => {
|
||||
beforeDelete();
|
||||
MailPoet.Ajax.post({
|
||||
api_version: window.mailpoet_api_version,
|
||||
endpoint: 'newsletterTemplates',
|
||||
action: 'delete',
|
||||
data: {
|
||||
id: id,
|
||||
},
|
||||
}).done(() => {
|
||||
afterDelete(true, id);
|
||||
}).fail((response) => {
|
||||
if (response.errors.length > 0) {
|
||||
MailPoet.Notice.error(
|
||||
response.errors.map(error => error.message),
|
||||
{ scroll: true }
|
||||
);
|
||||
}
|
||||
afterDelete(false);
|
||||
});
|
||||
};
|
||||
confirmAlert({
|
||||
title: MailPoet.I18n.t('confirmTitle'),
|
||||
message: MailPoet.I18n.t('confirmTemplateDeletion').replace('%$1s', name),
|
||||
confirmLabel: MailPoet.I18n.t('confirmLabel'),
|
||||
cancelLabel: MailPoet.I18n.t('cancelLabel'),
|
||||
onConfirm: onConfirm,
|
||||
onCancel: () => {},
|
||||
});
|
||||
}
|
||||
|
||||
onPreview() {
|
||||
MailPoet.Modal.popup({
|
||||
title: this.props.name,
|
||||
template: '<div class="mailpoet_boxes_preview" style="background-color: {{ body.globalStyles.body.backgroundColor }}"><img src="{{ thumbnail }}" /></div>',
|
||||
data: this.props,
|
||||
});
|
||||
}
|
||||
|
||||
onSelect() {
|
||||
const { newsletterId, name, beforeSelect, afterSelect } = this.props;
|
||||
let body = this.props.body;
|
||||
|
||||
if (!_.isUndefined(body)) {
|
||||
body = JSON.stringify(body);
|
||||
}
|
||||
|
||||
beforeSelect();
|
||||
|
||||
MailPoet.trackEvent('Emails > Template selected', {
|
||||
'MailPoet Free version': window.mailpoet_version,
|
||||
'Email name': name,
|
||||
});
|
||||
|
||||
MailPoet.Ajax.post({
|
||||
api_version: window.mailpoet_api_version,
|
||||
endpoint: 'newsletters',
|
||||
action: 'save',
|
||||
data: {
|
||||
id: newsletterId,
|
||||
body: body,
|
||||
},
|
||||
}).done((response) => {
|
||||
afterSelect(true, response.data.id);
|
||||
}).fail((response) => {
|
||||
if (response.errors.length > 0) {
|
||||
MailPoet.Notice.error(
|
||||
response.errors.map(error => error.message),
|
||||
{ scroll: true }
|
||||
);
|
||||
}
|
||||
afterSelect(false);
|
||||
});
|
||||
}
|
||||
|
||||
render() {
|
||||
const { index, name, thumbnail, description, readonly } = this.props;
|
||||
const onDelete = this.onDelete.bind(this);
|
||||
const onPreview = this.onPreview.bind(this);
|
||||
const onSelect = this.onSelect.bind(this);
|
||||
|
||||
const deleteLink = (
|
||||
<div className="mailpoet_delete">
|
||||
<a href="javascript:;" onClick={onDelete}>{MailPoet.I18n.t('delete')}</a>
|
||||
</div>
|
||||
);
|
||||
|
||||
let preview = '';
|
||||
if (typeof thumbnail === 'string' && thumbnail.length > 0) {
|
||||
preview = (
|
||||
<a href="javascript:;" onClick={onPreview}>
|
||||
<img src={thumbnail} />
|
||||
<div className="mailpoet_overlay"></div>
|
||||
</a>
|
||||
);
|
||||
}
|
||||
|
||||
return (
|
||||
<li>
|
||||
<div className="mailpoet_thumbnail">
|
||||
{ preview }
|
||||
</div>
|
||||
|
||||
<div className="mailpoet_description">
|
||||
<h3>{ name }</h3>
|
||||
<p>{ description }</p>
|
||||
</div>
|
||||
|
||||
<div className="mailpoet_actions">
|
||||
<a
|
||||
className="button button-secondary"
|
||||
onClick={onPreview}
|
||||
>{MailPoet.I18n.t('preview')}</a>
|
||||
|
||||
<a
|
||||
className="button button-primary"
|
||||
data-automation-id={`select_template_${index}`}
|
||||
onClick={onSelect}
|
||||
> {MailPoet.I18n.t('select')} </a>
|
||||
</div>
|
||||
{ readonly === '1' ? false : deleteLink }
|
||||
</li>
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
export default TemplateBox;
|
Reference in New Issue
Block a user