Fix newsletter related broken eslint rules

This commit is contained in:
Tautvidas Sipavičius
2018-11-01 01:49:35 +02:00
parent 70743b98b6
commit 5b077b3911
17 changed files with 479 additions and 382 deletions

View File

@@ -2,6 +2,7 @@ import React from 'react';
import ReactDOM from 'react-dom'; import ReactDOM from 'react-dom';
import { Router, Route, IndexRedirect, useRouterHistory } from 'react-router'; import { Router, Route, IndexRedirect, useRouterHistory } from 'react-router';
import { createHashHistory } from 'history'; import { createHashHistory } from 'history';
import PropTypes from 'prop-types';
import SystemStatus from 'help/system_status.jsx'; import SystemStatus from 'help/system_status.jsx';
import SystemInfo from 'help/system_info.jsx'; import SystemInfo from 'help/system_info.jsx';
@@ -15,6 +16,10 @@ class App extends React.Component {
} }
} }
App.propTypes = {
children: PropTypes.element.isRequired,
};
const container = document.getElementById('help_container'); const container = document.getElementById('help_container');
if (container) { if (container) {

View File

@@ -1,6 +1,7 @@
import React from 'react'; import React from 'react';
import classNames from 'classnames'; import classNames from 'classnames';
import { Link } from 'react-router'; import { Link } from 'react-router';
import PropTypes from 'prop-types';
import MailPoet from 'mailpoet'; import MailPoet from 'mailpoet';
class Breadcrumb extends React.Component { class Breadcrumb extends React.Component {
@@ -64,5 +65,14 @@ class Breadcrumb extends React.Component {
} }
} }
module.exports = Breadcrumb; Breadcrumb.propTypes = {
steps: PropTypes.arrayOf(PropTypes.object),
step: PropTypes.string,
};
Breadcrumb.defaultProps = {
steps: undefined,
step: null,
};
module.exports = Breadcrumb;

View File

@@ -1,6 +1,7 @@
import React from 'react'; import React from 'react';
import createReactClass from 'create-react-class'; import createReactClass from 'create-react-class';
import { Link } from 'react-router'; import { Link } from 'react-router';
import PropTypes from 'prop-types';
import Listing from 'listing/listing.jsx'; import Listing from 'listing/listing.jsx';
import ListingTabs from 'newsletters/listings/tabs.jsx'; import ListingTabs from 'newsletters/listings/tabs.jsx';
@@ -158,8 +159,15 @@ const newsletterActions = [
}, },
]; ];
const NewsletterListNotification = createReactClass({ const NewsletterListNotification = createReactClass({ // eslint-disable-line react/prefer-es6-class
displayName: 'NewsletterListNotification', displayName: 'NewsletterListNotification',
propTypes: {
location: PropTypes.object.isRequired, // eslint-disable-line react/forbid-prop-types
params: PropTypes.object.isRequired, // eslint-disable-line react/forbid-prop-types
},
mixins: [MailerMixin, CronMixin], mixins: [MailerMixin, CronMixin],
updateStatus: function updateStatus(e) { updateStatus: function updateStatus(e) {

View File

@@ -4,6 +4,7 @@ import { Link } from 'react-router';
import classNames from 'classnames'; import classNames from 'classnames';
import MailPoet from 'mailpoet'; import MailPoet from 'mailpoet';
import Hooks from 'wp-js-hooks'; import Hooks from 'wp-js-hooks';
import PropTypes from 'prop-types';
import Listing from 'listing/listing.jsx'; import Listing from 'listing/listing.jsx';
import ListingTabs from 'newsletters/listings/tabs.jsx'; import ListingTabs from 'newsletters/listings/tabs.jsx';
@@ -58,8 +59,14 @@ let newsletterActions = [
Hooks.addFilter('mailpoet_newsletters_listings_notification_history_actions', StatisticsMixin.addStatsCTAAction); Hooks.addFilter('mailpoet_newsletters_listings_notification_history_actions', StatisticsMixin.addStatsCTAAction);
newsletterActions = Hooks.applyFilters('mailpoet_newsletters_listings_notification_history_actions', newsletterActions); newsletterActions = Hooks.applyFilters('mailpoet_newsletters_listings_notification_history_actions', newsletterActions);
const NewsletterListNotificationHistory = createReactClass({ const NewsletterListNotificationHistory = createReactClass({ // eslint-disable-line react/prefer-es6-class, max-len
displayName: 'NewsletterListNotificationHistory', displayName: 'NewsletterListNotificationHistory',
propTypes: {
location: PropTypes.object.isRequired, // eslint-disable-line react/forbid-prop-types
params: PropTypes.object.isRequired, // eslint-disable-line react/forbid-prop-types
},
mixins: [QueueMixin, StatisticsMixin, MailerMixin, CronMixin], mixins: [QueueMixin, StatisticsMixin, MailerMixin, CronMixin],
renderItem: function renderItem(newsletter, actions, meta) { renderItem: function renderItem(newsletter, actions, meta) {

View File

@@ -4,6 +4,7 @@ import { confirmAlert } from 'react-confirm-alert';
import classNames from 'classnames'; import classNames from 'classnames';
import MailPoet from 'mailpoet'; import MailPoet from 'mailpoet';
import Hooks from 'wp-js-hooks'; import Hooks from 'wp-js-hooks';
import PropTypes from 'prop-types';
import Listing from 'listing/listing.jsx'; import Listing from 'listing/listing.jsx';
import ListingTabs from 'newsletters/listings/tabs.jsx'; import ListingTabs from 'newsletters/listings/tabs.jsx';
@@ -173,8 +174,14 @@ let newsletterActions = [
Hooks.addFilter('mailpoet_newsletters_listings_standard_actions', StatisticsMixin.addStatsCTAAction); Hooks.addFilter('mailpoet_newsletters_listings_standard_actions', StatisticsMixin.addStatsCTAAction);
newsletterActions = Hooks.applyFilters('mailpoet_newsletters_listings_standard_actions', newsletterActions); newsletterActions = Hooks.applyFilters('mailpoet_newsletters_listings_standard_actions', newsletterActions);
const NewsletterListStandard = createReactClass({ const NewsletterListStandard = createReactClass({ // eslint-disable-line react/prefer-es6-class
displayName: 'NewsletterListStandard', displayName: 'NewsletterListStandard',
propTypes: {
location: PropTypes.object.isRequired, // eslint-disable-line react/forbid-prop-types
params: PropTypes.object.isRequired, // eslint-disable-line react/forbid-prop-types
},
mixins: [QueueMixin, StatisticsMixin, MailerMixin, CronMixin], mixins: [QueueMixin, StatisticsMixin, MailerMixin, CronMixin],
renderItem: function renderItem(newsletter, actions, meta) { renderItem: function renderItem(newsletter, actions, meta) {

View File

@@ -3,6 +3,7 @@ import { Link } from 'react-router';
import classNames from 'classnames'; import classNames from 'classnames';
import MailPoet from 'mailpoet'; import MailPoet from 'mailpoet';
import Hooks from 'wp-js-hooks'; import Hooks from 'wp-js-hooks';
import PropTypes from 'prop-types';
class ListingTabs extends React.Component { class ListingTabs extends React.Component {
state = { state = {
@@ -53,4 +54,8 @@ class ListingTabs extends React.Component {
} }
} }
ListingTabs.propTypes = {
tab: PropTypes.string.isRequired,
};
module.exports = ListingTabs; module.exports = ListingTabs;

View File

@@ -1,6 +1,6 @@
import React from 'react'; import React from 'react';
import createReactClass from 'create-react-class'; import createReactClass from 'create-react-class';
import PropTypes from 'prop-types';
import Listing from 'listing/listing.jsx'; import Listing from 'listing/listing.jsx';
import ListingTabs from 'newsletters/listings/tabs.jsx'; import ListingTabs from 'newsletters/listings/tabs.jsx';
@@ -155,8 +155,14 @@ let newsletterActions = [
Hooks.addFilter('mailpoet_newsletters_listings_welcome_notification_actions', StatisticsMixin.addStatsCTAAction); Hooks.addFilter('mailpoet_newsletters_listings_welcome_notification_actions', StatisticsMixin.addStatsCTAAction);
newsletterActions = Hooks.applyFilters('mailpoet_newsletters_listings_welcome_notification_actions', newsletterActions); newsletterActions = Hooks.applyFilters('mailpoet_newsletters_listings_welcome_notification_actions', newsletterActions);
const NewsletterListWelcome = createReactClass({ const NewsletterListWelcome = createReactClass({ // eslint-disable-line react/prefer-es6-class
displayName: 'NewsletterListWelcome', displayName: 'NewsletterListWelcome',
propTypes: {
location: PropTypes.object.isRequired, // eslint-disable-line react/forbid-prop-types
params: PropTypes.object.isRequired, // eslint-disable-line react/forbid-prop-types
},
mixins: [StatisticsMixin, MailerMixin, CronMixin], mixins: [StatisticsMixin, MailerMixin, CronMixin],
updateStatus: function updateStatus(e) { updateStatus: function updateStatus(e) {

View File

@@ -4,6 +4,7 @@ import { Router, Route, IndexRedirect, useRouterHistory } from 'react-router';
import { createHashHistory } from 'history'; import { createHashHistory } from 'history';
import Hooks from 'wp-js-hooks'; import Hooks from 'wp-js-hooks';
import _ from 'underscore'; import _ from 'underscore';
import PropTypes from 'prop-types';
import NewsletterTypes from 'newsletters/types.jsx'; import NewsletterTypes from 'newsletters/types.jsx';
import NewsletterTemplates from 'newsletters/templates.jsx'; import NewsletterTemplates from 'newsletters/templates.jsx';
@@ -25,6 +26,10 @@ class App extends React.Component {
} }
} }
App.propTypes = {
children: PropTypes.element.isRequired,
};
const container = document.getElementById('newsletters_container'); const container = document.getElementById('newsletters_container');
const getAutomaticEmailsRoutes = () => { const getAutomaticEmailsRoutes = () => {

View File

@@ -11,10 +11,17 @@ import HelpTooltip from 'help-tooltip.jsx';
import jQuery from 'jquery'; import jQuery from 'jquery';
import { fromUrl } from 'common/thumbnail.jsx'; import { fromUrl } from 'common/thumbnail.jsx';
import Hooks from 'wp-js-hooks'; import Hooks from 'wp-js-hooks';
import PropTypes from 'prop-types';
const NewsletterSend = createReactClass({ const NewsletterSend = createReactClass({ // eslint-disable-line react/prefer-es6-class
displayName: 'NewsletterSend', displayName: 'NewsletterSend',
propTypes: {
params: PropTypes.shape({
id: PropTypes.string,
}).isRequired,
},
contextTypes: { contextTypes: {
router: React.PropTypes.object.isRequired, router: React.PropTypes.object.isRequired,
}, },
@@ -27,6 +34,15 @@ const NewsletterSend = createReactClass({
}; };
}, },
componentDidMount: function componentDidMount() {
this.loadItem(this.props.params.id);
jQuery('#mailpoet_newsletter').parsley();
},
componentWillReceiveProps: function componentWillReceiveProps(props) {
this.loadItem(props.params.id);
},
getFieldsByNewsletter: function getFieldsByNewsletter(newsletter) { getFieldsByNewsletter: function getFieldsByNewsletter(newsletter) {
const type = this.getSubtype(newsletter); const type = this.getSubtype(newsletter);
return type.getFields(newsletter); return type.getFields(newsletter);
@@ -49,15 +65,6 @@ const NewsletterSend = createReactClass({
return jQuery('#mailpoet_newsletter').parsley().isValid(); return jQuery('#mailpoet_newsletter').parsley().isValid();
}, },
componentDidMount: function componentDidMount() {
this.loadItem(this.props.params.id);
jQuery('#mailpoet_newsletter').parsley();
},
componentWillReceiveProps: function componentWillReceiveProps(props) {
this.loadItem(props.params.id);
},
loadItem: function loadItem(id) { loadItem: function loadItem(id) {
this.setState({ loading: true }); this.setState({ loading: true });

View File

@@ -0,0 +1,173 @@
import React from 'react';
import jQuery from 'jquery';
import _ from 'underscore';
import MailPoet from 'mailpoet';
import PropTypes from 'prop-types';
const datepickerTranslations = {
closeText: MailPoet.I18n.t('close'),
currentText: MailPoet.I18n.t('today'),
nextText: MailPoet.I18n.t('next'),
prevText: MailPoet.I18n.t('previous'),
monthNames: [
MailPoet.I18n.t('january'),
MailPoet.I18n.t('february'),
MailPoet.I18n.t('march'),
MailPoet.I18n.t('april'),
MailPoet.I18n.t('may'),
MailPoet.I18n.t('june'),
MailPoet.I18n.t('july'),
MailPoet.I18n.t('august'),
MailPoet.I18n.t('september'),
MailPoet.I18n.t('october'),
MailPoet.I18n.t('november'),
MailPoet.I18n.t('december'),
],
monthNamesShort: [
MailPoet.I18n.t('januaryShort'),
MailPoet.I18n.t('februaryShort'),
MailPoet.I18n.t('marchShort'),
MailPoet.I18n.t('aprilShort'),
MailPoet.I18n.t('mayShort'),
MailPoet.I18n.t('juneShort'),
MailPoet.I18n.t('julyShort'),
MailPoet.I18n.t('augustShort'),
MailPoet.I18n.t('septemberShort'),
MailPoet.I18n.t('octoberShort'),
MailPoet.I18n.t('novemberShort'),
MailPoet.I18n.t('decemberShort'),
],
dayNames: [
MailPoet.I18n.t('sunday'),
MailPoet.I18n.t('monday'),
MailPoet.I18n.t('tuesday'),
MailPoet.I18n.t('wednesday'),
MailPoet.I18n.t('thursday'),
MailPoet.I18n.t('friday'),
MailPoet.I18n.t('saturday'),
],
dayNamesShort: [
MailPoet.I18n.t('sundayShort'),
MailPoet.I18n.t('mondayShort'),
MailPoet.I18n.t('tuesdayShort'),
MailPoet.I18n.t('wednesdayShort'),
MailPoet.I18n.t('thursdayShort'),
MailPoet.I18n.t('fridayShort'),
MailPoet.I18n.t('saturdayShort'),
],
dayNamesMin: [
MailPoet.I18n.t('sundayMin'),
MailPoet.I18n.t('mondayMin'),
MailPoet.I18n.t('tuesdayMin'),
MailPoet.I18n.t('wednesdayMin'),
MailPoet.I18n.t('thursdayMin'),
MailPoet.I18n.t('fridayMin'),
MailPoet.I18n.t('saturdayMin'),
],
};
class DateText extends React.Component {
componentDidMount() {
const $element = jQuery(this.dateInput);
const that = this;
if ($element.datepicker) {
// Override jQuery UI datepicker Date parsing and formatting
jQuery.datepicker.parseDate = function parseDate(format, value) {
// Transform string format to Date object
return MailPoet.Date.toDate(value, {
parseFormat: this.props.dateDisplayFormat,
format,
});
};
jQuery.datepicker.formatDate = function formatDate(format, value) {
// Transform Date object to string format
const newValue = MailPoet.Date.format(value, {
format,
});
return newValue;
};
$element.datepicker(_.extend({
dateFormat: this.props.displayFormat,
isRTL: false,
onSelect: function onSelect(value) {
that.onChange({
target: {
name: that.getFieldName(),
value,
},
});
},
}, datepickerTranslations));
this.datepickerInitialized = true;
}
}
componentWillUnmount() {
if (this.datepickerInitialized) {
jQuery(this.dateInput).datepicker('destroy');
}
}
onChange = (event) => {
const changeEvent = event;
// Swap display format to storage format
const displayDate = changeEvent.target.value;
const storageDate = this.getStorageDate(displayDate);
changeEvent.target.value = storageDate;
this.props.onChange(changeEvent);
};
getFieldName = () => this.props.name || 'date';
getDisplayDate = (date) => {
const formatting = {
parseFormat: this.props.storageFormat,
format: this.props.displayFormat,
};
return MailPoet.Date.format(date, formatting);
};
getStorageDate = (date) => {
const formatting = {
parseFormat: this.props.displayFormat,
format: this.props.storageFormat,
};
return MailPoet.Date.format(date, formatting);
};
render() {
return (
<input
type="text"
size="30"
name={this.getFieldName()}
value={this.getDisplayDate(this.props.value)}
readOnly
disabled={this.props.disabled}
onChange={this.onChange}
ref={(c) => { this.dateInput = c; }}
{...this.props.validation}
/>
);
}
}
DateText.propTypes = {
displayFormat: PropTypes.string.isRequired,
onChange: PropTypes.func.isRequired,
name: PropTypes.string,
storageFormat: PropTypes.string.isRequired,
value: PropTypes.string.isRequired,
disabled: PropTypes.bool.isRequired,
validation: PropTypes.object.isRequired, // eslint-disable-line react/forbid-prop-types
dateDisplayFormat: PropTypes.string.isRequired,
};
DateText.defaultProps = {
name: 'date',
};
module.exports = DateText;

View File

@@ -0,0 +1,89 @@
import React from 'react';
import PropTypes from 'prop-types';
import DateText from 'newsletters/send/date_text.jsx';
import TimeSelect from 'newsletters/send/time_select.jsx';
class DateTime extends React.Component {
state = this.buildStateFromProps(this.props);
componentWillReceiveProps(nextProps) {
this.setState(this.buildStateFromProps(nextProps));
}
getDateTime = () => [this.state.date, this.state.time].join(this.DATE_TIME_SEPARATOR);
DATE_TIME_SEPARATOR = ' ';
buildStateFromProps = (props) => {
const value = props.value || this.props.defaultDateTime;
const [date, time] = value.split(this.DATE_TIME_SEPARATOR);
return {
date,
time,
};
};
handleChange = (event) => {
const newState = {};
newState[event.target.name] = event.target.value;
this.setState(newState, this.propagateChange);
};
propagateChange = () => {
if (this.props.onChange) {
this.props.onChange({
target: {
name: this.props.name || '',
value: this.getDateTime(),
},
});
}
};
render() {
return (
<span>
<DateText
name="date"
value={this.state.date}
onChange={this.handleChange}
displayFormat={this.props.dateDisplayFormat}
storageFormat={this.props.dateStorageFormat}
disabled={this.props.disabled}
validation={this.props.dateValidation}
/>
<TimeSelect
name="time"
value={this.state.time}
onChange={this.handleChange}
disabled={this.props.disabled}
validation={this.props.timeValidation}
timeOfDayItems={this.props.timeOfDayItems}
/>
</span>
);
}
}
DateTime.propTypes = {
defaultDateTime: PropTypes.string.isRequired,
dateDisplayFormat: PropTypes.string.isRequired,
dateStorageFormat: PropTypes.string.isRequired,
onChange: PropTypes.func,
name: PropTypes.string,
disabled: PropTypes.bool,
dateValidation: PropTypes.objectOf(PropTypes.string).isRequired,
timeValidation: PropTypes.any, // eslint-disable-line react/forbid-prop-types
timeOfDayItems: PropTypes.objectOf(PropTypes.string).isRequired,
};
DateTime.defaultProps = {
onChange: undefined,
name: '',
disabled: false,
timeValidation: undefined,
};
module.exports = DateTime;

View File

@@ -1,8 +1,10 @@
import React from 'react'; import React from 'react';
import jQuery from 'jquery';
import _ from 'underscore'; import _ from 'underscore';
import MailPoet from 'mailpoet'; import MailPoet from 'mailpoet';
import Hooks from 'wp-js-hooks'; import Hooks from 'wp-js-hooks';
import PropTypes from 'prop-types';
import DateTime from 'newsletters/send/date_time.jsx';
const currentTime = window.mailpoet_current_time || '00:00'; const currentTime = window.mailpoet_current_time || '00:00';
const defaultDateTime = `${window.mailpoet_current_date} 00:00:00`; const defaultDateTime = `${window.mailpoet_current_date} 00:00:00`;
@@ -10,259 +12,32 @@ const timeOfDayItems = window.mailpoet_schedule_time_of_day;
const dateDisplayFormat = window.mailpoet_date_display_format; const dateDisplayFormat = window.mailpoet_date_display_format;
const dateStorageFormat = window.mailpoet_date_storage_format; const dateStorageFormat = window.mailpoet_date_storage_format;
const datepickerTranslations = {
closeText: MailPoet.I18n.t('close'),
currentText: MailPoet.I18n.t('today'),
nextText: MailPoet.I18n.t('next'),
prevText: MailPoet.I18n.t('previous'),
monthNames: [
MailPoet.I18n.t('january'),
MailPoet.I18n.t('february'),
MailPoet.I18n.t('march'),
MailPoet.I18n.t('april'),
MailPoet.I18n.t('may'),
MailPoet.I18n.t('june'),
MailPoet.I18n.t('july'),
MailPoet.I18n.t('august'),
MailPoet.I18n.t('september'),
MailPoet.I18n.t('october'),
MailPoet.I18n.t('november'),
MailPoet.I18n.t('december'),
],
monthNamesShort: [
MailPoet.I18n.t('januaryShort'),
MailPoet.I18n.t('februaryShort'),
MailPoet.I18n.t('marchShort'),
MailPoet.I18n.t('aprilShort'),
MailPoet.I18n.t('mayShort'),
MailPoet.I18n.t('juneShort'),
MailPoet.I18n.t('julyShort'),
MailPoet.I18n.t('augustShort'),
MailPoet.I18n.t('septemberShort'),
MailPoet.I18n.t('octoberShort'),
MailPoet.I18n.t('novemberShort'),
MailPoet.I18n.t('decemberShort'),
],
dayNames: [
MailPoet.I18n.t('sunday'),
MailPoet.I18n.t('monday'),
MailPoet.I18n.t('tuesday'),
MailPoet.I18n.t('wednesday'),
MailPoet.I18n.t('thursday'),
MailPoet.I18n.t('friday'),
MailPoet.I18n.t('saturday'),
],
dayNamesShort: [
MailPoet.I18n.t('sundayShort'),
MailPoet.I18n.t('mondayShort'),
MailPoet.I18n.t('tuesdayShort'),
MailPoet.I18n.t('wednesdayShort'),
MailPoet.I18n.t('thursdayShort'),
MailPoet.I18n.t('fridayShort'),
MailPoet.I18n.t('saturdayShort'),
],
dayNamesMin: [
MailPoet.I18n.t('sundayMin'),
MailPoet.I18n.t('mondayMin'),
MailPoet.I18n.t('tuesdayMin'),
MailPoet.I18n.t('wednesdayMin'),
MailPoet.I18n.t('thursdayMin'),
MailPoet.I18n.t('fridayMin'),
MailPoet.I18n.t('saturdayMin'),
],
};
class DateText extends React.Component {
onChange = (event) => {
const changeEvent = event;
// Swap display format to storage format
const displayDate = changeEvent.target.value;
const storageDate = this.getStorageDate(displayDate);
changeEvent.target.value = storageDate;
this.props.onChange(changeEvent);
};
componentDidMount() {
const $element = jQuery(this.dateInput);
const that = this;
if ($element.datepicker) {
// Override jQuery UI datepicker Date parsing and formatting
jQuery.datepicker.parseDate = function parseDate(format, value) {
// Transform string format to Date object
return MailPoet.Date.toDate(value, {
parseFormat: dateDisplayFormat,
format,
});
};
jQuery.datepicker.formatDate = function formatDate(format, value) {
// Transform Date object to string format
const newValue = MailPoet.Date.format(value, {
format,
});
return newValue;
};
$element.datepicker(_.extend({
dateFormat: this.props.displayFormat,
isRTL: false,
onSelect: function onSelect(value) {
that.onChange({
target: {
name: that.getFieldName(),
value,
},
});
},
}, datepickerTranslations));
this.datepickerInitialized = true;
}
}
componentWillUnmount() {
if (this.datepickerInitialized) {
jQuery(this.dateInput).datepicker('destroy');
}
}
getFieldName = () => {
return this.props.name || 'date';
};
getDisplayDate = (date) => {
return MailPoet.Date.format(date, {
parseFormat: this.props.storageFormat,
format: this.props.displayFormat,
});
};
getStorageDate = (date) => {
return MailPoet.Date.format(date, {
parseFormat: this.props.displayFormat,
format: this.props.storageFormat,
});
};
render() {
return (
<input
type="text"
size="30"
name={this.getFieldName()}
value={this.getDisplayDate(this.props.value)}
readOnly
disabled={this.props.disabled}
onChange={this.onChange}
ref={(c) => { this.dateInput = c; }}
{...this.props.validation}
/>
);
}
}
class TimeSelect extends React.Component {
render() {
const options = Object.keys(timeOfDayItems).map(
value => (
<option
key={`option-${timeOfDayItems[value]}`}
value={value}
>
{ timeOfDayItems[value] }
</option>
)
);
return (
<select
name={this.props.name || 'time'}
value={this.props.value}
disabled={this.props.disabled}
onChange={this.props.onChange}
{...this.props.validation}
>
{options}
</select>
);
}
}
class DateTime extends React.Component {
DATE_TIME_SEPARATOR = ' ';
componentWillReceiveProps(nextProps) {
this.setState(this.buildStateFromProps(nextProps));
}
buildStateFromProps = (props) => {
const value = props.value || defaultDateTime;
const [date, time] = value.split(this.DATE_TIME_SEPARATOR);
return {
date,
time,
};
};
handleChange = (event) => {
const newState = {};
newState[event.target.name] = event.target.value;
this.setState(newState, this.propagateChange);
};
propagateChange = () => {
if (this.props.onChange) {
this.props.onChange({
target: {
name: this.props.name || '',
value: this.getDateTime(),
},
});
}
};
getDateTime = () => {
return [this.state.date, this.state.time].join(this.DATE_TIME_SEPARATOR);
};
state = this.buildStateFromProps(this.props);
render() {
return (
<span>
<DateText
name="date"
value={this.state.date}
onChange={this.handleChange}
displayFormat={dateDisplayFormat}
storageFormat={dateStorageFormat}
disabled={this.props.disabled}
validation={this.props.dateValidation}
/>
<TimeSelect
name="time"
value={this.state.time}
onChange={this.handleChange}
disabled={this.props.disabled}
validation={this.props.timeValidation}
/>
</span>
);
}
}
class StandardScheduling extends React.Component { class StandardScheduling extends React.Component {
getCurrentValue = () => { getCurrentValue = () => {
const schedulingOptions = {
isScheduled: '0',
scheduledAt: defaultDateTime,
};
return _.defaults( return _.defaults(
this.props.item[this.props.field.name] || {}, this.props.item[this.props.field.name] || {},
{ schedulingOptions
isScheduled: '0',
scheduledAt: defaultDateTime,
}
); );
}; };
getDateValidation = () => ({
'data-parsley-required': true,
'data-parsley-required-message': MailPoet.I18n.t('noScheduledDateError'),
'data-parsley-errors-container': '#mailpoet_scheduling',
});
isScheduled = () => this.getCurrentValue().isScheduled === '1';
handleCheckboxChange = (event) => {
const changeEvent = event;
changeEvent.target.value = this.isScheduledInput.checked ? '1' : '0';
return this.handleValueChange(changeEvent);
};
handleValueChange = (event) => { handleValueChange = (event) => {
const oldValue = this.getCurrentValue(); const oldValue = this.getCurrentValue();
const newValue = {}; const newValue = {};
@@ -276,24 +51,6 @@ class StandardScheduling extends React.Component {
}); });
}; };
handleCheckboxChange = (event) => {
const changeEvent = event;
changeEvent.target.value = this.isScheduledInput.checked ? '1' : '0';
return this.handleValueChange(changeEvent);
};
isScheduled = () => {
return this.getCurrentValue().isScheduled === '1';
};
getDateValidation = () => {
return {
'data-parsley-required': true,
'data-parsley-required-message': MailPoet.I18n.t('noScheduledDateError'),
'data-parsley-errors-container': '#mailpoet_scheduling',
};
};
render() { render() {
let schedulingOptions; let schedulingOptions;
@@ -306,6 +63,10 @@ class StandardScheduling extends React.Component {
onChange={this.handleValueChange} onChange={this.handleValueChange}
disabled={this.props.field.disabled} disabled={this.props.field.disabled}
dateValidation={this.getDateValidation()} dateValidation={this.getDateValidation()}
defaultDateTime={defaultDateTime}
timeOfDayItems={timeOfDayItems}
dateDisplayFormat={dateDisplayFormat}
dateStorageFormat={dateStorageFormat}
/> />
&nbsp; &nbsp;
<span> <span>
@@ -332,6 +93,19 @@ class StandardScheduling extends React.Component {
} }
} }
StandardScheduling.propTypes = {
item: PropTypes.object, // eslint-disable-line react/forbid-prop-types
field: PropTypes.shape({
name: PropTypes.string.isRequired,
disabled: PropTypes.bool,
}).isRequired,
onValueChange: PropTypes.func.isRequired,
};
StandardScheduling.defaultProps = {
item: {},
};
let fields = [ let fields = [
{ {
name: 'subject', name: 'subject',

View File

@@ -0,0 +1,45 @@
import React from 'react';
import PropTypes from 'prop-types';
class TimeSelect extends React.Component { // eslint-disable-line react/prefer-stateless-function
render() {
const options = Object.keys(this.props.timeOfDayItems).map(
value => (
<option
key={`option-${this.props.timeOfDayItems[value]}`}
value={value}
>
{ this.props.timeOfDayItems[value] }
</option>
)
);
return (
<select
name={this.props.name || 'time'}
value={this.props.value}
disabled={this.props.disabled}
onChange={this.props.onChange}
{...this.props.validation}
>
{options}
</select>
);
}
}
TimeSelect.propTypes = {
timeOfDayItems: PropTypes.objectOf(PropTypes.string).isRequired,
name: PropTypes.string,
value: PropTypes.string.isRequired,
disabled: PropTypes.bool,
onChange: PropTypes.func.isRequired,
validation: PropTypes.object.isRequired, // eslint-disable-line react/forbid-prop-types
};
TimeSelect.defaultProps = {
name: 'time',
disabled: false,
};
module.exports = TimeSelect;

View File

@@ -20,6 +20,29 @@ class NewsletterTypes extends React.Component {
} }
}; };
getAutomaticEmails = () => {
if (!window.mailpoet_automatic_emails) return [];
return _.map(window.mailpoet_automatic_emails, (automaticEmail) => {
const email = automaticEmail;
const onClick = _.partial(this.setupNewsletter, automaticEmail.slug);
email.action = (() => (
<div>
<a
className="button button-primary"
onClick={onClick}
role="button"
tabIndex={0}
>
{ MailPoet.I18n.t('setUp') }
</a>
</div>
))();
return email;
});
};
createNewsletter = (type) => { createNewsletter = (type) => {
MailPoet.trackEvent('Emails > Type selected', { MailPoet.trackEvent('Emails > Type selected', {
'MailPoet Free version': window.mailpoet_version, 'MailPoet Free version': window.mailpoet_version,
@@ -45,29 +68,6 @@ class NewsletterTypes extends React.Component {
}); });
}; };
getAutomaticEmails = () => {
if (!window.mailpoet_automatic_emails) return [];
return _.map(window.mailpoet_automatic_emails, (automaticEmail) => {
const email = automaticEmail;
const onClick = _.partial(this.setupNewsletter, automaticEmail.slug);
email.action = (() => (
<div>
<a
className="button button-primary"
onClick={onClick}
role="button"
tabIndex={0}
>
{ MailPoet.I18n.t('setUp') }
</a>
</div>
))();
return email;
});
};
render() { render() {
const createStandardNewsletter = _.partial(this.createNewsletter, 'standard'); const createStandardNewsletter = _.partial(this.createNewsletter, 'standard');
const createNotificationNewsletter = _.partial(this.setupNewsletter, 'notification'); const createNotificationNewsletter = _.partial(this.setupNewsletter, 'notification');

View File

@@ -1,5 +1,6 @@
import _ from 'underscore'; import _ from 'underscore';
import React from 'react'; import React from 'react';
import PropTypes from 'prop-types';
import Select from 'form/fields/select.jsx'; import Select from 'form/fields/select.jsx';
import { import {
intervalValues, intervalValues,
@@ -35,9 +36,7 @@ const nthWeekDayField = {
}; };
class NotificationScheduling extends React.Component { class NotificationScheduling extends React.Component {
getCurrentValue = () => { getCurrentValue = () => this.props.item[this.props.field.name] || {};
return (this.props.item[this.props.field.name] || {});
};
handleValueChange = (name, value) => { handleValueChange = (name, value) => {
const oldValue = this.getCurrentValue(); const oldValue = this.getCurrentValue();
@@ -53,40 +52,11 @@ class NotificationScheduling extends React.Component {
}); });
}; };
handleIntervalChange = (event) => { handleIntervalChange = event => this.handleValueChange('intervalType', event.target.value);
return this.handleValueChange( handleTimeOfDayChange = event => this.handleValueChange('timeOfDay', event.target.value);
'intervalType', handleWeekDayChange = event => this.handleValueChange('weekDay', event.target.value);
event.target.value handleMonthDayChange = event => this.handleValueChange('monthDay', event.target.value);
); handleNthWeekDayChange = event => this.handleValueChange('nthWeekDay', event.target.value);
};
handleTimeOfDayChange = (event) => {
return this.handleValueChange(
'timeOfDay',
event.target.value
);
};
handleWeekDayChange = (event) => {
return this.handleValueChange(
'weekDay',
event.target.value
);
};
handleMonthDayChange = (event) => {
return this.handleValueChange(
'monthDay',
event.target.value
);
};
handleNthWeekDayChange = (event) => {
return this.handleValueChange(
'nthWeekDay',
event.target.value
);
};
render() { render() {
const value = this.getCurrentValue(); const value = this.getCurrentValue();
@@ -153,4 +123,12 @@ class NotificationScheduling extends React.Component {
} }
} }
NotificationScheduling.propTypes = {
item: PropTypes.object.isRequired, // eslint-disable-line react/forbid-prop-types
field: PropTypes.shape({
name: PropTypes.string,
}).isRequired,
onValueChange: PropTypes.func.isRequired,
};
module.exports = NotificationScheduling; module.exports = NotificationScheduling;

View File

@@ -7,10 +7,6 @@ class NewsletterStandard extends React.Component {
router: React.PropTypes.object.isRequired, router: React.PropTypes.object.isRequired,
}; };
showTemplateSelection = (newsletterId) => {
this.context.router.push(`/template/${newsletterId}`);
};
componentDidMount() { componentDidMount() {
// No options for this type, create a newsletter upon mounting // No options for this type, create a newsletter upon mounting
MailPoet.Ajax.post({ MailPoet.Ajax.post({
@@ -32,6 +28,10 @@ class NewsletterStandard extends React.Component {
}); });
} }
showTemplateSelection = (newsletterId) => {
this.context.router.push(`/template/${newsletterId}`);
};
render() { render() {
return ( return (
<div> <div>

View File

@@ -4,6 +4,7 @@ import MailPoet from 'mailpoet';
import Select from 'form/fields/select.jsx'; import Select from 'form/fields/select.jsx';
import Text from 'form/fields/text.jsx'; import Text from 'form/fields/text.jsx';
import { timeDelayValues } from 'newsletters/scheduling/common.jsx'; import { timeDelayValues } from 'newsletters/scheduling/common.jsx';
import PropTypes from 'prop-types';
const availableRoles = window.mailpoet_roles || {}; const availableRoles = window.mailpoet_roles || {};
const availableSegments = _.filter( const availableSegments = _.filter(
@@ -52,9 +53,7 @@ class WelcomeScheduling extends React.Component {
router: React.PropTypes.object.isRequired, router: React.PropTypes.object.isRequired,
}; };
getCurrentValue = () => { getCurrentValue = () => this.props.item[this.props.field.name] || {};
return (this.props.item[this.props.field.name] || {});
};
handleValueChange = (name, value) => { handleValueChange = (name, value) => {
const oldValue = this.getCurrentValue(); const oldValue = this.getCurrentValue();
@@ -70,40 +69,11 @@ class WelcomeScheduling extends React.Component {
}); });
}; };
handleEventChange = (event) => { handleEventChange = event => this.handleValueChange('event', event.target.value);
return this.handleValueChange( handleSegmentChange = event => this.handleValueChange('segment', event.target.value);
'event', handleRoleChange = event => this.handleValueChange('role', event.target.value);
event.target.value handleAfterTimeNumberChange = event => this.handleValueChange('afterTimeNumber', event.target.value);
); handleAfterTimeTypeChange = event => this.handleValueChange('afterTimeType', event.target.value);
};
handleSegmentChange = (event) => {
return this.handleValueChange(
'segment',
event.target.value
);
};
handleRoleChange = (event) => {
return this.handleValueChange(
'role',
event.target.value
);
};
handleAfterTimeNumberChange = (event) => {
return this.handleValueChange(
'afterTimeNumber',
event.target.value
);
};
handleAfterTimeTypeChange = (event) => {
return this.handleValueChange(
'afterTimeType',
event.target.value
);
};
handleNext = () => { handleNext = () => {
MailPoet.Ajax.post({ MailPoet.Ajax.post({
@@ -184,4 +154,12 @@ class WelcomeScheduling extends React.Component {
} }
} }
WelcomeScheduling.propTypes = {
item: PropTypes.object.isRequired, // eslint-disable-line react/forbid-prop-types
field: PropTypes.shape({
name: PropTypes.string,
}).isRequired,
onValueChange: PropTypes.func.isRequired,
};
module.exports = WelcomeScheduling; module.exports = WelcomeScheduling;