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([
'react',
'mailpoet'
'react'
],
function(
React,
MailPoet
React
) {
var ListingBulkActions = React.createClass({
getInitialState: function() {

View File

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

View File

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

View File

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

View File

@ -5,7 +5,10 @@
},
"napa": {
"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": {
"backbone": "1.2.3",
@ -36,9 +39,6 @@
"devDependencies": {
"babel-core": "^5.8.22",
"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",
"chai": "2.2.0",
"chai-jq": "0.0.8",

View File

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