This commit is contained in:
Jonathan Labreuille
2015-08-25 18:51:47 +02:00
committed by marco
parent 5b93e1c8a6
commit 097b638e6b
7 changed files with 182 additions and 69 deletions

View File

@ -8,10 +8,3 @@
@require 'validation_engine'
@require 'form_editor'
.infinite-scroll-example__scrollable-parent {
height: 500px;
overflow-y: scroll;
position: relative;
}

View File

@ -40,10 +40,11 @@ define('subscribers.listing',
<input
type="search"
ref="search"
id="search_input" />
id="search_input"
defaultValue={this.props.search} />
<input
type="submit"
value="Search"
defaultValue="Search"
className="button" />
</p>
</form>
@ -60,10 +61,80 @@ define('subscribers.listing',
});
var ListingPages = React.createClass({
setFirstPage: function() {
this.props.onSetPage(1);
},
setLastPage: function() {
var last_page = Math.ceil(this.props.count / this.props.limit);
this.props.onSetPage(last_page);
},
setPreviousPage: function() {
this.props.onSetPage(this.getPageValue(this.props.page - 1));
},
setNextPage: function() {
this.props.onSetPage(this.getPageValue(this.props.page + 1));
},
getPageValue: function(page) {
var last_page = Math.ceil(this.props.count / this.props.limit);
return Math.min(Math.max(1, Math.abs(~~page)), last_page);
},
handleSetPage: function() {
this.props.onSetPage(
this.getPageValue(this.refs.page.getDOMNode().value)
);
},
render: function() {
return (
<div className="tablenav-pages">
<span className="displaying-num">{this.props.items.length} item(s)</span>
<span className="displaying-num">{this.props.count} item(s)</span>
<span className="pagination-links">
<a href="javascript:;"
onClick={this.setFirstPage}
className="first-page">
<span className="screen-reader-text">First page</span>
<span aria-hidden="true">«</span>
</a>
<a href="javascript:;"
onClick={this.setPreviousPage}
className="prev-page">
<span className="screen-reader-text">Previous page</span>
<span aria-hidden="true"></span>
</a>
<span className="paging-input">
<label
className="screen-reader-text"
htmlFor="current-page-selector">Current Page</label>
<input
type="text"
onChange={this.handleSetPage}
aria-describedby="table-paging"
size="1"
ref="page"
value={this.props.page}
name="paged"
id="current-page-selector"
className="current-page" />
&nbsp;of&nbsp;
<span className="total-pages">
{Math.ceil(this.props.count / this.props.limit)}
</span>
</span>
<a href="javascript:;"
onClick={this.setNextPage}
className="next-page">
<span className="screen-reader-text">Next page</span>
<span aria-hidden="true"></span>
</a>
<a href="javascript:;"
onClick={this.setLastPage}
className="last-page">
<span className="screen-reader-text">Last page</span>
<span aria-hidden="true">»</span>
</a>
</span>
</div>
);
}
@ -148,7 +219,7 @@ define('subscribers.listing',
Select { this.props.item.email }</label>
<input
type="checkbox"
value={ this.props.item.id }
defaultValue={ this.props.item.id }
name="item[]" id="cb-select-1" />
</th>
<td className="title column-title has-row-actions column-primary page-title">
@ -205,6 +276,7 @@ define('subscribers.listing',
return {
search: '',
page: 1,
count: 0,
limit: 10,
sort_by: 'email',
sort_order: 'asc',
@ -218,52 +290,47 @@ define('subscribers.listing',
MailPoet.Ajax.post({
endpoint: 'subscribers',
action: 'get',
data: {
offset: (this.state.page - 1) * this.state.limit,
limit: this.state.limit,
search: this.state.search,
sort_by: this.state.sort_by,
sort_order: this.state.sort_order
},
onSuccess: function(response) {
if(this.isMounted()) {
this.setState({
items: response
items: response.items,
count: response.count
});
}
}.bind(this)
});
},
handleSearch: function(search) {
this.setState({ search: search });
this.setState({ search: search }, function() {
this.getItems();
}.bind(this));
},
handleSort: function(sort_by, sort_order = 'asc') {
this.setState({
sort_by: sort_by,
sort_order: sort_order
});
}, function() {
this.getItems();
}.bind(this));
},
handleSetPage: function(page) {
this.setState({ page: page }, function() {
this.getItems();
}.bind(this));
},
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)
|| item.first_name.toLowerCase().match(search)
|| item.last_name.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;
}
}
});
// set sortable columns
columns = columns.map(function(column) {
column.sorted = (column.name === sort_by) ? sort_order : false;
return column;
@ -271,10 +338,18 @@ define('subscribers.listing',
return (
<div>
<ListingSearch onSearch={this.handleSearch} />
<div className="tablenav top clearfix">
<ListingGroups />
<ListingPages items={items} />
<ListingSearch
onSearch={this.handleSearch}
search={this.state.search} />
<div className="tablenav top clearfix">
<ListingBulkActions />
<ListingFilters />
<ListingPages
count={this.state.count}
page={this.state.page}
limit={this.state.limit}
onSetPage={this.handleSetPage} />
</div>
<table className="wp-list-table widefat fixed">
<thead>
@ -299,8 +374,12 @@ define('subscribers.listing',
</table>
<div className="tablenav bottom">
<ListingGroups />
<ListingPages items={items} />
<ListingBulkActions />
<ListingPages
count={this.state.count}
page={this.state.page}
limit={this.state.limit}
onSetPage={this.handleSetPage} />
</div>
</div>
);
@ -324,10 +403,6 @@ define('subscribers.listing',
label: 'Lastname',
sortable: true
},
{
name: 'status',
label: 'Status'
},
{
name: 'created_at',
label: 'Subscribed on',
@ -350,15 +425,3 @@ define('subscribers.listing',
}
}
);
/*
<ListingGroups />
<ListingSearch />
<ListingBulkActions />
<ListingFilters />
<ListingPages />
<ListingItems />
<ListingBulkActions />
<ListingPages />
*/

View File

@ -42,10 +42,50 @@ define('subscribers.table',
};
},
_renderLoadingMessage: function() {
if (this.state.loading) {
return (
<p>
Loading {this.state.limit} more items
</p>
);
} else {
return (
<p>{this.state.items.length} items</p>
);
}
},
_renderItems: function() {
return this.state.items.map(function(subscriber, index) {
return (
<p key={index}>{subscriber.email}</p>
<tr>
<th className="check-column" scope="row">
<label htmlFor="cb-select-1" className="screen-reader-text">
Select { subscriber.email }</label>
<input
type="checkbox"
value={ subscriber.id }
name="item[]" id="cb-select-1" />
</th>
<td className="title column-title has-row-actions column-primary page-title">
<strong>
<a className="row-title">{ subscriber.email }</a>
</strong>
</td>
<td>
{ subscriber.first_name }
</td>
<td>
{ subscriber.last_name }
</td>
<td className="date column-date">
<abbr title="">{ subscriber.created_at }</abbr>
</td>
<td className="date column-date">
<abbr title="">{ subscriber.updated_at }</abbr>
</td>
</tr>
);
});
},
@ -55,16 +95,15 @@ define('subscribers.table',
return (
<Waypoint
onEnter={this._loadMoreItems}
threshold={2.0} />
threshold={0.8} />
);
}
},
render: function() {
//MailPoet.Modal.loading(this.state.loading);
return (
<div>
<p>{this.state.items.length} items</p>
{this._renderLoadingMessage()}
<div className="infinite-scroll-example">
<div className="infinite-scroll-example__scrollable-parent">
{this._renderItems()}

View File

@ -28,6 +28,7 @@ class Initializer {
\ORM::configure(Env::$db_source_name);
\ORM::configure('username', Env::$db_username);
\ORM::configure('password', Env::$db_password);
\ORM::configure('logging', WP_DEBUG);
$subscribers = Env::$db_prefix . 'subscribers';
$settings = Env::$db_prefix . 'settings';

View File

@ -13,7 +13,26 @@ class Subscribers {
$data = $_POST['data'];
$offset = (isset($data['offset']) ? (int)$data['offset'] : 0);
$limit = (isset($data['limit']) ? (int)$data['limit'] : 50);
$collection = Subscriber::offset($offset)->limit($limit)->find_array();
$search = (isset($data['search']) ? $data['search'] : null);
$sort_by = (isset($data['sort_by']) ? $data['sort_by'] : 'id');
$sort_order = (isset($data['sort_order']) ? $data['sort_order'] : 'desc');
$collection = Subscriber::{'order_by_'.$sort_order}($sort_by);
if($search !== null) {
$collection->where_raw(
'(`email` LIKE ? OR `first_name` LIKE ? OR `last_name` LIKE ?)',
array('%'.$search.'%', '%'.$search.'%', '%'.$search.'%')
);
}
$collection = array(
'count' => $collection->count(),
'items' => $collection
->offset($offset)
->limit($limit)
->find_array()
);
} else {
$collection = Subscriber::find_array();
}

View File

@ -2,6 +2,5 @@
<% block content %>
<h1><%= __('Subscribers') %></h1>
<!-- <div id="mailpoet_subscribers_listing"></div> -->
<div id="example"></div>
<div id="mailpoet_subscribers_listing"></div>
<% endblock %>

View File

@ -36,8 +36,7 @@ config.push(_.extend({}, baseConfig, {
vendor: ['handlebars', 'handlebars_helpers'],
mailpoet: ['mailpoet', 'ajax', 'modal', 'notice'],
admin: [
'subscribers/table.jsx',
// 'subscribers/listing.jsx',
'subscribers/listing.jsx',
'settings.jsx',
'subscribers.jsx',
'newsletters_list.jsx',