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