Switch to contribution token instead of proposals

No vetos yet, and only for collections (not creation).

closes #20
This commit is contained in:
2019-04-09 12:55:44 +02:00
parent 9c4e431e3b
commit aa28a14d04
11 changed files with 274 additions and 28 deletions
@@ -0,0 +1,20 @@
import Component from '@ember/component';
export default Component.extend({
tagName: 'ul',
classNames: ['contribution-list'],
// actions: {
//
// veto (contributionId) {
// if (this.contractInteractionEnabled) {
// this.vetoContribution(contributionId);
// } else {
// window.alert('Only members can veto contributions. Please ask someone to set you up.');
// }
// }
//
// }
});
@@ -0,0 +1,16 @@
{{#each contributions as |contribution|}}
<li data-contribution-id={{contribution.id}} class={{if contribution.confirmed "confirmed" "unconfirmed"}}>
<p class="meta">
<span class="category {{contribution.kind}}">♥ ({{contribution.kind}})</span>
<span class="recipient">{{contribution.contributor.name}}:</span>
</p>
<p class="kredits-amount">
<span class="amount">{{contribution.amount}}</span><span class="symbol">₭S</span>
</p>
<p class="description">
<span class="description">{{contribution.description}}</span>
</p>
<p class="voting">
</p>
</li>
{{/each}}
+29 -9
View File
@@ -1,9 +1,11 @@
import Controller from '@ember/controller';
import { alias, filter, filterBy, sort } from '@ember/object/computed';
import { alias, filter, sort } from '@ember/object/computed';
import { inject as service } from '@ember/service';
import { computed } from '@ember/object';
export default Controller.extend({
kredits: service(),
currentBlock: alias('kredits.currentBlock'),
contributors: alias('kredits.contributors'),
contributorsWithKredits: filter('contributors', function(contributor) {
@@ -12,26 +14,44 @@ export default Controller.extend({
contributorsSorting: Object.freeze(['balance:desc']),
contributorsSorted: sort('contributorsWithKredits', 'contributorsSorting'),
proposals: alias('kredits.proposals'),
proposalsOpen: filterBy('proposals', 'isExecuted', false),
proposalsClosed: filterBy('proposals', 'isExecuted', true),
proposalsSorting: Object.freeze(['id:desc']),
proposalsClosedSorted: sort('proposalsClosed', 'proposalsSorting'),
proposalsOpenSorted: sort('proposalsOpen', 'proposalsSorting'),
contributions: alias('kredits.contributions'),
contributionsSorting: Object.freeze(['id:desc']),
contributionsUnconfirmed: computed('contributions.[]', 'currentBlock', function() {
return this.contributions.filter(contribution => {
return contribution.confirmedAt < this.currentBlock;
});
}),
contributionsConfirmed: computed('contributions.[]', 'currentBlock', function() {
return this.contributions.filter(contribution => {
return contribution.confirmedAt >= this.currentBlock;
});
}),
contributionsUnconfirmedSorted: sort('contributionsUnconfirmed', 'contributionsSorting'),
contributionsConfirmedSorted: sort('contributionsConfirmed', 'contributionsSorting'),
actions: {
confirmProposal(proposalId) {
vetoContribution (/* contributionId */) {
// this.kredits.vote(proposalId).then(transaction => {
// window.confirm('Vote submitted to Ethereum blockhain: '+transaction.hash);
// });
},
confirmProposal (proposalId) {
this.kredits.vote(proposalId).then(transaction => {
window.confirm('Vote submitted to Ethereum blockhain: '+transaction.hash);
});
},
save(contributor) {
save (contributor) {
return this.kredits.addContributor(contributor)
.then((contributor) => {
this.contributors.pushObject(contributor);
return contributor;
});
}
}
});
+28
View File
@@ -0,0 +1,28 @@
import EmberObject from '@ember/object';
import bignumber from 'kredits-web/utils/cps/bignumber';
export default EmberObject.extend({
// Contract
id: null,
contributorId: null,
amount: null,
confirmedAt: bignumber('confirmedAtBlock', 'toNumber'),
vetoed: null,
ipfsHash: null,
creatorAccount: null,
// IPFS
kind: null,
description: null,
details: null,
url: null,
ipfsData: '',
init () {
this._super(...arguments);
this.set('details', {});
}
});
+1 -1
View File
@@ -23,7 +23,7 @@ export default Route.extend({
},
afterModel() {
return this.kredits.loadContributorsAndProposals()
return this.kredits.loadInitialData()
.then(() => {
this.kredits.addContractEventHandlers();
});
+25 -5
View File
@@ -10,13 +10,16 @@ import { isEmpty } from '@ember/utils';
import config from 'kredits-web/config/environment';
import Contributor from 'kredits-web/models/contributor'
import Proposal from 'kredits-web/models/proposal'
import Contribution from 'kredits-web/models/contribution'
export default Service.extend({
currentBlock: null,
currentUserAccounts: null, // default to not having an account. this is the wen web3 is loaded.
currentUser: null,
contributors: null,
proposals: null,
contributions: null,
currentUserIsContributor: notEmpty('currentUser'),
currentUserIsCore: alias('currentUser.isCore'),
hasAccounts: notEmpty('currentUserAccounts'),
@@ -28,6 +31,7 @@ export default Service.extend({
this._super(...arguments);
this.set('contributors', []);
this.set('proposals', []);
this.set('contributions', []);
},
// this is called in the routes beforeModel(). So it is initialized before everything else
@@ -83,7 +87,6 @@ export default Service.extend({
setup() {
return this.getEthProvider().then((providerAndSigner) => {
let kredits = new Kredits(providerAndSigner.ethProvider, providerAndSigner.ethSigner, {
addresses: { Kernel: config.kreditsKernelAddress },
apm: config.kreditsApmDomain,
@@ -91,13 +94,16 @@ export default Service.extend({
});
return kredits
.init()
.then((kredits) => {
.then(async (kredits) => {
this.set('kredits', kredits);
this.set('currentBlock', await kredits.provider.getBlockNumber());
if (this.currentUserAccounts && this.currentUserAccounts.length > 0) {
this.getCurrentUser.then((contributorData) => {
this.set('currentUser', contributorData);
});
}
return kredits;
});
});
@@ -107,11 +113,11 @@ export default Service.extend({
return this.kredits.Token.functions.totalSupply();
}),
loadContributorsAndProposals() {
loadInitialData() {
return this.getContributors()
.then(contributors => this.contributors.pushObjects(contributors))
.then(() => this.getProposals())
.then(proposals => this.proposals.pushObjects(proposals))
.then(() => this.getContributions())
.then(contributions => this.contributions.pushObjects(contributions))
},
addContributor(attributes) {
@@ -154,6 +160,16 @@ export default Service.extend({
});
},
getContributions() {
return this.kredits.Contribution.all()
.then(contributions => {
return contributions.map(contribution => {
contribution.contributor = this.contributors.findBy('id', contribution.contributorId.toString());
return Contribution.create(contribution);
});
});
},
vote(proposalId) {
console.debug('[kredits] vote for', proposalId);
@@ -184,6 +200,10 @@ export default Service.extend({
return this.proposals.findBy('id', proposalId.toString());
},
findContributionById(contributionId) {
return this.contributions.findBy('id', contributionId.toString());
},
// Contract events
addContractEventHandlers() {
// Proposal events
-4
View File
@@ -36,10 +36,6 @@ main section {
@include media-max(small) {
margin-bottom: 5rem;
&#proposals-open, &#proposals-closed {
margin-top: 0;
}
}
header {
+1
View File
@@ -119,3 +119,4 @@ button, input[type=submit] {
@import "components/contributor-list";
@import "components/add-contributor";
@import "components/proposal-list";
@import "components/contribution-list";
@@ -0,0 +1,128 @@
main section {
@include media-max(small) {
&#contributions-unconfirmed, &#contributions-confirmed {
margin-top: 0;
}
}
}
ul.contribution-list {
clear: both;
width: 100%;
list-style: none;
li {
display: grid;
grid-template-columns: auto 5rem;
grid-row-gap: 0.5rem;
padding: 1rem 1.2rem;
background-color: rgba(255,255,255,0.1);
font-size: 1.2rem;
border-bottom: 1px solid rgba(255,255,255,0.2);
&:first-of-type {
border-top: 1px solid rgba(255,255,255,0.2);
}
p {
align-self: center;
margin: 0;
font-size: inherit;
line-height: 2rem;
&.kredits-amount, &.voting {
text-align: right;
}
&.description {
grid-column-start: span 2;
}
&.voting {
grid-column-start: span 2;
}
}
span {
font-size: inherit;
}
.description {
line-height: 1.4em;
font-size: 1rem;
}
.category {
color: $blue;
padding-right: 0.2rem;
&.community { color: $red; }
&.dev { color: $pink; }
&.design { color: $yellow; }
&.docs { color: $green; }
&.ops { color: $purple; }
}
.amount {
font-weight: 500;
}
.symbol {
font-size: 1rem;
font-weight: 500;
padding-left: 0.2rem;
}
.recipient {
font-weight: 500;
}
.votes {
font-size: 1rem;
color: $primary-color;
margin-right: 0.5rem;
}
button {
height: 2rem;
line-height: 2rem;
padding: 0 0.6rem;
}
}
}
@media (min-width: 550px) {
ul.proposal-list {
li {
grid-template-columns: auto 10rem;
grid-row-gap: 0.5rem;
p {
&.kredits-amount, &.voting {
text-align: right;
}
}
&.unconfirmed {
p {
&.kredits-amount, &.voting {
text-align: right;
}
&.description {
grid-column-start: span 1;
}
&.voting {
grid-column-start: span 1;
}
}
}
.description {
font-size: inherit;
}
}
}
}
+9 -9
View File
@@ -20,33 +20,33 @@
<h2>Contributions by type</h2>
</header>
<div class="content">
{{chart-contributions-by-type contributions=proposals}}
{{chart-contributions-by-type contributions=contributions}}
</div>
</section>
</div>
<div id="contributions">
{{#if proposalsOpen}}
<section id="proposals-open">
{{#if contributionsUnconfirmed}}
<section id="contributions-unconfirmed">
<header>
<h2>Unconfirmed Contributions</h2>
</header>
<div class="content">
{{!-- TODO: We need a better naming for kredits.hasAccounts --}}
{{proposal-list proposals=proposalsOpenSorted
confirmProposal=(action "confirmProposal")
contractInteractionEnabled=kredits.hasAccounts}}
{{contribution-list contributions=contributionsUnconfirmedSorted
vetoContribution=(action "vetoContribution")
contractInteractionEnabled=kredits.hasAccounts}}
</div>
</section>
{{/if}}
<section id="proposals-closed">
<section id="contributions-confirmed">
<header>
<h2>Confirmed Contributions</h2>
</header>
<div class="content">
{{proposal-list proposals=proposalsClosedSorted
confirmProposal=(action "confirmProposal")}}
{{contribution-list contributions=contributionsConfirmedSorted
vetoContribution=(action "vetoContribution")}}
</div>
{{!-- TODO: We need a better naming --}}