From d3f8e6a15774134b38825b9ba41e30242c03f9fd Mon Sep 17 00:00:00 2001 From: Stamates Date: Wed, 1 Aug 2018 11:39:03 -0400 Subject: [PATCH] Live reload blocks on block list page --- apps/explorer_web/assets/js/app.js | 1 + apps/explorer_web/assets/js/pages/block.js | 60 +++++++++++++++++++ apps/explorer_web/assets/js/pages/chain.js | 4 +- .../explorer_web/channels/block_channel.ex | 11 +++- .../templates/block/_tile.html.eex | 48 +++++++++++++++ .../templates/block/index.html.eex | 55 ++--------------- .../features/viewing_blocks_test.exs | 9 +++ 7 files changed, 135 insertions(+), 53 deletions(-) create mode 100644 apps/explorer_web/assets/js/pages/block.js create mode 100644 apps/explorer_web/lib/explorer_web/templates/block/_tile.html.eex diff --git a/apps/explorer_web/assets/js/app.js b/apps/explorer_web/assets/js/app.js index 0fbcfcbd28..7066c283c9 100644 --- a/apps/explorer_web/assets/js/app.js +++ b/apps/explorer_web/assets/js/app.js @@ -26,5 +26,6 @@ import './lib/tooltip' import './lib/smart_contract/read_function' import './pages/address' +import './pages/block' import './pages/chain' import './pages/transaction' diff --git a/apps/explorer_web/assets/js/pages/block.js b/apps/explorer_web/assets/js/pages/block.js new file mode 100644 index 0000000000..2c32d9ffae --- /dev/null +++ b/apps/explorer_web/assets/js/pages/block.js @@ -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() + } + } +})) diff --git a/apps/explorer_web/assets/js/pages/chain.js b/apps/explorer_web/assets/js/pages/chain.js index dbe1873731..dbc5441fa9 100644 --- a/apps/explorer_web/assets/js/pages/chain.js +++ b/apps/explorer_web/assets/js/pages/chain.js @@ -19,7 +19,7 @@ export function reducer (state = initialState, action) { switch (action.type) { case 'RECEIVED_NEW_BLOCK': { return Object.assign({}, state, { - newBlock: humps.camelizeKeys(action.msg).homepageBlockHtml + newBlock: action.msg.homepageBlockHtml }) } case 'RECEIVED_NEW_TRANSACTION_BATCH': { @@ -46,7 +46,7 @@ router.when('', { exactPathMatch: true }).then(({ locale }) => initRedux(reducer const blocksChannel = socket.channel(`blocks:new_block`) numeral.locale(locale) 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`) transactionsChannel.join() diff --git a/apps/explorer_web/lib/explorer_web/channels/block_channel.ex b/apps/explorer_web/lib/explorer_web/channels/block_channel.ex index 3a947ed9d0..24ca952827 100644 --- a/apps/explorer_web/lib/explorer_web/channels/block_channel.ex +++ b/apps/explorer_web/lib/explorer_web/channels/block_channel.ex @@ -4,7 +4,7 @@ defmodule ExplorerWeb.BlockChannel do """ use ExplorerWeb, :channel - alias ExplorerWeb.ChainView + alias ExplorerWeb.{BlockView, ChainView} alias Phoenix.View intercept(["new_block"]) @@ -16,6 +16,14 @@ defmodule ExplorerWeb.BlockChannel do def handle_out("new_block", %{block: block}, socket) do 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 = View.render_to_string( ChainView, @@ -26,6 +34,7 @@ defmodule ExplorerWeb.BlockChannel do push(socket, "new_block", %{ homepage_block_html: rendered_homepage_block, + block_html: rendered_block, blockNumber: block.number }) diff --git a/apps/explorer_web/lib/explorer_web/templates/block/_tile.html.eex b/apps/explorer_web/lib/explorer_web/templates/block/_tile.html.eex new file mode 100644 index 0000000000..b24e9005d8 --- /dev/null +++ b/apps/explorer_web/lib/explorer_web/templates/block/_tile.html.eex @@ -0,0 +1,48 @@ +
+
+
+ + <%= link( + @block, + class: "tile-title", + to: block_path(ExplorerWeb.Endpoint, :show, @locale, @block), + "data-test": "block_number", + "data-block-number": to_string(@block.number) + ) %> +
+ + + <%= ngettext("%{count} transaction", "%{count} transactions", Enum.count(@block.transactions)) %> + + + <%= Cldr.Unit.new(:byte, @block.size) |> Cldr.Unit.to_string! %> + + +
+
+ + <%= gettext "Miner" %> + + <%= link to: address_path(ExplorerWeb.Endpoint, :show, @locale, @block.miner_hash) do %> + <%= @block.miner_hash %> + <% end %> + +
+
+
+ +
+ <%= formatted_gas(@block.gas_used) %> + (<%= formatted_gas(@block.gas_used / @block.gas_limit, format: "#.#%") %>) + <%= gettext "Gas Used" %> +
+
+
;" aria-valuenow="50" aria-valuemin="0" aria-valuemax="100"> + +
+
+ + <%= formatted_gas(@block.gas_limit) %> <%= gettext "Gas Limit" %> +
+
+
diff --git a/apps/explorer_web/lib/explorer_web/templates/block/index.html.eex b/apps/explorer_web/lib/explorer_web/templates/block/index.html.eex index 54b43bec24..49c827566c 100644 --- a/apps/explorer_web/lib/explorer_web/templates/block/index.html.eex +++ b/apps/explorer_web/lib/explorer_web/templates/block/index.html.eex @@ -11,56 +11,11 @@ ) %>

- <%= for block <- @blocks do %> -
-
-
- - <%= 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) - ) %> -
- - - <%= ngettext("%{count} transaction", "%{count} transactions", Enum.count(block.transactions)) %> - - - <%= Cldr.Unit.new(:byte, block.size) |> Cldr.Unit.to_string! %> - - -
-
- - <%= gettext "Miner" %> - - <%= link to: address_path(ExplorerWeb.Endpoint, :show, @locale, block.miner_hash) do %> - <%= block.miner_hash %> - <% end %> - -
-
-
- -
- <%= formatted_gas(block.gas_used) %> - (<%= formatted_gas(block.gas_used / block.gas_limit, format: "#.#%") %>) - <%= gettext "Gas Used" %> -
-
-
;" aria-valuenow="50" aria-valuemin="0" aria-valuemax="100"> - -
-
- - <%= formatted_gas(block.gas_limit) %> <%= gettext "Gas Limit" %> -
-
-
- <% end %> + + <%= for block <- @blocks do %> + <%= render ExplorerWeb.BlockView, "_tile.html", locale: @locale, block: block %> + <% end %> + <%= if @next_page_params do %> <%= link( diff --git a/apps/explorer_web/test/explorer_web/features/viewing_blocks_test.exs b/apps/explorer_web/test/explorer_web/features/viewing_blocks_test.exs index 9b4b9a2a3e..b56b4fc63e 100644 --- a/apps/explorer_web/test/explorer_web/features/viewing_blocks_test.exs +++ b/apps/explorer_web/test/explorer_web/features/viewing_blocks_test.exs @@ -93,4 +93,13 @@ defmodule ExplorerWeb.ViewingBlocksTest do |> BlockListPage.visit_page() |> assert_has(BlockListPage.block(block)) 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