diff --git a/app/components/add-contribution/component.js b/app/components/add-contribution/component.js index 0c25c85..b9533f8 100644 --- a/app/components/add-contribution/component.js +++ b/app/components/add-contribution/component.js @@ -1,6 +1,7 @@ import Component from '@ember/component'; import { computed } from '@ember/object'; import { and, notEmpty } from '@ember/object/computed'; +import { isEmpty } from '@ember/utils'; import moment from 'moment'; export default Component.extend({ @@ -25,14 +26,17 @@ export default Component.extend({ this.set('defaultDate', moment().startOf('hour').toDate()); // Default attributes used by reset - this.set('attributes', { - contributorId: null, - kind: null, - date: this.defaultDate, - amount: null, - description: null, - url: null, - }); + if (isEmpty(this.attributes)) { + this.set('attributes', { + contributorId: null, + kind: null, + date: this.defaultDate, + amount: null, + description: null, + url: null, + details: null + }); + } this.reset(); }, @@ -67,7 +71,6 @@ export default Component.extend({ window.alert('Something went wrong. Check the browser console for details.'); }) .finally(() => this.set('inProgress', false)); - } } diff --git a/app/components/add-contribution/template.hbs b/app/components/add-contribution/template.hbs index 2d2751f..2174967 100644 --- a/app/components/add-contribution/template.hbs +++ b/app/components/add-contribution/template.hbs @@ -63,6 +63,17 @@

+ {{#if details}} + + {{/if}} +

{{input type="submit" disabled=inProgress diff --git a/app/components/icon-warning/component.js b/app/components/icon-warning/component.js new file mode 100644 index 0000000..6858137 --- /dev/null +++ b/app/components/icon-warning/component.js @@ -0,0 +1,5 @@ +import Component from '@ember/component'; + +export default Component.extend({ + tagName: "" +}); diff --git a/app/components/icon-warning/template.hbs b/app/components/icon-warning/template.hbs new file mode 100644 index 0000000..d4d53d6 --- /dev/null +++ b/app/components/icon-warning/template.hbs @@ -0,0 +1,15 @@ + + + + + + + + + + + + + + + diff --git a/app/controllers/contributions/resubmit.js b/app/controllers/contributions/resubmit.js new file mode 100644 index 0000000..ed37ace --- /dev/null +++ b/app/controllers/contributions/resubmit.js @@ -0,0 +1,7 @@ +import ContributionsNewController from 'kredits-web/controllers/contributions/new'; + +export default ContributionsNewController.extend({ + + attributes: null, + +}); diff --git a/app/controllers/dashboard/contributions/show.js b/app/controllers/dashboard/contributions/show.js new file mode 100644 index 0000000..ef7f280 --- /dev/null +++ b/app/controllers/dashboard/contributions/show.js @@ -0,0 +1,12 @@ + +import Controller from '@ember/controller'; +import { computed } from '@ember/object'; +import config from 'kredits-web/config/environment'; + +export default Controller.extend({ + + ipfsGatewayUrl: computed(function() { + return config.ipfs.gatewayUrl; + }).volatile() + +}); diff --git a/app/models/contribution.js b/app/models/contribution.js index a19c341..c6985fa 100644 --- a/app/models/contribution.js +++ b/app/models/contribution.js @@ -1,5 +1,7 @@ import EmberObject, { computed } from '@ember/object'; +import { isEmpty } from '@ember/utils'; import bignumber from 'kredits-web/utils/cps/bignumber'; +import moment from 'moment'; export default EmberObject.extend({ @@ -24,11 +26,15 @@ export default EmberObject.extend({ init () { this._super(...arguments); - this.set('details', {}); + if (isEmpty(this.details)) this.set('details', {}); }, iso8601Date: computed('date', 'time', function() { return this.time ? `${this.date}T${this.time}` : this.date; + }), + + jsDate: computed('iso8601Date', function() { + return moment(this.iso8601Date).toDate(); }) }); diff --git a/app/router.js b/app/router.js index e2c6349..014dbc8 100644 --- a/app/router.js +++ b/app/router.js @@ -21,6 +21,7 @@ Router.map(function() { }); this.route('contributions', function() { this.route('new'); + this.route('resubmit', { path: ':id/resubmit' }); }); this.route('contributors', function() { this.route('new'); diff --git a/app/routes/contributions/resubmit.js b/app/routes/contributions/resubmit.js new file mode 100644 index 0000000..2de1d5a --- /dev/null +++ b/app/routes/contributions/resubmit.js @@ -0,0 +1,25 @@ +import Route from '@ember/routing/route'; +import { inject as service } from '@ember/service'; + +export default Route.extend({ + + kredits: service(), + + model(params) { + const contribution = this.kredits.contributions.findBy('id', parseInt(params.id)); + contribution.contributorId = contribution.contributorId.toString(); + + return contribution; + }, + + setupController (controller, model) { + this._super(controller, model); + + controller.set('attributes', model.getProperties([ + 'kind', 'amount', 'description', 'url', 'details' + ])); + controller.set('attributes.contributorId', model.contributorId.toString()); + controller.set('attributes.date', model.jsDate); + } + +}); diff --git a/app/services/kredits.js b/app/services/kredits.js index e651336..3fc96d3 100644 --- a/app/services/kredits.js +++ b/app/services/kredits.js @@ -225,33 +225,36 @@ export default Service.extend({ console.debug('[kredits] add contribution response', data); attributes.contributor = this.contributors.findBy('id', attributes.contributorId); const contribution = Contribution.create(attributes); - // TODO receive from wrapper contribution.set('confirmedAtBlock', data.blockNumber + 40320); this.contributions.pushObject(contribution); return contribution; }); }, - addProposal (attributes) { - console.debug('[kredits] add proposal', attributes); + // + // TODO Implement proposals with voting + // - return this.kredits.Proposal.addProposal(attributes) - .then((data) => { - console.debug('[kredits] add proposal response', data); - attributes.contributor = this.contributors.findBy('id', attributes.contributorId); - return Proposal.create(attributes); - }); - }, + // addProposal (attributes) { + // console.debug('[kredits] add proposal', attributes); + // + // return this.kredits.Proposal.addProposal(attributes) + // .then((data) => { + // console.debug('[kredits] add proposal response', data); + // attributes.contributor = this.contributors.findBy('id', attributes.contributorId); + // return Proposal.create(attributes); + // }); + // }, - getProposals () { - return this.kredits.Proposal.all() - .then((proposals) => { - return proposals.map((proposal) => { - proposal.contributor = this.contributors.findBy('id', proposal.contributorId.toString()); - return Proposal.create(proposal); - }); - }); - }, + // getProposals () { + // return this.kredits.Proposal.all() + // .then(proposals => { + // return proposals.map(proposal => { + // proposal.contributor = this.contributors.findBy('id', proposal.contributorId.toString()); + // return Proposal.create(proposal); + // }); + // }); + // }, getContributions () { return this.kredits.Contribution.all({page: {size: 200}}) @@ -311,6 +314,7 @@ export default Service.extend({ .on('ContributorAdded', this.handleContributorChange.bind(this)) this.kredits.Contribution + .on('ContributionAdded', this.handleContributionAdded.bind(this)) .on('ContributionVetoed', this.handleContributionVetoed.bind(this)) this.kredits.Proposal @@ -338,6 +342,24 @@ export default Service.extend({ this.contributors.pushObject(newContributor); }, + async handleContributionAdded (id, contributorId, amount) { + console.debug('[kredits] ContributionAdded event received', { id, contributorId, amount }); + + const pendingContribution = this.contributions.find(c => { + return (c.id === null) && + (c.contributorId.toString() === contributorId.toString()) && + (c.amount.toString() === amount.toString()); + }); + + if (pendingContribution) { + const attributes = await this.kredits.Contribution.getById(id); + attributes.contributor = this.contributors.findBy('id', attributes.contributorId.toString()); + const newContribution = Contribution.create(attributes); + this.contributions.addObject(newContribution); + this.contributions.removeObject(pendingContribution); + } + }, + handleContributionVetoed (contributionId) { console.debug('[kredits] ContributionVetoed event received for ', contributionId); const contribution = this.contributions.findBy('id', contributionId); diff --git a/app/styles/components/_contribution-details.scss b/app/styles/components/_contribution-details.scss index d10e146..80c04b6 100644 --- a/app/styles/components/_contribution-details.scss +++ b/app/styles/components/_contribution-details.scss @@ -41,7 +41,7 @@ section#contribution-details { } } - a { + a:not(.button) { color: $primary-color; text-decoration: none; @@ -54,4 +54,35 @@ section#contribution-details { .actions { text-align: center; } + + &.vetoed { + .content { + h3 { + text-decoration: line-through; + } + } + } + + .hint.vetoed { + overflow: auto; + margin-top: 2rem; + padding-top: 2rem; + border-top: 1px solid rgba(255,255,255,0.2); + font-size: 1.2rem; + + .icon { + display: inline-block; + width: 40px; + height: 40px; + float: left; + margin-right: 1rem; + margin-bottom: 1rem; + + svg { + width: 100%; + height: auto; + } + } + } + } diff --git a/app/templates/contributions/resubmit.hbs b/app/templates/contributions/resubmit.hbs new file mode 100644 index 0000000..79f9a46 --- /dev/null +++ b/app/templates/contributions/resubmit.hbs @@ -0,0 +1,13 @@ +

+ +
+
+

Re-submit contribution #{{model.id}}

+
+ +
+ {{add-contribution attributes=attributes contributors=sortedContributors save=(action "save")}} +
+
+ +
diff --git a/app/templates/dashboard/contributions/show.hbs b/app/templates/dashboard/contributions/show.hbs index 9dcc8cd..b0d43b3 100644 --- a/app/templates/dashboard/contributions/show.hbs +++ b/app/templates/dashboard/contributions/show.hbs @@ -1,4 +1,4 @@ -
+

Contribution #{{model.id}}