Merge pull request #41 from 67P/refactor/cleanup-models
Cleanup controller, templates and service
This commit was merged in pull request #41.
This commit is contained in:
@@ -2,9 +2,11 @@
|
||||
<li data-proposal-id={{proposal.id}} title="({{proposal.kind}}) {{proposal.description}}">
|
||||
<span class="category {{proposal.kind}}">♥</span>
|
||||
<span class="amount">{{proposal.amount}}</span><span class="symbol">₭S</span>
|
||||
for <span class="recipient">{{proposal.recipientName}}</span>
|
||||
for <span class="recipient">{{proposal.contributor.name}}</span>
|
||||
<span class="votes">({{proposal.votesCount}}/{{proposal.votesNeeded}} votes)</span>
|
||||
|
||||
{{#unless proposal.executed}}<button {{action "confirm" proposal.id}}>+1</button>{{/unless}}
|
||||
{{#unless proposal.isExecuted}}
|
||||
<button {{action "confirm" proposal.id}}>+1</button>
|
||||
{{/unless}}
|
||||
</li>
|
||||
{{/each}}
|
||||
|
||||
+59
-84
@@ -1,51 +1,10 @@
|
||||
import Ember from 'ember';
|
||||
import Proposal from 'kredits-web/models/proposal';
|
||||
import Controller from 'ember-controller';
|
||||
import computed, { alias, filter, filterBy, sort } from 'ember-computed';
|
||||
import injectService from 'ember-service/inject';
|
||||
|
||||
const {
|
||||
computed,
|
||||
inject: {
|
||||
service
|
||||
}
|
||||
} = Ember;
|
||||
|
||||
export default Ember.Controller.extend({
|
||||
|
||||
kredits: service(),
|
||||
|
||||
contractInteractionEnabled: computed.alias('kredits.hasAccounts'),
|
||||
|
||||
proposalsOpen: function() {
|
||||
let proposals = this.get('model.proposals')
|
||||
.filterBy('executed', false)
|
||||
.map(p => {
|
||||
p.set('recipientName', this.get('model.contributors').findBy('id', p.get('recipientId')).name);
|
||||
return p;
|
||||
});
|
||||
return proposals;
|
||||
}.property('model.proposals.[]', 'model.proposals.@each.executed', 'model.contributors.[]'),
|
||||
|
||||
proposalsClosed: function() {
|
||||
let proposals = this.get('model.proposals')
|
||||
.filterBy('executed', true)
|
||||
.map(p => {
|
||||
p.set('recipientName', this.get('model.contributors').findBy('id', p.get('recipientId')).name);
|
||||
return p;
|
||||
});
|
||||
return proposals;
|
||||
}.property('model.proposals.[]', 'model.proposals.@each.executed', 'model.contributors.[]'),
|
||||
|
||||
proposalsSorting: ['id:desc'],
|
||||
proposalsClosedSorted: Ember.computed.sort('proposalsClosed', 'proposalsSorting'),
|
||||
proposalsOpenSorted: Ember.computed.sort('proposalsOpen', 'proposalsSorting'),
|
||||
|
||||
contributorsWithKredits: function() {
|
||||
return this.get('model.contributors').filter(c => {
|
||||
return c.get('balance') !== 0;
|
||||
});
|
||||
}.property('model.contributors.@each.balance'),
|
||||
|
||||
contributorsSorting: ['balance:desc'],
|
||||
contributorsSorted: Ember.computed.sort('contributorsWithKredits', 'contributorsSorting'),
|
||||
export default Controller.extend({
|
||||
kredits: injectService(),
|
||||
|
||||
init() {
|
||||
this._super(...arguments);
|
||||
@@ -58,60 +17,76 @@ export default Ember.Controller.extend({
|
||||
});
|
||||
},
|
||||
|
||||
_handleProposalCreated(proposalId, creatorAddress, recipientAddress, amount) {
|
||||
if (Ember.isPresent(this.get('model.proposals')
|
||||
.findBy('id', proposalId.toNumber()))) {
|
||||
contributors: alias('model.contributors'),
|
||||
contributorsWithKredits: filter('contributors', function(contributor) {
|
||||
return contributor.get('balance') !== 0;
|
||||
}),
|
||||
contributorsSorting: ['balance:desc'],
|
||||
contributorsSorted: sort('contributorsWithKredits', 'contributorsSorting'),
|
||||
|
||||
proposals: computed('model.proposals.[]', 'contributors.[]', function() {
|
||||
return this.get('model.proposals')
|
||||
.map((proposal) => {
|
||||
let contributor = this.get('contributors')
|
||||
.findBy('id', proposal.get('recipientId'));
|
||||
|
||||
proposal.set('contributor', contributor);
|
||||
|
||||
return proposal;
|
||||
});
|
||||
}),
|
||||
proposalsOpen: filterBy('proposals', 'isExecuted', false),
|
||||
proposalsClosed: filterBy('proposals', 'isExecuted', true),
|
||||
proposalsSorting: ['id:desc'],
|
||||
proposalsClosedSorted: sort('proposalsClosed', 'proposalsSorting'),
|
||||
proposalsOpenSorted: sort('proposalsOpen', 'proposalsSorting'),
|
||||
|
||||
_handleProposalCreated(proposalId) {
|
||||
// TODO: check if proposalId is already a string
|
||||
let proposal = this.get('proposals')
|
||||
.findBy('id', proposalId.toString());
|
||||
if (proposal) {
|
||||
Ember.Logger.debug('[index] proposal exists, not adding from event');
|
||||
return false;
|
||||
return;
|
||||
}
|
||||
|
||||
let proposal = Proposal.create({
|
||||
id: proposalId.toNumber(),
|
||||
creatorAddress: creatorAddress,
|
||||
recipientAddress: recipientAddress,
|
||||
recipientName: null,
|
||||
votesCount: 0,
|
||||
votesNeeded: 2,
|
||||
amount: amount.toNumber(),
|
||||
executed: false
|
||||
});
|
||||
|
||||
this.get('model.proposals').pushObject(proposal);
|
||||
proposal = this.get('kredits').getProposalById(proposalId);
|
||||
this.get('proposals').pushObject(proposal);
|
||||
},
|
||||
|
||||
_handleProposalExecuted(proposalId, recipientId, amount) {
|
||||
if (this.get('model.proposals')
|
||||
.findBy('id', recipientId.toNumber())
|
||||
.get('executed')) {
|
||||
// TODO: check if proposalId is already a string
|
||||
let proposal = this.get('proposals')
|
||||
.findBy('id', proposalId.toString());
|
||||
|
||||
if (proposal.get('isExecuted')) {
|
||||
Ember.Logger.debug('[index] proposal already executed, not adding from event');
|
||||
return false;
|
||||
return;
|
||||
}
|
||||
|
||||
this.get('model.proposals')
|
||||
.findBy('id', recipientId.toNumber())
|
||||
.setProperties({
|
||||
'executed': true,
|
||||
'votesCount': 2 // TODO use real count
|
||||
});
|
||||
proposal.setProperties({
|
||||
'executed': true,
|
||||
});
|
||||
|
||||
this.get('model.contributors')
|
||||
.findBy('id', recipientId)
|
||||
this.get('contributors')
|
||||
.findBy('id', recipientId.toString())
|
||||
.incrementProperty('balance', amount.toNumber());
|
||||
},
|
||||
|
||||
_handleProposalVoted(proposalId, voter, totalVotes) {
|
||||
this.get('model.proposals')
|
||||
.findBy('id', proposalId.toNumber())
|
||||
this.get('proposals')
|
||||
.findBy('id', proposalId.toString())
|
||||
.setProperties({ 'votesCount': totalVotes });
|
||||
},
|
||||
|
||||
_handleTransfer(data) {
|
||||
this.get('model.contributors')
|
||||
.findBy('address', data.args.from)
|
||||
.incrementProperty('balance', - data.args.value.toNumber());
|
||||
this.get('model.contributors')
|
||||
.findBy('address', data.args.to)
|
||||
.incrementProperty('balance', data.args.value.toNumber());
|
||||
_handleTransfer(from, to, value) {
|
||||
value = value.toNumber();
|
||||
this.get('contributors')
|
||||
.findBy('address', from)
|
||||
.decrementProperty('balance', value);
|
||||
this.get('contributors')
|
||||
.findBy('address', to)
|
||||
.incrementProperty('balance', value);
|
||||
},
|
||||
|
||||
|
||||
@@ -125,7 +100,7 @@ export default Ember.Controller.extend({
|
||||
save(contributor) {
|
||||
return this.get('kredits').addContributor(contributor)
|
||||
.then((contributor) => {
|
||||
this.get('model.contributors').pushObject(contributor);
|
||||
this.get('contributors').pushObject(contributor);
|
||||
return contributor;
|
||||
});
|
||||
}
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
import EmberObject from 'ember-object';
|
||||
import { alias } from 'ember-computed';
|
||||
|
||||
export default EmberObject.extend({
|
||||
// Contract
|
||||
@@ -11,6 +12,9 @@ export default EmberObject.extend({
|
||||
executed: null,
|
||||
ipfsHash: null,
|
||||
|
||||
// Shortcuts
|
||||
isExecuted: alias('executed'),
|
||||
|
||||
// IPFS
|
||||
kind: null,
|
||||
description: null,
|
||||
@@ -18,10 +22,6 @@ export default EmberObject.extend({
|
||||
url: null,
|
||||
ipfsData: '',
|
||||
|
||||
// Deprecated
|
||||
recipientAddress: null,
|
||||
recipientName: null,
|
||||
recipientProfile: null,
|
||||
|
||||
// TODO: add contributor relation
|
||||
// Relationships
|
||||
contributor: null,
|
||||
});
|
||||
|
||||
+20
-20
@@ -109,24 +109,22 @@ export default Service.extend({
|
||||
});
|
||||
},
|
||||
|
||||
// TODO: Should be part of the service
|
||||
buildContributor(attributes) {
|
||||
debug('[kredits] buildContributor', attributes);
|
||||
buildModel(name, attributes) {
|
||||
debug('[kredits] build', name, attributes);
|
||||
let model = getOwner(this).lookup(`model:${name}`);
|
||||
|
||||
let contributor = getOwner(this).lookup('model:contributor');
|
||||
contributor.setProperties(attributes);
|
||||
return contributor;
|
||||
},
|
||||
// coerce id to string
|
||||
if (attributes.id) {
|
||||
attributes.id = attributes.id.toString();
|
||||
}
|
||||
|
||||
buildProposal(attributes) {
|
||||
debug('[kredits] buildProposal', attributes);
|
||||
|
||||
let proposal = getOwner(this).lookup('model:proposal');
|
||||
proposal.setProperties(attributes);
|
||||
return proposal;
|
||||
model.setProperties(attributes);
|
||||
return model;
|
||||
},
|
||||
|
||||
getContributorById(id) {
|
||||
id = ethers.utils.bigNumberify(id);
|
||||
|
||||
return this.get('contributorsContract')
|
||||
.then((contract) => contract.getContributorById(id))
|
||||
.then(this.reassembleIpfsHash)
|
||||
@@ -135,7 +133,7 @@ export default Service.extend({
|
||||
let isCurrentUser = this.get('currentUserAccounts').includes(address);
|
||||
|
||||
return {
|
||||
id: id.toString(),
|
||||
id: id,
|
||||
address,
|
||||
balance: balance.toNumber(),
|
||||
ipfsHash,
|
||||
@@ -148,7 +146,7 @@ export default Service.extend({
|
||||
return this.fetchAndMergeIpfsData(data, ContributorSerializer);
|
||||
})
|
||||
.then((attributes) => {
|
||||
return this.buildContributor(attributes);
|
||||
return this.buildModel('contributor', attributes);
|
||||
});
|
||||
},
|
||||
|
||||
@@ -203,6 +201,8 @@ export default Service.extend({
|
||||
},
|
||||
|
||||
getProposalById(id) {
|
||||
id = ethers.utils.bigNumberify(id);
|
||||
|
||||
return this.get('kreditsContract')
|
||||
.then((contract) => contract.proposals(id))
|
||||
.then(this.reassembleIpfsHash)
|
||||
@@ -217,9 +217,9 @@ export default Service.extend({
|
||||
ipfsHash,
|
||||
}) => {
|
||||
return {
|
||||
id: id.toString(),
|
||||
id: id,
|
||||
creatorAddress,
|
||||
recipientId: recipientId.toNumber(),
|
||||
recipientId: recipientId.toString(),
|
||||
votesCount: votesCount.toNumber(),
|
||||
votesNeeded: votesNeeded.toNumber(),
|
||||
amount: amount.toNumber(),
|
||||
@@ -232,7 +232,7 @@ export default Service.extend({
|
||||
return this.fetchAndMergeIpfsData(data, ContributionSerializer);
|
||||
})
|
||||
.then((attributes) => {
|
||||
return this.buildProposal(attributes);
|
||||
return this.buildModel('proposal', attributes);
|
||||
});
|
||||
},
|
||||
|
||||
@@ -296,7 +296,7 @@ export default Service.extend({
|
||||
})
|
||||
.then((data) => {
|
||||
debug('[kredits] add contributor response', data);
|
||||
return this.buildContributor(attributes);
|
||||
return this.buildModel('contributor', attributes);
|
||||
});
|
||||
},
|
||||
|
||||
@@ -333,7 +333,7 @@ export default Service.extend({
|
||||
})
|
||||
.then((data) => {
|
||||
debug('[kredits] add proposal response', data);
|
||||
return this.buildProposal(attributes);
|
||||
return this.buildModel('proposal', attributes);
|
||||
});
|
||||
},
|
||||
|
||||
|
||||
+10
-8
@@ -30,11 +30,13 @@
|
||||
<h2>Open Proposals</h2>
|
||||
</header>
|
||||
<div class="content">
|
||||
{{!-- TODO: We need a better naming for kredits.hasAccounts --}}
|
||||
{{proposal-list proposals=proposalsOpenSorted
|
||||
confirmAction="confirmProposal"
|
||||
contractInteractionEnabled=contractInteractionEnabled}}
|
||||
contractInteractionEnabled=kredits.hasAccounts}}
|
||||
|
||||
{{#if contractInteractionEnabled}}
|
||||
{{!-- TODO: We need a better naming --}}
|
||||
{{#if kredits.hasAccounts}}
|
||||
<p class="actions">
|
||||
{{#link-to 'proposals.new'}}Create new proposal{{/link-to}}
|
||||
</p>
|
||||
@@ -51,7 +53,8 @@
|
||||
{{proposal-list proposals=proposalsClosedSorted
|
||||
confirmAction="confirmProposal"}}
|
||||
|
||||
{{#if contractInteractionEnabled}}
|
||||
{{!-- TODO: We need a better naming --}}
|
||||
{{#if kredits.hasAccounts}}
|
||||
<p class="actions">
|
||||
{{#link-to 'proposals.new'}}Create new proposal{{/link-to}}
|
||||
</p>
|
||||
@@ -65,11 +68,10 @@
|
||||
</header>
|
||||
|
||||
<div class="content">
|
||||
{{!--
|
||||
TODO:
|
||||
only show the form if currentUser.isCore else show:
|
||||
{{#if currentUser.isCore}}
|
||||
{{add-contributor contributors=model.contributors save=(action 'save')}}
|
||||
{{else}}
|
||||
Only core team members can add new contributors. Please ask someone to set you up.
|
||||
--}}
|
||||
{{add-contributor contributors=model.contributors save=(action 'save')}}
|
||||
{{/if}}
|
||||
</div>
|
||||
</section>
|
||||
|
||||
@@ -7,7 +7,6 @@ module('Serializers contribution');
|
||||
|
||||
test('#serialize returns a valid JSON-LD representation', function(assert) {
|
||||
let serialized = ContributionSerializer.serialize({
|
||||
recipientAddress: '0xd4a64570b12da659ee4bbd41c3509b7b1f9c51ac',
|
||||
kind: 'design',
|
||||
description: 'New logo design',
|
||||
url: 'http://opensourcedesign.org',
|
||||
|
||||
Reference in New Issue
Block a user