Manage subscriptions
- make use of the SubscriberSegment::status column to keep track of unsubscriptions - unsubscribed segments now appear grayed out in the Subscribers listing - added unsubscribed_at after segment names when editing a subscriber - added date() method for Twig (uses WP's date format / date_offset) - fixed typo in Form iframe export - fixed unit test for Newsletters - updated selection component (JSX) to allow more customization
This commit is contained in:
@@ -26,7 +26,7 @@ function(
|
||||
&& (this.props.item.id !== prevProps.item.id)
|
||||
) {
|
||||
jQuery('#'+this.refs.select.id)
|
||||
.val(this.props.item[this.props.field.name])
|
||||
.val(this.getSelectedValues())
|
||||
.trigger('change');
|
||||
}
|
||||
},
|
||||
@@ -45,7 +45,11 @@ function(
|
||||
if(item.element && item.element.selected) {
|
||||
return null;
|
||||
} else {
|
||||
return item.text;
|
||||
if(item.title) {
|
||||
return item.title;
|
||||
} else {
|
||||
return item.text;
|
||||
}
|
||||
}
|
||||
}
|
||||
});
|
||||
@@ -65,15 +69,25 @@ function(
|
||||
|
||||
select2.select2(
|
||||
'val',
|
||||
this.props.item[this.props.field.name]
|
||||
this.getSelectedValues()
|
||||
);
|
||||
|
||||
this.setState({ initialized: true });
|
||||
},
|
||||
getSelectedValues: function() {
|
||||
if(this.props.field['selected'] !== undefined) {
|
||||
return this.props.field['selected'](this.props.item);
|
||||
} else if(this.props.item !== undefined && this.props.field.name !== undefined) {
|
||||
return this.props.item[this.props.field.name];
|
||||
} else {
|
||||
return null;
|
||||
}
|
||||
},
|
||||
loadCachedItems: function() {
|
||||
if(typeof(window['mailpoet_'+this.props.field.endpoint]) !== 'undefined') {
|
||||
var items = window['mailpoet_'+this.props.field.endpoint];
|
||||
|
||||
|
||||
if(this.props.field['filter'] !== undefined) {
|
||||
items = items.filter(this.props.field.filter);
|
||||
}
|
||||
@@ -98,31 +112,48 @@ function(
|
||||
});
|
||||
}
|
||||
},
|
||||
getLabel: function(item) {
|
||||
if(this.props.field['getLabel'] !== undefined) {
|
||||
return this.props.field.getLabel(item, this.props.item);
|
||||
}
|
||||
return item.name;
|
||||
},
|
||||
getSearchLabel: function(item) {
|
||||
if(this.props.field['getSearchLabel'] !== undefined) {
|
||||
return this.props.field.getSearchLabel(item, this.props.item);
|
||||
}
|
||||
return null;
|
||||
},
|
||||
getValue: function(item) {
|
||||
if(this.props.field['getValue'] !== undefined) {
|
||||
return this.props.field.getValue(item, this.props.item);
|
||||
}
|
||||
return item.id;
|
||||
},
|
||||
render: function() {
|
||||
var options = this.state.items.map(function(item, index) {
|
||||
const options = this.state.items.map((item, index) => {
|
||||
let label = this.getLabel(item);
|
||||
let searchLabel = this.getSearchLabel(item);
|
||||
let value = this.getValue(item);
|
||||
|
||||
return (
|
||||
<option
|
||||
key={ item.id }
|
||||
value={ item.id }
|
||||
key={ 'option-'+index }
|
||||
value={ value }
|
||||
title={ searchLabel }
|
||||
>
|
||||
{ item.name }
|
||||
{ label }
|
||||
</option>
|
||||
);
|
||||
});
|
||||
|
||||
var default_value = (
|
||||
(this.props.item !== undefined && this.props.field.name !== undefined)
|
||||
? this.props.item[this.props.field.name]
|
||||
: null
|
||||
);
|
||||
|
||||
return (
|
||||
<select
|
||||
id={ this.props.field.id || this.props.field.name }
|
||||
ref="select"
|
||||
data-placeholder={ this.props.field.placeholder }
|
||||
multiple={ this.props.field.multiple }
|
||||
defaultValue={ default_value }
|
||||
defaultValue={ this.getSelectedValues() }
|
||||
{...this.props.field.validation}
|
||||
>{ options }</select>
|
||||
);
|
||||
|
@@ -181,13 +181,13 @@ const SegmentList = React.createClass({
|
||||
<abbr>{ segment.description }</abbr>
|
||||
</td>
|
||||
<td className="column-date" data-colname="Subscribed">
|
||||
<abbr>{ segment.subscribed || 0 }</abbr>
|
||||
<abbr>{ segment.subscribers_count.subscribed || 0 }</abbr>
|
||||
</td>
|
||||
<td className="column-date" data-colname="Unconfirmed">
|
||||
<abbr>{ segment.unconfirmed || 0 }</abbr>
|
||||
<abbr>{ segment.subscribers_count.unconfirmed || 0 }</abbr>
|
||||
</td>
|
||||
<td className="column-date" data-colname="Unsubscribed">
|
||||
<abbr>{ segment.unsubscribed || 0 }</abbr>
|
||||
<abbr>{ segment.subscribers_count.unsubscribed || 0 }</abbr>
|
||||
</td>
|
||||
<td className="column-date" data-colname="Created on">
|
||||
<abbr>{ segment.created_at }</abbr>
|
||||
|
@@ -3,15 +3,16 @@ define(
|
||||
'react',
|
||||
'react-router',
|
||||
'mailpoet',
|
||||
'form/form.jsx'
|
||||
'form/form.jsx',
|
||||
'moment'
|
||||
],
|
||||
function(
|
||||
React,
|
||||
Router,
|
||||
MailPoet,
|
||||
Form
|
||||
Form,
|
||||
Moment
|
||||
) {
|
||||
|
||||
var fields = [
|
||||
{
|
||||
name: 'email',
|
||||
@@ -45,8 +46,38 @@ define(
|
||||
placeholder: "Select a list",
|
||||
endpoint: "segments",
|
||||
multiple: true,
|
||||
selected: function(subscriber) {
|
||||
if (Array.isArray(subscriber.subscriptions) === false) {
|
||||
return null;
|
||||
}
|
||||
|
||||
return subscriber.subscriptions.map(function(subscription) {
|
||||
if (subscription.status === 'subscribed') {
|
||||
return subscription.segment_id;
|
||||
}
|
||||
});
|
||||
},
|
||||
filter: function(segment) {
|
||||
return !!(!segment.deleted_at);
|
||||
},
|
||||
getSearchLabel: function(segment, subscriber) {
|
||||
let label = '';
|
||||
|
||||
if (subscriber.subscriptions !== undefined) {
|
||||
subscriber.subscriptions.map(function(subscription) {
|
||||
if (segment.id === subscription.segment_id) {
|
||||
label = segment.name;
|
||||
|
||||
if (subscription.status === 'unsubscribed') {
|
||||
const unsubscribed_at = Moment(subscription.updated_at)
|
||||
.utcOffset(parseInt(mailpoet_date_offset))
|
||||
.format('ddd, D MMM YYYY HH:mm:ss');
|
||||
label += ' (Unsubscribed on '+unsubscribed_at+')';
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
return label;
|
||||
}
|
||||
}
|
||||
];
|
||||
@@ -58,11 +89,11 @@ define(
|
||||
label: custom_field.name,
|
||||
type: custom_field.type
|
||||
};
|
||||
if(custom_field.params) {
|
||||
if (custom_field.params) {
|
||||
field.params = custom_field.params;
|
||||
}
|
||||
|
||||
if(custom_field.params.values) {
|
||||
if (custom_field.params.values) {
|
||||
field.values = custom_field.params.values;
|
||||
}
|
||||
|
||||
|
@@ -231,6 +231,15 @@ const item_actions = [
|
||||
];
|
||||
|
||||
const SubscriberList = React.createClass({
|
||||
getSegmentFromId: function(segment_id) {
|
||||
let result = false;
|
||||
mailpoet_segments.map(function(segment) {
|
||||
if (segment.id === segment_id) {
|
||||
result = segment;
|
||||
}
|
||||
});
|
||||
return result;
|
||||
},
|
||||
renderItem: function(subscriber, actions) {
|
||||
let row_classes = classNames(
|
||||
'manage-column',
|
||||
@@ -255,11 +264,41 @@ const SubscriberList = React.createClass({
|
||||
break;
|
||||
}
|
||||
|
||||
let segments = mailpoet_segments.filter(function(segment) {
|
||||
return (jQuery.inArray(segment.id, subscriber.segments) !== -1);
|
||||
}).map(function(segment) {
|
||||
return segment.name;
|
||||
}).join(', ');
|
||||
let segments = false;
|
||||
|
||||
if (subscriber.subscriptions.length > 0) {
|
||||
let subscribed_segments = [];
|
||||
let unsubscribed_segments = [];
|
||||
|
||||
subscriber.subscriptions.map((subscription) => {
|
||||
const segment = this.getSegmentFromId(subscription.segment_id);
|
||||
if (subscription.status === 'subscribed') {
|
||||
subscribed_segments.push(segment.name);
|
||||
} else {
|
||||
unsubscribed_segments.push(segment.name);
|
||||
}
|
||||
});
|
||||
|
||||
segments = (
|
||||
<span>
|
||||
<span className="mailpoet_segments_subscribed">
|
||||
{ subscribed_segments.join(', ') }
|
||||
{
|
||||
(
|
||||
subscribed_segments.length > 0
|
||||
&& unsubscribed_segments.length > 0
|
||||
) ? ' / ' : ''
|
||||
}
|
||||
</span>
|
||||
<span
|
||||
className="mailpoet_segments_unsubscribed"
|
||||
title="Lists to which the subscriber was subscribed."
|
||||
>
|
||||
{ unsubscribed_segments.join(', ') }
|
||||
</span>
|
||||
</span>
|
||||
);
|
||||
}
|
||||
|
||||
let avatar = false;
|
||||
if(subscriber.avatar_url) {
|
||||
|
Reference in New Issue
Block a user