diff --git a/app/src/renderer/components/govern/PageProposals.vue b/app/src/renderer/components/govern/PageProposals.vue
index 2f622fd400..c8e0c12f7f 100644
--- a/app/src/renderer/components/govern/PageProposals.vue
+++ b/app/src/renderer/components/govern/PageProposals.vue
@@ -9,7 +9,8 @@ page(title='Proposals')
.label Search
modal-search(type="proposals")
- data-empty(v-if="proposals.length === 0")
+ data-loading(v-if="proposals.loading")
+ data-empty(v-else-if="proposals.length === 0")
data-empty-search(v-else-if="filteredProposals.length === 0")
li-proposal(
v-else
@@ -22,6 +23,7 @@ page(title='Proposals')
import { mapGetters } from 'vuex'
import { includes, orderBy } from 'lodash'
import Mousetrap from 'mousetrap'
+import DataLoading from 'common/NiDataLoading'
import DataEmpty from 'common/NiDataEmpty'
import DataEmptySearch from 'common/NiDataEmptySearch'
import LiProposal from 'govern/LiProposal'
@@ -33,6 +35,7 @@ import Part from 'common/NiPart'
export default {
name: 'page-proposals',
components: {
+ DataLoading,
DataEmpty,
DataEmptySearch,
LiProposal,
@@ -45,9 +48,9 @@ export default {
computed: {
...mapGetters(['proposals', 'filters']),
filteredProposals () {
- if (this.proposals && this.filters) {
+ if (this.proposals.items && this.filters) {
let query = this.filters.proposals.search.query
- let proposals = orderBy(this.proposals, [this.sort.property], [this.sort.order])
+ let proposals = orderBy(this.proposals.items, [this.sort.property], [this.sort.order])
if (this.filters.proposals.search.visible) {
return proposals.filter(p => includes(p.title.toLowerCase(), query))
} else {
diff --git a/app/src/renderer/components/monitor/PageBlock.vue b/app/src/renderer/components/monitor/PageBlock.vue
index 75ae746134..bbe90a091c 100644
--- a/app/src/renderer/components/monitor/PageBlock.vue
+++ b/app/src/renderer/components/monitor/PageBlock.vue
@@ -41,14 +41,16 @@ page(:title="pageBlockTitle" v-if="block.header")
:dd="p.signature.data")
part(title='Transactions')
- list-item(v-if="block.header.num_txs > 0" v-for="tx in block.data.txs" :key="tx.id" dt="Transaction" :dd="TODO")
- data-empty(v-if="block.header.num_txs === 0" title="Empty Block" subtitle="There were no transactions in this block.")
+ data-loading(v-if="blockchain.blockLoading")
+ data-empty(v-else-if="block.header.num_txs === 0" title="Empty Block" subtitle="There were no transactions in this block.")
+ list-item(v-else v-for="tx in block.data.txs" :key="tx.id" dt="Transaction" :dd="TODO")
diff --git a/app/src/renderer/components/staking/LiDelegate.vue b/app/src/renderer/components/staking/LiDelegate.vue
index 0178d51b1a..2f1e68e3d2 100644
--- a/app/src/renderer/components/staking/LiDelegate.vue
+++ b/app/src/renderer/components/staking/LiDelegate.vue
@@ -42,13 +42,13 @@ export default {
return value
},
vpMax () {
- if (this.delegates.length > 0) {
- let richestDelegate = maxBy(this.delegates, 'voting_power')
+ if (this.delegates.delegates.length > 0) {
+ let richestDelegate = maxBy(this.delegates.delegates, 'voting_power')
return richestDelegate.voting_power
} else { return 0 }
},
vpTotal () {
- return this.delegates
+ return this.delegates.delegates
.slice()
.sort((a, b) => b.voting_power - a.voting_power)
.slice(0, 100)
diff --git a/app/src/renderer/components/staking/PageDelegate.vue b/app/src/renderer/components/staking/PageDelegate.vue
index 6760f4c62b..7070968264 100644
--- a/app/src/renderer/components/staking/PageDelegate.vue
+++ b/app/src/renderer/components/staking/PageDelegate.vue
@@ -54,8 +54,8 @@ export default {
let value = {
description: {}
}
- if (this.delegates && this.$route.params.delegate) {
- value = this.delegates.find(v => v.id === this.$route.params.delegate) || value
+ if (this.delegates.delegates && this.$route.params.delegate) {
+ value = this.delegates.delegates.find(v => v.id === this.$route.params.delegate) || value
}
return value
},
diff --git a/app/src/renderer/components/staking/PageDelegates.vue b/app/src/renderer/components/staking/PageDelegates.vue
index c74145716b..cde373d2ca 100644
--- a/app/src/renderer/components/staking/PageDelegates.vue
+++ b/app/src/renderer/components/staking/PageDelegates.vue
@@ -11,7 +11,8 @@ page#page-delegates(title='Delegates')
modal-search(type="delegates")
.delegates-container
- data-loading(v-if="delegates.length === 0")
+ data-loading(v-if="delegates.loading")
+ data-empty(v-else-if="delegates.delegates.length === 0")
data-empty-search(v-else-if="filteredDelegates.length === 0")
template(v-else)
panel-sort(:sort='sort')
@@ -32,6 +33,7 @@ import { includes, orderBy } from 'lodash'
import Mousetrap from 'mousetrap'
import LiDelegate from 'staking/LiDelegate'
import Btn from '@nylira/vue-button'
+import DataEmpty from 'common/NiDataEmpty'
import DataEmptySearch from 'common/NiDataEmptySearch'
import DataLoading from 'common/NiDataLoading'
import Field from '@nylira/vue-field'
@@ -45,6 +47,7 @@ export default {
components: {
LiDelegate,
Btn,
+ DataEmpty,
DataEmptySearch,
DataLoading,
Field,
@@ -59,7 +62,7 @@ export default {
address () { return this.user.address },
filteredDelegates () {
let query = this.filters.delegates.search.query
- let list = orderBy(this.delegates, [this.sort.property], [this.sort.order])
+ let list = orderBy(this.delegates.delegates, [this.sort.property], [this.sort.order])
if (this.filters.delegates.search.visible) {
return list.filter(i => includes(JSON.stringify(i).toLowerCase(), query.toLowerCase()))
} else {
diff --git a/app/src/renderer/components/wallet/PageBalances.vue b/app/src/renderer/components/wallet/PageBalances.vue
index e07cfd9772..7928e6db11 100644
--- a/app/src/renderer/components/wallet/PageBalances.vue
+++ b/app/src/renderer/components/wallet/PageBalances.vue
@@ -14,7 +14,8 @@ page(title='Balances')
li-copy(:value="wallet.key.address")
part(title="Denomination Balances")
- data-empty(v-if="wallet.balances.length === 0")
+ data-loading(v-if="wallet.balancesLoading")
+ data-empty(v-else-if="wallet.balances.length === 0")
data-empty-search(v-else-if="filteredBalances.length === 0")
list-item(
v-for="i in filteredBalances"
@@ -37,6 +38,7 @@ page(title='Balances')
import { mapGetters } from 'vuex'
import { includes, orderBy } from 'lodash'
import Mousetrap from 'mousetrap'
+import DataLoading from 'common/NiDataLoading'
import DataEmpty from 'common/NiDataEmpty'
import DataEmptySearch from 'common/NiDataEmptySearch'
import LiCopy from 'common/NiLiCopy'
@@ -48,6 +50,7 @@ import ToolBar from 'common/NiToolBar'
export default {
name: 'page-balances',
components: {
+ DataLoading,
DataEmpty,
DataEmptySearch,
LiCopy,
diff --git a/app/src/renderer/components/wallet/PageTransactions.vue b/app/src/renderer/components/wallet/PageTransactions.vue
index 3509502208..609fd897e9 100644
--- a/app/src/renderer/components/wallet/PageTransactions.vue
+++ b/app/src/renderer/components/wallet/PageTransactions.vue
@@ -7,7 +7,8 @@ page(title='Transactions')
modal-search(type="transactions")
- data-empty-tx(v-if='transactions.length === 0')
+ data-loading(v-if="wallet.historyLoading")
+ data-empty-tx(v-else-if='transactions.length === 0')
data-empty-search(v-else-if="filteredTransactions.length === 0")
li-transaction(
v-else
@@ -23,6 +24,7 @@ import shortid from 'shortid'
import { mapGetters } from 'vuex'
import { includes, orderBy, uniqBy } from 'lodash'
import Mousetrap from 'mousetrap'
+import DataLoading from 'common/NiDataLoading'
import DataEmptySearch from 'common/NiDataEmptySearch'
import DataEmptyTx from 'common/NiDataEmptyTx'
import LiTransaction from 'wallet/LiTransaction'
@@ -34,6 +36,7 @@ export default {
name: 'page-transactions',
components: {
LiTransaction,
+ DataLoading,
DataEmptySearch,
DataEmptyTx,
ModalSearch,
diff --git a/app/src/renderer/vuex/modules/blockchain.js b/app/src/renderer/vuex/modules/blockchain.js
index 9cc05b86ec..8f24070187 100644
--- a/app/src/renderer/vuex/modules/blockchain.js
+++ b/app/src/renderer/vuex/modules/blockchain.js
@@ -9,6 +9,7 @@ export default ({ commit, node }) => {
abciInfo: {},
blocks: [],
block: {},
+ blockLoading: false,
url: ''
}
@@ -35,9 +36,11 @@ export default ({ commit, node }) => {
const actions = {
async getBlock ({ state, commit }, height) {
+ state.blockLoading = true
const blockUrl = url + '/block?height=' + height
let block = (await axios.get(blockUrl)).data.result
commit('setBlock', block)
+ state.blockLoading = false
}
}
diff --git a/app/src/renderer/vuex/modules/delegates.js b/app/src/renderer/vuex/modules/delegates.js
index 14611b1f1d..80e6fec5ff 100644
--- a/app/src/renderer/vuex/modules/delegates.js
+++ b/app/src/renderer/vuex/modules/delegates.js
@@ -1,7 +1,10 @@
import axios from 'axios'
export default ({ dispatch, node }) => {
- const state = []
+ const state = {
+ delegates: [],
+ loading: false
+ }
const mutations = {
addDelegate (state, delegate) {
@@ -9,23 +12,26 @@ export default ({ dispatch, node }) => {
Object.assign(delegate, delegate.description)
// update if we already have this delegate
- for (let existingDelegate of state) {
+ for (let existingDelegate of state.delegates) {
if (existingDelegate.id === delegate.id) {
Object.assign(existingDelegate, delegate)
return
}
}
- state.push(delegate)
+ state.delegates.push(delegate)
}
}
const actions = {
- async getDelegates ({ dispatch }) {
+ async getDelegates ({ state, dispatch }) {
+ state.loading = true
let delegatePubkeys = (await node.candidates()).data
- return Promise.all(delegatePubkeys.map(pubkey => {
+ let delegates = await Promise.all(delegatePubkeys.map(pubkey => {
return dispatch('getDelegate', pubkey)
}))
+ state.loading = false
+ return delegates
},
async getDelegate ({ commit }, pubkey) {
let delegate = (await axios.get(`http://localhost:${node.relayPort}/query/stake/candidate/${pubkey.data}`)).data.data
diff --git a/app/src/renderer/vuex/modules/proposals.js b/app/src/renderer/vuex/modules/proposals.js
index cd7e1a0b16..84c069cf64 100644
--- a/app/src/renderer/vuex/modules/proposals.js
+++ b/app/src/renderer/vuex/modules/proposals.js
@@ -1,7 +1,11 @@
import data from '../json/proposals.json'
export default ({ commit }) => {
- const state = data
+ const state = {
+ items: data,
+ loading: false
+ }
+
const mutations = {
}
return { state, mutations }
diff --git a/app/src/renderer/vuex/modules/validators.js b/app/src/renderer/vuex/modules/validators.js
index b969080903..e923596e19 100644
--- a/app/src/renderer/vuex/modules/validators.js
+++ b/app/src/renderer/vuex/modules/validators.js
@@ -1,6 +1,7 @@
-export default ({ commit, node }) => {
+export default ({ node }) => {
const state = {
validators: {},
+ loading: false,
validatorHash: null
}
@@ -14,21 +15,21 @@ export default ({ commit, node }) => {
}
const actions = {
- maybeUpdateValidators ({state, commit}, header) {
+ getValidators ({state, commit}) {
+ state.loading = true
+ node.rpc.validators((err, { validators }) => {
+ if (err) return console.error('error fetching validator set')
+ commit('setValidators', validators)
+ state.loading = false
+ })
+ },
+ maybeUpdateValidators ({state, commit, dispatch}, header) {
let validatorHash = header.validators_hash
if (validatorHash === state.validatorHash) return
commit('setValidatorHash', validatorHash)
- getValidators()
+ dispatch('getValidators')
}
}
- function getValidators () {
- node.rpc.validators((err, { validators }) => {
- if (err) return console.error('error fetching validator set')
- commit('setValidators', validators)
- })
- }
- getValidators()
-
return { state, mutations, actions }
}
diff --git a/app/src/renderer/vuex/modules/wallet.js b/app/src/renderer/vuex/modules/wallet.js
index 6a162b55a8..5dcc16dcd6 100644
--- a/app/src/renderer/vuex/modules/wallet.js
+++ b/app/src/renderer/vuex/modules/wallet.js
@@ -5,8 +5,10 @@ let root = require('../../../root.js')
export default ({ commit, node }) => {
let state = {
balances: [],
+ balancesLoading: false,
key: { address: '' },
history: [],
+ historyLoading: false,
denoms: [],
blockMetas: []
}
@@ -49,8 +51,12 @@ export default ({ commit, node }) => {
dispatch('queryWalletHistory')
},
async queryWalletBalances ({ state, rootState, commit }) {
+ state.balancesLoading = true
let res = await node.queryAccount(state.key.address)
- if (!res) return
+ if (!res) {
+ state.balancesLoading = false
+ return
+ }
commit('setWalletBalances', res.data.coins)
for (let coin of res.data.coins) {
if (coin.denom === rootState.config.bondingDenom) {
@@ -58,8 +64,10 @@ export default ({ commit, node }) => {
break
}
}
+ state.balancesLoading = false
},
async queryWalletHistory ({ state, commit, dispatch }) {
+ state.historyLoading = true
let res = await node.coinTxs(state.key.address)
if (!res) return
commit('setWalletHistory', res)
@@ -70,9 +78,10 @@ export default ({ commit, node }) => {
blockHeights.push(t.height)
}
})
- return Promise.all(blockHeights.map(h =>
+ await Promise.all(blockHeights.map(h =>
dispatch('queryTransactionTime', h)
))
+ state.historyLoading = false
},
async queryTransactionTime ({ commit, dispatch }, blockHeight) {
let blockMetaInfo = await dispatch('queryBlockInfo', blockHeight)
diff --git a/test/unit/specs/components/staking/LiDelegate.spec.js b/test/unit/specs/components/staking/LiDelegate.spec.js
index e895073323..e0a2448994 100644
--- a/test/unit/specs/components/staking/LiDelegate.spec.js
+++ b/test/unit/specs/components/staking/LiDelegate.spec.js
@@ -45,7 +45,7 @@ describe('LiDelegate', () => {
}
})
- delegate = store.state.delegates[0]
+ delegate = store.state.delegates.delegates[0]
wrapper.setData({ delegate })
})
@@ -73,12 +73,12 @@ describe('LiDelegate', () => {
expect(wrapper.html()).not.toContain('li-delegate-active')
wrapper.find('#add-to-cart').trigger('click')
expect(wrapper.vm.inCart).toBeTruthy()
- expect(store.commit).toHaveBeenCalledWith('addToCart', store.state.delegates[0])
+ expect(store.commit).toHaveBeenCalledWith('addToCart', store.state.delegates.delegates[0])
expect(wrapper.html()).toContain('li-delegate-active')
})
it('should remove from cart', () => {
- store.commit('addToCart', store.state.delegates[0])
+ store.commit('addToCart', store.state.delegates.delegates[0])
wrapper.update()
expect(wrapper.vm.inCart).toBeTruthy()
wrapper.find('#remove-from-cart').trigger('click')
diff --git a/test/unit/specs/components/staking/PageDelegates.spec.js b/test/unit/specs/components/staking/PageDelegates.spec.js
index 6b62aec089..00f5f7560a 100644
--- a/test/unit/specs/components/staking/PageDelegates.spec.js
+++ b/test/unit/specs/components/staking/PageDelegates.spec.js
@@ -75,8 +75,8 @@ describe('PageDelegates', () => {
})
it('should show the amount of selected delegates', () => {
- store.commit('addToCart', store.state.delegates[0])
- store.commit('addToCart', store.state.delegates[1])
+ store.commit('addToCart', store.state.delegates.delegates[0])
+ store.commit('addToCart', store.state.delegates.delegates[1])
wrapper.update()
expect(wrapper.find('.fixed-button-bar strong').text().trim()).toContain('2')
})
@@ -84,7 +84,10 @@ describe('PageDelegates', () => {
it('should show placeholder if delegates are loading', () => {
let {wrapper} = mount(PageDelegates, {
getters: {
- delegates: () => []
+ delegates: () => ({
+ delegates: [],
+ loading: true
+ })
},
stubs: {
'data-loading': ''
diff --git a/test/unit/specs/store/delegates.spec.js b/test/unit/specs/store/delegates.spec.js
index c41aceb6ae..77017150d8 100644
--- a/test/unit/specs/store/delegates.spec.js
+++ b/test/unit/specs/store/delegates.spec.js
@@ -15,21 +15,21 @@ describe('Module: Delegates', () => {
it('adds delegate to state', () => {
store.commit('addDelegate', { pub_key: { data: 'foo' } })
- expect(store.state.delegates[0]).toEqual({
+ expect(store.state.delegates.delegates[0]).toEqual({
id: 'foo',
pub_key: { data: 'foo' }
})
- expect(store.state.delegates.length).toBe(1)
+ expect(store.state.delegates.delegates.length).toBe(1)
})
it('replaces existing delegate with same id', () => {
store.commit('addDelegate', { pub_key: { data: 'foo' }, updated: true })
- expect(store.state.delegates[0]).toEqual({
+ expect(store.state.delegates.delegates[0]).toEqual({
id: 'foo',
pub_key: { data: 'foo' },
updated: true
})
- expect(store.state.delegates.length).toBe(1)
+ expect(store.state.delegates.delegates.length).toBe(1)
})
it('fetches a candidate', async () => {
@@ -45,7 +45,7 @@ describe('Module: Delegates', () => {
await store.dispatch('getDelegate', { data: 'foo' })
expect(axios.get.mock.calls[0][0]).toBe('http://localhost:9060/query/stake/candidate/foo')
- expect(store.state.delegates[0].test).toBe(123)
+ expect(store.state.delegates.delegates[0].test).toBe(123)
})
it('fetches all candidates', async () => {
@@ -78,7 +78,7 @@ describe('Module: Delegates', () => {
await store.dispatch('getDelegates')
expect(axios.get.mock.calls[0][0]).toBe('http://localhost:9060/query/stake/candidate/foo')
expect(axios.get.mock.calls[1][0]).toBe('http://localhost:9060/query/stake/candidate/bar')
- expect(store.state.delegates[0].test).toBe(123)
- expect(store.state.delegates[1].test).toBe(456)
+ expect(store.state.delegates.delegates[0].test).toBe(123)
+ expect(store.state.delegates.delegates[1].test).toBe(456)
})
})
diff --git a/test/unit/specs/store/wallet.spec.js b/test/unit/specs/store/wallet.spec.js
index 870edd6fe4..3e93358543 100644
--- a/test/unit/specs/store/wallet.spec.js
+++ b/test/unit/specs/store/wallet.spec.js
@@ -16,8 +16,10 @@ describe('Module: Wallet', () => {
it('should have an empty state by default', () => {
const state = {
balances: [],
+ balancesLoading: false,
key: { address: '' },
history: [],
+ historyLoading: false,
denoms: [],
blockMetas: []
}