diff --git a/apps/block_scout_web/assets/css/components/_stakes_table.scss b/apps/block_scout_web/assets/css/components/_stakes_table.scss index ded5ae30f0..a39da533e5 100644 --- a/apps/block_scout_web/assets/css/components/_stakes_table.scss +++ b/apps/block_scout_web/assets/css/components/_stakes_table.scss @@ -86,6 +86,13 @@ $stakes-link-color: $primary !default; padding: 0 15px; min-width: 930px; min-height: 311px; + + .refresh-informer { + text-align: right; + padding-top: 15px; + padding-right: 15px; + display: none; + } } .stakes-table-th { diff --git a/apps/block_scout_web/assets/js/pages/stakes.js b/apps/block_scout_web/assets/js/pages/stakes.js index ef0b8fdf96..5e277bce8f 100644 --- a/apps/block_scout_web/assets/js/pages/stakes.js +++ b/apps/block_scout_web/assets/js/pages/stakes.js @@ -16,6 +16,8 @@ import { openWithdrawStakeModal } from './stakes/withdraw_stake' import { openClaimWithdrawalModal } from './stakes/claim_withdrawal' import { openWarningModal } from '../lib/modals' +const stakesPageSelector = '[data-page="stakes"]' + export const initialState = { account: null, blockRewardContract: null, @@ -87,11 +89,26 @@ export function reducer (state = initialState, action) { tokenSymbol: action.tokenSymbol }) } + case 'FINISH_REQUEST': { + $(stakesPageSelector).fadeTo(0, 1) + return state + } default: return state } } +function reloadPoolList(msg, store) { + store.dispatch({ + type: 'RECEIVED_UPDATE', + lastBlockNumber: msg.block_number, + lastEpochNumber: msg.epoch_number, + stakingAllowed: msg.staking_allowed, + validatorSetApplyBlock: msg.validator_set_apply_block + }) + refreshPage(store) +} + const elements = { '[data-page="stakes"]': { load ($el) { @@ -106,7 +123,7 @@ const elements = { } } -const $stakesPage = $('[data-page="stakes"]') +const $stakesPage = $(stakesPageSelector) const $stakesTop = $('[data-selector="stakes-top"]') if ($stakesPage.length) { const store = createAsyncLoadStore(reducer, initialState, 'dataset.identifierPool') @@ -115,6 +132,8 @@ if ($stakesPage.length) { const channel = subscribeChannel('stakes:staking_update') store.dispatch({ type: 'CHANNEL_CONNECTED', channel }) + const $refreshInformer = $('.refresh-informer', $stakesPage) + channel.on('staking_update', msg => { // hide tooltip on tooltip triggering element reloading // due to issues with bootstrap tooltips https://github.com/twbs/bootstrap/issues/13133 @@ -129,21 +148,34 @@ if ($stakesPage.length) { $stakesPage.find('[pool-filter-my]').prop('checked', false); } + let lastBlockNumber = state.lastBlockNumber + if ( msg.staking_allowed !== state.stakingAllowed || msg.epoch_number > state.lastEpochNumber || msg.validator_set_apply_block != state.validatorSetApplyBlock || (state.refreshInterval && msg.block_number >= state.lastBlockNumber + state.refreshInterval) ) { - store.dispatch({ - type: 'RECEIVED_UPDATE', - lastBlockNumber: msg.block_number, - lastEpochNumber: msg.epoch_number, - stakingAllowed: msg.staking_allowed, - validatorSetApplyBlock: msg.validator_set_apply_block - }) - refreshPage(store) + reloadPoolList(msg, store) + lastBlockNumber = msg.block_number } + + const refreshGap = msg.block_number - lastBlockNumber + $refreshInformer.find('span').html(refreshGap) + if (refreshGap > 0) { + $refreshInformer.show() + } else { + $refreshInformer.hide() + } + + const $refreshInformerLink = $refreshInformer.find('a') + $refreshInformerLink.off('click') + $refreshInformerLink.on('click', (event) => { + event.preventDefault() + $refreshInformer.hide() + $stakesPage.fadeTo(0, 0.5) + reloadPoolList(msg, store) + }) }) channel.on('contracts', msg => { diff --git a/apps/block_scout_web/config/config.exs b/apps/block_scout_web/config/config.exs index a034c8312c..575bec2610 100644 --- a/apps/block_scout_web/config/config.exs +++ b/apps/block_scout_web/config/config.exs @@ -24,7 +24,7 @@ config :block_scout_web, BlockScoutWeb.Chain, logo_text: System.get_env("LOGO_TEXT"), has_emission_funds: false, staking_enabled: not is_nil(System.get_env("POS_STAKING_CONTRACT")), - staking_table_refresh_interval: 10 + staking_pool_list_refresh_interval: 5 # how often (in blocks) the list of pools should autorefresh in UI (zero turns off autorefreshing) config :block_scout_web, link_to_other_explorers: System.get_env("LINK_TO_OTHER_EXPLORERS") == "true", diff --git a/apps/block_scout_web/lib/block_scout_web/controllers/stakes_controller.ex b/apps/block_scout_web/lib/block_scout_web/controllers/stakes_controller.ex index db018663d7..59131fec9f 100644 --- a/apps/block_scout_web/lib/block_scout_web/controllers/stakes_controller.ex +++ b/apps/block_scout_web/lib/block_scout_web/controllers/stakes_controller.ex @@ -127,7 +127,7 @@ defmodule BlockScoutWeb.StakesController do pools_type: filter, current_path: current_path(conn), average_block_time: AverageBlockTime.average_block_time(), - refresh_interval: Application.get_env(:block_scout_web, BlockScoutWeb.Chain)[:staking_table_refresh_interval] + refresh_interval: Application.get_env(:block_scout_web, BlockScoutWeb.Chain)[:staking_pool_list_refresh_interval] ) end diff --git a/apps/block_scout_web/lib/block_scout_web/templates/stakes/_table.html.eex b/apps/block_scout_web/lib/block_scout_web/templates/stakes/_table.html.eex index 7149d8c842..82bb92882a 100644 --- a/apps/block_scout_web/lib/block_scout_web/templates/stakes/_table.html.eex +++ b/apps/block_scout_web/lib/block_scout_web/templates/stakes/_table.html.eex @@ -29,5 +29,7 @@
+ +
<%= raw gettext("The table refreshed block(s) ago.") %> <%= gettext("Refresh now") %>