refactored bulk actions & implemented bulk trash for all listings

This commit is contained in:
Jonathan Labreuille
2015-09-18 17:39:25 +02:00
parent cbcd614b6f
commit 239e2583d2
16 changed files with 259 additions and 160 deletions

View File

@ -275,9 +275,13 @@ define(
} else { } else {
this.props.messages['created'](); this.props.messages['created']();
} }
} else {
if(response === false) {
// unknown error occurred
} else { } else {
this.setState({ errors: response }); this.setState({ errors: response });
} }
}
}.bind(this)); }.bind(this));
}, },
handleValueChange: function(e) { handleValueChange: function(e) {

View File

@ -241,12 +241,12 @@ define(
var data = params || {}; var data = params || {};
data.selection = selected_ids;
data.listing = { data.listing = {
offset: 0, offset: 0,
limit: 0, limit: 0,
group: this.state.group, group: this.state.group,
search: this.state.search search: this.state.search,
selection: selected_ids
} }
MailPoet.Ajax.post({ MailPoet.Ajax.post({

View File

@ -27,6 +27,13 @@ define(
} }
]; ];
var bulk_actions = [
{
name: 'trash',
label: 'Trash'
}
];
var NewsletterList = React.createClass({ var NewsletterList = React.createClass({
renderItem: function(newsletter, actions) { renderItem: function(newsletter, actions) {
var rowClasses = classNames( var rowClasses = classNames(
@ -57,8 +64,8 @@ define(
<Listing <Listing
endpoint="newsletters" endpoint="newsletters"
onRenderItem={this.renderItem} onRenderItem={this.renderItem}
items={this.getItems} columns={columns}
columns={columns} /> bulk_actions={ bulk_actions } />
); );
} }
}); });

View File

@ -27,6 +27,13 @@ define(
} }
]; ];
var bulk_actions = [
{
name: 'trash',
label: 'Trash'
}
];
var SegmentList = React.createClass({ var SegmentList = React.createClass({
renderItem: function(segment, actions) { renderItem: function(segment, actions) {
var rowClasses = classNames( var rowClasses = classNames(
@ -57,8 +64,8 @@ define(
<Listing <Listing
endpoint="segments" endpoint="segments"
onRenderItem={this.renderItem} onRenderItem={this.renderItem}
items={this.getItems} columns={columns}
columns={columns} /> bulk_actions={ bulk_actions } />
); );
} }
}); });

View File

@ -67,7 +67,7 @@ define(
action: 'listing', action: 'listing',
data: { data: {
'offset': 0, 'offset': 0,
'limit': 5, 'limit': 100,
'search': '', 'search': '',
'sort_by': 'name', 'sort_by': 'name',
'sort_order': 'asc' 'sort_order': 'asc'
@ -145,7 +145,7 @@ define(
var bulk_actions = [ var bulk_actions = [
{ {
name: 'move', name: 'moveToList',
label: 'Move to list...', label: 'Move to list...',
onSelect: function() { onSelect: function() {
return ( return (
@ -161,7 +161,7 @@ define(
} }
}, },
{ {
name: 'add', name: 'addToList',
label: 'Add to list...', label: 'Add to list...',
onSelect: function() { onSelect: function() {
return ( return (
@ -177,7 +177,7 @@ define(
} }
}, },
{ {
name: 'remove', name: 'removeFromList',
label: 'Remove from list...', label: 'Remove from list...',
onSelect: function() { onSelect: function() {
return ( return (
@ -198,7 +198,7 @@ define(
} }
]; ];
var List = React.createClass({ var SubscriberList = React.createClass({
renderItem: function(subscriber, actions) { renderItem: function(subscriber, actions) {
var row_classes = classNames( var row_classes = classNames(
'manage-column', 'manage-column',
@ -259,6 +259,6 @@ define(
} }
}); });
return List; return SubscriberList;
} }
); );

View File

@ -29,6 +29,9 @@ class Initializer {
\ORM::configure('username', Env::$db_username); \ORM::configure('username', Env::$db_username);
\ORM::configure('password', Env::$db_password); \ORM::configure('password', Env::$db_password);
\ORM::configure('logging', WP_DEBUG); \ORM::configure('logging', WP_DEBUG);
\ORM::configure('driver_options', array(
\PDO::MYSQL_ATTR_INIT_COMMAND => 'SET NAMES utf8'
));
$subscribers = Env::$db_prefix . 'subscribers'; $subscribers = Env::$db_prefix . 'subscribers';
$settings = Env::$db_prefix . 'settings'; $settings = Env::$db_prefix . 'settings';

View File

@ -0,0 +1,28 @@
<?php
namespace MailPoet\Listing;
if(!defined('ABSPATH')) exit;
class BulkAction {
private $listing = null;
private $data = null;
private $model = null;
function __construct($model, $data) {
$this->model = $model;
$this->data = $data;
$this->listing = new Handler(
\Model::factory($this->model),
$this->data['listing']
);
return $this;
}
function apply() {
return call_user_func_array(
array($this->model, $this->data['action']),
array($this->listing, $this->data)
);
}
}

View File

@ -20,7 +20,9 @@ class Handler {
'sort_by' => (isset($data['sort_by']) ? $data['sort_by'] : 'id'), 'sort_by' => (isset($data['sort_by']) ? $data['sort_by'] : 'id'),
'sort_order' => (isset($data['sort_order']) ? $data['sort_order'] : 'asc'), 'sort_order' => (isset($data['sort_order']) ? $data['sort_order'] : 'asc'),
// grouping // grouping
'group' => (isset($data['group']) ? $data['group'] : null) 'group' => (isset($data['group']) ? $data['group'] : null),
// selection
'selection' => (isset($data['selection']) ? $data['selection'] : null)
); );
$this->setSearch(); $this->setSearch();
@ -47,18 +49,18 @@ class Handler {
return $this->model->filter('group', $this->data['group']); return $this->model->filter('group', $this->data['group']);
} }
function getSelection($ids = array()) { function getSelection() {
if(!empty($ids)) { if(!empty($this->data['selection'])) {
$this->model->whereIn('id', $ids); $this->model->whereIn('id', $this->data['selection']);
} }
return $this->model; return $this->model;
} }
function getSelectionIds($ids = array()) { function getSelectionIds() {
$subscribers = $this->getSelection($ids)->select('id')->findMany(); $models = $this->getSelection()->select('id')->findMany();
return array_map(function($subscriber) { return array_map(function($model) {
return (int)$subscriber->id; return (int)$model->id;
}, $subscribers); }, $models);
} }
function get() { function get() {

View File

@ -48,10 +48,18 @@ class Newsletter extends Model {
$saved = $newsletter->save(); $saved = $newsletter->save();
if($saved === false) { if($saved === true) {
return $newsletter->getValidationErrors();
} else {
return true; return true;
} else {
$errors = $newsletter->getValidationErrors();
if(!empty($errors)) {
return $errors;
} }
} }
return false;
}
static function trash($listing) {
return $listing->getSelection()->deleteMany();
}
} }

View File

@ -57,10 +57,18 @@ class Segment extends Model {
$saved = $segment->save(); $saved = $segment->save();
if($saved === false) { if($saved === true) {
return $segment->getValidationErrors();
} else {
return true; return true;
} else {
$errors = $segment->getValidationErrors();
if(!empty($errors)) {
return $errors;
} }
} }
return false;
}
static function trash($listing) {
return $listing->getSelection()->deleteMany();
}
} }

View File

@ -95,10 +95,76 @@ class Subscriber extends Model {
$saved = $subscriber->save(); $saved = $subscriber->save();
if($saved === false) { if($saved === true) {
return $subscriber->getValidationErrors(); return true;
} else { } else {
$errors = $subscriber->getValidationErrors();
if(!empty($errors)) {
return $errors;
}
}
return false;
}
static function moveToList($listing, $data = array()) {
$segment_id = (isset($data['segment_id']) ? (int)$data['segment_id'] : 0);
$segment = Segment::findOne($segment_id);
if($segment !== false) {
$subscribers = $listing->getSelection()->findMany();
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();
}
return true; return true;
} }
return false;
}
static function removeFromList($listing, $data = array()) {
$segment_id = (isset($data['segment_id']) ? (int)$data['segment_id'] : 0);
$segment = Segment::findOne($segment_id);
if($segment !== false) {
// delete relations with segment
$subscriber_ids = $listing->getSelectionIds();
SubscriberSegment::whereIn('subscriber_id', $subscriber_ids)
->where('segment_id', $segment->id)
->deleteMany();
return true;
}
return false;
}
static function addToList($listing, $data = array()) {
$segment_id = (isset($data['segment_id']) ? (int)$data['segment_id'] : 0);
$segment = Segment::findOne($segment_id);
if($segment !== false) {
$subscribers = $listing->getSelection()->findMany();
foreach($subscribers as $subscriber) {
// create relation with segment
$association = \MailPoet\Models\SubscriberSegment::create();
$association->subscriber_id = $subscriber->id;
$association->segment_id = $segment->id;
$association->save();
}
return true;
}
return false;
}
static function trash($listing) {
// delete relations with all segments
$subscriber_ids = $listing->getSelectionIds();
\MailPoet\Models\SubscriberSegment::whereIn('subscriber_id', $subscriber_ids)->deleteMany();
return $listing->getSelection()->deleteMany();
} }
} }

View File

@ -62,4 +62,13 @@ class Newsletters {
$mailer = new Bridge($newsletter, $subscribers); $mailer = new Bridge($newsletter, $subscribers);
wp_send_json($mailer->send()); wp_send_json($mailer->send());
} }
function bulk_action($data = array()) {
$bulk_action = new Listing\BulkAction(
'\MailPoet\Models\Newsletter',
$data
);
wp_send_json($bulk_action->apply());
}
} }

View File

@ -24,7 +24,7 @@ class Router {
$class = ucfirst($_POST['endpoint']); $class = ucfirst($_POST['endpoint']);
$endpoint = __NAMESPACE__ . "\\" . $class; $endpoint = __NAMESPACE__ . "\\" . $class;
$method = $_POST['method']; $method = $_POST['method'];
$data = isset($_POST['data']) ? $_POST['data'] : array(); $data = isset($_POST['data']) ? stripslashes_deep($_POST['data']) : array();
$endpoint = new $endpoint(); $endpoint = new $endpoint();
$endpoint->$method($data); $endpoint->$method($data);
} }

View File

@ -53,4 +53,13 @@ class Segments {
wp_send_json($result); wp_send_json($result);
} }
function bulk_action($data = array()) {
$bulk_action = new Listing\BulkAction(
'\MailPoet\Models\Segment',
$data
);
wp_send_json($bulk_action->apply());
}
} }

View File

@ -30,69 +30,6 @@ class Subscribers {
wp_send_json($listing->get()); 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() { function getAll() {
$collection = Subscriber::findArray(); $collection = Subscriber::findArray();
wp_send_json($collection); wp_send_json($collection);
@ -112,4 +49,13 @@ class Subscribers {
} }
wp_send_json($result); wp_send_json($result);
} }
function bulk_action($data = array()) {
$bulk_action = new Listing\BulkAction(
'\MailPoet\Models\Subscriber',
$data
);
wp_send_json($bulk_action->apply());
}
} }

View File

@ -122,8 +122,9 @@ abstract class ValidModel extends \Model
} }
$errs = $this->getValidationErrors(); $errs = $this->getValidationErrors();
if (!empty($errs)) if (!empty($errs)) {
$this->doValidationError(self::ON_SAVE); $this->doValidationError(self::ON_SAVE);
}
parent::save(); parent::save();
} }
@ -148,9 +149,10 @@ abstract class ValidModel extends \Model
// Protected methods // Protected methods
protected function doValidationError($context) protected function doValidationError($context)
{ {
if ($context == $this->_validationOptions['throw']) if ($context == $this->_validationOptions['throw']) {
throw new \Sudzy\ValidationException($this->_validationErrors); throw new \Sudzy\ValidationException($this->_validationErrors);
} }
}
protected function addValidationError($msg, $field = null) protected function addValidationError($msg, $field = null)
{ {
@ -177,4 +179,4 @@ abstract class ValidModel extends \Model
{ {
if (null == $this->_validator) $this->_validator = new \Sudzy\Engine(); // Is lazy setup worth it? if (null == $this->_validator) $this->_validator = new \Sudzy\Engine(); // Is lazy setup worth it?
} }
} }