1
0
mirror of https://github.com/ascribe/onion.git synced 2025-01-03 10:25:08 +01:00

implement piece list filter widget functionality

This commit is contained in:
Tim Daubenschütz 2015-08-04 11:39:33 +02:00
parent 7ee296c963
commit e3b46c69a5
6 changed files with 105 additions and 21 deletions

View File

@ -14,7 +14,7 @@ class PieceListActions {
); );
} }
fetchPieceList(page, pageSize, search, orderBy, orderAsc) { fetchPieceList(page, pageSize, search, orderBy, orderAsc, filterBy) {
// To prevent flickering on a pagination request, // To prevent flickering on a pagination request,
// we overwrite the piecelist with an empty list before // we overwrite the piecelist with an empty list before
// pieceListCount === -1 defines the loading state // pieceListCount === -1 defines the loading state
@ -24,6 +24,7 @@ class PieceListActions {
search, search,
orderBy, orderBy,
orderAsc, orderAsc,
filterBy,
'pieceList': [], 'pieceList': [],
'pieceListCount': -1 'pieceListCount': -1
}); });
@ -32,7 +33,7 @@ class PieceListActions {
return Q.Promise((resolve, reject) => { return Q.Promise((resolve, reject) => {
PieceListFetcher PieceListFetcher
.fetch(page, pageSize, search, orderBy, orderAsc) .fetch(page, pageSize, search, orderBy, orderAsc, filterBy)
.then((res) => { .then((res) => {
this.actions.updatePieceList({ this.actions.updatePieceList({
page, page,
@ -40,6 +41,7 @@ class PieceListActions {
search, search,
orderBy, orderBy,
orderAsc, orderAsc,
filterBy,
'pieceList': res.pieces, 'pieceList': res.pieces,
'pieceListCount': res.count 'pieceListCount': res.count
}); });

View File

@ -44,7 +44,8 @@ let PieceListToolbar = React.createClass({
addonAfter={searchIcon} /> addonAfter={searchIcon} />
</span> </span>
<span className="pull-right"> <span className="pull-right">
<PieceListToolbarFilterWidget /> <PieceListToolbarFilterWidget
filterParams={['acl_transfer', 'acl_consign']} />
</span> </span>
</div> </div>
</div> </div>

View File

@ -2,12 +2,70 @@
import React from 'react'; import React from 'react';
import PieceListStore from '../../stores/piece_list_store';
import PieceListActions from '../../actions/piece_list_actions';
import Glyphicon from 'react-bootstrap/lib/Glyphicon'; import Glyphicon from 'react-bootstrap/lib/Glyphicon';
import DropdownButton from 'react-bootstrap/lib/DropdownButton'; import DropdownButton from 'react-bootstrap/lib/DropdownButton';
import MenuItem from 'react-bootstrap/lib/MenuItem'; import MenuItem from 'react-bootstrap/lib/MenuItem';
import { getLangText } from '../../utils/lang_utils.js'; import { getLangText } from '../../utils/lang_utils.js';
let PieceListToolbarFilterWidgetFilter = React.createClass({ let PieceListToolbarFilterWidgetFilter = React.createClass({
propTypes: {
filterParams: React.PropTypes.arrayOf(React.PropTypes.string).isRequired
},
getInitialState() {
return PieceListStore.getState();
},
componentDidMount() {
PieceListStore.listen(this.onChange);
},
componentWillUnmount() {
PieceListStore.unlisten(this.onChange);
},
onChange(state) {
this.setState(state);
},
generateFilterByStatement(param) {
let filterBy = this.state.filterBy;
if(filterBy) {
// we need hasOwnProperty since the values are all booleans
if(filterBy.hasOwnProperty(param)) {
filterBy[param] = !filterBy[param];
// if the parameter is false, then we want to remove it again
// from the list of queryParameters as this component is only about
// which actions *CAN* be done and not what *CANNOT*
if(!filterBy[param]) {
delete filterBy[param];
}
} else {
filterBy[param] = true;
}
}
return filterBy;
},
/**
* We need overloading here to find the correct parameter of the label
* the user is clicking on.
*/
filterBy(param) {
return () => {
let filterBy = this.generateFilterByStatement(param);
PieceListActions.fetchPieceList(this.state.page, this.state.pageSize, this.state.search,
this.state.orderBy, this.state.orderAsc, filterBy);
};
},
render() { render() {
let filterIcon = <Glyphicon glyph='filter' className="filter-glyph"/>; let filterIcon = <Glyphicon glyph='filter' className="filter-glyph"/>;
@ -17,18 +75,25 @@ let PieceListToolbarFilterWidgetFilter = React.createClass({
title={filterIcon} title={filterIcon}
className="ascribe-piece-list-toolbar-filter-widget"> className="ascribe-piece-list-toolbar-filter-widget">
<li style={{'textAlign': 'center'}}> <li style={{'textAlign': 'center'}}>
<em>{getLangText('Show Pieces that')}:</em> <em>{getLangText('Show works that')}:</em>
</li> </li>
<MenuItem eventKey='1' style={{'textAlign': 'center'}}> {this.props.filterParams.map((param, i) => {
<div className="checkbox-line"> let name = param.split('_')[1];
<label>{getLangText('I can transfer')}<input type="checkbox" /></label> return (
</div> <MenuItem
</MenuItem> key={i}
<MenuItem eventKey='2' style={{'textAlign': 'center'}}> style={{'textAlign': 'center'}}>
<div className="checkbox-line"> <div className="checkbox-line">
<label>{getLangText('I can consign')}<input type="checkbox" /></label> <span onClick={this.filterBy(param)}>
</div> {getLangText('I can') + ' ' + getLangText(name)}
</MenuItem> <input
type="checkbox"
checked={this.state.filterBy[param]} />
</span>
</div>
</MenuItem>
);
})}
</DropdownButton> </DropdownButton>
); );
} }

View File

@ -1,17 +1,31 @@
'use strict'; 'use strict';
import { generateOrderingQueryParams } from '../utils/fetch_api_utils';
import requests from '../utils/requests'; import requests from '../utils/requests';
import { mergeOptions } from '../utils/general_utils';
import { generateOrderingQueryParams } from '../utils/fetch_api_utils';
let PieceListFetcher = { let PieceListFetcher = {
/** /**
* Fetches a list of pieces from the API. * Fetches a list of pieces from the API.
* Can be called with all supplied queryparams the API. * Can be called with all supplied queryparams the API.
*/ */
fetch(page, pageSize, search, orderBy, orderAsc) { fetch(page, pageSize, search, orderBy, orderAsc, filterBy) {
let ordering = generateOrderingQueryParams(orderBy, orderAsc); let ordering = generateOrderingQueryParams(orderBy, orderAsc);
return requests.get('pieces_list', { page, pageSize, search, ordering });
// filterBy is an object of acl key-value pairs.
// The values are booleans
let queryParams = mergeOptions(
{
page,
pageSize,
search,
ordering
},
filterBy
);
return requests.get('pieces_list', queryParams);
}, },
fetchRequestActions() { fetchRequestActions() {

View File

@ -26,16 +26,18 @@ class PieceListStore {
this.search = ''; this.search = '';
this.orderBy = 'artist_name'; this.orderBy = 'artist_name';
this.orderAsc = true; this.orderAsc = true;
this.filterBy = {};
this.bindActions(PieceListActions); this.bindActions(PieceListActions);
} }
onUpdatePieceList({ page, pageSize, search, pieceList, orderBy, orderAsc, pieceListCount }) { onUpdatePieceList({ page, pageSize, search, pieceList, orderBy, orderAsc, pieceListCount, filterBy }) {
this.page = page; this.page = page;
this.pageSize = pageSize; this.pageSize = pageSize;
this.search = search; this.search = search;
this.orderAsc = orderAsc; this.orderAsc = orderAsc;
this.orderBy = orderBy; this.orderBy = orderBy;
this.pieceListCount = pieceListCount; this.pieceListCount = pieceListCount;
this.filterBy = filterBy;
/** /**
* Pagination - Known Issue: * Pagination - Known Issue:

View File

@ -5,7 +5,7 @@
} }
.search-bar { .search-bar {
max-width: 160px; max-width: 200px;
input { input {
height: 33px; height: 33px;
} }
@ -14,8 +14,8 @@
.ascribe-piece-list-toolbar-filter-widget { .ascribe-piece-list-toolbar-filter-widget {
margin-right: 1em; margin-right: 1em;
.checkbox-line { .checkbox-line {
label { span {
font-weight: normal; cursor: pointer;
} }
input { input {
position: relative; position: relative;