Skip to content

Commit

Permalink
Merge pull request #335 from zalando-stups/314-add-all-accounts
Browse files Browse the repository at this point in the history
314 add all accounts
  • Loading branch information
prayerslayer committed Oct 27, 2015
2 parents 38a2bf9 + d212801 commit a6ea172
Show file tree
Hide file tree
Showing 6 changed files with 176 additions and 30 deletions.
5 changes: 1 addition & 4 deletions build.sh
Original file line number Diff line number Diff line change
Expand Up @@ -11,13 +11,10 @@ then
exit 1
fi

# create new version
npm version "$1"
# build
npm install
cd client
gulp build
cd ..
# push
docker build -t "$DEFAULT_DOCKER_REGISTRY/stups/yourturn:$1" . && docker push "$DEFAULT_DOCKER_REGISTRY/stups/yourturn:$1"
git push --tags
docker build -t "$DEFAULT_DOCKER_REGISTRY/stups/yourturn:$1" . && docker push "$DEFAULT_DOCKER_REGISTRY/stups/yourturn:$1"
1 change: 1 addition & 0 deletions client/Gulpfile.js
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@ var LODASH_FUNCS = [
'groupBy',
'intersection',
'isEmpty',
'partition',
'pluck',
'reverse',
'sortBy',
Expand Down
12 changes: 11 additions & 1 deletion client/lib/common/asset/less/common/account-selector.less
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,11 @@
.account-selector {
padding: @padding-small 0;

.account-selector-list {
max-height: 300px;
overflow: auto;
}

label {
.transition(background, color);
cursor: pointer;
Expand Down Expand Up @@ -50,9 +55,13 @@
}
}

.account-selector-toggle-buttons {
padding: @padding-tiniest 0;
}

.input-group {
display: flex;
padding-bottom: @padding-small;
width: 30em;
.fa {
user-select: none;
flex: 0 0 auto;
Expand All @@ -69,6 +78,7 @@
input {
border-top-left-radius: 0px;
border-bottom-left-radius: 0px;
width: 100%;
}
}
}
66 changes: 65 additions & 1 deletion client/lib/common/src/lodash.custom.js
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
/**
* @license
* lodash 3.9.3 (Custom Build) <https://lodash.com/>
* Build: `lodash modern include="chain,debounce,difference,extend,filter,findLastIndex,flatten,forOwn,groupBy,intersection,isEmpty,pluck,reverse,sortBy,slice,take,times,value,values" -d -o lib/common/src/lodash.custom.js`
* Build: `lodash modern include="chain,debounce,difference,extend,filter,findLastIndex,flatten,forOwn,groupBy,intersection,isEmpty,partition,pluck,reverse,sortBy,slice,take,times,value,values" -d -o lib/common/src/lodash.custom.js`
* Copyright 2012-2015 The Dojo Foundation <http://dojofoundation.org/>
* Based on Underscore.js 1.8.3 <http://underscorejs.org/LICENSE>
* Copyright 2009-2015 Jeremy Ashkenas, DocumentCloud and Investigative Reporters & Editors
Expand Down Expand Up @@ -3354,6 +3354,69 @@
return func(collection, iteratee);
}

/**
* Creates an array of elements split into two groups, the first of which
* contains elements `predicate` returns truthy for, while the second of which
* contains elements `predicate` returns falsey for. The predicate is bound
* to `thisArg` and invoked with three arguments: (value, index|key, collection).
*
* If a property name is provided for `predicate` the created `_.property`
* style callback returns the property value of the given element.
*
* If a value is also provided for `thisArg` the created `_.matchesProperty`
* style callback returns `true` for elements that have a matching property
* value, else `false`.
*
* If an object is provided for `predicate` the created `_.matches` style
* callback returns `true` for elements that have the properties of the given
* object, else `false`.
*
* @static
* @memberOf _
* @category Collection
* @param {Array|Object|string} collection The collection to iterate over.
* @param {Function|Object|string} [predicate=_.identity] The function invoked
* per iteration.
* @param {*} [thisArg] The `this` binding of `predicate`.
* @returns {Array} Returns the array of grouped elements.
* @example
*
* _.partition([1, 2, 3], function(n) {
* return n % 2;
* });
* // => [[1, 3], [2]]
*
* _.partition([1.2, 2.3, 3.4], function(n) {
* return this.floor(n) % 2;
* }, Math);
* // => [[1.2, 3.4], [2.3]]
*
* var users = [
* { 'user': 'barney', 'age': 36, 'active': false },
* { 'user': 'fred', 'age': 40, 'active': true },
* { 'user': 'pebbles', 'age': 1, 'active': false }
* ];
*
* var mapper = function(array) {
* return _.pluck(array, 'user');
* };
*
* // using the `_.matches` callback shorthand
* _.map(_.partition(users, { 'age': 1, 'active': false }), mapper);
* // => [['pebbles'], ['barney', 'fred']]
*
* // using the `_.matchesProperty` callback shorthand
* _.map(_.partition(users, 'active', false), mapper);
* // => [['barney', 'pebbles'], ['fred']]
*
* // using the `_.property` callback shorthand
* _.map(_.partition(users, 'active'), mapper);
* // => [['fred'], ['barney', 'pebbles']]
*/
var partition = createAggregator(function(result, value, key) {
result[key ? 0 : 1].push(value);
}, function() { return [[], []]; });

/**
* Gets the property value of `path` from all elements in `collection`.
*
Expand Down Expand Up @@ -4461,6 +4524,7 @@
lodash.matches = matches;
lodash.mixin = mixin;
lodash.pairs = pairs;
lodash.partition = partition;
lodash.pluck = pluck;
lodash.property = property;
lodash.restParam = restParam;
Expand Down
120 changes: 97 additions & 23 deletions client/lib/violation/src/account-selector.jsx
Original file line number Diff line number Diff line change
@@ -1,40 +1,50 @@
import React from 'react';
import Icon from 'react-fa';
import _ from 'lodash';
import {Typeahead} from 'react-typeahead';
import fuzzysearch from 'fuzzysearch';
import 'common/asset/less/common/account-selector.less';

function filterOptionFn(input, option) {
return input
.trim()
.split(' ')
.some(term => (option.name + option.id).indexOf(term) >= 0);
.some(term => fuzzysearch(term, option.name + option.id));
}

function getDisplayedAccounts(selected, filter) {
return filter ?
selected.filter(a => fuzzysearch(filter, a.name)) :
selected;
}

class AccountSelector extends React.Component {
constructor(props) {
super();
this.state = {
allSelected: props.selectedAccounts ? props.selectedAccounts.length === props.selectableAccounts.length : false,
filter: '',
selectedAccounts: props.selectedAccounts || []
};
}

_selectAll() {
this.props.onToggleAccount(this.props.selectableAccounts.map(a => a.id));

this.setState({
allSelected: true,
selectedAccounts: _.sortBy(this.props.selectableAccounts, 'name')
});
}

_selectAccount(account) {
let {id} = account;
if (this.state.selectedAccounts.map(a => a.id).indexOf(id) >= 0) {
return;
}
this.state.selectedAccounts.push(account);
this.state.selectedAccounts
.sort((a, b) => {
let aName = a.name.toLowerCase(),
bName = b.name.toLowerCase();
return aName < bName ?
-1 :
bName < aName ?
1 : 0;
});
this.setState({
selectedAccounts: this.state.selectedAccounts
selectedAccounts: _.sortBy(this.state.selectedAccounts, 'name')
});
let {activeAccountIds} = this.props;
if (activeAccountIds.indexOf(account.id) < 0) {
Expand All @@ -56,23 +66,75 @@ class AccountSelector extends React.Component {
}
}

_toggleAll() {
let displayedIds = getDisplayedAccounts(this.state.selectedAccounts, this.state.filter).map(a => a.id),
activeIds = this.props.activeAccountIds.concat(displayedIds);
// dedup
activeIds = activeIds.filter((el, idx, all) => all.lastIndexOf(el) === idx);
this.props.onToggleAccount(activeIds);
}

_untoggleAll() {
let displayedIds = getDisplayedAccounts(this.state.selectedAccounts, this.state.filter).map(a => a.id),
activeIds = this.props.activeAccountIds.filter(a => displayedIds.indexOf(a) < 0);
this.props.onToggleAccount(activeIds);
}

_filter(evt) {
this.setState({
filter: evt.target.value
});
}

render() {
let {selectableAccounts, activeAccountIds} = this.props,
{selectedAccounts} = this.state;
{selectedAccounts} = this.state,
displayedAccounts = getDisplayedAccounts(selectedAccounts, this.state.filter),
partitionedAccounts = _.partition(displayedAccounts, a => activeAccountIds.indexOf(a.id) >= 0),
activeAccounts = partitionedAccounts[0],
inactiveAccounts = partitionedAccounts[1];
return <div className='account-selector'>
<div>Show violations in accounts:</div>
<small>You can search by name or account number.</small>
<div className='input-group'>
<Icon name='search' />
<Typeahead
placeholder='stups-test 123456'
options={selectableAccounts}
displayOption={option => `${option.name} (${option.id})`}
filterOption={filterOptionFn}
onOptionSelected={this._selectAccount.bind(this)}
maxVisible={10} />
{!this.state.allSelected ?
<div>
<div>
<small>You can search by name or account number or <span
onClick={this._selectAll.bind(this)}
className='btn btn-default btn-small'>
<Icon name='plus' /> Select all accounts
</span>
</small>
</div>
<div className='input-group'>
<Icon name='search' />
<Typeahead
placeholder='stups-test 123456'
options={selectableAccounts}
displayOption={option => `${option.name} (${option.id})`}
filterOption={filterOptionFn}
onOptionSelected={this._selectAccount.bind(this)}
maxVisible={10} />
</div>
</div>
:
<div className='input-group'>
<Icon name='search' />
<input
onChange={this._filter.bind(this)}
placeholder='Search in selected accounts'
type='text'/>
</div>}
<div className='account-selector-toggle-buttons btn-group'>
<div onClick={this._toggleAll.bind(this)} className='btn btn-default'>
<Icon name='check-square-o'/> Toggle all
</div>
<div onClick={this._untoggleAll.bind(this)} className='btn btn-default'>
<Icon name='square-o' /> Untoggle all
</div>
</div>
{selectedAccounts.map(a =>
<div className='account-selector-list'>
{_.sortBy(activeAccounts, 'name')
.map(a =>
<label
key={a.id}
className={activeAccountIds.indexOf(a.id) >= 0 ? 'is-checked' : ''}>
Expand All @@ -82,6 +144,18 @@ class AccountSelector extends React.Component {
onChange={this._toggleAccount.bind(this, a.id)}
defaultChecked={activeAccountIds.indexOf(a.id) >= 0}/> {a.name} <small>({a.id})</small>
</label>)}
{_.sortBy(inactiveAccounts, 'name')
.map(a =>
<label
key={a.id}
className={activeAccountIds.indexOf(a.id) >= 0 ? 'is-checked' : ''}>
<input
type='checkbox'
value={a.id}
onChange={this._toggleAccount.bind(this, a.id)}
defaultChecked={activeAccountIds.indexOf(a.id) >= 0}/> {a.name} <small>({a.id})</small>
</label>)}
</div>
</div>;
}
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -120,7 +120,7 @@ class ViolationAnalysis extends React.Component {
return <div className='violation-analysis-empty'>
<div><Icon name='smile-o' size='4x' /></div>
<span>No violations!</span>
</div>
</div>;
}
}
ViolationAnalysis.displayName = 'ViolationAnalysis';
Expand Down

0 comments on commit a6ea172

Please sign in to comment.