Live reload blocks on block list page

pull/497/head
Stamates 6 years ago committed by jimmay5469
parent f7852e7eb7
commit d3f8e6a157
  1. 1
      apps/explorer_web/assets/js/app.js
  2. 60
      apps/explorer_web/assets/js/pages/block.js
  3. 4
      apps/explorer_web/assets/js/pages/chain.js
  4. 11
      apps/explorer_web/lib/explorer_web/channels/block_channel.ex
  5. 48
      apps/explorer_web/lib/explorer_web/templates/block/_tile.html.eex
  6. 55
      apps/explorer_web/lib/explorer_web/templates/block/index.html.eex
  7. 9
      apps/explorer_web/test/explorer_web/features/viewing_blocks_test.exs

@ -26,5 +26,6 @@ import './lib/tooltip'
import './lib/smart_contract/read_function' import './lib/smart_contract/read_function'
import './pages/address' import './pages/address'
import './pages/block'
import './pages/chain' import './pages/chain'
import './pages/transaction' import './pages/transaction'

@ -0,0 +1,60 @@
import $ from 'jquery'
import humps from 'humps'
import socket from '../socket'
import router from '../router'
import { updateAllAges } from '../lib/from_now'
import { initRedux } from '../utils'
export const initialState = {
beyondPageOne: null,
channelDisconnected: false,
newBlock: null
}
export function reducer (state = initialState, action) {
switch (action.type) {
case 'PAGE_LOAD': {
return Object.assign({}, state, {
beyondPageOne: !!action.blockNumber
})
}
case 'CHANNEL_DISCONNECTED': {
if (state.beyondPageOne) return state
return Object.assign({}, state, {
channelDisconnected: true
})
}
case 'RECEIVED_NEW_BLOCK': {
if (state.channelDisconnected || state.beyondPageOne) return state
return Object.assign({}, state, {
newBlock: action.msg.blockHtml
})
}
default:
return state
}
}
router.when('/blocks', { exactPathMatch: true }).then(({ blockNumber }) => initRedux(reducer, {
main (store) {
const blocksChannel = socket.channel(`blocks:new_block`, {})
store.dispatch({ type: 'PAGE_LOAD', blockNumber })
blocksChannel.join()
blocksChannel.onError(() => store.dispatch({ type: 'CHANNEL_DISCONNECTED' }))
blocksChannel.on('new_block', (msg) =>
store.dispatch({ type: 'RECEIVED_NEW_BLOCK', msg: humps.camelizeKeys(msg) })
)
},
render (state, oldState) {
const $channelDisconnected = $('[data-selector="channel-disconnected-message"]')
const $blocksList = $('[data-selector="blocks-list"]')
if (state.channelDisconnected) $channelDisconnected.show()
if (oldState.newBlock !== state.newBlock) {
$blocksList.prepend(state.newBlock)
updateAllAges()
}
}
}))

@ -19,7 +19,7 @@ export function reducer (state = initialState, action) {
switch (action.type) { switch (action.type) {
case 'RECEIVED_NEW_BLOCK': { case 'RECEIVED_NEW_BLOCK': {
return Object.assign({}, state, { return Object.assign({}, state, {
newBlock: humps.camelizeKeys(action.msg).homepageBlockHtml newBlock: action.msg.homepageBlockHtml
}) })
} }
case 'RECEIVED_NEW_TRANSACTION_BATCH': { case 'RECEIVED_NEW_TRANSACTION_BATCH': {
@ -46,7 +46,7 @@ router.when('', { exactPathMatch: true }).then(({ locale }) => initRedux(reducer
const blocksChannel = socket.channel(`blocks:new_block`) const blocksChannel = socket.channel(`blocks:new_block`)
numeral.locale(locale) numeral.locale(locale)
blocksChannel.join() blocksChannel.join()
blocksChannel.on('new_block', msg => store.dispatch({ type: 'RECEIVED_NEW_BLOCK', msg })) blocksChannel.on('new_block', msg => store.dispatch({ type: 'RECEIVED_NEW_BLOCK', msg: humps.camelizeKeys(msg) }))
const transactionsChannel = socket.channel(`transactions:new_transaction`) const transactionsChannel = socket.channel(`transactions:new_transaction`)
transactionsChannel.join() transactionsChannel.join()

@ -4,7 +4,7 @@ defmodule ExplorerWeb.BlockChannel do
""" """
use ExplorerWeb, :channel use ExplorerWeb, :channel
alias ExplorerWeb.ChainView alias ExplorerWeb.{BlockView, ChainView}
alias Phoenix.View alias Phoenix.View
intercept(["new_block"]) intercept(["new_block"])
@ -16,6 +16,14 @@ defmodule ExplorerWeb.BlockChannel do
def handle_out("new_block", %{block: block}, socket) do def handle_out("new_block", %{block: block}, socket) do
Gettext.put_locale(ExplorerWeb.Gettext, socket.assigns.locale) Gettext.put_locale(ExplorerWeb.Gettext, socket.assigns.locale)
rendered_block =
View.render_to_string(
BlockView,
"_tile.html",
locale: socket.assigns.locale,
block: block
)
rendered_homepage_block = rendered_homepage_block =
View.render_to_string( View.render_to_string(
ChainView, ChainView,
@ -26,6 +34,7 @@ defmodule ExplorerWeb.BlockChannel do
push(socket, "new_block", %{ push(socket, "new_block", %{
homepage_block_html: rendered_homepage_block, homepage_block_html: rendered_homepage_block,
block_html: rendered_block,
blockNumber: block.number blockNumber: block.number
}) })

@ -0,0 +1,48 @@
<div class="tile">
<div class="row">
<div class="col-md-6">
<!-- block height -->
<%= link(
@block,
class: "tile-title",
to: block_path(ExplorerWeb.Endpoint, :show, @locale, @block),
"data-test": "block_number",
"data-block-number": to_string(@block.number)
) %>
<div>
<!-- transactions -->
<span class="mr-2">
<%= ngettext("%{count} transaction", "%{count} transactions", Enum.count(@block.transactions)) %>
</span>
<!-- size -->
<span class="mr-2"> <%= Cldr.Unit.new(:byte, @block.size) |> Cldr.Unit.to_string! %> </span>
<!-- age -->
<span data-from-now="<%= @block.timestamp %>"></span>
</div>
<div class="">
<!-- validator -->
<%= gettext "Miner" %>
<span class="ml-2">
<%= link to: address_path(ExplorerWeb.Endpoint, :show, @locale, @block.miner_hash) do %>
<%= @block.miner_hash %>
<% end %>
</span>
</div>
</div>
<div class="col-md-6 text-right d-flex flex-column align-items-end justify-content-end">
<!-- Gas Used -->
<div class="">
<%= formatted_gas(@block.gas_used) %>
(<%= formatted_gas(@block.gas_used / @block.gas_limit, format: "#.#%") %>)
<%= gettext "Gas Used" %>
</div>
<div class="progress w-25">
<div class="progress-bar" role="progressbar" style="width: <%= formatted_gas(@block.gas_used / @block.gas_limit, format: "#.#%") %>;" aria-valuenow="50" aria-valuemin="0" aria-valuemax="100">
</div>
</div>
<!-- Gas Limit -->
<span> <%= formatted_gas(@block.gas_limit) %> <%= gettext "Gas Limit" %> </span>
</div>
</div>
</div>

@ -11,56 +11,11 @@
) %> ) %>
</p> </p>
<%= for block <- @blocks do %> <span data-selector="blocks-list">
<div class="tile"> <%= for block <- @blocks do %>
<div class="row"> <%= render ExplorerWeb.BlockView, "_tile.html", locale: @locale, block: block %>
<div class="col-md-6"> <% end %>
<!-- block height --> </span>
<%= link(
block,
class: "tile-title",
to: block_path(@conn, :show, @conn.assigns.locale, block),
"data-test": "block_number",
"data-block-number": to_string(block.number)
) %>
<div>
<!-- transactions -->
<span class="mr-2">
<%= ngettext("%{count} transaction", "%{count} transactions", Enum.count(block.transactions)) %>
</span>
<!-- size -->
<span class="mr-2"> <%= Cldr.Unit.new(:byte, block.size) |> Cldr.Unit.to_string! %> </span>
<!-- age -->
<span data-from-now="<%= block.timestamp %>"></span>
</div>
<div class="">
<!-- validator -->
<%= gettext "Miner" %>
<span class="ml-2">
<%= link to: address_path(ExplorerWeb.Endpoint, :show, @locale, block.miner_hash) do %>
<%= block.miner_hash %>
<% end %>
</span>
</div>
</div>
<div class="col-md-6 text-right d-flex flex-column align-items-end justify-content-end">
<!-- Gas Used -->
<div class="">
<%= formatted_gas(block.gas_used) %>
(<%= formatted_gas(block.gas_used / block.gas_limit, format: "#.#%") %>)
<%= gettext "Gas Used" %>
</div>
<div class="progress w-25">
<div class="progress-bar" role="progressbar" style="width: <%= formatted_gas(block.gas_used / block.gas_limit, format: "#.#%") %>;" aria-valuenow="50" aria-valuemin="0" aria-valuemax="100">
</div>
</div>
<!-- Gas Limit -->
<span> <%= formatted_gas(block.gas_limit) %> <%= gettext "Gas Limit" %> </span>
</div>
</div>
</div>
<% end %>
<%= if @next_page_params do %> <%= if @next_page_params do %>
<%= link( <%= link(

@ -93,4 +93,13 @@ defmodule ExplorerWeb.ViewingBlocksTest do
|> BlockListPage.visit_page() |> BlockListPage.visit_page()
|> assert_has(BlockListPage.block(block)) |> assert_has(BlockListPage.block(block))
end end
test "viewing new blocks via live update on list page", %{session: session} do
BlockListPage.visit_page(session)
block = insert(:block, number: 42)
Notifier.handle_event({:chain_event, :blocks, [block]})
assert_has(session, BlockListPage.block(block))
end
end end

Loading…
Cancel
Save