Merge pull request #1254 from mailpoet/am_display_events_chunk1

Makes necessary changes for automatic emails feature to work [PREMIUM-63]
This commit is contained in:
Tautvidas Sipavičius
2018-02-05 17:48:23 +02:00
committed by GitHub
5 changed files with 97 additions and 26 deletions

View File

@@ -28,6 +28,20 @@ a:focus
.select2-container .select2-container
width: 25em !important width: 25em !important
placeholder-color = #999 /* default Select2 placeholder color for single dropdown */
input.select2-search__field::-webkit-input-placeholder
color: placeholder-color
input.select2-search__field:-moz-placeholder
color: placeholder-color
input.select2-search__field::-moz-placeholder
color: placeholder-color
input.select2-search__field:-ms-input-placeholder
color: placeholder-color
.select2-container--default.select2-container--focus .select2-selection--multiple
border: 1px solid #aaa; /* default Select2 border for single dropdown */
// textareas // textareas
textarea.regular-text textarea.regular-text
width: 25em !important width: 25em !important

View File

@@ -10,20 +10,11 @@ define([
jQuery jQuery
) => { ) => {
const Selection = React.createClass({ const Selection = React.createClass({
getInitialState: function () {
return {
items: [],
select2: false,
};
},
componentWillMount: function () {
this.loadCachedItems();
},
allowMultipleValues: function () { allowMultipleValues: function () {
return (this.props.field.multiple === true); return (this.props.field.multiple === true);
}, },
isSelect2Initialized: function () { isSelect2Initialized: function () {
return (this.state.select2 === true); return (jQuery(`#${this.refs.select.id}`).hasClass('select2-hidden-accessible') === true);
}, },
componentDidMount: function () { componentDidMount: function () {
if (this.allowMultipleValues() || this.props.field.forceSelect2) { if (this.allowMultipleValues() || this.props.field.forceSelect2) {
@@ -31,31 +22,57 @@ define([
} }
}, },
componentDidUpdate: function (prevProps) { componentDidUpdate: function (prevProps) {
if ( if ((this.props.item !== undefined && prevProps.item !== undefined)
(this.props.item !== undefined && prevProps.item !== undefined)
&& (this.props.item.id !== prevProps.item.id) && (this.props.item.id !== prevProps.item.id)
) { ) {
jQuery(`#${this.refs.select.id}`) jQuery(`#${this.refs.select.id}`)
.val(this.getSelectedValues()) .val(this.getSelectedValues())
.trigger('change'); .trigger('change');
} }
if (this.isSelect2Initialized() &&
(this.getFieldId(this.props) !== this.getFieldId(prevProps)) &&
this.props.field.resetSelect2OnUpdate !== undefined
) {
this.resetSelect2();
}
}, },
componentWillUnmount: function () { componentWillUnmount: function () {
if (this.allowMultipleValues() || this.props.field.forceSelect2) { if (this.allowMultipleValues() || this.props.field.forceSelect2) {
this.destroySelect2(); this.destroySelect2();
} }
}, },
getFieldId: function (data) {
const props = data || this.props;
return props.field.id || props.field.name;
},
resetSelect2: function () {
this.destroySelect2();
this.setupSelect2();
},
destroySelect2: function () { destroySelect2: function () {
if (this.isSelect2Initialized()) { if (this.isSelect2Initialized()) {
jQuery(`#${this.refs.select.id}`).select2('destroy'); jQuery(`#${this.refs.select.id}`).select2('destroy');
this.cleanupAfterSelect2();
} }
}, },
cleanupAfterSelect2: function () {
// remove DOM elements created by Select2 that are not tracked by React
jQuery(`#${this.refs.select.id}`)
.find('option:not(.default)')
.remove();
// unbind events (https://select2.org/programmatic-control/methods#event-unbinding)
jQuery(`#${this.refs.select.id}`)
.off('select2:unselecting')
.off('select2:opening');
},
setupSelect2: function () { setupSelect2: function () {
if (this.isSelect2Initialized()) { if (this.isSelect2Initialized()) {
return; return;
} }
const select2 = jQuery(`#${this.refs.select.id}`).select2({ let select2Options = {
width: (this.props.width || ''), width: (this.props.width || ''),
templateResult: function (item) { templateResult: function (item) {
if (item.element && item.element.selected) { if (item.element && item.element.selected) {
@@ -65,7 +82,45 @@ define([
} }
return item.text; return item.text;
}, },
}); };
const remoteQuery = this.props.field.remoteQuery || null;
if (remoteQuery) {
select2Options = Object.assign(select2Options, {
ajax: {
url: window.ajaxurl,
type: 'POST',
dataType: 'json',
data: function (params) {
return {
action: 'mailpoet',
api_version: window.mailpoet_api_version,
token: window.mailpoet_token,
endpoint: remoteQuery.endpoint,
method: remoteQuery.method,
data: Object.assign(
remoteQuery.data,
{ query: params.term }
),
};
},
processResults: function (response) {
return {
results: response.data.map(item => (
{ id: item.id || item.value, text: item.name || item.text }
)),
};
},
},
minimumInputLength: remoteQuery.minimumInputLength || 2,
});
}
if (this.props.field.extendSelect2Options !== undefined) {
select2Options = Object.assign(select2Options, this.props.field.extendSelect2Options);
}
const select2 = jQuery(`#${this.refs.select.id}`).select2(select2Options);
let hasRemoved = false; let hasRemoved = false;
select2.on('select2:unselecting', () => { select2.on('select2:unselecting', () => {
@@ -79,8 +134,6 @@ define([
}); });
select2.on('change', this.handleChange); select2.on('change', this.handleChange);
this.setState({ select2: true });
}, },
getSelectedValues: function () { getSelectedValues: function () {
if (this.props.field.selected !== undefined) { if (this.props.field.selected !== undefined) {
@@ -96,7 +149,7 @@ define([
} }
return null; return null;
}, },
loadCachedItems: function () { getItems: function () {
let items; let items;
if (typeof (window[`mailpoet_${this.props.field.endpoint}`]) !== 'undefined') { if (typeof (window[`mailpoet_${this.props.field.endpoint}`]) !== 'undefined') {
items = window[`mailpoet_${this.props.field.endpoint}`]; items = window[`mailpoet_${this.props.field.endpoint}`];
@@ -108,11 +161,9 @@ define([
if (this.props.field.filter !== undefined) { if (this.props.field.filter !== undefined) {
items = items.filter(this.props.field.filter); items = items.filter(this.props.field.filter);
} }
this.setState({
items: items,
});
} }
return items;
}, },
handleChange: function (e) { handleChange: function (e) {
let value; let value;
@@ -163,11 +214,12 @@ define([
// For single selects only, in order for the placeholder value to appear, // For single selects only, in order for the placeholder value to appear,
// we must have a blank <option> as the first option in the <select> control. // we must have a blank <option> as the first option in the <select> control.
if (this.allowMultipleValues()) return undefined; if (this.allowMultipleValues()) return undefined;
if (this.props.field.placeholder) return (<option />); if (this.props.field.placeholder) return (<option className="default" />);
return undefined; return undefined;
}, },
render: function () { render: function () {
const options = this.state.items.map((item, index) => { const items = this.getItems(this.props.field);
const options = items.map((item, index) => {
const label = this.getLabel(item); const label = this.getLabel(item);
const searchLabel = this.getSearchLabel(item); const searchLabel = this.getSearchLabel(item);
const value = this.getValue(item); const value = this.getValue(item);
@@ -175,6 +227,7 @@ define([
return ( return (
<option <option
key={`option-${index}`} key={`option-${index}`}
className="default"
value={value} value={value}
title={searchLabel} title={searchLabel}
> >
@@ -185,7 +238,7 @@ define([
return ( return (
<select <select
id={this.props.field.id || this.props.field.name} id={this.getFieldId()}
ref="select" ref="select"
disabled={this.props.field.disabled} disabled={this.props.field.disabled}
data-placeholder={this.props.field.placeholder} data-placeholder={this.props.field.placeholder}

View File

@@ -45,7 +45,7 @@ define(
return `${segment.name} (${parseInt(segment.subscribers, 10).toLocaleString()})`; return `${segment.name} (${parseInt(segment.subscribers, 10).toLocaleString()})`;
}, },
transformChangedValue: function (segmentIds) { transformChangedValue: function (segmentIds) {
const allSegments = this.state.items; const allSegments = this.getItems();
return _.map(segmentIds, id => _.find(allSegments, segment => segment.id === id)); return _.map(segmentIds, id => _.find(allSegments, segment => segment.id === id));
}, },
validation: { validation: {

View File

@@ -351,7 +351,7 @@ define(
return `${segment.name} (${parseInt(segment.subscribers, 10).toLocaleString()})`; return `${segment.name} (${parseInt(segment.subscribers, 10).toLocaleString()})`;
}, },
transformChangedValue: function (segmentIds) { transformChangedValue: function (segmentIds) {
const allSegments = this.state.items; const allSegments = this.getItems();
return _.map(segmentIds, id => _.find(allSegments, segment => segment.id === id)); return _.map(segmentIds, id => _.find(allSegments, segment => segment.id === id));
}, },
validation: { validation: {

View File

@@ -105,6 +105,10 @@ var baseConfig = {
test: /form.jsx/i, test: /form.jsx/i,
loader: 'expose-loader?' + globalPrefix + '.Form!babel-loader', loader: 'expose-loader?' + globalPrefix + '.Form!babel-loader',
}, },
{
include: path.resolve(__dirname, 'assets/js/src/form/fields/selection.jsx'),
loader: 'expose-loader?' + globalPrefix + '.FormFieldSelection!babel-loader',
},
{ {
include: path.resolve(__dirname, 'assets/js/src/newsletters/badges/stats.jsx'), include: path.resolve(__dirname, 'assets/js/src/newsletters/badges/stats.jsx'),
loader: 'expose-loader?' + globalPrefix + '.StatsBadge!babel-loader', loader: 'expose-loader?' + globalPrefix + '.StatsBadge!babel-loader',