Refresh staking page top panel when new blocks arrive (#2407)
Top panel is entirely rendered on server-side using a dedicated controller function for proper gettext support and reduced fiddling with jQuery. Reducer is simplified and made pure as per Redux guidelines. Co-Authored-By: Anatoly Nikiforov <anatolyniky@gmail.com> Co-Authored-By: Kirill Andreev <hindmost.one@gmail.com>staking
parent
26715dcf00
commit
c64f77fe94
@ -1 +1,42 @@ |
||||
import '../../css/stakes.scss' |
||||
|
||||
import $ from 'jquery' |
||||
import _ from 'lodash' |
||||
import { subscribeChannel } from '../socket' |
||||
import { connectElements } from '../lib/redux_helpers.js' |
||||
import { createAsyncLoadStore } from '../lib/async_listing_load' |
||||
|
||||
export const initialState = { |
||||
channel: null |
||||
} |
||||
|
||||
export function reducer (state = initialState, action) { |
||||
switch (action.type) { |
||||
case 'PAGE_LOAD': |
||||
case 'ELEMENTS_LOAD': { |
||||
return Object.assign({}, state, _.omit(action, 'type')) |
||||
} |
||||
case 'CHANNEL_CONNECTED': { |
||||
return Object.assign({}, state, { channel: action.channel }) |
||||
} |
||||
default: |
||||
return state |
||||
} |
||||
} |
||||
|
||||
const elements = { |
||||
} |
||||
|
||||
const $stakesPage = $('[data-page="stakes"]') |
||||
if ($stakesPage.length) { |
||||
const store = createAsyncLoadStore(reducer, initialState, 'dataset.identifierPool') |
||||
connectElements({ store, elements }) |
||||
|
||||
const channel = subscribeChannel('stakes:staking_update') |
||||
channel.on('staking_update', msg => onStakingUpdate(msg, store)) |
||||
store.dispatch({ type: 'CHANNEL_CONNECTED', channel }) |
||||
} |
||||
|
||||
function onStakingUpdate (msg, store) { |
||||
$('[data-selector="stakes-top"]').html(msg.top_html) |
||||
} |
||||
|
@ -0,0 +1,22 @@ |
||||
defmodule BlockScoutWeb.StakesChannel do |
||||
@moduledoc """ |
||||
Establishes pub/sub channel for staking page live updates. |
||||
""" |
||||
use BlockScoutWeb, :channel |
||||
|
||||
alias BlockScoutWeb.StakesController |
||||
|
||||
intercept(["staking_update"]) |
||||
|
||||
def join("stakes:staking_update", _params, socket) do |
||||
{:ok, %{}, socket} |
||||
end |
||||
|
||||
def handle_out("staking_update", _data, socket) do |
||||
push(socket, "staking_update", %{ |
||||
top_html: StakesController.render_top() |
||||
}) |
||||
|
||||
{:noreply, socket} |
||||
end |
||||
end |
@ -0,0 +1,4 @@ |
||||
<div class="stakes-top-stats-item"> |
||||
<span class="stakes-top-stats-label"><%= @title %></span> |
||||
<span class="stakes-top-stats-value"><%= @value %></span> |
||||
</div> |
@ -0,0 +1,13 @@ |
||||
<div class="stakes-top"> |
||||
<div class="container"> |
||||
<div class="stakes-top-stats"> |
||||
<%= render BlockScoutWeb.StakesView, "_stakes_stats_item.html", title: gettext("Epoch number"), value: @epoch_number %> |
||||
<%= render BlockScoutWeb.StakesView, "_stakes_stats_item.html", title: gettext("Block number"), value: @block_number %> |
||||
<%= render BlockScoutWeb.StakesView, "_stakes_stats_item.html", title: gettext("Next epoch in"), value: ngettext("%{blocks} block", "%{blocks} blocks", @epoch_end_in, blocks: @epoch_end_in) %> |
||||
<!-- Buttons --> |
||||
<div class="stakes-top-buttons"> |
||||
</div> |
||||
</div> |
||||
</div> |
||||
</div> |
||||
<%= render BlockScoutWeb.StakesView, "_stakes_modal_become_candidate.html" %> |
@ -0,0 +1,20 @@ |
||||
defmodule BlockScoutWeb.StakesChannelTest do |
||||
use BlockScoutWeb.ChannelCase |
||||
|
||||
alias BlockScoutWeb.Notifier |
||||
|
||||
test "subscribed user is notified of staking_update event" do |
||||
topic = "stakes:staking_update" |
||||
@endpoint.subscribe(topic) |
||||
|
||||
Notifier.handle_event({:chain_event, :staking_update}) |
||||
|
||||
receive do |
||||
%Phoenix.Socket.Broadcast{topic: ^topic, event: "staking_update", payload: %{epoch_number: _}} -> |
||||
assert true |
||||
after |
||||
:timer.seconds(5) -> |
||||
assert false, "Expected message received nothing." |
||||
end |
||||
end |
||||
end |
Loading…
Reference in new issue