Add live update to block confirmations on transaction page

Refactor to use redux
pull/364/head
Stamates 7 years ago
parent 569a1cc59f
commit 17f5c9a742
  1. 14
      apps/explorer_web/assets/__tests__/pages/transaction.js
  2. 1
      apps/explorer_web/assets/js/app.js
  3. 38
      apps/explorer_web/assets/js/pages/transaction.js
  4. 32
      apps/explorer_web/lib/explorer_web/channels/transaction_channel.ex
  5. 1
      apps/explorer_web/lib/explorer_web/channels/user_socket.ex
  6. 1
      apps/explorer_web/lib/explorer_web/templates/transaction/_confirmations.html.eex
  7. 4
      apps/explorer_web/lib/explorer_web/templates/transaction/overview.html.eex
  8. 31
      apps/explorer_web/test/explorer_web/channels/transaction_channel_test.exs
  9. 4
      apps/explorer_web/test/explorer_web/features/pages/transaction_page.ex
  10. 12
      apps/explorer_web/test/explorer_web/features/viewing_transactions_test.exs

@ -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)
})

@ -25,3 +25,4 @@ import './lib/reload_button'
import './lib/tooltip'
import './pages/address'
import './pages/transaction'

@ -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())
}
}
}))

@ -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

@ -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

@ -0,0 +1 @@
(<%= gettext "%{confirmations} block confirmations", confirmations: confirmations(@transaction, max_block_number: @max_block_number) %>)

@ -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) %>)
<span data-selector="block_confirmations">
<%= render "_confirmations.html", max_block_number: @max_block_number, transaction: @transaction %>
</span>
</td>
</tr>
<tr>

@ -0,0 +1,31 @@
defmodule ExplorerWeb.AddressTransactionTest do
use ExplorerWeb.ChannelCase
describe "transactions channel tests" do
test "subscribed user can receive block confirmations event" do
channel = "transactions"
@endpoint.subscribe(channel)
block = insert(:block, number: 1)
transaction =
:transaction
|> insert()
|> with_block(block)
ExplorerWeb.Endpoint.broadcast(channel, "confirmations", %{max_block_number: 3, transaction: transaction})
receive do
%Phoenix.Socket.Broadcast{
event: "confirmations",
topic: ^channel,
payload: %{max_block_number: 3, transaction: ^transaction}
} ->
assert true
after
5_000 ->
assert false, "Expected message received nothing."
end
end
end
end

@ -7,6 +7,10 @@ defmodule ExplorerWeb.TransactionPage do
alias Explorer.Chain.{InternalTransaction, Transaction, Hash}
def block_confirmations() do
css("[data-selector='block_confirmations']")
end
def click_logs(session) do
click(session, css("[data-test='transaction_logs_link']"))
end

@ -160,5 +160,17 @@ defmodule ExplorerWeb.ViewingTransactionsTest do
|> TransactionLogsPage.click_address(lincoln)
|> assert_has(AddressPage.detail_hash(lincoln))
end
test "block confirmations via live update", %{session: session, transaction: transaction} do
session
|> TransactionPage.visit_page(transaction)
ExplorerWeb.Endpoint.broadcast!("transactions:#{transaction.hash}", "confirmations", %{
max_block_number: transaction.block_number + 3,
transaction: transaction
})
assert_text(session, TransactionPage.block_confirmations(), "(3 block confirmations)")
end
end
end

Loading…
Cancel
Save