Subscribers Listing
- sortable - searchable
This commit is contained in:
committed by
marco
parent
3c46c3cd3a
commit
f721119c9f
@ -1,6 +1,7 @@
|
|||||||
define('subscribers.listing',
|
define('subscribers.listing',
|
||||||
['react/addons', 'jquery', 'mailpoet', 'classnames'],
|
['react/addons', 'jquery', 'mailpoet', 'classnames'],
|
||||||
function(React, jQuery, MailPoet, classNames) {
|
function(React, jQuery, MailPoet, classNames) {
|
||||||
|
|
||||||
var ListingGroups = React.createClass({
|
var ListingGroups = React.createClass({
|
||||||
render: function() {
|
render: function() {
|
||||||
return (
|
return (
|
||||||
@ -62,28 +63,52 @@ define('subscribers.listing',
|
|||||||
});
|
});
|
||||||
|
|
||||||
var ListingColumn = React.createClass({
|
var ListingColumn = React.createClass({
|
||||||
|
handleSort: function() {
|
||||||
|
var sort_by = this.props.column.name,
|
||||||
|
sort_order = (this.props.column.sorted === 'asc') ? 'desc' : 'asc';
|
||||||
|
this.props.onSort(sort_by, sort_order);
|
||||||
|
},
|
||||||
render: function() {
|
render: function() {
|
||||||
var order = '';
|
|
||||||
if(this.props.column.sortable) {
|
|
||||||
order = this.props.column.order || 'asc';
|
|
||||||
}
|
|
||||||
var classes = classNames(
|
var classes = classNames(
|
||||||
'manage-column',
|
'manage-column',
|
||||||
{ 'sortable': this.props.column.sortable },
|
{ 'sortable': this.props.column.sortable },
|
||||||
order
|
this.props.column.sorted
|
||||||
);
|
);
|
||||||
|
|
||||||
|
var label;
|
||||||
|
|
||||||
|
if(this.props.column.sortable === true) {
|
||||||
|
label = (
|
||||||
|
<a onClick={this.handleSort}>
|
||||||
|
<span>{ this.props.column.label }</span>
|
||||||
|
<span className="sorting-indicator"></span>
|
||||||
|
</a>
|
||||||
|
);
|
||||||
|
} else {
|
||||||
|
label = this.props.column.label;
|
||||||
|
}
|
||||||
return (
|
return (
|
||||||
<th
|
<th
|
||||||
className={ classes }
|
className={ classes }
|
||||||
id={ this.props.column.name }
|
id={this.props.column.name }
|
||||||
scope="col">{ this.props.column.label }</th>
|
scope="col">
|
||||||
|
{label}
|
||||||
|
</th>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
var ListingHeader = React.createClass({
|
var ListingHeader = React.createClass({
|
||||||
render: function() {
|
render: function() {
|
||||||
|
var columns = this.props.columns.map(function(column) {
|
||||||
|
return (
|
||||||
|
<ListingColumn
|
||||||
|
onSort={this.props.onSort}
|
||||||
|
sort_by={this.props.sort_by}
|
||||||
|
key={column.name}
|
||||||
|
column={column} />
|
||||||
|
);
|
||||||
|
}.bind(this));
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<tr>
|
<tr>
|
||||||
@ -93,9 +118,7 @@ define('subscribers.listing',
|
|||||||
</label>
|
</label>
|
||||||
<input type="checkbox" id="cb-select-all-1" />
|
<input type="checkbox" id="cb-select-all-1" />
|
||||||
</td>
|
</td>
|
||||||
{ this.props.columns.map(function(column) {
|
{columns}
|
||||||
return (<ListingColumn key={column.name} column={column} />);
|
|
||||||
})}
|
|
||||||
</tr>
|
</tr>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
@ -115,10 +138,7 @@ define('subscribers.listing',
|
|||||||
</th>
|
</th>
|
||||||
<td className="title column-title has-row-actions column-primary page-title">
|
<td className="title column-title has-row-actions column-primary page-title">
|
||||||
<strong>
|
<strong>
|
||||||
<a
|
<a className="row-title">{ this.props.item.email }</a>
|
||||||
title="Edit “{ this.props.item.email }”"
|
|
||||||
href="#"
|
|
||||||
className="row-title">{ this.props.item.email }</a>
|
|
||||||
</strong>
|
</strong>
|
||||||
</td>
|
</td>
|
||||||
<td></td>
|
<td></td>
|
||||||
@ -135,18 +155,28 @@ define('subscribers.listing',
|
|||||||
|
|
||||||
var ListingItems = React.createClass({
|
var ListingItems = React.createClass({
|
||||||
render: function() {
|
render: function() {
|
||||||
return (
|
if(this.props.items.length === 0) {
|
||||||
<tbody>
|
return (
|
||||||
{this.props.items.map(function(item) {
|
<tbody>
|
||||||
return (
|
<td
|
||||||
<ListingItem
|
colSpan={this.props.columns.length + 1}
|
||||||
columns={this.props.columns}
|
className="colspanchange">No subscribers found.</td>
|
||||||
key={item.id}
|
</tbody>
|
||||||
item={item} />
|
);
|
||||||
);
|
} else {
|
||||||
}.bind(this))}
|
return (
|
||||||
</tbody>
|
<tbody>
|
||||||
);
|
{this.props.items.map(function(item) {
|
||||||
|
return (
|
||||||
|
<ListingItem
|
||||||
|
columns={this.props.columns}
|
||||||
|
key={item.id}
|
||||||
|
item={item} />
|
||||||
|
);
|
||||||
|
}.bind(this))}
|
||||||
|
</tbody>
|
||||||
|
);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
@ -156,6 +186,8 @@ define('subscribers.listing',
|
|||||||
search: '',
|
search: '',
|
||||||
page: 1,
|
page: 1,
|
||||||
limit: 10,
|
limit: 10,
|
||||||
|
sort_by: 'email',
|
||||||
|
sort_order: 'asc',
|
||||||
items: []
|
items: []
|
||||||
};
|
};
|
||||||
},
|
},
|
||||||
@ -166,9 +198,6 @@ define('subscribers.listing',
|
|||||||
MailPoet.Ajax.post({
|
MailPoet.Ajax.post({
|
||||||
endpoint: 'subscribers',
|
endpoint: 'subscribers',
|
||||||
action: 'get',
|
action: 'get',
|
||||||
data: {
|
|
||||||
search: this.state.search
|
|
||||||
},
|
|
||||||
onSuccess: function(response) {
|
onSuccess: function(response) {
|
||||||
if(this.isMounted()) {
|
if(this.isMounted()) {
|
||||||
this.setState({
|
this.setState({
|
||||||
@ -179,11 +208,45 @@ define('subscribers.listing',
|
|||||||
});
|
});
|
||||||
},
|
},
|
||||||
handleSearch: function(search) {
|
handleSearch: function(search) {
|
||||||
this.setState({ search: search }, function() {
|
this.setState({ search: search });
|
||||||
this.getItems();
|
},
|
||||||
}.bind(this));
|
handleSort: function(sort_by, sort_order = 'asc') {
|
||||||
|
this.setState({
|
||||||
|
sort_by: sort_by,
|
||||||
|
sort_order: sort_order
|
||||||
|
});
|
||||||
},
|
},
|
||||||
render: function() {
|
render: function() {
|
||||||
|
var items = this.state.items,
|
||||||
|
search = this.state.search.trim().toLowerCase(),
|
||||||
|
sort_by = this.state.sort_by,
|
||||||
|
sort_order = this.state.sort_order;
|
||||||
|
|
||||||
|
// search
|
||||||
|
if(search.length > 0) {
|
||||||
|
items = items.filter(function(item){
|
||||||
|
return item.email.toLowerCase().match(search);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
// sorting
|
||||||
|
items = items.sort(function(a, b) {
|
||||||
|
if(a[sort_by] === b[sort_by]) {
|
||||||
|
return 0;
|
||||||
|
} else {
|
||||||
|
if(sort_order === 'asc') {
|
||||||
|
return (a[sort_by] > b[sort_by]) ? 1 : -1;
|
||||||
|
} else {
|
||||||
|
return (a[sort_by] < b[sort_by]) ? 1 : -1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
columns = columns.map(function(column) {
|
||||||
|
column.sorted = (column.name === sort_by) ? sort_order : false;
|
||||||
|
return column;
|
||||||
|
});
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div>
|
<div>
|
||||||
<ListingSearch onSearch={this.handleSearch} />
|
<ListingSearch onSearch={this.handleSearch} />
|
||||||
@ -193,15 +256,21 @@ define('subscribers.listing',
|
|||||||
<table className="wp-list-table widefat fixed">
|
<table className="wp-list-table widefat fixed">
|
||||||
<thead>
|
<thead>
|
||||||
<ListingHeader
|
<ListingHeader
|
||||||
|
onSort={this.handleSort}
|
||||||
|
sort_by={this.state.sort_by}
|
||||||
|
sort_order={this.state.sort_order}
|
||||||
columns={this.props.columns} />
|
columns={this.props.columns} />
|
||||||
</thead>
|
</thead>
|
||||||
|
|
||||||
<ListingItems
|
<ListingItems
|
||||||
columns={this.props.columns}
|
columns={this.props.columns}
|
||||||
items={this.state.items} />
|
items={items} />
|
||||||
|
|
||||||
<tfoot>
|
<tfoot>
|
||||||
<ListingHeader
|
<ListingHeader
|
||||||
|
onSort={this.handleSort}
|
||||||
|
sort_by={this.state.sort_by}
|
||||||
|
sort_order={this.state.sort_order}
|
||||||
columns={this.props.columns} />
|
columns={this.props.columns} />
|
||||||
</tfoot>
|
</tfoot>
|
||||||
|
|
||||||
@ -223,16 +292,17 @@ define('subscribers.listing',
|
|||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: 'status',
|
name: 'status',
|
||||||
label: 'Status',
|
label: 'Status'
|
||||||
sortable: true
|
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: 'created_at',
|
name: 'created_at',
|
||||||
label: 'Subscribed on'
|
label: 'Subscribed on',
|
||||||
|
sortable: true
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: 'updated_at',
|
name: 'updated_at',
|
||||||
label: 'Last modified on'
|
label: 'Last modified on',
|
||||||
|
sortable: true
|
||||||
},
|
},
|
||||||
];
|
];
|
||||||
|
|
||||||
|
40
composer.lock
generated
40
composer.lock
generated
@ -309,25 +309,29 @@
|
|||||||
},
|
},
|
||||||
{
|
{
|
||||||
"name": "twig/twig",
|
"name": "twig/twig",
|
||||||
"version": "v1.20.0",
|
"version": "v1.21.0",
|
||||||
"source": {
|
"source": {
|
||||||
"type": "git",
|
"type": "git",
|
||||||
"url": "https://github.com/twigphp/Twig.git",
|
"url": "https://github.com/twigphp/Twig.git",
|
||||||
"reference": "1ea4e5f81c6d005fe84d0b38e1c4f1955eb86844"
|
"reference": "913d282caca9ee0e8d05940c6caa486d58810dd4"
|
||||||
},
|
},
|
||||||
"dist": {
|
"dist": {
|
||||||
"type": "zip",
|
"type": "zip",
|
||||||
"url": "https://api.github.com/repos/twigphp/Twig/zipball/1ea4e5f81c6d005fe84d0b38e1c4f1955eb86844",
|
"url": "https://api.github.com/repos/twigphp/Twig/zipball/913d282caca9ee0e8d05940c6caa486d58810dd4",
|
||||||
"reference": "1ea4e5f81c6d005fe84d0b38e1c4f1955eb86844",
|
"reference": "913d282caca9ee0e8d05940c6caa486d58810dd4",
|
||||||
"shasum": ""
|
"shasum": ""
|
||||||
},
|
},
|
||||||
"require": {
|
"require": {
|
||||||
"php": ">=5.2.7"
|
"php": ">=5.2.7"
|
||||||
},
|
},
|
||||||
|
"require-dev": {
|
||||||
|
"symfony/debug": "~2.7",
|
||||||
|
"symfony/phpunit-bridge": "~2.7"
|
||||||
|
},
|
||||||
"type": "library",
|
"type": "library",
|
||||||
"extra": {
|
"extra": {
|
||||||
"branch-alias": {
|
"branch-alias": {
|
||||||
"dev-master": "1.20-dev"
|
"dev-master": "1.21-dev"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"autoload": {
|
"autoload": {
|
||||||
@ -362,7 +366,7 @@
|
|||||||
"keywords": [
|
"keywords": [
|
||||||
"templating"
|
"templating"
|
||||||
],
|
],
|
||||||
"time": "2015-08-12 15:56:39"
|
"time": "2015-08-24 09:51:18"
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
"packages-dev": [
|
"packages-dev": [
|
||||||
@ -1211,16 +1215,16 @@
|
|||||||
},
|
},
|
||||||
{
|
{
|
||||||
"name": "phpunit/phpunit",
|
"name": "phpunit/phpunit",
|
||||||
"version": "4.8.5",
|
"version": "4.8.6",
|
||||||
"source": {
|
"source": {
|
||||||
"type": "git",
|
"type": "git",
|
||||||
"url": "https://github.com/sebastianbergmann/phpunit.git",
|
"url": "https://github.com/sebastianbergmann/phpunit.git",
|
||||||
"reference": "9b7417edaf28059ea63d86be941e6004dbfcc0cc"
|
"reference": "2246830f4a1a551c67933e4171bf2126dc29d357"
|
||||||
},
|
},
|
||||||
"dist": {
|
"dist": {
|
||||||
"type": "zip",
|
"type": "zip",
|
||||||
"url": "https://api.github.com/repos/sebastianbergmann/phpunit/zipball/9b7417edaf28059ea63d86be941e6004dbfcc0cc",
|
"url": "https://api.github.com/repos/sebastianbergmann/phpunit/zipball/2246830f4a1a551c67933e4171bf2126dc29d357",
|
||||||
"reference": "9b7417edaf28059ea63d86be941e6004dbfcc0cc",
|
"reference": "2246830f4a1a551c67933e4171bf2126dc29d357",
|
||||||
"shasum": ""
|
"shasum": ""
|
||||||
},
|
},
|
||||||
"require": {
|
"require": {
|
||||||
@ -1279,7 +1283,7 @@
|
|||||||
"testing",
|
"testing",
|
||||||
"xunit"
|
"xunit"
|
||||||
],
|
],
|
||||||
"time": "2015-08-19 09:20:57"
|
"time": "2015-08-24 04:09:38"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"name": "phpunit/phpunit-mock-objects",
|
"name": "phpunit/phpunit-mock-objects",
|
||||||
@ -2801,20 +2805,20 @@
|
|||||||
},
|
},
|
||||||
{
|
{
|
||||||
"name": "twig/extensions",
|
"name": "twig/extensions",
|
||||||
"version": "v1.2.0",
|
"version": "v1.3.0",
|
||||||
"source": {
|
"source": {
|
||||||
"type": "git",
|
"type": "git",
|
||||||
"url": "https://github.com/twigphp/Twig-extensions.git",
|
"url": "https://github.com/twigphp/Twig-extensions.git",
|
||||||
"reference": "8cf4b9fe04077bd54fc73f4fde83347040c3b8cd"
|
"reference": "449e3c8a9ffad7c2479c7864557275a32b037499"
|
||||||
},
|
},
|
||||||
"dist": {
|
"dist": {
|
||||||
"type": "zip",
|
"type": "zip",
|
||||||
"url": "https://api.github.com/repos/twigphp/Twig-extensions/zipball/8cf4b9fe04077bd54fc73f4fde83347040c3b8cd",
|
"url": "https://api.github.com/repos/twigphp/Twig-extensions/zipball/449e3c8a9ffad7c2479c7864557275a32b037499",
|
||||||
"reference": "8cf4b9fe04077bd54fc73f4fde83347040c3b8cd",
|
"reference": "449e3c8a9ffad7c2479c7864557275a32b037499",
|
||||||
"shasum": ""
|
"shasum": ""
|
||||||
},
|
},
|
||||||
"require": {
|
"require": {
|
||||||
"twig/twig": "~1.12"
|
"twig/twig": "~1.20|~2.0"
|
||||||
},
|
},
|
||||||
"require-dev": {
|
"require-dev": {
|
||||||
"symfony/translation": "~2.3"
|
"symfony/translation": "~2.3"
|
||||||
@ -2825,7 +2829,7 @@
|
|||||||
"type": "library",
|
"type": "library",
|
||||||
"extra": {
|
"extra": {
|
||||||
"branch-alias": {
|
"branch-alias": {
|
||||||
"dev-master": "1.2.x-dev"
|
"dev-master": "1.3-dev"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"autoload": {
|
"autoload": {
|
||||||
@ -2849,7 +2853,7 @@
|
|||||||
"i18n",
|
"i18n",
|
||||||
"text"
|
"text"
|
||||||
],
|
],
|
||||||
"time": "2014-10-30 14:30:03"
|
"time": "2015-08-22 16:38:35"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"name": "umpirsky/twig-gettext-extractor",
|
"name": "umpirsky/twig-gettext-extractor",
|
||||||
|
@ -9,17 +9,7 @@ class Subscribers {
|
|||||||
}
|
}
|
||||||
|
|
||||||
function get() {
|
function get() {
|
||||||
if(isset($_POST['data'])) {
|
$collection = Subscriber::find_array();
|
||||||
// search filter
|
|
||||||
$search = (isset($_POST['data']['search']))
|
|
||||||
? $_POST['data']['search']
|
|
||||||
: '';
|
|
||||||
|
|
||||||
$collection = Subscriber::where_like('email', '%'.$search.'%')->find_array();
|
|
||||||
} else {
|
|
||||||
$collection = Subscriber::find_array();
|
|
||||||
}
|
|
||||||
|
|
||||||
wp_send_json($collection);
|
wp_send_json($collection);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Reference in New Issue
Block a user