WIP Sync contributions
This commit is contained in:
@@ -29,7 +29,7 @@
|
||||
</div>
|
||||
{{/if}}
|
||||
|
||||
<ul class="contribution-list">
|
||||
<ul class="contribution-list {{if @loading 'loading'}}">
|
||||
{{#each this.contributionsFiltered as |contribution|}}
|
||||
<li role="button" data-contribution-id={{contribution.id}}
|
||||
{{action "openContributionDetails" contribution}}
|
||||
|
||||
@@ -2,12 +2,10 @@ import Component from '@ember/component';
|
||||
import { inject as service } from '@ember/service';
|
||||
|
||||
export default Component.extend({
|
||||
tagName: '',
|
||||
|
||||
router: service(),
|
||||
|
||||
tagName: 'table',
|
||||
classNames: 'contributor-list',
|
||||
|
||||
selectedContributorId: null,
|
||||
|
||||
actions: {
|
||||
@@ -17,5 +15,4 @@ export default Component.extend({
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
});
|
||||
|
||||
@@ -1,21 +1,25 @@
|
||||
<tbody>
|
||||
{{#each @contributorList as |c|}}
|
||||
<tr role="button"
|
||||
onclick={{action "openContributorDetails" c.contributor}}
|
||||
class="{{if (is-current-user c.contributor) "current-user"}} {{if (eq c.contributor.id @selectedContributorId) "selected"}}">
|
||||
<td class="person">
|
||||
<UserAvatar @contributor={{c.contributor}} /> {{c.contributor.name}}
|
||||
</td>
|
||||
<td class="kredits">
|
||||
<span class="amount">
|
||||
{{#if @showUnconfirmedKredits}}
|
||||
{{c.amountTotal}}
|
||||
{{else}}
|
||||
{{c.amountConfirmed}}
|
||||
{{/if}}
|
||||
</span>
|
||||
<span class="symbol">₭S</span>
|
||||
</td>
|
||||
</tr>
|
||||
{{/each}}
|
||||
</tbody>
|
||||
<table class="contributor-list {{if @loading 'loading'}}">
|
||||
<thead>
|
||||
</thead>
|
||||
<tbody>
|
||||
{{#each @contributorList as |c|}}
|
||||
<tr role="button"
|
||||
onclick={{action "openContributorDetails" c.contributor}}
|
||||
class="{{if (is-current-user c.contributor) "current-user"}} {{if (eq c.contributor.id @selectedContributorId) "selected"}}">
|
||||
<td class="person">
|
||||
<UserAvatar @contributor={{c.contributor}} /> {{c.contributor.name}}
|
||||
</td>
|
||||
<td class="kredits">
|
||||
<span class="amount">
|
||||
{{#if @showUnconfirmedKredits}}
|
||||
{{c.amountTotal}}
|
||||
{{else}}
|
||||
{{c.amountConfirmed}}
|
||||
{{/if}}
|
||||
</span>
|
||||
<span class="symbol">₭S</span>
|
||||
</td>
|
||||
</tr>
|
||||
{{/each}}
|
||||
</tbody>
|
||||
</table>
|
||||
|
||||
@@ -25,9 +25,11 @@ export default Route.extend({
|
||||
})
|
||||
.then(() => {
|
||||
if (this.kredits.contributorsNeedFetch) {
|
||||
schedule('afterRender', this.kredits, this.kredits.fetchContributors);
|
||||
schedule('afterRender', this.kredits.syncContributors,
|
||||
this.kredits.syncContributors.perform);
|
||||
}
|
||||
schedule('afterRender', this.kredits, this.kredits.fetchContributions);
|
||||
schedule('afterRender', this.kredits.syncContributions,
|
||||
this.kredits.syncContributions.perform);
|
||||
});
|
||||
}
|
||||
});
|
||||
|
||||
+44
-1
@@ -8,6 +8,8 @@ import { alias, notEmpty } from '@ember/object/computed';
|
||||
import { isEmpty, isPresent } from '@ember/utils';
|
||||
import { inject as service } from '@ember/service';
|
||||
|
||||
import { task } from 'ember-concurrency';
|
||||
|
||||
import groupBy from 'kredits-web/utils/group-by';
|
||||
import processContributorData from 'kredits-web/utils/process-contributor-data';
|
||||
import processContributionData from 'kredits-web/utils/process-contribution-data';
|
||||
@@ -240,6 +242,7 @@ export default Service.extend({
|
||||
const loadedContributor = this.contributors.findBy('id', contributor.id);
|
||||
if (loadedContributor) { this.contributors.removeObject(loadedContributor); }
|
||||
this.contributors.pushObject(contributor);
|
||||
return contributor;
|
||||
},
|
||||
|
||||
async cacheLoadedContributors () {
|
||||
@@ -258,6 +261,10 @@ export default Service.extend({
|
||||
});
|
||||
},
|
||||
|
||||
syncContributors: task(function * () {
|
||||
yield this.fetchContributors();
|
||||
}),
|
||||
|
||||
addContribution (attributes) {
|
||||
console.debug('[kredits] add contribution', attributes);
|
||||
|
||||
@@ -278,7 +285,7 @@ export default Service.extend({
|
||||
return this.kredits.Contribution.all(options)
|
||||
.then(contributions => {
|
||||
return contributions.map(data => {
|
||||
loadContributionFromData(data);
|
||||
const contribution = this.loadContributionFromData(data);
|
||||
return contribution;
|
||||
});
|
||||
})
|
||||
@@ -298,6 +305,7 @@ export default Service.extend({
|
||||
const loadedContribution = this.contributions.findBy('id', contribution.id);
|
||||
if (loadedContribution) { this.contributions.removeObject(loadedContribution); }
|
||||
this.contributions.pushObject(contribution);
|
||||
return contribution;
|
||||
},
|
||||
|
||||
async cacheLoadedContributions () {
|
||||
@@ -316,6 +324,41 @@ export default Service.extend({
|
||||
});
|
||||
},
|
||||
|
||||
syncContributions: task(function * () {
|
||||
yield this.fetchNewContributions.perform();
|
||||
yield this.syncUnconfirmedContributions.perform();
|
||||
}),
|
||||
|
||||
fetchNewContributions: task(function * () {
|
||||
const count = yield this.kredits.Contribution.functions.contributionsCount();
|
||||
const lastKnownContributionId = Math.max.apply(null, this.contributions.mapBy('id'));
|
||||
const toFetch = count - lastKnownContributionId;
|
||||
|
||||
if (toFetch > 0) {
|
||||
console.debug(`[kredits] Fetching ${toFetch} new contributions`);
|
||||
for (let id = lastKnownContributionId; id <= count; id++) {
|
||||
const data = yield this.kredits.Contribution.getById(id);
|
||||
const c = this.loadContributionFromData(data);
|
||||
yield this.browserCache.contributions.setItem(c.id.toString(), c.serialize());
|
||||
}
|
||||
} else {
|
||||
console.debug(`[kredits] No new contributions to fetch`);
|
||||
}
|
||||
}),
|
||||
|
||||
syncUnconfirmedContributions: task(function * () {
|
||||
if (this.contributionsUnconfirmed.length > 0) {
|
||||
console.debug(`[kredits] Syncing unconfirmed contributions`);
|
||||
for (const c of this.contributionsUnconfirmed) {
|
||||
const data = yield this.kredits.Contribution.getById(c.id);
|
||||
const contribution = this.loadContributionFromData(data);
|
||||
yield this.browserCache.contributions.setItem(c.id.toString(), contribution.serialize());
|
||||
}
|
||||
} else {
|
||||
console.debug(`[kredits] No unconfirmed contributions to sync`);
|
||||
}
|
||||
}),
|
||||
|
||||
veto (contributionId) {
|
||||
console.debug('[kredits] veto against', contributionId);
|
||||
const contribution = this.contributions.findBy('id', contributionId);
|
||||
|
||||
@@ -0,0 +1,17 @@
|
||||
@mixin loading-border-top {
|
||||
&::before {
|
||||
display: block;
|
||||
width: 100%;
|
||||
height: 1px;
|
||||
content: '';
|
||||
background-image: linear-gradient(45deg, rgba(255, 255, 255, 0.2) 40%, #68d7fb 60%, rgba(255, 255, 255, 0.2));
|
||||
background-size: 200% 200%;
|
||||
animation: kitt 2.5s linear infinite;
|
||||
}
|
||||
}
|
||||
|
||||
@keyframes kitt {
|
||||
0%{ background-position: 0% 0%}
|
||||
50%{ background-position: 100% 0%}
|
||||
100%{ background-position: 0% 0%}
|
||||
}
|
||||
@@ -88,6 +88,7 @@ section {
|
||||
|
||||
@import "buttons";
|
||||
@import "forms";
|
||||
@import "sugar";
|
||||
|
||||
@import "components/contribution-list";
|
||||
@import "components/contribution-details";
|
||||
|
||||
@@ -114,4 +114,13 @@ ul.contribution-list {
|
||||
}
|
||||
}
|
||||
|
||||
&.loading {
|
||||
@include loading-border-top;
|
||||
|
||||
li {
|
||||
&:first-of-type {
|
||||
border-top: none;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
table.contributor-list {
|
||||
position: relative;
|
||||
width: 100%;
|
||||
border-collapse: collapse;
|
||||
margin-bottom: 1.5rem;
|
||||
@@ -48,4 +49,11 @@ table.contributor-list {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
&.loading {
|
||||
@include loading-border-top;
|
||||
&::before {
|
||||
position: absolute;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -29,7 +29,8 @@
|
||||
<div class="content">
|
||||
<ContributorList @contributorList={{this.kreditsToplist}}
|
||||
@showUnconfirmedKredits={{this.showUnconfirmedKredits}}
|
||||
@selectedContributorId={{this.selectedContributorId}} />
|
||||
@selectedContributorId={{this.selectedContributorId}}
|
||||
@loading={{this.kredits.syncContributors.isRunning}} />
|
||||
|
||||
<p class="stats">
|
||||
<span class="number">{{await this.kredits.totalKreditsEarned}}</span> kredits confirmed and issued to
|
||||
@@ -58,7 +59,9 @@
|
||||
{{#if this.contributionsUnconfirmed}}
|
||||
<section id="contributions-unconfirmed">
|
||||
<header class="with-nav">
|
||||
<h2>Latest Contributions</h2>
|
||||
<h2>
|
||||
Latest Contributions
|
||||
</h2>
|
||||
<nav>
|
||||
<button type="button"
|
||||
onclick={{action "toggleQuickFilterUnconfirmed"}}
|
||||
@@ -78,7 +81,8 @@
|
||||
@vetoContribution={{action "vetoContribution"}}
|
||||
@contractInteractionEnabled={{this.kredits.hasAccounts}}
|
||||
@selectedContributionId={{this.selectedContributionId}}
|
||||
@showQuickFilter={{this.showQuickFilterUnconfirmed}} />
|
||||
@showQuickFilter={{this.showQuickFilterUnconfirmed}}
|
||||
@loading={{this.kredits.syncContributions.isRunning}}/>
|
||||
</div>
|
||||
</section>
|
||||
{{/if}}
|
||||
|
||||
Reference in New Issue
Block a user