diff --git a/app/components/add-expense-item/component.js b/app/components/add-expense-item/component.js
index 72790e6..a2022ba 100644
--- a/app/components/add-expense-item/component.js
+++ b/app/components/add-expense-item/component.js
@@ -81,7 +81,9 @@ export default class AddExpenseItemComponent extends Component {
}
if (isPresent(this.tags)) {
- expense.tags = this.tags.split(',').map(t => t.trim());
+ expense.tags = this.tags.split(',')
+ .map(t => t.trim())
+ .filter(t => t.length > 0);
}
this.args.addExpenseItem(expense);
diff --git a/app/components/add-reimbursement/component.js b/app/components/add-reimbursement/component.js
index fd00dea..5fc0397 100644
--- a/app/components/add-reimbursement/component.js
+++ b/app/components/add-reimbursement/component.js
@@ -6,6 +6,7 @@ import { action } from '@ember/object';
import { A } from '@ember/array';
import { scheduleOnce } from '@ember/runloop';
import isValidAmount from 'kredits-web/utils/is-valid-amount';
+import readFileContent from 'kredits-web/utils/read-file-content';
import config from 'kredits-web/config/environment';
export default class AddReimbursementComponent extends Component {
@@ -84,8 +85,25 @@ export default class AddReimbursementComponent extends Component {
this.total = btcAmount.toFixed(8);
}
+ // TODO use ember-concurrency here
+ // https://github.com/67P/kredits-web/pull/209#discussion_r1064234421
@action
- updateContributor(event) {
+ async addExpensesFromFile (evt) {
+ const content = await readFileContent(evt.target.files[0]);
+ const expenses = JSON.parse(content);
+
+ if (expenses instanceof Array) {
+ for (const item of expenses) {
+ this.addExpenseItem(item);
+ }
+ } else {
+ console.warn("Expenses in file must be a list of items:");
+ console.debug(content);
+ }
+ }
+
+ @action
+ updateContributor (event) {
this.recipientId = event.target.value;
}
diff --git a/app/components/add-reimbursement/template.hbs b/app/components/add-reimbursement/template.hbs
index 6c1c06a..43235b3 100644
--- a/app/components/add-reimbursement/template.hbs
+++ b/app/components/add-reimbursement/template.hbs
@@ -87,3 +87,9 @@
@@ -26,6 +30,17 @@
+ + Inspect IPFS data + + +
+ {{/if}} {{/each}} \ No newline at end of file diff --git a/app/services/kredits.js b/app/services/kredits.js index f47954d..dc62d47 100644 --- a/app/services/kredits.js +++ b/app/services/kredits.js @@ -617,6 +617,18 @@ export default Service.extend({ yield this.fetchMissingObjects.perform('Reimbursement'); }).group('syncTaskGroup'), + vetoReimbursement (id) { + console.debug('[kredits] veto against reimbursement', id); + const reimbursement = this.reimbursements.findBy('id', id); + + return this.kredits.Reimbursement.functions.veto(id, { gasLimit: 300000 }) + .then(data => { + console.debug('[kredits] veto response', data); + reimbursement.set('pendingTx', data); + return data; + }); + }, + // // Contract events // @@ -676,7 +688,7 @@ export default Service.extend({ }, async handleContributionVetoed (contributionId) { - console.debug('[kredits] ContributionVetoed event received for ', contributionId); + console.debug('[kredits] ContributionVetoed event received for #', contributionId); const c = this.contributions.findBy('id', contributionId); if (c) { @@ -687,9 +699,6 @@ export default Service.extend({ } }, - // - // TODO test when reimbursement txs are successful - // async handleReimbursementAdded (id, addedByAccount, amount) { console.debug('[kredits] ReimbursementAdded event received', { id, addedByAccount, amount }); @@ -703,20 +712,19 @@ export default Service.extend({ } const data = await this.kredits.Reimbursement.getById(id); - this.loadReimbursementFromData(data); + const r = this.loadReimbursementFromData(data); + this.browserCache.reimbursements.setItem(r.id.toString(), r.serialize()); }, - // - // TODO test when reimbursement txs are successful and veto is implemented - // - handleReimbursementVetoed (id) { - console.debug('[kredits] ReimbursementVetoed received for ', id); - const reimbursement = this.reimbursements.findBy('id', id); - console.debug('[kredits] reimbursement', this.reimbursement); + async handleReimbursementVetoed (id) { + console.debug(`[kredits] ReimbursementVetoed received for #${id}`); + const r = this.reimbursements.findBy('id', id); + console.debug('[kredits] reimbursement', r); - if (reimbursement) { - reimbursement.set('vetoed', true); - reimbursement.set('pendingTx', null); + if (r) { + r.set('vetoed', true); + r.set('pendingTx', null); + this.browserCache.reimbursements.setItem(r.id.toString(), r.serialize()); } }, diff --git a/app/styles/components/_reimbursement-list.scss b/app/styles/components/_reimbursement-list.scss index 3c22894..dfbb5d8 100644 --- a/app/styles/components/_reimbursement-list.scss +++ b/app/styles/components/_reimbursement-list.scss @@ -7,6 +7,11 @@ ul.reimbursement-list { grid-row-gap: 0.5rem; padding-top: 1.6rem; + &.vetoed { + text-decoration: line-through; + opacity: 0.6; + } + .token-amount { text-align: right; diff --git a/app/utils/read-file-content.js b/app/utils/read-file-content.js new file mode 100644 index 0000000..0413399 --- /dev/null +++ b/app/utils/read-file-content.js @@ -0,0 +1,8 @@ +export default function (file) { + const reader = new FileReader(); + return new Promise((resolve, reject) => { + reader.onload = event => resolve(event.target.result) + reader.onerror = error => reject(error) + reader.readAsText(file) + }) +}