Store proper contributor profile in IPFS

This commit is contained in:
2017-06-05 21:58:46 +02:00
parent f8b75cca61
commit 33e81a7668
9 changed files with 154 additions and 72 deletions
+43 -31
View File
@@ -1,41 +1,58 @@
import Ember from 'ember'; import Ember from 'ember';
import Contributor from 'kredits-web/models/contributor';
export default Ember.Component.extend({ const {
Component,
isPresent,
inject: {
service
},
computed
} = Ember;
id: null, export default Component.extend({
realName: null,
address: null,
ipfsHash: null,
isCore: false,
kredits: service(),
newContributor: null,
inProgress: false, inProgress: false,
isValidId: function() {
return Ember.isPresent(this.get('id'));
}.property('id'),
isValidRealName: function() {
return Ember.isPresent(this.get('realName'));
}.property('realName'),
isValidAddress: function() { isValidAddress: function() {
return this.get('kredits.web3Instance').isAddress(this.get('address')); return this.get('kredits.web3Instance')
}.property('address'), .isAddress(this.get('newContributor.address'));
}.property('newContributor.address'),
isValid: function() { isValidName: function() {
return this.get('isValidId') && this.get('isValidRealName') && this.get('isValidAddress'); return isPresent(this.get('newContributor.name'));
}.property('isValidAddress', 'isValidId', 'isValidRealName'), }.property('newContributor.name'),
isValidURL: function() {
return isPresent(this.get('newContributor.url'));
}.property('newContributor.name'),
isValidGithubUID: function() {
return isPresent(this.get('newContributor.github_uid'));
}.property('newContributor.github_uid'),
isValidGithubUsername: function() {
return isPresent(this.get('newContributor.github_username'));
}.property('newContributor.github_username'),
isValidWikiUsername: function() {
return isPresent(this.get('newContributor.wiki_username'));
}.property('newContributor.wiki_username'),
isValid: computed.and(
'isValidAddress',
'isValidName',
'isValidGithubUID'
),
reset: function() { reset: function() {
this.setProperties({ this.setProperties({
id: null, newContributor: Contributor.create({ kind: 'person' }),
realName: null,
address: null,
ipfsHash: null,
isCore: true,
inProgress: false inProgress: false
}); });
}, },
actions: { actions: {
@@ -49,12 +66,7 @@ export default Ember.Component.extend({
if (this.get('isValid')) { if (this.get('isValid')) {
this.set('inProgress', true); this.set('inProgress', true);
this.get('kredits').addContributor( this.get('kredits').addContributor(this.get('newContributor')).then(contributor => {
this.get('address'),
this.get('realName'),
this.get('isCore'),
this.get('id')
).then(contributor => {
this.reset(); this.reset();
this.get('contributors').pushObject(contributor); this.get('contributors').pushObject(contributor);
window.scroll(0,0); window.scroll(0,0);
+44 -16
View File
@@ -1,31 +1,59 @@
<form {{action "save" on="submit"}}> <form {{action "save" on="submit"}}>
newContributor: {{newContributor.kredits}}
<p> <p>
{{input type="checkbox" name="is-core" id="is-core" checked=isCore}} {{input type="checkbox" name="is-core" id="is-core" checked=newContributor.isCore}}
<label for="is-core" class="checkbox"> <label for="is-core" class="checkbox">
Core team member (can add contributors) Core team member (can add contributors)
</label> </label>
</p> </p>
<p>
{{input name="id"
type="text"
placeholder="GitHub UID (123)"
value=id
class=(if isValidId 'valid' '')}}
</p>
<p>
{{input name="realname"
type="text"
placeholder="GitHub username"
value=realName
class=(if isValidRealName 'valid' '')}}
</p>
<p> <p>
{{input name="address" {{input name="address"
type="text" type="text"
placeholder="0xF18E631Ea191aE4ebE70046Fcb01a436554421BA4" placeholder="0xF18E631Ea191aE4ebE70046Fcb01a436554421BA4"
value=address value=newContributor.address
class=(if isValidAddress 'valid' '')}} class=(if isValidAddress 'valid' '')}}
</p> </p>
<p>
<select required onchange={{action (mut newContributor.kind) value="target.value"}}>
<option value="person" selected={{eq newContributor.kind "person"}}>Person</option>
<option value="organization" selected={{eq newContributor.kind "organization"}}>Organization</option>
</select>
</p>
<p>
{{input name="name"
type="text"
placeholder="Name"
value=newContributor.name
class=(if isValidName 'valid' '')}}
</p>
<p>
{{input name="url"
type="text"
placeholder="URL"
value=newContributor.url
class=(if isValidURL 'valid' '')}}
</p>
<p>
{{input name="github_uid"
type="text"
placeholder="GitHub UID (123)"
value=newContributor.github_uid
class=(if isValidGithubUID 'valid' '')}}
</p>
<p>
{{input name="github_username"
type="text"
placeholder="GitHub username"
value=newContributor.github_username
class=(if isValidGithubUsername 'valid' '')}}
</p>
<p>
{{input name="wiki_username"
type="text"
placeholder="Wiki Username"
value=newContributor.wiki_username
class=(if isValidWikiUsername 'valid' '')}}
</p>
<p class="actions"> <p class="actions">
{{input type="submit" value=(if inProgress 'Processing' 'Save') disabled=inProgress}} {{input type="submit" value=(if inProgress 'Processing' 'Save') disabled=inProgress}}
</p> </p>
+34 -9
View File
@@ -3,8 +3,12 @@ import Ember from 'ember';
export default Ember.Object.extend({ export default Ember.Object.extend({
address: null, address: null,
name: null,
kind: null,
url: null,
github_username: null, github_username: null,
github_uid: null, github_uid: null,
wiki_username: null,
ipfsHash: null, ipfsHash: null,
kredits: null, kredits: null,
isCore: false, isCore: false,
@@ -14,18 +18,39 @@ export default Ember.Object.extend({
return `https\:\/\/avatars2.githubusercontent.com/u/${this.get('github_uid')}?v=3&s=128`; return `https\:\/\/avatars2.githubusercontent.com/u/${this.get('github_uid')}?v=3&s=128`;
}.property('github_uid'), }.property('github_uid'),
serialize() { toJSON() {
return JSON.stringify({ let contributor = {
profiles: { "@context": "https://schema.kosmos.org",
'github.com': { "@type": "Contributor",
uid: this.get('github_uid'), "kind": this.get('kind'),
username: this.get('github_username'), "name": this.get('name'),
"accounts": []
};
if (Ember.isPresent(this.get('url'))) {
contributor["url"] = this.get('url');
} }
// 'wiki.kosmos.org': { if (Ember.isPresent(this.get('github_uid'))) {
// username: this.get('wiki_username') contributor.accounts.push({
// } "site": "github.com",
"uid": this.get('github_uid'),
"username": this.get('github_username'),
"url": `https://github.com/${this.get('github_username')}`
});
} }
if (Ember.isPresent(this.get('wiki_username'))) {
contributor.accounts.push({
"site": "wiki.kosmos.org",
"username": this.get('wiki_username'),
"url": `https://wiki.kosmos.org/User:${this.get('wiki_username')}`
}); });
} }
return contributor;
},
serialize() {
return JSON.stringify(this.toJSON());
}
}); });
+3 -1
View File
@@ -1,4 +1,5 @@
import Ember from 'ember'; import Ember from 'ember';
import Contributor from 'kredits-web/models/contributor';
export default Ember.Route.extend({ export default Ember.Route.extend({
@@ -10,7 +11,8 @@ export default Ember.Route.extend({
return Ember.RSVP.hash({ return Ember.RSVP.hash({
contributors: kredits.getContributors(), contributors: kredits.getContributors(),
totalSupply: kredits.getValueFromContract('tokenContract', 'totalSupply'), totalSupply: kredits.getValueFromContract('tokenContract', 'totalSupply'),
proposals: kredits.getProposals() proposals: kredits.getProposals(),
newContributor: Contributor.create({ kind: 'person' })
}); });
} }
+5 -10
View File
@@ -175,23 +175,18 @@ export default Service.extend({
}); });
}, },
addContributor(address, name, isCore, id) { addContributor(contributor) {
Ember.Logger.debug('[kredits] add contributor', name, address); Ember.Logger.debug('[kredits] add contributor', contributor);
let contributor = Contributor.create({ contributor.setProperties({
address: address,
github_username: name,
github_uid: id,
kredits: 0, kredits: 0,
isCore: isCore, isCurrentUser: this.get('currentUserAccounts').includes(contributor.address)
isCurrentUser: this.get('currentUserAccounts').includes(address)
}); });
return new Ember.RSVP.Promise((resolve, reject) => { return new Ember.RSVP.Promise((resolve, reject) => {
this.get('ipfs').storeFile(contributor.serialize()).then(ipfsHash => { this.get('ipfs').storeFile(contributor.serialize()).then(ipfsHash => {
contributor.set('ipfsHash', ipfsHash); contributor.set('ipfsHash', ipfsHash);
Ember.Logger.debug('ADD', address, name, ipfsHash, isCore, id); this.get('kreditsContract').addContributor(contributor.address, contributor.name, contributor.ipfsHash, contributor.isCore, contributor.github_uid, (err, data) => {
this.get('kreditsContract').addContributor(address, name, ipfsHash, isCore, id, (err, data) => {
if (err) { reject(err); return; } if (err) { reject(err); return; }
Ember.Logger.debug('[kredits] add contributor response', data); Ember.Logger.debug('[kredits] add contributor response', data);
resolve(contributor); resolve(contributor);
+2 -2
View File
@@ -54,8 +54,8 @@
</header> </header>
<div class="content"> <div class="content">
{{add-contributor kredits=kredits {{add-contributor contributors=model.contributors
contributors=model.contributors newContributor=model.newContributor
contractInteractionEnabled=contractInteractionEnabled}} contractInteractionEnabled=contractInteractionEnabled}}
</div> </div>
</section> </section>
+1
View File
@@ -23,6 +23,7 @@ module.exports = function(environment) {
}, },
browserify: { browserify: {
tests: true,
transform: [ transform: [
["babelify", { ["babelify", {
presets: ["es2015"], presets: ["es2015"],
+2
View File
@@ -55,8 +55,10 @@
"ember-resolver": "^2.0.3", "ember-resolver": "^2.0.3",
"ember-truth-helpers": "1.3.0", "ember-truth-helpers": "1.3.0",
"ipfs-api": "^12.1.7", "ipfs-api": "^12.1.7",
"kosmos-schemas": "~1.1.0",
"kredits-contracts": "^2.4.0", "kredits-contracts": "^2.4.0",
"loader.js": "^4.0.10", "loader.js": "^4.0.10",
"tv4": "^1.3.0",
"web3": "^0.18.2" "web3": "^0.18.2"
}, },
"engines": { "engines": {
+18 -1
View File
@@ -1,9 +1,26 @@
import { moduleFor, test } from 'ember-qunit'; import { moduleFor, test } from 'ember-qunit';
import schemas from 'npm:kosmos-schemas';
import tv4 from 'npm:tv4';
moduleFor('model:contributor', 'Unit | Model | contributor'); moduleFor('model:contributor', 'Unit | Model | contributor');
test('avatarURL returns correct URL', function(assert) { test('#avatarURL() returns correct URL', function(assert) {
let model = this.subject(); let model = this.subject();
model.set('github_uid', '318'); model.set('github_uid', '318');
assert.equal(model.get('avatarURL'), 'https://avatars2.githubusercontent.com/u/318?v=3&s=128'); assert.equal(model.get('avatarURL'), 'https://avatars2.githubusercontent.com/u/318?v=3&s=128');
}); });
test('#toJSON() returns a valid JSON-LD representation of the model', function(assert) {
let model = this.subject();
model.setProperties({
name: 'Satoshi Nakamoto',
kind: 'person',
github_uid: 123,
github_username: 'therealsatoshi',
wiki_username: 'Satoshi',
});
assert.ok(tv4.validate(model.toJSON(), schemas['contributor']));
});