Bulk actions + Extra data
- fixed issue on bulk action being run even without any items selected - added WP like feature regarding item selection, if all items are checked, it also checks the header/footer checkboxes - fixed issue where the selection state was not properly reset - added List column to subscribers - added json_encode/json_decode to Twig
This commit is contained in:
@@ -32,9 +32,15 @@ function(
|
|||||||
e.preventDefault();
|
e.preventDefault();
|
||||||
|
|
||||||
var action = this.getSelectedAction();
|
var action = this.getSelectedAction();
|
||||||
|
|
||||||
|
if(action === null) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
var selected_ids = (this.props.selection !== 'all')
|
var selected_ids = (this.props.selection !== 'all')
|
||||||
? this.props.selected_ids
|
? this.props.selected_ids
|
||||||
: [];
|
: [];
|
||||||
|
|
||||||
var data = (action['getData'] !== undefined)
|
var data = (action['getData'] !== undefined)
|
||||||
? action.getData()
|
? action.getData()
|
||||||
: {};
|
: {};
|
||||||
@@ -78,17 +84,17 @@ function(
|
|||||||
|
|
||||||
<select ref="action" value={ this.state.action } onChange={this.handleChangeAction}>
|
<select ref="action" value={ this.state.action } onChange={this.handleChangeAction}>
|
||||||
<option value="">Bulk Actions</option>
|
<option value="">Bulk Actions</option>
|
||||||
{this.props.bulk_actions.map(function(action, index) {
|
{ this.props.bulk_actions.map(function(action, index) {
|
||||||
return (
|
return (
|
||||||
<option
|
<option
|
||||||
value={ action.name }
|
value={ action.name }
|
||||||
key={ 'action-' + index }
|
key={ 'action-' + index }
|
||||||
>{ action.label }</option>
|
>{ action.label }</option>
|
||||||
);
|
);
|
||||||
}.bind(this))}
|
}.bind(this)) }
|
||||||
</select>
|
</select>
|
||||||
<input
|
<input
|
||||||
onClick={this.handleApplyAction}
|
onClick={ this.handleApplyAction }
|
||||||
type="submit"
|
type="submit"
|
||||||
defaultValue="Apply"
|
defaultValue="Apply"
|
||||||
className="button action" />
|
className="button action" />
|
||||||
|
@@ -237,6 +237,10 @@ define(
|
|||||||
}.bind(this));
|
}.bind(this));
|
||||||
},
|
},
|
||||||
handleBulkAction: function(selected_ids, params) {
|
handleBulkAction: function(selected_ids, params) {
|
||||||
|
if(this.state.selection === false) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
this.setState({ loading: true });
|
this.setState({ loading: true });
|
||||||
|
|
||||||
var data = params || {};
|
var data = params || {};
|
||||||
@@ -275,21 +279,29 @@ define(
|
|||||||
}.bind(this));
|
}.bind(this));
|
||||||
},
|
},
|
||||||
handleSelectItem: function(id, is_checked) {
|
handleSelectItem: function(id, is_checked) {
|
||||||
var selected_ids = this.state.selected_ids;
|
var selected_ids = this.state.selected_ids,
|
||||||
|
selection = false;
|
||||||
|
|
||||||
if(is_checked) {
|
if(is_checked) {
|
||||||
selected_ids = jQuery.merge(selected_ids, [ id ]);
|
selected_ids = jQuery.merge(selected_ids, [ id ]);
|
||||||
|
// check whether all items on the page are selected
|
||||||
|
if(
|
||||||
|
jQuery('tbody .check-column :checkbox:not(:checked)').length === 0
|
||||||
|
) {
|
||||||
|
selection = 'page';
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
selected_ids.splice(selected_ids.indexOf(id), 1);
|
selected_ids.splice(selected_ids.indexOf(id), 1);
|
||||||
}
|
}
|
||||||
|
|
||||||
this.setState({
|
this.setState({
|
||||||
selection: false,
|
selection: selection,
|
||||||
selected_ids: selected_ids
|
selected_ids: selected_ids
|
||||||
});
|
});
|
||||||
},
|
},
|
||||||
handleSelectItems: function(is_checked) {
|
handleSelectItems: function(is_checked) {
|
||||||
if(is_checked === false) {
|
if(is_checked === false) {
|
||||||
|
this.clearSelection();
|
||||||
} else {
|
} else {
|
||||||
var selected_ids = this.state.items.map(function(item) {
|
var selected_ids = this.state.items.map(function(item) {
|
||||||
return ~~item.id;
|
return ~~item.id;
|
||||||
|
@@ -1,6 +1,7 @@
|
|||||||
define(
|
define(
|
||||||
[
|
[
|
||||||
'react',
|
'react',
|
||||||
|
'react-router',
|
||||||
'listing/listing.jsx',
|
'listing/listing.jsx',
|
||||||
'classnames',
|
'classnames',
|
||||||
'mailpoet',
|
'mailpoet',
|
||||||
@@ -9,11 +10,14 @@ define(
|
|||||||
],
|
],
|
||||||
function(
|
function(
|
||||||
React,
|
React,
|
||||||
|
Router,
|
||||||
Listing,
|
Listing,
|
||||||
classNames,
|
classNames,
|
||||||
MailPoet,
|
MailPoet,
|
||||||
jQuery
|
jQuery
|
||||||
) {
|
) {
|
||||||
|
var Link = Router.Link;
|
||||||
|
|
||||||
var columns = [
|
var columns = [
|
||||||
{
|
{
|
||||||
name: 'email',
|
name: 'email',
|
||||||
@@ -35,6 +39,12 @@ define(
|
|||||||
label: 'Status',
|
label: 'Status',
|
||||||
sortable: true
|
sortable: true
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
name: 'lists',
|
||||||
|
label: 'Lists',
|
||||||
|
sortable: false
|
||||||
|
},
|
||||||
|
|
||||||
{
|
{
|
||||||
name: 'created_at',
|
name: 'created_at',
|
||||||
label: 'Subscribed on',
|
label: 'Subscribed on',
|
||||||
@@ -57,7 +67,16 @@ define(
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
componentDidMount: function() {
|
componentDidMount: function() {
|
||||||
this.loadItems();
|
// this.loadItems();
|
||||||
|
this.loadCachedItems();
|
||||||
|
},
|
||||||
|
loadCachedItems: function() {
|
||||||
|
if(typeof(window['mailpoet_'+this.props.endpoint]) !== 'undefined') {
|
||||||
|
var items = window['mailpoet_'+this.props.endpoint];
|
||||||
|
this.setState({
|
||||||
|
items: items
|
||||||
|
});
|
||||||
|
}
|
||||||
},
|
},
|
||||||
loadItems: function() {
|
loadItems: function() {
|
||||||
this.setState({ loading: true });
|
this.setState({ loading: true });
|
||||||
@@ -222,11 +241,19 @@ define(
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
var segments = mailpoet_segments.filter(function(segment) {
|
||||||
|
return (jQuery.inArray(segment.id, subscriber.segments) !== -1);
|
||||||
|
}).map(function(segment) {
|
||||||
|
return segment.name;
|
||||||
|
}).join(', ');
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div>
|
<div>
|
||||||
<td className={ row_classes }>
|
<td className={ row_classes }>
|
||||||
<strong>
|
<strong>
|
||||||
<a>{ subscriber.email }</a>
|
<Link to="edit" params={{ id: subscriber.id }}>
|
||||||
|
{ subscriber.email }
|
||||||
|
</Link>
|
||||||
</strong>
|
</strong>
|
||||||
{ actions }
|
{ actions }
|
||||||
</td>
|
</td>
|
||||||
@@ -239,6 +266,9 @@ define(
|
|||||||
<td className="column" data-colname="Status">
|
<td className="column" data-colname="Status">
|
||||||
{ status }
|
{ status }
|
||||||
</td>
|
</td>
|
||||||
|
<td className="column" data-colname="Status">
|
||||||
|
{ segments }
|
||||||
|
</td>
|
||||||
<td className="column-date" data-colname="Subscribed on">
|
<td className="column-date" data-colname="Subscribed on">
|
||||||
<abbr>{ subscriber.created_at }</abbr>
|
<abbr>{ subscriber.created_at }</abbr>
|
||||||
</td>
|
</td>
|
||||||
|
@@ -1,5 +1,6 @@
|
|||||||
<?php
|
<?php
|
||||||
namespace MailPoet\Config;
|
namespace MailPoet\Config;
|
||||||
|
use \MailPoet\Models\Segment;
|
||||||
|
|
||||||
if(!defined('ABSPATH')) exit;
|
if(!defined('ABSPATH')) exit;
|
||||||
|
|
||||||
@@ -80,6 +81,9 @@ class Menu {
|
|||||||
|
|
||||||
function subscribers() {
|
function subscribers() {
|
||||||
$data = array();
|
$data = array();
|
||||||
|
|
||||||
|
$data['segments'] = Segment::findArray();
|
||||||
|
|
||||||
echo $this->renderer->render('subscribers.html', $data);
|
echo $this->renderer->render('subscribers.html', $data);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@@ -18,6 +18,7 @@ class Renderer {
|
|||||||
|
|
||||||
function init() {
|
function init() {
|
||||||
$this->setupTranslations();
|
$this->setupTranslations();
|
||||||
|
$this->setupFunctions();
|
||||||
$this->setupHandlebars();
|
$this->setupHandlebars();
|
||||||
$this->setupGlobalVariables();
|
$this->setupGlobalVariables();
|
||||||
$this->setupSyntax();
|
$this->setupSyntax();
|
||||||
@@ -28,6 +29,10 @@ class Renderer {
|
|||||||
$this->renderer->addExtension(new Twig\i18n(Env::$plugin_name));
|
$this->renderer->addExtension(new Twig\i18n(Env::$plugin_name));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function setupFunctions() {
|
||||||
|
$this->renderer->addExtension(new Twig\Functions());
|
||||||
|
}
|
||||||
|
|
||||||
function setupHandlebars() {
|
function setupHandlebars() {
|
||||||
$this->renderer->addExtension(new Twig\Handlebars());
|
$this->renderer->addExtension(new Twig\Handlebars());
|
||||||
}
|
}
|
||||||
@@ -51,7 +56,9 @@ class Renderer {
|
|||||||
|
|
||||||
function detectCache() {
|
function detectCache() {
|
||||||
$cache_path = Env::$views_path . '/cache';
|
$cache_path = Env::$views_path . '/cache';
|
||||||
if (WP_DEBUG === false) return $cache_path;
|
if(WP_DEBUG === false) {
|
||||||
|
return $cache_path;
|
||||||
|
}
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@@ -27,7 +27,21 @@ class Subscribers {
|
|||||||
\Model::factory('\MailPoet\Models\Subscriber'),
|
\Model::factory('\MailPoet\Models\Subscriber'),
|
||||||
$data
|
$data
|
||||||
);
|
);
|
||||||
wp_send_json($listing->get());
|
|
||||||
|
|
||||||
|
$listing_data = $listing->get();
|
||||||
|
|
||||||
|
// fetch segments relations for each returned item
|
||||||
|
foreach($listing_data['items'] as &$item) {
|
||||||
|
$segments = SubscriberSegment::select('segment_id')
|
||||||
|
->where('subscriber_id', $item['id'])
|
||||||
|
->findMany();
|
||||||
|
$item['segments'] = array_map(function($relation) {
|
||||||
|
return $relation->segment_id;
|
||||||
|
}, $segments);
|
||||||
|
}
|
||||||
|
|
||||||
|
wp_send_json($listing_data);
|
||||||
}
|
}
|
||||||
|
|
||||||
function getAll() {
|
function getAll() {
|
||||||
|
27
lib/Twig/Functions.php
Normal file
27
lib/Twig/Functions.php
Normal file
@@ -0,0 +1,27 @@
|
|||||||
|
<?php
|
||||||
|
namespace MailPoet\Twig;
|
||||||
|
|
||||||
|
class Functions extends \Twig_Extension {
|
||||||
|
|
||||||
|
public function __construct() {
|
||||||
|
}
|
||||||
|
|
||||||
|
public function getName() {
|
||||||
|
return 'functions';
|
||||||
|
}
|
||||||
|
|
||||||
|
public function getFunctions() {
|
||||||
|
return array(
|
||||||
|
new \Twig_SimpleFunction(
|
||||||
|
'json_encode',
|
||||||
|
'json_encode',
|
||||||
|
array('is_safe' => array('all'))
|
||||||
|
),
|
||||||
|
new \Twig_SimpleFunction(
|
||||||
|
'json_decode',
|
||||||
|
'json_decode',
|
||||||
|
array('is_safe' => array('all'))
|
||||||
|
)
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
@@ -12,4 +12,8 @@
|
|||||||
'selectAllLink': __('Select all pages.'),
|
'selectAllLink': __('Select all pages.'),
|
||||||
'clearSelection': __('Clear selection.')
|
'clearSelection': __('Clear selection.')
|
||||||
}) %>
|
}) %>
|
||||||
|
|
||||||
|
<script type="text/javascript">
|
||||||
|
var mailpoet_segments = <%= json_encode(segments) %>;
|
||||||
|
</script>
|
||||||
<% endblock %>
|
<% endblock %>
|
||||||
|
Reference in New Issue
Block a user