diff --git a/app/components/add-reimbursement/template.hbs b/app/components/add-reimbursement/template.hbs index 43235b3..0e6a74c 100644 --- a/app/components/add-reimbursement/template.hbs +++ b/app/components/add-reimbursement/template.hbs @@ -44,26 +44,10 @@

Expense items

{{#if this.expenses}} - + +

diff --git a/app/components/confirmed-in/component.js b/app/components/confirmed-in/component.js new file mode 100644 index 0000000..487419b --- /dev/null +++ b/app/components/confirmed-in/component.js @@ -0,0 +1,20 @@ +import Component from '@glimmer/component'; +import { inject as service } from '@ember/service'; +import moment from 'moment'; + +export default class ConfirmedInComponent extends Component { + @service kredits; + + get confirmedInBlocks () { + return this.args.confirmedAtBlock - this.kredits.currentBlock; + } + + get confirmedInSeconds () { + // A new block is mined every 30 seconds on average + return this.confirmedInBlocks * 30; + } + + get confirmedInHumanTime () { + return moment.duration(this.confirmedInSeconds, "seconds").humanize(); + } +} diff --git a/app/components/confirmed-in/template.hbs b/app/components/confirmed-in/template.hbs new file mode 100644 index 0000000..1529053 --- /dev/null +++ b/app/components/confirmed-in/template.hbs @@ -0,0 +1 @@ +Confirming in {{this.confirmedInBlocks}} blocks (~ {{this.confirmedInHumanTime}}) diff --git a/app/components/expense-list/component.js b/app/components/expense-list/component.js new file mode 100644 index 0000000..640d820 --- /dev/null +++ b/app/components/expense-list/component.js @@ -0,0 +1,9 @@ +import Component from '@glimmer/component'; + +export default class ExpenseListComponent extends Component { + + get showDeleteButton () { + return !!this.args.deletable; + } + +} diff --git a/app/components/expense-list/template.hbs b/app/components/expense-list/template.hbs new file mode 100644 index 0000000..3633663 --- /dev/null +++ b/app/components/expense-list/template.hbs @@ -0,0 +1,29 @@ +

diff --git a/app/components/reimbursement-list/template.hbs b/app/components/reimbursement-list/template.hbs index b904207..50dcedf 100644 --- a/app/components/reimbursement-list/template.hbs +++ b/app/components/reimbursement-list/template.hbs @@ -3,44 +3,36 @@
  • - - Expenses covered by {{reimbursement.contributor.name}} - + + Expenses covered by {{reimbursement.contributor.name}} +

    {{sats-to-btc reimbursement.amount}}BTC

    - - {{#if this.kredits.currentUserIsCore}} -

    + + + +

    +

    + +

    +

    Inspect IPFS data - + {{#if this.kredits.currentUserIsCore}} + + {{/if}}

    - {{/if}} +
  • {{/each}} \ No newline at end of file diff --git a/app/helpers/fmt-date-localized.js b/app/helpers/fmt-date-localized.js new file mode 100644 index 0000000..a27bb28 --- /dev/null +++ b/app/helpers/fmt-date-localized.js @@ -0,0 +1,8 @@ +import { helper } from '@ember/component/helper'; +import getLocale from 'kredits-web/utils/get-locale'; + +export default helper(function(dateStr) { + const date = new Date(dateStr); + const locale = getLocale(); + return new Intl.DateTimeFormat(locale).format(date); +}); diff --git a/app/services/kredits.js b/app/services/kredits.js index dc62d47..12a58eb 100644 --- a/app/services/kredits.js +++ b/app/services/kredits.js @@ -118,9 +118,12 @@ export default Service.extend({ }); await kredits.init(); - this.set('kredits', kredits); - this.set('currentBlock', await kredits.provider.getBlockNumber()); + this.set('currentBlock', await this.kredits.provider.getBlockNumber()); + this.kredits.provider.on('block', blockNumber => { + console.debug('[kredits] New block mined:', blockNumber); + this.set('currentBlock', blockNumber) + }); if (this.currentUserAccounts && this.currentUserAccounts.length > 0) { this.getCurrentUser.then(contributorData => { @@ -738,5 +741,5 @@ export default Service.extend({ this.contributors .findBy('address', to) .incrementProperty('balance', value); - }, + } }); diff --git a/app/styles/_buttons.scss b/app/styles/_buttons.scss index eb0c2ff..db5a8bc 100644 --- a/app/styles/_buttons.scss +++ b/app/styles/_buttons.scss @@ -31,32 +31,53 @@ button, input[type=submit], .button { &.small { font-size: 0.86rem; padding: 0.2rem 0.8rem; + + svg { + width: 1em; + height: 1em; + vertical-align: middle; + margin-right: 0.4rem; + } } &.danger:not(:disabled) { color: $red; background-color: rgba(40, 21, 21, 0.6); border-color: rgba(40, 21, 21, 1); - - &:hover { - background-color: rgba(40, 21, 21, 0.8); - } - &:focus, &:active, &.active { - border-color: $red; - } + &:hover { background-color: rgba(40, 21, 21, 0.8); } + &:focus, &:active, &.active { border-color: $red; } } &.green:not(:disabled) { color: $green; background-color: rgba(21, 40, 21, 0.6); border-color: rgba(21, 40, 21, 1); + &:hover { background-color: rgba(21, 40, 21, 0.8); } + &:focus, &:active, &.active { border-color: $green; } + } - &:hover { - background-color: rgba(21, 40, 21, 0.8); - } - &:focus, &:active, &.active { - border-color: $green; - } + &.pink:not(:disabled) { + color: $pink; + background-color: rgba(40, 21, 40, 0.6); + border-color: rgba(40, 21, 40, 1); + &:hover { background-color: rgba(40, 21, 40, 0.8); } + &:focus, &:active, &.active { border-color: $pink; } + } + + &.purple:not(:disabled) { + color: $purple; + background-color: rgba(24, 21, 40, 0.6); + border-color: rgba(24, 21, 40, 1); + &:hover { background-color: rgba(24, 21, 40, 0.8); } + &:focus, &:active, &.active { border-color: $purple; } + } + + &.yellow:not(:disabled) { + color: $yellow; + background-color: rgba(40, 40, 21, 0.6); + border-color: rgba(40, 40, 21, 1); + &:hover { background-color: rgba(40, 40, 21, 0.8); } + &:focus, &:active, &.active { border-color: $yellow; } } &.icon { diff --git a/app/styles/components/_expense-list.scss b/app/styles/components/_expense-list.scss index b369f5f..b5a9650 100644 --- a/app/styles/components/_expense-list.scss +++ b/app/styles/components/_expense-list.scss @@ -17,32 +17,30 @@ ul.expense-list { } } - .description { - grid-row-start: 1; - grid-row-end: 3; - } - - .amount { - justify-self: end; - // font-weight: normal; - } - - .actions { - justify-self: end; - } - h4 { font-size: 1.2rem; font-weight: normal; line-height: 2rem; } - p { - line-height: 2rem; + .amount { + justify-self: end; + } - &.description { - font-size: 1rem; - opacity: 0.7; + .description { + font-size: 1rem; + opacity: 0.7; + grid-column-start: span 2; + } + + .tags { + button { + margin-left: 0; } } + + .actions { + justify-self: end; + } + } diff --git a/app/styles/components/_reimbursement-list.scss b/app/styles/components/_reimbursement-list.scss index dfbb5d8..556f69a 100644 --- a/app/styles/components/_reimbursement-list.scss +++ b/app/styles/components/_reimbursement-list.scss @@ -31,4 +31,24 @@ ul.reimbursement-list { } } } + + div.meta { + grid-column-start: 1; + grid-column-end: 3; + margin-top: 0.6rem; + border-top: 1px solid $item-border-color; + display: flex; + + p { + flex: 1; + padding: 1.6rem 0 1rem 0; + + &.confirmation-eta { + } + + &.actions { + text-align: right; + } + } + } } diff --git a/app/templates/components/icon-tag.hbs b/app/templates/components/icon-tag.hbs new file mode 100644 index 0000000..7219b15 --- /dev/null +++ b/app/templates/components/icon-tag.hbs @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/app/utils/get-locale.js b/app/utils/get-locale.js new file mode 100644 index 0000000..f80eb77 --- /dev/null +++ b/app/utils/get-locale.js @@ -0,0 +1,5 @@ +export default function() { + return (navigator.languages && navigator.languages.length) ? + navigator.languages[0] : + navigator.language; +} diff --git a/tests/unit/components/confirmed-in-test.js b/tests/unit/components/confirmed-in-test.js new file mode 100644 index 0000000..7f1831c --- /dev/null +++ b/tests/unit/components/confirmed-in-test.js @@ -0,0 +1,40 @@ +import { module, test } from 'qunit'; +import { setupTest } from 'ember-qunit'; +import createComponent from 'kredits-web/tests/helpers/create-component'; +// import moment from 'moment'; + +module('Unit | Component | confirmed-in', function(hooks) { + setupTest(hooks); + + test('it exists', function(assert) { + let component = createComponent('component:confirmed-in'); + assert.ok(component); + }); + + test('#confirmedInBlocks', function(assert) { + const kredits = this.owner.lookup('service:kredits'); + kredits.set('currentBlock', 419550); + let component = createComponent('component:confirmed-in'); + component.args.confirmedAtBlock = 420000; + + assert.equal(component.confirmedInBlocks, 450); + }) + + test('#confirmedInSeconds', function(assert) { + const kredits = this.owner.lookup('service:kredits'); + kredits.set('currentBlock', 419550); + let component = createComponent('component:confirmed-in'); + component.args.confirmedAtBlock = 420000; + + assert.equal(component.confirmedInSeconds, 13500); + }) + + test('#confirmedInHumanTime', function(assert) { + const kredits = this.owner.lookup('service:kredits'); + kredits.set('currentBlock', 419550); + let component = createComponent('component:confirmed-in'); + component.args.confirmedAtBlock = 420000; + + assert.equal(component.confirmedInHumanTime, '4 hours'); + }) +});