Merge pull request #134 from 67P/feature/quick_filter
Add quick filters
This commit was merged in pull request #134.
This commit is contained in:
@@ -1,9 +1,53 @@
|
|||||||
import Component from '@ember/component';
|
import Component from '@ember/component';
|
||||||
|
import { computed } from '@ember/object';
|
||||||
|
import { sort } from '@ember/object/computed';
|
||||||
|
import { isPresent } from '@ember/utils';
|
||||||
|
import { inject as service } from '@ember/service';
|
||||||
|
|
||||||
export default Component.extend({
|
export default Component.extend({
|
||||||
|
|
||||||
tagName: 'ul',
|
tagName: 'div',
|
||||||
classNames: ['contribution-list'],
|
classNames: ['contributions'],
|
||||||
|
|
||||||
|
showQuickFilter: false,
|
||||||
|
hideSmallContributions: false,
|
||||||
|
contributorId: null,
|
||||||
|
contributionKind: null,
|
||||||
|
|
||||||
|
kredits: service(),
|
||||||
|
|
||||||
|
contributorsSorting: Object.freeze(['name:asc']),
|
||||||
|
contributors: sort('kredits.contributors', 'contributorsSorting'),
|
||||||
|
|
||||||
|
contributorsActive: computed('contributors.[]', 'contributions', function() {
|
||||||
|
let activeIds = this.contributions.mapBy('contributorId')
|
||||||
|
.map(id => id.toString())
|
||||||
|
.uniq();
|
||||||
|
return this.contributors.filter(c => {
|
||||||
|
return activeIds.includes(c.id.toString());
|
||||||
|
});
|
||||||
|
}),
|
||||||
|
|
||||||
|
contributionKinds: computed('contributions.[]', function() {
|
||||||
|
return this.contributions.mapBy('kind').uniq();
|
||||||
|
}),
|
||||||
|
|
||||||
|
contributionsFiltered: computed('contributions.[]', 'hideSmallContributions', 'contributorId', 'contributionKind', function() {
|
||||||
|
return this.contributions.filter(c => {
|
||||||
|
let included = true;
|
||||||
|
|
||||||
|
if (this.hideSmallContributions &&
|
||||||
|
c.amount <= 500) { included = false; }
|
||||||
|
|
||||||
|
if (isPresent(this.contributorId) &&
|
||||||
|
c.contributorId.toString() !== this.contributorId.toString()) { included = false; }
|
||||||
|
|
||||||
|
if (isPresent(this.contributionKind) &&
|
||||||
|
c.kind !== this.contributionKind) { included = false; }
|
||||||
|
|
||||||
|
return included;
|
||||||
|
});
|
||||||
|
}),
|
||||||
|
|
||||||
actions: {
|
actions: {
|
||||||
|
|
||||||
|
|||||||
@@ -1,4 +1,36 @@
|
|||||||
{{#each contributions as |contribution|}}
|
{{#if showQuickFilter}}
|
||||||
|
<div class="quick-filter">
|
||||||
|
<p>
|
||||||
|
<label class="filter-contributor">
|
||||||
|
Contributor:
|
||||||
|
<select onchange={{action (mut contributorId) value="target.value"}}>
|
||||||
|
<option value="" selected>all</option>
|
||||||
|
{{#each contributorsActive as |contributor|}}
|
||||||
|
<option value={{contributor.id}} selected={{eq contributorId contributor.id}}>{{contributor.name}}</option>
|
||||||
|
{{/each}}
|
||||||
|
</select>
|
||||||
|
</label>
|
||||||
|
|
||||||
|
<label class="filter-contribution-kind">
|
||||||
|
Kind:
|
||||||
|
<select onchange={{action (mut contributionKind) value="target.value"}}>
|
||||||
|
<option value="" selected>all</option>
|
||||||
|
{{#each contributionKinds as |kind|}}
|
||||||
|
<option value={{kind}} selected={{eq contributionKind kind}}>{{capitalize-string kind}}</option>
|
||||||
|
{{/each}}
|
||||||
|
</select>
|
||||||
|
</label>
|
||||||
|
|
||||||
|
<label class="filter-contribution-size">
|
||||||
|
{{input type="checkbox" checked=hideSmallContributions}}
|
||||||
|
Hide small contributions
|
||||||
|
</label>
|
||||||
|
</p>
|
||||||
|
</div>
|
||||||
|
{{/if}}
|
||||||
|
|
||||||
|
<ul class="contribution-list">
|
||||||
|
{{#each contributionsFiltered as |contribution|}}
|
||||||
<li data-contribution-id={{contribution.id}} class="{{contribution-status contribution}} {{if contribution.vetoed "vetoed"}}">
|
<li data-contribution-id={{contribution.id}} class="{{contribution-status contribution}} {{if contribution.vetoed "vetoed"}}">
|
||||||
<p class="meta">
|
<p class="meta">
|
||||||
<span class="recipient">{{user-avatar contributor=contribution.contributor}}</span>
|
<span class="recipient">{{user-avatar contributor=contribution.contributor}}</span>
|
||||||
@@ -23,3 +55,4 @@
|
|||||||
{{/unless}}
|
{{/unless}}
|
||||||
</li>
|
</li>
|
||||||
{{/each}}
|
{{/each}}
|
||||||
|
</ul>
|
||||||
@@ -25,6 +25,9 @@ export default Controller.extend({
|
|||||||
showUnconfirmedKredits: true,
|
showUnconfirmedKredits: true,
|
||||||
hideUnconfirmedKredits: not('showUnconfirmedKredits'),
|
hideUnconfirmedKredits: not('showUnconfirmedKredits'),
|
||||||
|
|
||||||
|
showQuickFilterUnconfirmed: false,
|
||||||
|
showQuickFilterConfirmed: false,
|
||||||
|
|
||||||
actions: {
|
actions: {
|
||||||
|
|
||||||
vetoContribution (contributionId) {
|
vetoContribution (contributionId) {
|
||||||
@@ -37,6 +40,14 @@ export default Controller.extend({
|
|||||||
this.kredits.vote(proposalId).then(transaction => {
|
this.kredits.vote(proposalId).then(transaction => {
|
||||||
console.debug('[controllers:index] Vote submitted to Ethereum blockhain: '+transaction.hash);
|
console.debug('[controllers:index] Vote submitted to Ethereum blockhain: '+transaction.hash);
|
||||||
});
|
});
|
||||||
|
},
|
||||||
|
|
||||||
|
toggleQuickFilterUnconfirmed () {
|
||||||
|
this.toggleProperty('showQuickFilterUnconfirmed');
|
||||||
|
},
|
||||||
|
|
||||||
|
toggleQuickFilterConfirmed () {
|
||||||
|
this.toggleProperty('showQuickFilterConfirmed');
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -0,0 +1,7 @@
|
|||||||
|
import Helper from '@ember/component/helper';
|
||||||
|
|
||||||
|
export default Helper.extend({
|
||||||
|
compute([string]) {
|
||||||
|
return string.charAt(0).toUpperCase() + string.slice(1);
|
||||||
|
}
|
||||||
|
});
|
||||||
@@ -11,10 +11,18 @@ button, input[type=submit], .button {
|
|||||||
cursor: pointer;
|
cursor: pointer;
|
||||||
letter-spacing: 0.1em;
|
letter-spacing: 0.1em;
|
||||||
|
|
||||||
|
&+button, &+input[type=submit], &+.button {
|
||||||
|
margin-left: 0.5rem;
|
||||||
|
}
|
||||||
|
|
||||||
&:hover {
|
&:hover {
|
||||||
background-color: rgba(22, 21, 40, 0.8);
|
background-color: rgba(22, 21, 40, 0.8);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
&:active, &.active {
|
||||||
|
border-color: $primary-color;
|
||||||
|
}
|
||||||
|
|
||||||
&.small {
|
&.small {
|
||||||
font-size: 0.8rem;
|
font-size: 0.8rem;
|
||||||
padding: 0.2rem 0.8rem;
|
padding: 0.2rem 0.8rem;
|
||||||
@@ -28,6 +36,9 @@ button, input[type=submit], .button {
|
|||||||
&:hover {
|
&:hover {
|
||||||
background-color: rgba(40, 21, 21, 0.8);
|
background-color: rgba(40, 21, 21, 0.8);
|
||||||
}
|
}
|
||||||
|
&:active, &.active {
|
||||||
|
border-color: $red;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
&.green {
|
&.green {
|
||||||
@@ -38,5 +49,8 @@ button, input[type=submit], .button {
|
|||||||
&:hover {
|
&:hover {
|
||||||
background-color: rgba(21, 40, 21, 0.8);
|
background-color: rgba(21, 40, 21, 0.8);
|
||||||
}
|
}
|
||||||
|
&:active, &.active {
|
||||||
|
border-color: $green;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -6,6 +6,24 @@ main section {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.quick-filter {
|
||||||
|
font-size: 1.2rem;
|
||||||
|
margin-bottom: 2rem;
|
||||||
|
|
||||||
|
p {
|
||||||
|
font-size: inherit;
|
||||||
|
padding: 0.2rem 0 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
label {
|
||||||
|
font-size: inherit;
|
||||||
|
|
||||||
|
&+ label {
|
||||||
|
margin-left: 3.6rem;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
ul.contribution-list {
|
ul.contribution-list {
|
||||||
clear: both;
|
clear: both;
|
||||||
width: 100%;
|
width: 100%;
|
||||||
|
|||||||
@@ -42,6 +42,7 @@
|
|||||||
<h2>Latest Contributions</h2>
|
<h2>Latest Contributions</h2>
|
||||||
{{#if kredits.hasAccounts}}
|
{{#if kredits.hasAccounts}}
|
||||||
<nav>
|
<nav>
|
||||||
|
<button {{action "toggleQuickFilterUnconfirmed"}} class="small {{if showQuickFilterUnconfirmed "active"}}">filter</button>
|
||||||
{{link-to "add" "contributions.new" title="Submit a contribution" class="button small green"}}
|
{{link-to "add" "contributions.new" title="Submit a contribution" class="button small green"}}
|
||||||
</nav>
|
</nav>
|
||||||
{{/if}}
|
{{/if}}
|
||||||
@@ -50,18 +51,23 @@
|
|||||||
{{!-- TODO: We need a better naming for kredits.hasAccounts --}}
|
{{!-- TODO: We need a better naming for kredits.hasAccounts --}}
|
||||||
{{contribution-list contributions=contributionsUnconfirmedSorted
|
{{contribution-list contributions=contributionsUnconfirmedSorted
|
||||||
vetoContribution=(action "vetoContribution")
|
vetoContribution=(action "vetoContribution")
|
||||||
contractInteractionEnabled=kredits.hasAccounts}}
|
contractInteractionEnabled=kredits.hasAccounts
|
||||||
|
showQuickFilter=showQuickFilterUnconfirmed}}
|
||||||
</div>
|
</div>
|
||||||
</section>
|
</section>
|
||||||
{{/if}}
|
{{/if}}
|
||||||
|
|
||||||
<section id="contributions-confirmed">
|
<section id="contributions-confirmed">
|
||||||
<header>
|
<header class="with-nav">
|
||||||
<h2>Confirmed Contributions</h2>
|
<h2>Confirmed Contributions</h2>
|
||||||
|
<nav>
|
||||||
|
<button {{action "toggleQuickFilterConfirmed"}} class="small {{if showQuickFilterConfirmed "active"}}">filter</button>
|
||||||
|
</nav>
|
||||||
</header>
|
</header>
|
||||||
<div class="content">
|
<div class="content">
|
||||||
{{contribution-list contributions=contributionsConfirmedSorted
|
{{contribution-list contributions=contributionsConfirmedSorted
|
||||||
vetoContribution=(action "vetoContribution")}}
|
vetoContribution=(action "vetoContribution")
|
||||||
|
showQuickFilter=showQuickFilterConfirmed}}
|
||||||
</div>
|
</div>
|
||||||
</section>
|
</section>
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
Vendored
+9
-9
@@ -3,15 +3,15 @@ import Model from 'kredits-web/models/contribution';
|
|||||||
const items = [];
|
const items = [];
|
||||||
|
|
||||||
const data = [
|
const data = [
|
||||||
{ id: 1, contributorId: 1, confirmedAtBlock: 1000, claimed: false, vetoed: false, amount: 1500 },
|
{ id: 1, contributorId: 1, confirmedAtBlock: 1000, claimed: false, vetoed: false, amount: 1500, kind: 'dev' },
|
||||||
{ id: 2, contributorId: 1, confirmedAtBlock: 1000, claimed: false, vetoed: false, amount: 5000 },
|
{ id: 2, contributorId: 1, confirmedAtBlock: 1000, claimed: false, vetoed: false, amount: 5000, kind: 'ops' },
|
||||||
{ id: 3, contributorId: 2, confirmedAtBlock: 1000, claimed: false, vetoed: false, amount: 1500 },
|
{ id: 3, contributorId: 2, confirmedAtBlock: 1000, claimed: false, vetoed: false, amount: 1500, kind: 'ops' },
|
||||||
{ id: 4, contributorId: 2, confirmedAtBlock: 1000, claimed: false, vetoed: false, amount: 1500 },
|
{ id: 4, contributorId: 2, confirmedAtBlock: 1000, claimed: false, vetoed: false, amount: 1500, kind: 'docs' },
|
||||||
{ id: 5, contributorId: 1, confirmedAtBlock: 1000, claimed: false, vetoed: false, amount: 5000 },
|
{ id: 5, contributorId: 1, confirmedAtBlock: 1000, claimed: false, vetoed: false, amount: 5000, kind: 'design' },
|
||||||
{ id: 6, contributorId: 1, confirmedAtBlock: 1000, claimed: false, vetoed: true, amount: 500 },
|
{ id: 6, contributorId: 1, confirmedAtBlock: 1000, claimed: false, vetoed: true, amount: 500, kind: 'dev' },
|
||||||
{ id: 7, contributorId: 3, confirmedAtBlock: 2000, claimed: false, vetoed: false, amount: 5000 },
|
{ id: 7, contributorId: 3, confirmedAtBlock: 2000, claimed: false, vetoed: false, amount: 5000, kind: 'dev' },
|
||||||
{ id: 8, contributorId: 1, confirmedAtBlock: 2000, claimed: false, vetoed: false, amount: 1500 },
|
{ id: 8, contributorId: 1, confirmedAtBlock: 2000, claimed: false, vetoed: false, amount: 1500, kind: 'community' },
|
||||||
{ id: 9, contributorId: 3, confirmedAtBlock: 2000, claimed: false, vetoed: true, amount: 1500 },
|
{ id: 9, contributorId: 3, confirmedAtBlock: 2000, claimed: false, vetoed: true, amount: 1500, kind: 'docs' },
|
||||||
];
|
];
|
||||||
|
|
||||||
data.forEach(attrs => items.push(Model.create(attrs)));
|
data.forEach(attrs => items.push(Model.create(attrs)));
|
||||||
|
|||||||
@@ -1,17 +1,34 @@
|
|||||||
import { module, test } from 'qunit';
|
import { module, test } from 'qunit';
|
||||||
import { setupRenderingTest } from 'ember-qunit';
|
import { setupRenderingTest } from 'ember-qunit';
|
||||||
import { render } from '@ember/test-helpers';
|
import { click, fillIn, render } from '@ember/test-helpers';
|
||||||
import hbs from 'htmlbars-inline-precompile';
|
import hbs from 'htmlbars-inline-precompile';
|
||||||
|
import contributors from '../../../fixtures/contributors';
|
||||||
|
import contributions from '../../../fixtures/contributions';
|
||||||
|
|
||||||
module('Integration | Component | contribution-list', function(hooks) {
|
module('Integration | Component | contribution-list', function(hooks) {
|
||||||
setupRenderingTest(hooks);
|
setupRenderingTest(hooks);
|
||||||
|
|
||||||
test('it renders', async function(assert) {
|
test('it renders all contributions', async function(assert) {
|
||||||
// Set any properties with this.set('myProperty', 'value');
|
this.set('fixtures', contributions);
|
||||||
// Handle any actions with this.set('myAction', function(val) { ... });
|
await render(hbs`{{contribution-list contributions=fixtures}}`);
|
||||||
|
|
||||||
await render(hbs`{{contribution-list}}`);
|
assert.equal(this.element.querySelectorAll('li').length, 9);
|
||||||
|
});
|
||||||
|
|
||||||
assert.equal(this.element.textContent.trim(), '');
|
test('it renders filtered contributions', async function(assert) {
|
||||||
|
let service = this.owner.lookup('service:kredits');
|
||||||
|
service.set('contributors', contributors);
|
||||||
|
|
||||||
|
this.set('fixtures', contributions);
|
||||||
|
await render(hbs`{{contribution-list contributions=fixtures showQuickFilter=true}}`);
|
||||||
|
|
||||||
|
await fillIn('.filter-contributor select', '1');
|
||||||
|
assert.equal(this.element.querySelectorAll('li').length, 5, 'select contributor');
|
||||||
|
|
||||||
|
await click('.filter-contribution-size input');
|
||||||
|
assert.equal(this.element.querySelectorAll('li').length, 4, 'hide small contributions');
|
||||||
|
|
||||||
|
await fillIn('.filter-contribution-kind select', 'dev');
|
||||||
|
assert.equal(this.element.querySelectorAll('li').length, 1, 'select kind');
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|||||||
Reference in New Issue
Block a user