diff --git a/apps/explorer_web/assets/__tests__/pages/transaction.js b/apps/explorer_web/assets/__tests__/pages/transaction.js new file mode 100644 index 0000000000..ee4cf72e33 --- /dev/null +++ b/apps/explorer_web/assets/__tests__/pages/transaction.js @@ -0,0 +1,14 @@ +import { reducer, initialState } from '../../js/pages/transaction' + +test('RECEIVED_UPDATED_CONFIRMATIONS', () => { + const state = initialState + const action = { + type: 'RECEIVED_UPDATED_CONFIRMATIONS', + msg: { + confirmations: 5 + } + } + const output = reducer(state, action) + + expect(output.confirmations).toBe(5) +}) diff --git a/apps/explorer_web/assets/js/app.js b/apps/explorer_web/assets/js/app.js index 70766708c7..5b071039f0 100644 --- a/apps/explorer_web/assets/js/app.js +++ b/apps/explorer_web/assets/js/app.js @@ -25,3 +25,4 @@ import './lib/reload_button' import './lib/tooltip' import './pages/address' +import './pages/transaction' diff --git a/apps/explorer_web/assets/js/pages/transaction.js b/apps/explorer_web/assets/js/pages/transaction.js new file mode 100644 index 0000000000..79cafefc6c --- /dev/null +++ b/apps/explorer_web/assets/js/pages/transaction.js @@ -0,0 +1,38 @@ +import $ from 'jquery' +import numeral from 'numeral' +import 'numeral/locales' +import socket from '../socket' +import router from '../router' +import { initRedux } from '../utils' + +export const initialState = {confirmations: null} + +export function reducer (state = initialState, action) { + switch (action.type) { + case 'RECEIVED_UPDATED_CONFIRMATIONS': { + return Object.assign({}, state, { + confirmations: action.msg.confirmations + }) + } + default: + return state + } +} + +router.when('/transactions/:transactionHash').then((params) => initRedux(reducer, { + main (store) { + const { transactionHash, locale } = params + const channel = socket.channel(`transactions:${transactionHash}`, {}) + numeral.locale(locale) + channel.join() + .receive('ok', resp => { console.log('Joined successfully', `transactions:${transactionHash}`, resp) }) + .receive('error', resp => { console.log('Unable to join', `transactions:${transactionHash}`, resp) }) + channel.on('confirmations', (msg) => store.dispatch({ type: 'RECEIVED_UPDATED_CONFIRMATIONS', msg })) + }, + render (state, oldState) { + const $blockConfirmations = $('[data-selector="block_confirmations"]') + if (oldState.confirmations !== state.confirmations) { + $blockConfirmations.empty().append(numeral(msg.confirmations).format()) + } + } +})) diff --git a/apps/explorer_web/lib/explorer_web/channels/transaction_channel.ex b/apps/explorer_web/lib/explorer_web/channels/transaction_channel.ex new file mode 100644 index 0000000000..b382d86c3d --- /dev/null +++ b/apps/explorer_web/lib/explorer_web/channels/transaction_channel.ex @@ -0,0 +1,32 @@ +defmodule ExplorerWeb.TransactionChannel do + @moduledoc """ + Establishes pub/sub channel for transaction page live updates. + """ + use ExplorerWeb, :channel + + alias ExplorerWeb.TransactionView + alias Phoenix.View + + intercept(["confirmations"]) + + def join("transactions:" <> _transaction_hash, _params, socket) do + {:ok, %{}, socket} + end + + def handle_out("confirmations", %{max_block_number: max_block_number, transaction: transaction}, socket) do + Gettext.put_locale(ExplorerWeb.Gettext, socket.assigns.locale) + + rendered = + View.render_to_string( + TransactionView, + "_confirmations.html", + locale: socket.assigns.locale, + max_block_number: max_block_number, + transaction: transaction + ) + + push(socket, "confirmations", %{confirmations: rendered}) + + {:noreply, socket} + end +end diff --git a/apps/explorer_web/lib/explorer_web/channels/user_socket.ex b/apps/explorer_web/lib/explorer_web/channels/user_socket.ex index 1c76a2124c..68a13fbd38 100644 --- a/apps/explorer_web/lib/explorer_web/channels/user_socket.ex +++ b/apps/explorer_web/lib/explorer_web/channels/user_socket.ex @@ -2,6 +2,7 @@ defmodule ExplorerWeb.UserSocket do use Phoenix.Socket channel("addresses:*", ExplorerWeb.AddressChannel) + channel("transactions:*", ExplorerWeb.TransactionChannel) transport(:websocket, Phoenix.Transports.WebSocket, timeout: 45_000) # transport :longpoll, Phoenix.Transports.LongPoll diff --git a/apps/explorer_web/lib/explorer_web/templates/transaction/_confirmations.html.eex b/apps/explorer_web/lib/explorer_web/templates/transaction/_confirmations.html.eex new file mode 100644 index 0000000000..bb2e6d779f --- /dev/null +++ b/apps/explorer_web/lib/explorer_web/templates/transaction/_confirmations.html.eex @@ -0,0 +1 @@ +(<%= gettext "%{confirmations} block confirmations", confirmations: confirmations(@transaction, max_block_number: @max_block_number) %>) diff --git a/apps/explorer_web/lib/explorer_web/templates/transaction/overview.html.eex b/apps/explorer_web/lib/explorer_web/templates/transaction/overview.html.eex index 3005f7a1f8..7e6d4dffdb 100644 --- a/apps/explorer_web/lib/explorer_web/templates/transaction/overview.html.eex +++ b/apps/explorer_web/lib/explorer_web/templates/transaction/overview.html.eex @@ -41,7 +41,9 @@ to: block_path(@conn, :show, @conn.assigns.locale, block) ) %> <% end %> - (<%= gettext "%{confirmations} block confirmations", confirmations: confirmations(@transaction, max_block_number: @max_block_number) %>) + + <%= render "_confirmations.html", max_block_number: @max_block_number, transaction: @transaction %> +