Listing filters
This commit is contained in:
@ -1,10 +1,8 @@
|
||||
define([
|
||||
'react',
|
||||
'mailpoet'
|
||||
'react'
|
||||
],
|
||||
function(
|
||||
React,
|
||||
MailPoet
|
||||
React
|
||||
) {
|
||||
var ListingBulkActions = React.createClass({
|
||||
getInitialState: function() {
|
||||
|
@ -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>
|
||||
);
|
||||
}
|
||||
});
|
||||
|
||||
|
@ -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 }
|
||||
|
@ -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'])
|
||||
|
@ -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')
|
||||
|
@ -28,7 +28,6 @@ class Subscribers {
|
||||
$data
|
||||
);
|
||||
|
||||
|
||||
$listing_data = $listing->get();
|
||||
|
||||
// fetch segments relations for each returned item
|
||||
|
@ -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",
|
||||
|
@ -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');
|
||||
}
|
||||
|
Reference in New Issue
Block a user