diff --git a/app/src/renderer/components/common/AppMenu.vue b/app/src/renderer/components/common/AppMenu.vue index 8ec6f9e9c2..d77d6bbfb4 100644 --- a/app/src/renderer/components/common/AppMenu.vue +++ b/app/src/renderer/components/common/AppMenu.vue @@ -6,7 +6,7 @@ menu.app-menu list-item(to="/staking" exact @click.native="close" title="Delegates") list-item(to="/validators" exact @click.native="close" title="Validators" v-bind:class="{ 'active': isValidatorPage }") list-item(to="/proposals" exact @click.native="close" title="Proposals" v-if="config.devMode") - list-item(to="/blockchain" exact @click.native="close" title="Blocks") + list-item(to="/blocks" exact @click.native="close" title="Blocks") connectivity user-pane diff --git a/app/src/renderer/components/common/NiFormMsg.vue b/app/src/renderer/components/common/NiFormMsg.vue index 277359333a..b44c3b66ad 100644 --- a/app/src/renderer/components/common/NiFormMsg.vue +++ b/app/src/renderer/components/common/NiFormMsg.vue @@ -70,17 +70,17 @@ export default { content '' font-family 'Material Icons' padding-right 0.35rem - + .ni-form-msg.ni-form-msg--error color danger - + .ni-form-msg.ni-form-msg--error:before content 'error' color danger - + .ni-form-msg.ni-form-msg--desc color warning - + .ni-form-msg.ni-form-msg--desc:before content 'priority_high' color warning diff --git a/app/src/renderer/components/common/NiModalSearch.vue b/app/src/renderer/components/common/NiModalSearch.vue index 5ac2fceb0c..668dd9b1d0 100644 --- a/app/src/renderer/components/common/NiModalSearch.vue +++ b/app/src/renderer/components/common/NiModalSearch.vue @@ -1,21 +1,48 @@ -.ni-modal-search(v-if="open"): .ni-modal-search-container - field.mousetrap(type="text" placeholder="Search..." v-model="query") - btn(icon="close" @click.native="close") +.ni-modal-search(v-if="open") + form.ni-modal-search-container( + v-if="type === 'blocks'" + v-on:submit.prevent.default="gotoBlock") + form-group(field-id="search-input" field-label="" + :error="$v.filters.blocks.search.query.$invalid") + .ni-modal-search-field + field#search-input.mousetrap( + type="number" + step="1" + placeholder="View block height..." + v-model="query") + btn(value="Go") + btn(type="button" icon="close" @click.native="close") + form-msg(name="Query" type="numeric" + v-if="!$v.filters.blocks.search.query.numeric") + form-msg(name="Query" type="between" min="0" + :max="$v.filters.blocks.search.query.$params.between.max" + v-if="!$v.filters.blocks.search.query.between") + .ni-modal-search-container(v-else) + form-group(field-id="search-input" field-label="") + .ni-modal-search-field + field#search-input.mousetrap( + type="text" placeholder="Search..." v-model="query") + btn(icon="close" @click.native="close") diff --git a/app/src/renderer/components/monitor/PageBlocks.vue b/app/src/renderer/components/monitor/PageBlocks.vue new file mode 100644 index 0000000000..f50c5f22d4 --- /dev/null +++ b/app/src/renderer/components/monitor/PageBlocks.vue @@ -0,0 +1,90 @@ + +page(title='Block Explorer') + div(slot="menu"): tool-bar + a(@click='setSearch(true)') + i.material-icons search + .label Search + + modal-search(type="blocks") + + part(title='Current Block') + list-item(dt='Block Height' :dd='num.prettyInt(lastHeader.height)' :to="{ name: 'block', params: { block: lastHeader.height} }") + list-item(dt='Block Time' :dd='latestBlockTime') + list-item(dt='Block Hash' :dd='status.latest_block_hash') + + part(title='Latest Blocks') + list-item.column-header(dt="Block Height" dd="# of Transactions") + list-item( + v-for="block in blocks" + :key="block.header.height" + :dt="num.prettyInt(block.header.height)" + :dd="block.data.txs.length" + :to="{ name: 'block', params: { block: block.header.height} }") + + + + + diff --git a/app/src/renderer/routes.js b/app/src/renderer/routes.js index 60cd55f337..27f29d22a4 100644 --- a/app/src/renderer/routes.js +++ b/app/src/renderer/routes.js @@ -27,8 +27,8 @@ export default [ }, // MONITOR - { path: '/block/:block', name: 'block', component: monitor('Block') }, - { path: '/blockchain', name: 'blockchain', component: monitor('Blockchain') }, + { path: '/blocks', name: 'blocks', component: monitor('Blocks') }, + { path: '/blocks/:block', name: 'block', component: monitor('Block') }, { path: '/validators', name: 'validators', component: monitor('Validators') }, { path: '/validators/:validator', diff --git a/app/src/renderer/vuex/modules/blockchain.js b/app/src/renderer/vuex/modules/blockchain.js index ec2c151ffe..81f20f08bb 100644 --- a/app/src/renderer/vuex/modules/blockchain.js +++ b/app/src/renderer/vuex/modules/blockchain.js @@ -7,7 +7,8 @@ export default ({ commit, node }) => { urlSuffix: '-node0.testnets.interblock.io', status: {}, abciInfo: {}, - topAvgTxRate: 0 + topAvgTxRate: 0, + blocks: [] } const mutations = { @@ -31,13 +32,18 @@ export default ({ commit, node }) => { } } - // function getBlocks () { - // node.rpc.subscribe({ event: 'NewBlockHeader' }, (err, event) => { - // if (err) return console.error('error subscribing to new block headers', err) - // console.log(event) - // }) - // } - // getBlocks() + function subscribe () { + node.rpc.subscribe({ query: "tm.event = 'NewBlock'" }, (err, event) => { + if (err) return console.error('error subscribing to new block headers', err) + + state.blocks.unshift(event.data.data.block) + + if (state.blocks.length === 20) { + state.blocks.pop() + } + }) + } + subscribe() setTimeout(() => { mutations.getStatus(state) diff --git a/app/src/renderer/vuex/modules/filters.js b/app/src/renderer/vuex/modules/filters.js index f0e0ef383c..4caf182bc5 100644 --- a/app/src/renderer/vuex/modules/filters.js +++ b/app/src/renderer/vuex/modules/filters.js @@ -6,6 +6,12 @@ export default ({ commit }) => { query: '' } }, + blocks: { + search: { + visible: false, + query: '' + } + }, delegates: { search: { visible: false, @@ -32,6 +38,10 @@ export default ({ commit }) => { } } const mutations = { + resetSearch (state, type) { + state[type].search.visible = false + state[type].search.query = '' + }, setSearchVisible (state, [type, bool]) { state[type].search.visible = bool }, diff --git a/test/unit/specs/components/common/__snapshots__/NiModalSearch.spec.js.snap b/test/unit/specs/components/common/__snapshots__/NiModalSearch.spec.js.snap index 10e83678ab..41c20d2469 100644 --- a/test/unit/specs/components/common/__snapshots__/NiModalSearch.spec.js.snap +++ b/test/unit/specs/components/common/__snapshots__/NiModalSearch.spec.js.snap @@ -7,26 +7,41 @@ exports[`NiModalSearch has the expected html structure 1`] = `