Update contributor profiles #123
@@ -1,6 +1,7 @@
|
||||
import Component from '@ember/component';
|
||||
import { and, notEmpty } from '@ember/object/computed';
|
||||
import { inject as service } from '@ember/service';
|
||||
import { isPresent } from '@ember/utils';
|
||||
|
||||
export default Component.extend({
|
||||
|
||||
@@ -26,6 +27,12 @@ export default Component.extend({
|
||||
|
||||
init () {
|
||||
this._super(...arguments);
|
||||
this.setDefaultAttributes();
|
||||
this.reset();
|
||||
},
|
||||
|
||||
setDefaultAttributes () {
|
||||
if (isPresent(this.attributes)) { return; }
|
||||
|
||||
this.set('attributes', {
|
||||
account: null,
|
||||
@@ -37,8 +44,6 @@ export default Component.extend({
|
||||
gitea_username: null,
|
||||
wiki_username: null
|
||||
});
|
||||
|
||||
this.reset();
|
||||
},
|
||||
|
||||
reset: function() {
|
||||
|
||||
@@ -1,62 +1,50 @@
|
||||
<form {{action "submit" on="submit"}}>
|
||||
<p>
|
||||
{{input name="account"
|
||||
type="text"
|
||||
<label for="c-account">Ethereum account</label>
|
||||
{{input name="account" id="c-account"
|
||||
type="text" value=account
|
||||
placeholder="0xF18E631Ea191aE4ebE70046Fcb01a436554421BA4"
|
||||
value=account
|
||||
class=(if isValidAccount "valid" "")}}
|
||||
</p>
|
||||
<p>
|
||||
<select required onchange={{action (mut kind) value="target.value"}}>
|
||||
<label for="c-kind">Kind</label>
|
||||
<select required onchange={{action (mut kind) value="target.value"}} id="c-kind">
|
||||
<option value="person" selected={{eq kind "person"}}>Person</option>
|
||||
<option value="organization" selected={{eq kind "organization"}}>Organization</option>
|
||||
</select>
|
||||
</p>
|
||||
<p>
|
||||
{{input name="name"
|
||||
type="text"
|
||||
placeholder="Name"
|
||||
value=name
|
||||
class=(if isValidName "valid" "")}}
|
||||
<label for="c-name">Name</label>
|
||||
{{input name="name" type="text" value=name placeholder="Zero Cool"
|
||||
class=(if isValidName "valid" "") id="c-name"}}
|
||||
</p>
|
||||
<p>
|
||||
{{input name="url"
|
||||
type="text"
|
||||
placeholder="URL"
|
||||
value=url
|
||||
class=(if isValidURL "valid" "")}}
|
||||
<label for="c-url">URL</label>
|
||||
{{input name="url" type="text" value=url placeholder="http://zerocool.bit"
|
||||
class=(if isValidURL "valid" "") id="c-url"}}
|
||||
</p>
|
||||
<p>
|
||||
{{input name="github_uid"
|
||||
type="text"
|
||||
placeholder="GitHub UID (123)"
|
||||
value=github_uid
|
||||
class=(if isValidGithubUID "valid" "")}}
|
||||
<label for="c-github-uid">GitHub UID</label>
|
||||
{{input name="github_uid" type="text" value=github_uid placeholder="2342"
|
||||
class=(if isValidGithubUID "valid" "") id="c-github-uid"}}
|
||||
</p>
|
||||
<p>
|
||||
{{input name="github_username"
|
||||
type="text"
|
||||
placeholder="GitHub username"
|
||||
value=github_username
|
||||
class=(if isValidGithubUsername "valid" "")}}
|
||||
<label for="c-github-username">GitHub username</label>
|
||||
{{input name="github_username" type="text" value=github_username placeholder="zerocool"
|
||||
class=(if isValidGithubUsername "valid" "") id="c-github-username"}}
|
||||
</p>
|
||||
<p>
|
||||
{{input name="gitea_username"
|
||||
type="text"
|
||||
placeholder="Gitea username"
|
||||
value=gitea_username
|
||||
class=(if isValidGiteaUsername "valid" "")}}
|
||||
<label for="c-gitea-username">Gitea username</label>
|
||||
{{input name="gitea_username" type="text" value=gitea_username placeholder="zerocool"
|
||||
class=(if isValidGiteaUsername "valid" "") id="c-gitea-username"}}
|
||||
</p>
|
||||
<p>
|
||||
{{input name="wiki_username"
|
||||
type="text"
|
||||
placeholder="Wiki Username"
|
||||
value=wiki_username
|
||||
class=(if isValidWikiUsername "valid" "")}}
|
||||
<label for="c-wiki-username">Wiki username</label>
|
||||
{{input name="wiki_username" type="text" value=wiki_username placeholder="ZeroCool"
|
||||
class=(if isValidWikiUsername "valid" "") id="c-wiki-username"}}
|
||||
</p>
|
||||
<p class="actions">
|
||||
{{input type="submit"
|
||||
disabled=inProgress
|
||||
{{input type="submit" disabled=inProgress
|
||||
value=(if inProgress "Processing" "Save")}}
|
||||
</p>
|
||||
</form>
|
||||
|
||||
@@ -26,6 +26,9 @@
|
||||
<a href="https://ipfs.io/ipfs/{{c.contributor.ipfsHash}}" target="_blank" rel="noopener">Inspect IPFS profile</a>
|
||||
</li>
|
||||
{{/if}}
|
||||
<li>
|
||||
{{link-to "Edit profile" "contributors.edit" c.contributor.id}}
|
||||
</li>
|
||||
</ul>
|
||||
{{#if c.showMetadata}}
|
||||
<pre>{{c.contributor.ipfsData}}</pre>
|
||||
|
||||
@@ -0,0 +1,18 @@
|
||||
import Controller from '@ember/controller';
|
||||
import { inject as service } from '@ember/service';
|
||||
|
||||
export default Controller.extend({
|
||||
|
||||
kredits: service(),
|
||||
|
||||
actions: {
|
||||
|
||||
save (attributes) {
|
||||
return this.kredits
|
||||
.updateContributor(this.model.id, attributes)
|
||||
.then(() => this.transitionToRoute('index'))
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
});
|
||||
@@ -1,21 +1,16 @@
|
||||
import Controller from '@ember/controller';
|
||||
import { alias } from '@ember/object/computed';
|
||||
import { inject as service } from '@ember/service';
|
||||
|
||||
export default Controller.extend({
|
||||
|
||||
kredits: service(),
|
||||
|
||||
contributors: alias('kredits.contributors'),
|
||||
|
||||
actions: {
|
||||
|
||||
save (contributor) {
|
||||
return this.kredits.addContributor(contributor)
|
||||
.then(contributor => {
|
||||
this.transitionToRoute('index');
|
||||
return contributor;
|
||||
});
|
||||
return this.kredits
|
||||
.addContributor(contributor)
|
||||
.then(() => this.transitionToRoute('index'))
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -15,6 +15,7 @@ Router.map(function() {
|
||||
});
|
||||
this.route('contributors', function() {
|
||||
this.route('new');
|
||||
this.route('edit', { path: ':id/edit' });
|
||||
});
|
||||
});
|
||||
|
||||
|
||||
@@ -0,0 +1,29 @@
|
||||
import { inject as service } from '@ember/service';
|
||||
import Route from '@ember/routing/route';
|
||||
import { alias } from '@ember/object/computed';
|
||||
|
||||
export default Route.extend({
|
||||
|
||||
kredits: service(),
|
||||
contributors: alias('kredits.contributors'),
|
||||
|
||||
model(params) {
|
||||
return this.kredits.contributors.findBy('id', params.id);
|
||||
},
|
||||
|
||||
setupController (controller, model) {
|
||||
this._super(controller, model);
|
||||
|
||||
controller.set('attributes', {
|
||||
account: model.account,
|
||||
name: model.name,
|
||||
kind: model.kind,
|
||||
url: model.url,
|
||||
github_username: model.github_username,
|
||||
github_uid: model.github_uid,
|
||||
gitea_username: model.gitea_username,
|
||||
wiki_username: model.wiki_username
|
||||
|
|
||||
});
|
||||
}
|
||||
|
||||
});
|
||||
+53
-21
@@ -47,7 +47,7 @@ export default Service.extend({
|
||||
});
|
||||
}),
|
||||
|
||||
kreditsByContributor: computed('contributionsUnconfirmed.@each.vetoed', 'contributors', function() {
|
||||
kreditsByContributor: computed('contributionsUnconfirmed.@each.vetoed', 'contributors.[]', function() {
|
||||
const contributionsUnconfirmed = this.contributionsUnconfirmed.filterBy('vetoed', false);
|
||||
const contributionsGrouped = groupBy(contributionsUnconfirmed, 'contributorId');
|
||||
const contributorsWithUnconfirmed = contributionsGrouped.map(c => c.value.toString());
|
||||
@@ -87,7 +87,7 @@ export default Service.extend({
|
||||
// This is called in the application route's beforeModel(). So it is
|
||||
// initialized before everything else, and we can rely on the ethProvider and
|
||||
// the potential currentUserAccounts to be available
|
||||
getEthProvider: function() {
|
||||
getEthProvider () {
|
||||
let ethProvider;
|
||||
|
||||
return new RSVP.Promise(async (resolve) => {
|
||||
@@ -136,7 +136,7 @@ export default Service.extend({
|
||||
});
|
||||
},
|
||||
|
||||
setup() {
|
||||
setup () {
|
||||
return this.getEthProvider().then((providerAndSigner) => {
|
||||
let kredits = new Kredits(providerAndSigner.ethProvider, providerAndSigner.ethSigner, {
|
||||
addresses: { Kernel: config.kreditsKernelAddress },
|
||||
@@ -172,14 +172,14 @@ export default Service.extend({
|
||||
}),
|
||||
|
||||
|
||||
loadInitialData() {
|
||||
loadInitialData () {
|
||||
return this.getContributors()
|
||||
.then(contributors => this.contributors.pushObjects(contributors))
|
||||
.then(() => this.getContributions())
|
||||
.then(contributions => this.contributions.pushObjects(contributions))
|
||||
},
|
||||
|
||||
addContributor(attributes) {
|
||||
addContributor (attributes) {
|
||||
if (attributes.github_uid) {
|
||||
const uidInt = parseInt(attributes.github_uid);
|
||||
attributes.github_uid = uidInt;
|
||||
@@ -190,13 +190,24 @@ export default Service.extend({
|
||||
return this.kredits.Contributor.add(attributes, { gasLimit: 350000 })
|
||||
.then(data => {
|
||||
console.debug('[kredits] add contributor response', data);
|
||||
const contributor = Contributor.create(attributes);
|
||||
this.contributors.pushObject(contributor);
|
||||
return contributor;
|
||||
});
|
||||
},
|
||||
|
||||
getContributors() {
|
||||
updateContributor (id, attributes) {
|
||||
if (attributes.github_uid) {
|
||||
const uidInt = parseInt(attributes.github_uid);
|
||||
attributes.github_uid = uidInt;
|
||||
}
|
||||
|
||||
console.debug('[kredits] update contributor', attributes);
|
||||
|
||||
return this.kredits.Contributor.updateProfile(id, attributes, { gasLimit: 350000 })
|
||||
.then(data => {
|
||||
console.debug('[kredits] updateProfile response', data);
|
||||
});
|
||||
},
|
||||
|
||||
getContributors () {
|
||||
return this.kredits.Contributor.all()
|
||||
.then((contributors) => {
|
||||
return contributors.map((contributor) => {
|
||||
@@ -205,7 +216,7 @@ export default Service.extend({
|
||||
});
|
||||
},
|
||||
|
||||
addContribution(attributes) {
|
||||
addContribution (attributes) {
|
||||
console.debug('[kredits] add contribution', attributes);
|
||||
|
||||
return this.kredits.Contribution.addContribution(attributes, { gasLimit: 300000 })
|
||||
@@ -220,7 +231,7 @@ export default Service.extend({
|
||||
});
|
||||
},
|
||||
|
||||
addProposal(attributes) {
|
||||
addProposal (attributes) {
|
||||
console.debug('[kredits] add proposal', attributes);
|
||||
|
||||
return this.kredits.Proposal.addProposal(attributes)
|
||||
@@ -231,7 +242,7 @@ export default Service.extend({
|
||||
});
|
||||
},
|
||||
|
||||
getProposals() {
|
||||
getProposals () {
|
||||
return this.kredits.Proposal.all()
|
||||
.then((proposals) => {
|
||||
return proposals.map((proposal) => {
|
||||
@@ -241,7 +252,7 @@ export default Service.extend({
|
||||
});
|
||||
},
|
||||
|
||||
getContributions() {
|
||||
getContributions () {
|
||||
return this.kredits.Contribution.all({page: {size: 200}})
|
||||
.then(contributions => {
|
||||
return contributions.map(contribution => {
|
||||
@@ -251,7 +262,7 @@ export default Service.extend({
|
||||
});
|
||||
},
|
||||
|
||||
vote(proposalId) {
|
||||
vote (proposalId) {
|
||||
console.debug('[kredits] vote for', proposalId);
|
||||
|
||||
return this.kredits.Proposal.functions.vote(proposalId)
|
||||
@@ -261,7 +272,7 @@ export default Service.extend({
|
||||
});
|
||||
},
|
||||
|
||||
veto(contributionId) {
|
||||
veto (contributionId) {
|
||||
console.debug('[kredits] veto against', contributionId);
|
||||
|
||||
return this.kredits.Contribution.functions.veto(contributionId, { gasLimit: 300000 })
|
||||
@@ -292,7 +303,12 @@ export default Service.extend({
|
||||
},
|
||||
|
||||
// Contract events
|
||||
addContractEventHandlers() {
|
||||
addContractEventHandlers () {
|
||||
this.kredits.Contributor
|
||||
.on('ContributorProfileUpdated', this.handleContributorChange.bind(this))
|
||||
.on('ContributorAccountUpdated', this.handleContributorChange.bind(this))
|
||||
.on('ContributorAdded', this.handleContributorChange.bind(this))
|
||||
|
||||
this.kredits.Contribution
|
||||
.on('ContributionVetoed', this.handleContributionVetoed.bind(this))
|
||||
|
||||
@@ -305,7 +321,23 @@ export default Service.extend({
|
||||
.on('Transfer', this.handleTransfer.bind(this));
|
||||
},
|
||||
|
||||
handleContributionVetoed(contributionId) {
|
||||
async handleContributorChange (contributorId, ...args) {
|
||||
console.debug('[kredits] Contributor add/update event received for ID', contributorId);
|
||||
console.debug('[kredits] Event data:', args);
|
||||
const contributorData = await this.kredits.Contributor.getById(contributorId);
|
||||
const newContributor = Contributor.create(contributorData);
|
||||
|
||||
const oldContributor = this.contributors.findBy('id', contributorId.toString());
|
||||
if (oldContributor) {
|
||||
console.debug('[kredits] old contributor', oldContributor);
|
||||
this.contributors.removeObject(oldContributor);
|
||||
}
|
||||
|
||||
console.debug('[kredits] new contributor', newContributor);
|
||||
this.contributors.pushObject(newContributor);
|
||||
},
|
||||
|
||||
handleContributionVetoed (contributionId) {
|
||||
console.debug('[kredits] ContributionVetoed event received for ', contributionId);
|
||||
const contribution = this.contributions.findBy('id', contributionId);
|
||||
console.debug('[kredits] contribution', contribution);
|
||||
@@ -315,7 +347,7 @@ export default Service.extend({
|
||||
}
|
||||
},
|
||||
|
||||
handleProposalCreated(proposalId) {
|
||||
handleProposalCreated (proposalId) {
|
||||
let proposal = this.findProposalById(proposalId);
|
||||
|
||||
if (proposal) {
|
||||
@@ -331,7 +363,7 @@ export default Service.extend({
|
||||
},
|
||||
|
||||
// TODO: We may want to reload that proposal to show the voter as voted
|
||||
handleProposalVoted(proposalId, voterId, totalVotes) {
|
||||
handleProposalVoted (proposalId, voterId, totalVotes) {
|
||||
let proposal = this.findProposalById(proposalId);
|
||||
|
||||
if (proposal) {
|
||||
@@ -339,7 +371,7 @@ export default Service.extend({
|
||||
}
|
||||
},
|
||||
|
||||
handleProposalExecuted(proposalId, contributorId, amount) {
|
||||
handleProposalExecuted (proposalId, contributorId, amount) {
|
||||
let proposal = this.findProposalById(proposalId);
|
||||
|
||||
if (proposal.get('isExecuted')) {
|
||||
@@ -354,7 +386,7 @@ export default Service.extend({
|
||||
.incrementProperty('balance', amount);
|
||||
},
|
||||
|
||||
handleTransfer(from, to, value) {
|
||||
handleTransfer (from, to, value) {
|
||||
value = value.toNumber();
|
||||
|
||||
this.contributors
|
||||
|
||||
@@ -17,6 +17,12 @@ section#add-proposal {
|
||||
}
|
||||
}
|
||||
|
||||
label {
|
||||
display: block;
|
||||
margin-bottom: 0.5rem;
|
||||
opacity: 0.7;
|
||||
}
|
||||
|
||||
input[type=text], select {
|
||||
width: 100%;
|
||||
padding: 1rem;
|
||||
@@ -25,9 +31,14 @@ section#add-proposal {
|
||||
background-color: rgba(22, 21, 40, 0.3);
|
||||
color: #fff;
|
||||
font-size: 1.2rem;
|
||||
transition: border-color 0.1s linear;
|
||||
|
||||
&:focus, &.valid {
|
||||
background-color: rgba(22, 21, 40, 0.6);
|
||||
}
|
||||
&:focus {
|
||||
border-color: $blue;
|
||||
}
|
||||
&::placeholder {
|
||||
color: rgba(238, 238, 238, 0.5);
|
||||
}
|
||||
|
||||
@@ -0,0 +1,13 @@
|
||||
<main class="center-column">
|
||||
|
||||
<section id="add-contributor">
|
||||
<header>
|
||||
<h2>Update contributor profile</h2>
|
||||
</header>
|
||||
|
||||
<div class="content">
|
||||
{{add-contributor attributes=attributes save=(action "save")}}
|
||||
</div>
|
||||
</section>
|
||||
|
||||
</main>
|
||||
@@ -6,7 +6,7 @@
|
||||
</header>
|
||||
|
||||
<div class="content">
|
||||
{{add-contributor contributors=contributors save=(action "save")}}
|
||||
{{add-contributor save=(action "save")}}
|
||||
</div>
|
||||
</section>
|
||||
|
||||
|
||||
Reference in New Issue
Block a user
do you think we can use the
accountsarray here already? with adding more services we at some point would want to directly add entries to the accounts array.That should be a separate PR, as it requires quite some changes in the code.