implemented all bulk actions for Subscribers
This commit is contained in:
@ -35,18 +35,22 @@ define('ajax', ['mailpoet', 'jquery'], function(MailPoet, jQuery) {
|
||||
this.options.token = window.mailpoet_token;
|
||||
}
|
||||
},
|
||||
request: function(method, options) {
|
||||
// set options
|
||||
this.init(options);
|
||||
|
||||
// set request params
|
||||
var params = {
|
||||
getParams: function() {
|
||||
return {
|
||||
action: 'mailpoet',
|
||||
token: this.options.token,
|
||||
endpoint: this.options.endpoint,
|
||||
method: this.options.action,
|
||||
data: this.options.data || {}
|
||||
}, jqXHR;
|
||||
}
|
||||
},
|
||||
request: function(method, options) {
|
||||
// set options
|
||||
this.init(options);
|
||||
|
||||
// set request params
|
||||
var params = this.getParams();
|
||||
var jqXHR;
|
||||
|
||||
// make ajax request depending on method
|
||||
if(method === 'get') {
|
||||
|
@ -1,21 +1,54 @@
|
||||
define(['react'], function(React) {
|
||||
|
||||
define([
|
||||
'react',
|
||||
'mailpoet'
|
||||
],
|
||||
function(
|
||||
React,
|
||||
MailPoet
|
||||
) {
|
||||
var ListingBulkActions = React.createClass({
|
||||
getInitialState: function() {
|
||||
return {
|
||||
action: false,
|
||||
extra: false
|
||||
}
|
||||
},
|
||||
handleChangeAction: function(e) {
|
||||
this.setState({
|
||||
action: e.target.value,
|
||||
extra: false
|
||||
});
|
||||
|
||||
var action = this.getSelectedAction();
|
||||
|
||||
// action on select callback
|
||||
if(action !== null && action['onSelect'] !== undefined) {
|
||||
action.onSelect(e);
|
||||
this.setState({
|
||||
extra: action.onSelect(e)
|
||||
});
|
||||
}
|
||||
},
|
||||
handleApplyAction: function(e) {
|
||||
e.preventDefault();
|
||||
|
||||
var action = this.getSelectedAction();
|
||||
var selected_ids = (this.props.selection !== 'all')
|
||||
? this.props.selected_ids
|
||||
: [];
|
||||
var data = (action['getData'] !== undefined)
|
||||
? action.getData()
|
||||
: {};
|
||||
|
||||
if(action !== null && action['onApply'] !== undefined) {
|
||||
action.onApply();
|
||||
data.action = this.state.action;
|
||||
|
||||
if(data.action) {
|
||||
this.props.onBulkAction(selected_ids, data);
|
||||
}
|
||||
|
||||
this.setState({
|
||||
action: false,
|
||||
extra: false
|
||||
});
|
||||
},
|
||||
getSelectedAction: function() {
|
||||
var selected_action = jQuery(this.refs.action.getDOMNode()).val();
|
||||
@ -43,13 +76,13 @@ define(['react'], function(React) {
|
||||
Select bulk action
|
||||
</label>
|
||||
|
||||
<select ref="action" onChange={this.handleChangeAction}>
|
||||
<select ref="action" value={ this.state.action } onChange={this.handleChangeAction}>
|
||||
<option value="">Bulk Actions</option>
|
||||
{this.props.bulk_actions.map(function(action, index) {
|
||||
return (
|
||||
<option
|
||||
value={action.name}
|
||||
key={index}
|
||||
value={ action.name }
|
||||
key={ 'action-' + index }
|
||||
>{ action.label }</option>
|
||||
);
|
||||
}.bind(this))}
|
||||
@ -59,6 +92,8 @@ define(['react'], function(React) {
|
||||
type="submit"
|
||||
defaultValue="Apply"
|
||||
className="button action" />
|
||||
|
||||
{ this.state.extra }
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
@ -200,6 +200,8 @@ define(
|
||||
getItems: function() {
|
||||
this.setState({ loading: true });
|
||||
|
||||
this.clearSelection();
|
||||
|
||||
MailPoet.Ajax.post({
|
||||
endpoint: this.props.endpoint,
|
||||
action: 'listing',
|
||||
@ -234,6 +236,27 @@ define(
|
||||
this.getItems();
|
||||
}.bind(this));
|
||||
},
|
||||
handleBulkAction: function(selected_ids, params) {
|
||||
this.setState({ loading: true });
|
||||
|
||||
var data = params || {};
|
||||
|
||||
data.selection = selected_ids;
|
||||
data.listing = {
|
||||
offset: 0,
|
||||
limit: 0,
|
||||
group: this.state.group,
|
||||
search: this.state.search
|
||||
}
|
||||
|
||||
MailPoet.Ajax.post({
|
||||
endpoint: this.props.endpoint,
|
||||
action: 'bulk_action',
|
||||
data: data
|
||||
}).done(function() {
|
||||
this.getItems();
|
||||
}.bind(this));
|
||||
},
|
||||
handleSearch: function(search) {
|
||||
this.setState({
|
||||
search: search,
|
||||
@ -248,7 +271,6 @@ define(
|
||||
sort_by: sort_by,
|
||||
sort_order: sort_order,
|
||||
}, function() {
|
||||
this.clearSelection();
|
||||
this.getItems();
|
||||
}.bind(this));
|
||||
},
|
||||
@ -268,7 +290,6 @@ define(
|
||||
},
|
||||
handleSelectItems: function(is_checked) {
|
||||
if(is_checked === false) {
|
||||
this.clearSelection();
|
||||
} else {
|
||||
var selected_ids = this.state.items.map(function(item) {
|
||||
return ~~item.id;
|
||||
@ -282,7 +303,6 @@ define(
|
||||
},
|
||||
handleSelectAll: function() {
|
||||
if(this.state.selection === 'all') {
|
||||
this.clearSelection();
|
||||
} else {
|
||||
this.setState({
|
||||
selection: 'all',
|
||||
@ -306,7 +326,6 @@ define(
|
||||
search: '',
|
||||
page: 1
|
||||
}, function() {
|
||||
this.clearSelection();
|
||||
this.getItems();
|
||||
}.bind(this));
|
||||
},
|
||||
@ -354,7 +373,10 @@ define(
|
||||
search={ this.state.search } />
|
||||
<div className="tablenav top clearfix">
|
||||
<ListingBulkActions
|
||||
bulk_actions={ bulk_actions } />
|
||||
bulk_actions={ bulk_actions }
|
||||
selection={ this.state.selection }
|
||||
selected_ids={ this.state.selected_ids }
|
||||
onBulkAction={ this.handleBulkAction } />
|
||||
<ListingFilters filters={ this.state.filters } />
|
||||
<ListingPages
|
||||
count={ this.state.count }
|
||||
@ -381,8 +403,8 @@ define(
|
||||
is_selectable={ bulk_actions.length > 0 }
|
||||
onSelectItem={ this.handleSelectItem }
|
||||
onSelectAll={ this.handleSelectAll }
|
||||
selected_ids={ this.state.selected_ids }
|
||||
selection={ this.state.selection }
|
||||
selected_ids={ this.state.selected_ids }
|
||||
loading={ this.state.loading }
|
||||
count={ this.state.count }
|
||||
limit={ this.state.limit }
|
||||
@ -402,7 +424,10 @@ define(
|
||||
</table>
|
||||
<div className="tablenav bottom">
|
||||
<ListingBulkActions
|
||||
bulk_actions={ bulk_actions } />
|
||||
bulk_actions={ bulk_actions }
|
||||
selection={ this.state.selection }
|
||||
selected_ids={ this.state.selected_ids }
|
||||
onBulkAction={ this.handleBulkAction } />
|
||||
<ListingPages
|
||||
count={ this.state.count }
|
||||
page={ this.state.page }
|
||||
|
@ -2,12 +2,17 @@ define(
|
||||
[
|
||||
'react',
|
||||
'listing/listing.jsx',
|
||||
'classnames'
|
||||
'classnames',
|
||||
'mailpoet',
|
||||
'jquery',
|
||||
'select2'
|
||||
],
|
||||
function(
|
||||
React,
|
||||
Listing,
|
||||
classNames
|
||||
classNames,
|
||||
MailPoet,
|
||||
jQuery
|
||||
) {
|
||||
var columns = [
|
||||
{
|
||||
@ -42,18 +47,154 @@ define(
|
||||
},
|
||||
];
|
||||
|
||||
var ItemSelection = React.createClass({
|
||||
getInitialState: function() {
|
||||
return {
|
||||
loading: false,
|
||||
items: [],
|
||||
selected: false,
|
||||
multiple: false
|
||||
}
|
||||
},
|
||||
componentDidMount: function() {
|
||||
this.loadItems();
|
||||
},
|
||||
loadItems: function() {
|
||||
this.setState({ loading: true });
|
||||
|
||||
MailPoet.Ajax.post({
|
||||
endpoint: this.props.endpoint,
|
||||
action: 'listing',
|
||||
data: {
|
||||
'offset': 0,
|
||||
'limit': 5,
|
||||
'search': '',
|
||||
'sort_by': 'name',
|
||||
'sort_order': 'asc'
|
||||
}
|
||||
})
|
||||
.done(function(response) {
|
||||
if(this.isMounted()) {
|
||||
if(response === false) {
|
||||
this.setState({
|
||||
loading: false,
|
||||
items: []
|
||||
});
|
||||
} else {
|
||||
this.setState({
|
||||
loading: false,
|
||||
items: response.items
|
||||
});
|
||||
}
|
||||
}
|
||||
}.bind(this));
|
||||
},
|
||||
handleChange: function() {
|
||||
var new_value = this.refs.selection.getDOMNode().value;
|
||||
|
||||
if(this.state.multiple === false) {
|
||||
if(new_value.trim().length === 0) {
|
||||
new_value = false;
|
||||
}
|
||||
|
||||
this.setState({
|
||||
selected: new_value
|
||||
});
|
||||
} else {
|
||||
var selected_values = this.state.selected || [];
|
||||
|
||||
if(selected_values.indexOf(new_value) !== -1) {
|
||||
// value already present so remove it
|
||||
selected_values.splice(selected_values.indexOf(new_value), 1);
|
||||
} else {
|
||||
selected_values.push(new_value);
|
||||
}
|
||||
|
||||
this.setState({
|
||||
selected: selected_values
|
||||
});
|
||||
}
|
||||
},
|
||||
getSelected: function() {
|
||||
return this.state.selected;
|
||||
},
|
||||
render: function() {
|
||||
var options = this.state.items.map(function(item, index) {
|
||||
return (
|
||||
<option
|
||||
key={ 'action-' + index }
|
||||
value={ item.id }>
|
||||
{ item.name }
|
||||
</option>
|
||||
);
|
||||
});
|
||||
|
||||
return (
|
||||
<select
|
||||
ref="selection"
|
||||
id={ this.props.id }
|
||||
value={ this.state.selected }
|
||||
onChange={ this.handleChange }
|
||||
multiple={ this.state.multiple }>
|
||||
<option value="">Select a list</option>
|
||||
{ options }
|
||||
</select>
|
||||
);
|
||||
}
|
||||
});
|
||||
|
||||
var bulk_actions = [
|
||||
{
|
||||
name: 'move',
|
||||
label: 'Move to list...'
|
||||
label: 'Move to list...',
|
||||
onSelect: function() {
|
||||
return (
|
||||
<ItemSelection
|
||||
endpoint="segments"
|
||||
id="move_to_segment" />
|
||||
);
|
||||
},
|
||||
getData: function() {
|
||||
return {
|
||||
segment_id: ~~(jQuery('#move_to_segment').val())
|
||||
}
|
||||
}
|
||||
},
|
||||
{
|
||||
name: 'add',
|
||||
label: 'Add to list...'
|
||||
label: 'Add to list...',
|
||||
onSelect: function() {
|
||||
return (
|
||||
<ItemSelection
|
||||
endpoint="segments"
|
||||
id="add_to_segment" />
|
||||
);
|
||||
},
|
||||
getData: function() {
|
||||
return {
|
||||
segment_id: ~~(jQuery('#add_to_segment').val())
|
||||
}
|
||||
}
|
||||
},
|
||||
{
|
||||
name: 'remove',
|
||||
label: 'Remove from list...'
|
||||
label: 'Remove from list...',
|
||||
onSelect: function() {
|
||||
return (
|
||||
<ItemSelection
|
||||
endpoint="segments"
|
||||
id="remove_from_segment" />
|
||||
);
|
||||
},
|
||||
getData: function() {
|
||||
return {
|
||||
segment_id: ~~(jQuery('#remove_from_segment').val())
|
||||
}
|
||||
}
|
||||
},
|
||||
{
|
||||
name: 'trash',
|
||||
label: 'Trash'
|
||||
}
|
||||
];
|
||||
|
||||
|
@ -29,7 +29,7 @@ class Handler {
|
||||
}
|
||||
|
||||
private function setSearch() {
|
||||
if($this->data['search'] === null) {
|
||||
if(empty($this->data['search'])) {
|
||||
return;
|
||||
}
|
||||
return $this->model->filter('search', $this->data['search']);
|
||||
@ -47,6 +47,20 @@ class Handler {
|
||||
return $this->model->filter('group', $this->data['group']);
|
||||
}
|
||||
|
||||
function getSelection($ids = array()) {
|
||||
if(!empty($ids)) {
|
||||
$this->model->whereIn('id', $ids);
|
||||
}
|
||||
return $this->model;
|
||||
}
|
||||
|
||||
function getSelectionIds($ids = array()) {
|
||||
$subscribers = $this->getSelection($ids)->select('id')->findMany();
|
||||
return array_map(function($subscriber) {
|
||||
return (int)$subscriber->id;
|
||||
}, $subscribers);
|
||||
}
|
||||
|
||||
function get() {
|
||||
return array(
|
||||
'count' => $this->model->count(),
|
||||
@ -55,7 +69,7 @@ class Handler {
|
||||
'items' => $this->model
|
||||
->offset($this->data['offset'])
|
||||
->limit($this->data['limit'])
|
||||
->find_array()
|
||||
->findArray()
|
||||
);
|
||||
}
|
||||
}
|
@ -15,6 +15,13 @@ class Subscriber extends Model {
|
||||
));
|
||||
}
|
||||
|
||||
function delete() {
|
||||
// delete all relations to segments
|
||||
SubscriberSegment::where('subscriber_id', $this->id)->deleteMany();
|
||||
|
||||
parent::delete();
|
||||
}
|
||||
|
||||
static function search($orm, $search = '') {
|
||||
if(strlen(trim($search) === 0)) {
|
||||
return $orm;
|
||||
|
@ -3,6 +3,7 @@ namespace MailPoet\Router;
|
||||
|
||||
use MailPoet\Listing;
|
||||
use MailPoet\Models\Subscriber;
|
||||
use MailPoet\Models\SubscriberSegment;
|
||||
|
||||
if(!defined('ABSPATH')) exit;
|
||||
|
||||
@ -29,6 +30,69 @@ class Subscribers {
|
||||
wp_send_json($listing->get());
|
||||
}
|
||||
|
||||
function bulk_action($data = array()) {
|
||||
$action = $data['action'];
|
||||
$selection = (isset($data['selection']) ? $data['selection'] : null);
|
||||
$listing_data = $data['listing'];
|
||||
|
||||
$listing = new Listing\Handler(
|
||||
\Model::factory('\MailPoet\Models\Subscriber'),
|
||||
$listing_data
|
||||
);
|
||||
|
||||
$selected = $listing->getSelection($selection);
|
||||
$subscribers = $selected->findMany();
|
||||
|
||||
$result = false;
|
||||
switch($action) {
|
||||
case 'move':
|
||||
$segment_id = (isset($data['segment_id']) ? (int)$data['segment_id'] : 0);
|
||||
foreach($subscribers as $subscriber) {
|
||||
// remove subscriber from all segments
|
||||
SubscriberSegment::where('subscriber_id', $subscriber->id)->deleteMany();
|
||||
|
||||
// create relation with segment
|
||||
$association = SubscriberSegment::create();
|
||||
$association->subscriber_id = $subscriber->id;
|
||||
$association->segment_id = $segment_id;
|
||||
$association->save();
|
||||
}
|
||||
$result = true;
|
||||
break;
|
||||
|
||||
case 'remove':
|
||||
$segment_id = (isset($data['segment_id']) ? (int)$data['segment_id'] : 0);
|
||||
// delete relations with segment
|
||||
$subscriber_ids = $listing->getSelectionIds($selection);
|
||||
$result = SubscriberSegment::whereIn('subscriber_id', $subscriber_ids)
|
||||
->where('segment_id', $segment_id)
|
||||
->deleteMany();
|
||||
break;
|
||||
|
||||
case 'add':
|
||||
$segment_id = (isset($data['segment_id']) ? (int)$data['segment_id'] : 0);
|
||||
foreach($subscribers as $subscriber) {
|
||||
// create relation with segment
|
||||
$association = SubscriberSegment::create();
|
||||
$association->subscriber_id = $subscriber->id;
|
||||
$association->segment_id = $segment_id;
|
||||
$association->save();
|
||||
}
|
||||
$result = true;
|
||||
break;
|
||||
|
||||
case 'trash':
|
||||
// delete relations with all segments
|
||||
$subscriber_ids = $listing->getSelectionIds($selection);
|
||||
SubscriberSegment::whereIn('subscriber_id', $subscriber_ids)->deleteMany();
|
||||
|
||||
$result = $selected->deleteMany();
|
||||
break;
|
||||
}
|
||||
|
||||
wp_send_json($result);
|
||||
}
|
||||
|
||||
function getAll() {
|
||||
$collection = Subscriber::findArray();
|
||||
wp_send_json($collection);
|
||||
|
Reference in New Issue
Block a user