Introduce budget, reimbursements for expenses #195

Merged
raucao merged 57 commits from feature/expenses into master 2021-06-03 14:23:45 +00:00
11 changed files with 212 additions and 110 deletions
Showing only changes of commit eaac245f4e - Show all commits
@@ -0,0 +1,7 @@
import Component from '@glimmer/component';
import { sort } from '@ember/object/computed';
export default class ReimbursementListComponent extends Component {
itemSorting = Object.freeze(['id:desc']);
@sort('args.items', 'itemSorting') itemsSorted;
}
@@ -0,0 +1,14 @@
<ul class="item-list">
{{#each this.itemsSorted as |reimbursement|}}
<li>
{{reimbursement.id}}<br>
{{reimbursement.amount}} WBTC<br>
vetoed: {{reimbursement.vetoed}}<br>
pay out to: {{reimbursement.contributor.name}}<br>
{{#each reimbursement.expenses as |expense|}}
{{expense.date}}: {{expense.title}}
{{/each}}
</li>
{{/each}}
</ul>
+10
View File
@@ -0,0 +1,10 @@
import Controller from '@ember/controller';
import { inject as service } from '@ember/service';
import { alias } from '@ember/object/computed';
export default class BudgetController extends Controller {
@service kredits;
@alias('kredits.reimbursementsUnconfirmed') reimbursementsUnconfirmed;
@alias('kredits.reimbursementsConfirmed') reimbursementsConfirmed;
}
+16
View File
@@ -14,6 +14,15 @@ main {
"contributions";
}
&#budget {
width: 100%;
display: grid;
grid-row-gap: 2rem;
grid-template-areas:
"aside"
"content";
}
&.center-column {
display: flex;
flex-direction: column;
@@ -111,6 +120,13 @@ main {
"stats contributions details";
}
}
&#budget {
grid-column-gap: 3rem;
grid-template-columns: 2fr 4fr 2fr;
grid-template-areas:
"aside content empty";
}
}
}
+66 -48
View File
@@ -1,55 +1,73 @@
<main id="budget">
<section id="main-nav">
<header>
<h2>Budget</h2>
</header>
<div class="content">
<ul>
<li>
<LinkTo @route="budget.expenses">Expenses</LinkTo>
</li>
<li>
<a href="#">Rewards</a>
</li>
</ul>
</div>
</section>
<div id="aside">
<section id="main-nav">
<header>
<h2>Budget</h2>
</header>
<div class="content">
<ul>
<li>
<LinkTo @route="budget.expenses">Expenses</LinkTo>
</li>
<li>
<a href="#">Rewards</a>
</li>
</ul>
</div>
</section>
<section id="funds">
<header>
<h2>Community funds</h2>
</header>
<div class="content">
<table>
<thead>
<tr>
<td>Token</td>
<td>Amount</td>
<td>Fiat value</td>
</tr>
</thead>
<tbody>
<tr>
<td>WBTC</td>
<td>1.17215</td>
<td>11031.15 USD</td>
</tr>
<tr>
<td>ETH</td>
<td>0.5</td>
<td>115.60 USD</td>
</tr>
</tbody>
</table>
</div>
</section>
<section id="funds">
<header>
<h2>Community funds</h2>
</header>
<div class="content">
<table>
<thead>
<tr>
<td>Token</td>
<td>Amount</td>
<td>Fiat value</td>
</tr>
</thead>
<tbody>
<tr>
<td>WBTC</td>
<td>1.17215</td>
<td>11031.15 USD</td>
</tr>
<tr>
<td>ETH</td>
<td>0.5</td>
<td>115.60 USD</td>
</tr>
</tbody>
</table>
</div>
</section>
</div>
{{!-- TODO #if sub-route (i.e. filtered list) --}}
{{!-- {{outlet}} --}}
{{!-- {{else}} --}}
<div id="content">
<section id="expenses-unconfirmed">
<header>
<h2>Proposed Reimbursements</h2>
</header>
<div class="content">
<ReimbursementList @items={{this.reimbursementsUnconfirmed}} />
</div>
</section>
<section id="expenses">
</section>
<section id="expenses-confirmed">
<header>
<h2>Confirmed Expenses</h2>
</header>
<div class="content">
<ReimbursementList @items={{this.reimbursementsConfirmed}} />
</div>
</section>
</div>
<div id="empty">
</div>
</main>
+4 -2
View File
@@ -1,5 +1,7 @@
export default function processReimbursementData(data) {
const processed = {}
const processed = {
amount: data.amount.toNumber()
}
if (data.confirmedAtBlock && (typeof data.confirmedAtBlock.toNumber === 'function')) {
processed.confirmedAt = data.confirmedAtBlock.toNumber();
@@ -8,7 +10,7 @@ export default function processReimbursementData(data) {
}
const otherProperties = [
'id', 'contributorId', 'token', 'amount', 'vetoed', 'ipfsHash',
'id', 'contributorId', 'token', 'vetoed', 'ipfsHash',
'expenses', 'pendingTx'
];
+4
View File
@@ -46,6 +46,10 @@ module.exports = function(environment) {
port: '5444',
protocol: 'https',
gatewayUrl: 'https://ipfs.kosmos.org/ipfs'
},
tokens: {
'WBTC': '0x2260fac5e5542a773aa44fbcfedf7c193bc2c599'
}
};
+52 -59
View File
@@ -2938,8 +2938,9 @@
"dev": true
},
"@kosmos/schemas": {
"version": "github:67P/kosmos-schemas#67cc3d9d746c93907a68a7b6283bb914c283a612",
"from": "github:67P/kosmos-schemas#feature/browser-compat",
"version": "3.0.0",
"resolved": "https://registry.npmjs.org/@kosmos/schemas/-/schemas-3.0.0.tgz",
"integrity": "sha512-7hnirq0ShsDjENBPjNnu6izwzVjkDzEZ4SKvPzQJJfkeJ/NRVHKvfdn9rkE7CRXTi2hMzsZVFOnlF6D/eYXTCA==",
"dev": true,
"requires": {
"brfs-babel": "^1.0.0"
@@ -6759,13 +6760,6 @@
"to-regex-range": "^5.0.1"
}
},
"fsevents": {
"version": "2.1.3",
"resolved": "https://registry.npmjs.org/fsevents/-/fsevents-2.1.3.tgz",
"integrity": "sha512-Auw9a4AxqWpa9GUfj370BMPzzyncfBABW8Mab7BGWBYDj4Isgq+cDKtx0i6u9jcX9pQDnswsaaOTgTmA5pEjuQ==",
"dev": true,
"optional": true
},
"glob-parent": {
"version": "5.1.1",
"resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-5.1.1.tgz",
@@ -10890,6 +10884,39 @@
"ms": "^2.1.1"
}
},
"ember-get-config": {
"version": "0.2.4",
"resolved": "https://registry.npmjs.org/ember-get-config/-/ember-get-config-0.2.4.tgz",
"integrity": "sha1-EYSSoqA9c+RgBO13eSiUICH+Hs0=",
"dev": true,
"requires": {
"broccoli-file-creator": "^1.1.1",
"ember-cli-babel": "^6.3.0"
},
"dependencies": {
"ember-cli-babel": {
"version": "6.18.0",
"resolved": "https://registry.npmjs.org/ember-cli-babel/-/ember-cli-babel-6.18.0.tgz",
"integrity": "sha512-7ceC8joNYxY2wES16iIBlbPSxwKDBhYwC8drU3ZEvuPDMwVv1KzxCNu1fvxyFEBWhwaRNTUxSCsEVoTd9nosGA==",
"dev": true,
"requires": {
"amd-name-resolver": "1.2.0",
"babel-plugin-debug-macros": "^0.2.0-beta.6",
"babel-plugin-ember-modules-api-polyfill": "^2.6.0",
"babel-plugin-transform-es2015-modules-amd": "^6.24.0",
"babel-polyfill": "^6.26.0",
"babel-preset-env": "^1.7.0",
"broccoli-babel-transpiler": "^6.5.0",
"broccoli-debug": "^0.6.4",
"broccoli-funnel": "^2.0.0",
"broccoli-source": "^1.1.0",
"clone": "^2.0.0",
"ember-cli-version-checker": "^2.1.2",
"semver": "^5.5.0"
}
}
}
},
"fs-extra": {
"version": "5.0.0",
"resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-5.0.0.tgz",
@@ -11830,39 +11857,6 @@
}
}
},
"ember-get-config": {
"version": "0.2.4",
"resolved": "https://registry.npmjs.org/ember-get-config/-/ember-get-config-0.2.4.tgz",
"integrity": "sha1-EYSSoqA9c+RgBO13eSiUICH+Hs0=",
"dev": true,
"requires": {
"broccoli-file-creator": "^1.1.1",
"ember-cli-babel": "^6.3.0"
},
"dependencies": {
"ember-cli-babel": {
"version": "6.18.0",
"resolved": "https://registry.npmjs.org/ember-cli-babel/-/ember-cli-babel-6.18.0.tgz",
"integrity": "sha512-7ceC8joNYxY2wES16iIBlbPSxwKDBhYwC8drU3ZEvuPDMwVv1KzxCNu1fvxyFEBWhwaRNTUxSCsEVoTd9nosGA==",
"dev": true,
"requires": {
"amd-name-resolver": "1.2.0",
"babel-plugin-debug-macros": "^0.2.0-beta.6",
"babel-plugin-ember-modules-api-polyfill": "^2.6.0",
"babel-plugin-transform-es2015-modules-amd": "^6.24.0",
"babel-polyfill": "^6.26.0",
"babel-preset-env": "^1.7.0",
"broccoli-babel-transpiler": "^6.5.0",
"broccoli-debug": "^0.6.4",
"broccoli-funnel": "^2.0.0",
"broccoli-source": "^1.1.0",
"clone": "^2.0.0",
"ember-cli-version-checker": "^2.1.2",
"semver": "^5.5.0"
}
}
}
},
"ember-getowner-polyfill": {
"version": "2.2.0",
"resolved": "https://registry.npmjs.org/ember-getowner-polyfill/-/ember-getowner-polyfill-2.2.0.tgz",
@@ -16494,15 +16488,11 @@
"dev": true
},
"fsevents": {
"version": "1.2.13",
"resolved": "https://registry.npmjs.org/fsevents/-/fsevents-1.2.13.tgz",
"integrity": "sha512-oWb1Z6mkHIskLzEJ/XWX0srkpkTQ7vaopMQkyaEIoq0fmtFVxOthb8cCxeT+p3ynTdkk/RZwbgG4brR5BeWECw==",
"version": "2.1.3",
"resolved": "https://registry.npmjs.org/fsevents/-/fsevents-2.1.3.tgz",
"integrity": "sha512-Auw9a4AxqWpa9GUfj370BMPzzyncfBABW8Mab7BGWBYDj4Isgq+cDKtx0i6u9jcX9pQDnswsaaOTgTmA5pEjuQ==",
"dev": true,
"optional": true,
"requires": {
"bindings": "^1.5.0",
"nan": "^2.12.1"
}
"optional": true
},
"function-bind": {
"version": "1.1.1",
@@ -18606,11 +18596,11 @@
"dev": true
},
"kredits-contracts": {
"version": "github:67P/kredits-contracts#17cc44cb981074b32b7732744ce5699949fc1f2f",
"version": "github:67P/kredits-contracts#c63fcc002b05c5907d3f1ebd9487ee074e80d6e9",
"from": "github:67P/kredits-contracts#feature/expenses",
"dev": true,
"requires": {
"@kosmos/schemas": "github:67P/kosmos-schemas#feature/browser-compat",
"@kosmos/schemas": "^3.0.0",
"ethers": "^4.0.47",
"ipfs-http-client": "^41.0.1",
"node-fetch": "^2.6.0",
@@ -20303,13 +20293,6 @@
"integrity": "sha512-nnbWWOkoWyUsTjKrhgD0dcz22mdkSnpYqbEjIm2nhwhuxlSkpywJmBo8h0ZqJdkp73mb90SssHkN4rsRaBAfAA==",
"dev": true
},
"nan": {
"version": "2.13.2",
"resolved": "https://registry.npmjs.org/nan/-/nan-2.13.2.tgz",
"integrity": "sha512-TghvYc72wlMGMVMluVo9WRJc0mB8KxxF/gZ4YYFy7V2ZQX9l7rgbPg7vjS9mt6U5HXODVFVI2bOduCzwOMv/lw==",
"dev": true,
"optional": true
},
"nanomatch": {
"version": "1.2.13",
"resolved": "https://registry.npmjs.org/nanomatch/-/nanomatch-1.2.13.tgz",
@@ -25437,6 +25420,16 @@
"upath": "^1.1.1"
}
},
"fsevents": {
"version": "1.2.13",
"resolved": "https://registry.npmjs.org/fsevents/-/fsevents-1.2.13.tgz",
"integrity": "sha512-oWb1Z6mkHIskLzEJ/XWX0srkpkTQ7vaopMQkyaEIoq0fmtFVxOthb8cCxeT+p3ynTdkk/RZwbgG4brR5BeWECw==",
"dev": true,
"optional": true,
"requires": {
"bindings": "^1.5.0"
}
},
"normalize-path": {
"version": "3.0.0",
"resolved": "https://registry.npmjs.org/normalize-path/-/normalize-path-3.0.0.tgz",
+1 -1
View File
@@ -29,7 +29,7 @@
"@ember/optional-features": "^1.3.0",
"@glimmer/component": "^1.0.0",
"@glimmer/tracking": "^1.0.0",
"@kosmos/schemas": "github:67P/kosmos-schemas#feature/browser-compat",
"@kosmos/schemas": "^3.0.0",
"babel-eslint": "^10.1.0",
"babel-preset-es2015": "^6.22.0",
"babelify": "^7.3.0",
@@ -0,0 +1,26 @@
import { module, test } from 'qunit';
import { setupRenderingTest } from 'ember-qunit';
import { render } from '@ember/test-helpers';
import { hbs } from 'ember-cli-htmlbars';
module('Integration | Component | reimbursement-list', function(hooks) {
setupRenderingTest(hooks);
test('it renders', async function(assert) {
// Set any properties with this.set('myProperty', 'value');
// Handle any actions with this.set('myAction', function(val) { ... });
await render(hbs`<ReimbursementList />`);
assert.equal(this.element.textContent.trim(), '');
// Template block usage:
await render(hbs`
<ReimbursementList>
template block text
</ReimbursementList>
`);
assert.equal(this.element.textContent.trim(), 'template block text');
});
});
+12
View File
@@ -0,0 +1,12 @@
import { module, test } from 'qunit';
import { setupTest } from 'ember-qunit';
module('Unit | Controller | budget', function(hooks) {
setupTest(hooks);
// Replace this with your real tests.
test('it exists', function(assert) {
let controller = this.owner.lookup('controller:budget');
assert.ok(controller);
});
});