From 7b91e64af4b709568be394f8508adba3f49fddd9 Mon Sep 17 00:00:00 2001
From: Sebastian Kippe
+ +
{{input type="text" placeholder="100" @@ -15,15 +24,15 @@
{{input type="text" - placeholder="URL" - value=proposal.url - class=(if isValidUrl 'valid' '')}} + placeholder="Description" + value=proposal.description + class=(if isValidDescription 'valid' '')}}
{{input type="text" - placeholder="IPFS Hash" - value=proposal.ipfsHash - class=(if isValidIpfsHash 'valid' '')}} + placeholder="URL (optional)" + value=proposal.url + class=(if isValidUrl 'valid' '')}}
{{input type="submit" value=(if inProgress 'Processing' 'Save') disabled=inProgress}} diff --git a/app/models/proposal.js b/app/models/proposal.js index 1ac4b1c..ea59765 100644 --- a/app/models/proposal.js +++ b/app/models/proposal.js @@ -1,16 +1,69 @@ import Ember from 'ember'; +const { + isPresent, + isEmpty, +} = Ember; + export default Ember.Object.extend({ id: null, creatorAddress: null, recipientAddress: null, recipientName: null, + recipientProfile: null, votesCount: null, votesNeeded: null, amount: null, executed: null, + contribution: null, + kind: null, + description: null, url: null, - ipfsHash: null + details: null, + ipfsHash: null, + + /** + * Creates a JSON-LD object of the contribution, according to + * https://github.com/67P/kosmos-schemas/blob/master/schemas/contribution.json + * + * @method + * @public + */ + contributionToJSON() { + if (isEmpty(this.get('recipientProfile'))) { + throw new Error('IPFS hash for recipient profile missing from proposal object'); + } + if (isEmpty(this.get('kind')) || isEmpty(this.get('description'))) { + throw new Error('Missing one or more required properties: kind, description'); + } + + let contribution = { + "@context": "https://schema.kosmos.org", + "@type": "Contribution", + "contributor": { + "ipfs": this.get('recipientProfile') + }, + "kind": this.get('kind'), + "description": this.get('description'), + "details": {} + }; + + if (isPresent(this.get('url'))) { + contribution["url"] = this.get('url'); + } + + return contribution; + }, + + /** + * Returns the JSON-LD representation of the contribution as a string + * + * @method + * @public + */ + serializeContribution() { + return JSON.stringify(this.contributionToJSON()); + } }); diff --git a/app/routes/proposals/new.js b/app/routes/proposals/new.js index 26b77a5..f5870d9 100644 --- a/app/routes/proposals/new.js +++ b/app/routes/proposals/new.js @@ -18,6 +18,7 @@ export default Route.extend({ recipientAddress: params.recipient, amount: params.amount, url: params.url, + kind: params.kind || 'dev', ipfsHash: params.ipfsHash }); diff --git a/app/services/kredits.js b/app/services/kredits.js index b6014ba..e133093 100644 --- a/app/services/kredits.js +++ b/app/services/kredits.js @@ -102,6 +102,8 @@ export default Service.extend({ this.getValueFromContract('kreditsContract', 'contributorAddresses', i).then(address => { this.getValueFromContract('kreditsContract', 'contributors', address).then(person => { this.getValueFromContract('tokenContract', 'balanceOf', address).then(balance => { + Ember.Logger.debug('[kredits] person', address, person); + let contributor = Contributor.create({ address: address, ipfsHash: person[2], @@ -203,14 +205,15 @@ export default Service.extend({ const { recipientAddress, amount, - url, - ipfsHash - } = proposal.getProperties('recipientAddress', 'amount', 'url', 'ipfsHash'); + url + } = proposal.getProperties('recipientAddress', 'amount', 'url'); - this.get('kreditsContract').addProposal(recipientAddress, amount, url, ipfsHash, (err, data) => { - if (err) { reject(err); return; } - Ember.Logger.debug('[kredits] add proposal response', data); - resolve(); + this.get('ipfs').storeFile(proposal.serializeContribution()).then(ipfsHash => { + this.get('kreditsContract').addProposal(recipientAddress, amount, url, ipfsHash, (err, data) => { + if (err) { reject(err); return; } + Ember.Logger.debug('[kredits] add proposal response', data); + resolve(); + }); }); }); }, diff --git a/tests/unit/models/proposal-test.js b/tests/unit/models/proposal-test.js index d91008f..023708b 100644 --- a/tests/unit/models/proposal-test.js +++ b/tests/unit/models/proposal-test.js @@ -1,9 +1,49 @@ import { moduleFor, test } from 'ember-qunit'; +import schemas from 'npm:kosmos-schemas'; +import tv4 from 'npm:tv4'; moduleFor('model:proposal', 'Unit | Model | proposal'); -test('it exists', function(assert) { +test('#toJSON() requires a recipient profile IPFS hash to be set', function(assert) { let model = this.subject(); - // let store = this.store(); - assert.ok(!!model); + + model.setProperties({ + recipientAddress: '0xd4a64570b12da659ee4bbd41c3509b7b1f9c51ac' + }); + + try { + let json = model.contributionToJSON(); + assert.notOk(json, true); + } catch(e) { + assert.ok(e.message.match(/IPFS hash .* missing/i)); + } +}); + +test('#toJSON() requires kind and description to be set', function(assert) { + let model = this.subject(); + + model.setProperties({ + recipientProfile: 'QmT2A7rY4e7uoKktkcFHQNN7BD1oXdZTgd8wNkr1u9nNVE' + }); + + try { + let json = model.contributionToJSON(); + assert.notOk(json, true); + } catch(e) { + assert.ok(e.message.match(/Missing .* kind.*description/i)); + } +}); + +test('#toJSON() returns a valid JSON-LD representation of the model', function(assert) { + let model = this.subject(); + + model.setProperties({ + recipientAddress: '0xd4a64570b12da659ee4bbd41c3509b7b1f9c51ac', + kind: 'design', + description: 'New logo design', + url: 'http://opensourcedesign.org', + recipientProfile: 'QmT2A7rY4e7uoKktkcFHQNN7BD1oXdZTgd8wNkr1u9nNVE' + }); + + assert.ok(tv4.validate(model.contributionToJSON(), schemas['contribution'])); });