From 92a336cb5a299ec691e68e0e8242ff1387f0112a Mon Sep 17 00:00:00 2001 From: NickolaiYurchenko Date: Wed, 22 Jul 2020 18:15:24 +0300 Subject: [PATCH] web/storagenode: held returned block added WHAT: held information block on payout page WHY: to show held and held disposed amounts Change-Id: I34b8f17993f93d7fdbc65021d0a088c8a5490f8d --- .../app/components/payments/TotalHeldArea.vue | 120 ++++++++++++++++++ web/storagenode/src/app/types/payout.ts | 3 +- web/storagenode/src/app/views/PayoutArea.vue | 39 +++--- .../src/storagenode/payouts/payouts.ts | 2 + .../components/payments/TotalHeldArea.spec.ts | 77 +++++++++++ .../__snapshots__/TotalHeldArea.spec.ts.snap | 49 +++++++ .../tests/unit/store/payout.spec.ts | 7 +- 7 files changed, 279 insertions(+), 18 deletions(-) create mode 100644 web/storagenode/src/app/components/payments/TotalHeldArea.vue create mode 100644 web/storagenode/tests/unit/components/payments/TotalHeldArea.spec.ts create mode 100644 web/storagenode/tests/unit/components/payments/__snapshots__/TotalHeldArea.spec.ts.snap diff --git a/web/storagenode/src/app/components/payments/TotalHeldArea.vue b/web/storagenode/src/app/components/payments/TotalHeldArea.vue new file mode 100644 index 000000000..3809a2abf --- /dev/null +++ b/web/storagenode/src/app/components/payments/TotalHeldArea.vue @@ -0,0 +1,120 @@ +// Copyright (C) 2020 Storj Labs, Inc. +// See LICENSE for copying information. + + + + + + diff --git a/web/storagenode/src/app/types/payout.ts b/web/storagenode/src/app/types/payout.ts index e35d5b7c6..8975b365d 100644 --- a/web/storagenode/src/app/types/payout.ts +++ b/web/storagenode/src/app/types/payout.ts @@ -4,7 +4,8 @@ import { EstimatedPayout, PayoutPeriod, - SatelliteHeldHistory, SatellitePayoutForPeriod, + SatelliteHeldHistory, + SatellitePayoutForPeriod, TotalHeldAndPaid, TotalPaystubForPeriod, } from '@/storagenode/payouts/payouts'; diff --git a/web/storagenode/src/app/views/PayoutArea.vue b/web/storagenode/src/app/views/PayoutArea.vue index f806e37a4..0cf5842ca 100644 --- a/web/storagenode/src/app/views/PayoutArea.vue +++ b/web/storagenode/src/app/views/PayoutArea.vue @@ -27,10 +27,13 @@

- - + +
+ + +
- + @@ -45,6 +48,7 @@ import HeldHistoryTable from '@/app/components/payments/HeldHistoryMonthlyBreakd import HeldProgress from '@/app/components/payments/HeldProgress.vue'; import PayoutHistoryTable from '@/app/components/payments/PayoutHistoryTable.vue'; import SingleInfo from '@/app/components/payments/SingleInfo.vue'; +import TotalHeldArea from '@/app/components/payments/TotalHeldArea.vue'; import SatelliteSelection from '@/app/components/SatelliteSelection.vue'; import BackArrowIcon from '@/../static/images/notifications/backArrow.svg'; @@ -54,11 +58,11 @@ import { NODE_ACTIONS } from '@/app/store/modules/node'; import { NOTIFICATIONS_ACTIONS } from '@/app/store/modules/notifications'; import { PAYOUT_ACTIONS } from '@/app/store/modules/payout'; import { NotificationsCursor } from '@/app/types/notifications'; -import { SatelliteInfo } from '@/storagenode/dashboard'; -import { PayoutPeriod } from '@/storagenode/payouts/payouts'; +import { PayoutPeriod, TotalHeldAndPaid } from '@/storagenode/payouts/payouts'; @Component ({ components: { + TotalHeldArea, PayoutHistoryTable, HeldHistoryArea, HeldProgress, @@ -110,20 +114,15 @@ export default class PayoutArea extends Vue { await this.$store.dispatch(APPSTATE_ACTIONS.SET_LOADING, false); } - public get totalHeld(): number { - return this.$store.state.payoutModule.totalHeldAndPaid.held; - } - - public get heldPercentage(): number { - return this.$store.state.payoutModule.heldPercentage; + public get totalHeldAndPaid(): TotalHeldAndPaid { + return this.$store.state.payoutModule.totalHeldAndPaid; } /** - * selectedSatellite - current selected satellite from store. - * @return SatelliteInfo - current selected satellite + * Indicates if satellite is selected. */ - public get selectedSatellite(): SatelliteInfo { - return this.$store.state.node.selectedSatellite.id; + public get isSatelliteSelected(): boolean { + return !!this.$store.state.node.selectedSatellite.id; } public get payoutPeriods(): PayoutPeriod[] { @@ -222,6 +221,12 @@ export default class PayoutArea extends Vue { } } + .row { + display: flex; + justify-content: space-between; + width: 100%; + } + @media screen and (max-width: 890px) { .payout-area-container { @@ -259,5 +264,9 @@ export default class PayoutArea extends Vue { } } } + + .row { + flex-direction: column; + } } diff --git a/web/storagenode/src/storagenode/payouts/payouts.ts b/web/storagenode/src/storagenode/payouts/payouts.ts index 798a6e3e5..17310f5cd 100644 --- a/web/storagenode/src/storagenode/payouts/payouts.ts +++ b/web/storagenode/src/storagenode/payouts/payouts.ts @@ -172,6 +172,7 @@ export class TotalPaystubForPeriod { export class TotalHeldAndPaid { public held: number = 0; public paid: number = 0; + public disposed: number = 0; // TODO: remove public currentMonthEarnings: number = 0; @@ -181,6 +182,7 @@ export class TotalHeldAndPaid { paystubs.forEach(paystub => { this.held += this.convertToCents(paystub.held - paystub.disposed); this.paid += this.convertToCents(paystub.paid); + this.disposed += this.convertToCents(paystub.disposed); }); } diff --git a/web/storagenode/tests/unit/components/payments/TotalHeldArea.spec.ts b/web/storagenode/tests/unit/components/payments/TotalHeldArea.spec.ts new file mode 100644 index 000000000..538cead46 --- /dev/null +++ b/web/storagenode/tests/unit/components/payments/TotalHeldArea.spec.ts @@ -0,0 +1,77 @@ +// Copyright (C) 2020 Storj Labs, Inc. +// See LICENSE for copying information. + +import Vuex from 'vuex'; + +import TotalHeldArea from '@/app/components/payments/TotalHeldArea.vue'; + +import { makeNodeModule, NODE_MUTATIONS } from '@/app/store/modules/node'; +import { makePayoutModule, PAYOUT_MUTATIONS } from '@/app/store/modules/payout'; +import { PayoutHttpApi } from '@/storagenode/api/payout'; +import { SNOApi } from '@/storagenode/api/storagenode'; +import { Paystub, TotalHeldAndPaid } from '@/storagenode/payouts/payouts'; +import { PayoutService } from '@/storagenode/payouts/service'; +import { Metric, Satellite, Stamp } from '@/storagenode/satellite'; +import { createLocalVue, shallowMount } from '@vue/test-utils'; + +const localVue = createLocalVue(); +localVue.use(Vuex); + +localVue.filter('centsToDollars', (cents: number): string => { + return `$${(cents / 100).toFixed(2)}`; +}); + +const payoutApi = new PayoutHttpApi(); +const payoutService = new PayoutService(payoutApi); +const payoutModule = makePayoutModule(payoutApi, payoutService); +const nodeApi = new SNOApi(); +const nodeModule = makeNodeModule(nodeApi); + +const store = new Vuex.Store({ modules: { payoutModule, node: nodeModule }}); + +describe('TotalHeldArea', (): void => { + it('renders correctly', (): void => { + const wrapper = shallowMount(TotalHeldArea, { + store, + localVue, + }); + + expect(wrapper).toMatchSnapshot(); + }); + + it('renders correctly with actual values', async (): Promise => { + const wrapper = shallowMount(TotalHeldArea, { + store, + localVue, + }); + + const testJoinAt = new Date(Date.UTC(2018, 0, 30)); + + const satelliteInfo = new Satellite( + '3', + [new Stamp()], + [], + [], + [], + 111, + 222, + 50, + 70, + new Metric(1, 1, 1, 0, 1), + new Metric(2, 1, 1, 0, 1), + testJoinAt, + ); + const paystub = new Paystub(); + paystub.held = 600000; + paystub.disposed = 100000; + paystub.paid = 1000000; + + const totalHeldAndPaid = new TotalHeldAndPaid([paystub]); + + await store.commit(NODE_MUTATIONS.SELECT_SATELLITE, satelliteInfo); + + await store.commit(PAYOUT_MUTATIONS.SET_TOTAL, totalHeldAndPaid); + + expect(wrapper).toMatchSnapshot(); + }); +}); diff --git a/web/storagenode/tests/unit/components/payments/__snapshots__/TotalHeldArea.spec.ts.snap b/web/storagenode/tests/unit/components/payments/__snapshots__/TotalHeldArea.spec.ts.snap new file mode 100644 index 000000000..959e4c72a --- /dev/null +++ b/web/storagenode/tests/unit/components/payments/__snapshots__/TotalHeldArea.spec.ts.snap @@ -0,0 +1,49 @@ +// Jest Snapshot v1, https://goo.gl/fbAQLP + +exports[`TotalHeldArea renders correctly 1`] = ` +
+
+
+

Held Amount Rate

+

0%

+
+
+

Total Held Amount

+

$0.00

+
+
+

Total Held Returned

+

$0.00

+
+
+
+ + + +
+
+`; + +exports[`TotalHeldArea renders correctly with actual values 1`] = ` +
+
+
+

Held Amount Rate

+

0%

+
+
+

Total Held Amount

+

$0.50

+
+
+

Total Held Returned

+

$0.10

+
+
+
+ + + +
+
+`; diff --git a/web/storagenode/tests/unit/store/payout.spec.ts b/web/storagenode/tests/unit/store/payout.spec.ts index a537aef0e..5c542d09a 100644 --- a/web/storagenode/tests/unit/store/payout.spec.ts +++ b/web/storagenode/tests/unit/store/payout.spec.ts @@ -64,6 +64,7 @@ describe('mutations', (): void => { expect(state.payoutModule.totalHeldAndPaid.held).toBe(50); expect(state.payoutModule.totalHeldAndPaid.paid).toBe(100); + expect(state.payoutModule.totalHeldAndPaid.disposed).toBe(10); expect(state.payoutModule.currentMonthEarnings).toBe(22); }); @@ -246,6 +247,7 @@ describe('actions', () => { it('success get total', async (): Promise => { const paystub = new Paystub(); paystub.held = 100000; + paystub.disposed = 50000; paystub.paid = 200000; jest.spyOn(payoutApi, 'getPaystubsForPeriod').mockReturnValue( @@ -254,8 +256,9 @@ describe('actions', () => { await store.dispatch(PAYOUT_ACTIONS.GET_TOTAL); - expect(state.payoutModule.totalHeldAndPaid.held).toBe(10); + expect(state.payoutModule.totalHeldAndPaid.held).toBe(5); expect(state.payoutModule.totalHeldAndPaid.paid).toBe(20); + expect(state.payoutModule.totalHeldAndPaid.disposed).toBe(5); expect(state.payoutModule.currentMonthEarnings).toBe(0); }); @@ -266,7 +269,7 @@ describe('actions', () => { await store.dispatch(PAYOUT_ACTIONS.GET_TOTAL); expect(true).toBe(false); } catch (error) { - expect(state.payoutModule.totalHeldAndPaid.held).toBe(10); + expect(state.payoutModule.totalHeldAndPaid.held).toBe(5); expect(state.payoutModule.totalHeldAndPaid.paid).toBe(20); expect(state.payoutModule.currentMonthEarnings).toBe(0); }