Listing filters

This commit is contained in:
Jonathan Labreuille
2015-10-06 10:00:18 +02:00
parent bfaf6e49f8
commit c15359f1b4
8 changed files with 158 additions and 24 deletions

View File

@ -1,10 +1,8 @@
define([ define([
'react', 'react'
'mailpoet'
], ],
function( function(
React, React
MailPoet
) { ) {
var ListingBulkActions = React.createClass({ var ListingBulkActions = React.createClass({
getInitialState: function() { getInitialState: function() {

View File

@ -1,8 +1,72 @@
define(['react'], function(React) { define([
'react'
],
function(
React
) {
var ListingFilters = React.createClass({ var ListingFilters = React.createClass({
handleFilterAction: function() {
var filters = this.props.filters.map(function(filter, index) {
var value = this.refs['filter-'+index].getDOMNode().value;
if(value) {
return {
'name': filter.name,
'value': value
};
}
}.bind(this));
return this.props.onSelectFilter(filters);
},
handleChangeAction: function() {
return true;
},
render: function() { render: function() {
return null; var filters = this.props.filters
.filter(function(filter) {
return !(
filter.options.length === 0
|| (
filter.options.length === 1
&& !filter.options[0].value
)
);
})
.map(function(filter, i) {
return (
<select
ref={ 'filter-'+i }
key={ 'filter-'+i }
onChange={ this.handleChangeAction }>
{ filter.options.map(function(option, j) {
return (
<option
value={ option.value }
key={ 'filter-option-' + j }
>{ option.label }</option>
);
}.bind(this)) }
</select>
);
}.bind(this));
var button = false;
if(filters.length > 0) {
button = (
<input
onClick={ this.handleFilterAction }
type="submit"
defaultValue="Filter"
className="button" />
);
}
return (
<div className="alignleft actions actions">
{ filters }
{ button }
</div>
);
} }
}); });

View File

@ -209,6 +209,7 @@ define(
groups: [], groups: [],
group: 'all', group: 'all',
filters: [], filters: [],
filter: [],
selected_ids: [], selected_ids: [],
selection: false selection: false
}; };
@ -228,6 +229,7 @@ define(
offset: (this.state.page - 1) * this.state.limit, offset: (this.state.page - 1) * this.state.limit,
limit: this.state.limit, limit: this.state.limit,
group: this.state.group, group: this.state.group,
filter: this.state.filter,
search: this.state.search, search: this.state.search,
sort_by: this.state.sort_by, sort_by: this.state.sort_by,
sort_order: this.state.sort_order sort_order: this.state.sort_order
@ -270,6 +272,7 @@ define(
data.listing = { data.listing = {
offset: 0, offset: 0,
limit: 0, limit: 0,
filter: this.state.filter,
group: this.state.group, group: this.state.group,
search: this.state.search, search: this.state.search,
selection: selected_ids selection: selected_ids
@ -350,13 +353,21 @@ define(
selected_ids: [] selected_ids: []
}); });
}, },
handleFilter: function(filters) {
this.setState({
filter: filters,
page: 1
}, function() {
this.getItems();
}.bind(this));
},
handleGroup: function(group) { handleGroup: function(group) {
// reset search // reset search
jQuery('#search_input').val(''); jQuery('#search_input').val('');
this.setState({ this.setState({
group: group, group: group,
filters: [], filter: [],
search: '', search: '',
page: 1 page: 1
}, function() { }, function() {
@ -414,7 +425,10 @@ define(
selection={ this.state.selection } selection={ this.state.selection }
selected_ids={ this.state.selected_ids } selected_ids={ this.state.selected_ids }
onBulkAction={ this.handleBulkAction } /> onBulkAction={ this.handleBulkAction } />
<ListingFilters filters={ this.state.filters } /> <ListingFilters
filters={ this.state.filters }
filter={ this.state.filter }
onSelectFilter={ this.handleFilter } />
<ListingPages <ListingPages
count={ this.state.count } count={ this.state.count }
page={ this.state.page } page={ this.state.page }

View File

@ -21,13 +21,16 @@ class Handler {
'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),
// filters
'filter' => (isset($data['filter']) ? $data['filter'] : null),
// selection // selection
'selection' => (isset($data['selection']) ? $data['selection'] : null) 'selection' => (isset($data['selection']) ? $data['selection'] : null)
); );
$this->setSearch(); $this->setSearch();
$this->setOrder();
$this->setGroup(); $this->setGroup();
$this->setFilter();
$this->setOrder();
} }
private function setSearch() { private function setSearch() {
@ -39,25 +42,35 @@ class Handler {
private function setOrder() { private function setOrder() {
return $this->model return $this->model
->{'order_by_'.$this->data['sort_order']}($this->data['sort_by']); ->tableAlias('model')
->{'order_by_'.$this->data['sort_order']}(
'model.'.$this->data['sort_by']
);
} }
private function setGroup() { private function setGroup() {
if($this->data['group'] === null) { if($this->data['group'] === null) {
return; return;
} }
return $this->model->filter('group', $this->data['group']); return $this->model->filter('groupBy', $this->data['group']);
}
private function setFilter() {
if($this->data['filter'] === null) {
return;
}
return $this->model->filter('filterBy', $this->data['filter']);
} }
function getSelection() { function getSelection() {
if(!empty($this->data['selection'])) { if(!empty($this->data['selection'])) {
$this->model->whereIn('id', $this->data['selection']); $this->model->whereIn('model.id', $this->data['selection']);
} }
return $this->model; return $this->model;
} }
function getSelectionIds() { function getSelectionIds() {
$models = $this->getSelection()->select('id')->findMany(); $models = $this->getSelection()->select('model.id')->findMany();
return array_map(function($model) { return array_map(function($model) {
return (int)$model->id; return (int)$model->id;
}, $models); }, $models);
@ -66,7 +79,7 @@ class Handler {
function get() { function get() {
return array( return array(
'count' => $this->model->count(), 'count' => $this->model->count(),
'filters' => [], 'filters' => $this->model->filter('filters'),
'groups' => $this->model->filter('groups'), 'groups' => $this->model->filter('groups'),
'items' => $this->model 'items' => $this->model
->offset($this->data['offset']) ->offset($this->data['offset'])

View File

@ -33,6 +33,52 @@ class Subscriber extends Model {
); );
} }
static function filters() {
$segments = Segment::orderByAsc('name')->findMany();
$segment_list = array();
$segment_list[] = array(
'label' => __('All lists'),
'value' => ''
);
foreach($segments as $segment) {
$subscribers_count = $segment->subscribers()->count();
if($subscribers_count > 0) {
$segment_list[] = array(
'label' => sprintf('%s (%d)', $segment->name, $subscribers_count),
'value' => $segment->id()
);
}
}
$filters = array(
array(
'name' => 'segment',
'options' => $segment_list
)
);
return $filters;
}
static function filterBy($orm, $filters = null) {
if(empty($filters)) {
return $orm;
}
foreach($filters as $filter) {
if($filter['name'] === 'segment') {
$segment = Segment::findOne($filter['value']);
if($segment !== false) {
$orm = $segment->subscribers();
}
}
}
return $orm;
}
static function groups() { static function groups() {
return array( return array(
array( array(
@ -58,7 +104,7 @@ class Subscriber extends Model {
); );
} }
static function group($orm, $group = null) { static function groupBy($orm, $group = null) {
if($group === null or !in_array( if($group === null or !in_array(
$group, $group,
array('subscribed', 'unconfirmed', 'unsubscribed') array('subscribed', 'unconfirmed', 'unsubscribed')

View File

@ -28,7 +28,6 @@ class Subscribers {
$data $data
); );
$listing_data = $listing->get(); $listing_data = $listing->get();
// fetch segments relations for each returned item // fetch segments relations for each returned item

View File

@ -5,7 +5,10 @@
}, },
"napa": { "napa": {
"sticky-kit": "leafo/sticky-kit.git", "sticky-kit": "leafo/sticky-kit.git",
"interact.js": "taye/interact.js.git" "interact.js": "taye/interact.js.git",
"export-loader": "webpack/exports-loader.git",
"import-loader": "webpack/imports-loader.git",
"expose-loader": "webpack/expose-loader.git"
}, },
"dependencies": { "dependencies": {
"backbone": "1.2.3", "backbone": "1.2.3",
@ -36,9 +39,6 @@
"devDependencies": { "devDependencies": {
"babel-core": "^5.8.22", "babel-core": "^5.8.22",
"babel-loader": "^5.3.2", "babel-loader": "^5.3.2",
"export-loader": "webpack/exports-loader.git",
"import-loader": "webpack/imports-loader.git",
"expose-loader": "webpack/expose-loader.git",
"amd-inject-loader": "latest", "amd-inject-loader": "latest",
"chai": "2.2.0", "chai": "2.2.0",
"chai-jq": "0.0.8", "chai-jq": "0.0.8",

View File

@ -84,17 +84,17 @@ class SubscriberCest {
} }
function itHasAGroupFilter() { function itHasAGroupFilter() {
$subscribers = Subscriber::filter('group', 'unconfirmed')->findMany(); $subscribers = Subscriber::filter('groupBy', 'unconfirmed')->findMany();
foreach($subscribers as $subscriber) { foreach($subscribers as $subscriber) {
expect($subscriber->status)->equals('unconfirmed'); expect($subscriber->status)->equals('unconfirmed');
} }
$subscribers = Subscriber::filter('group', 'subscribed')->findMany(); $subscribers = Subscriber::filter('groupBy', 'subscribed')->findMany();
foreach($subscribers as $subscriber) { foreach($subscribers as $subscriber) {
expect($subscriber->status)->equals('subscribed'); expect($subscriber->status)->equals('subscribed');
} }
$subscribers = Subscriber::filter('group', 'unsubscribed')->findMany(); $subscribers = Subscriber::filter('groupBy', 'unsubscribed')->findMany();
foreach($subscribers as $subscriber) { foreach($subscribers as $subscriber) {
expect($subscriber->status)->equals('unsubscribed'); expect($subscriber->status)->equals('unsubscribed');
} }