Refresh list of pools on account change and show correct buttons (#2455)

AsyncLoadStore is improved to allow sending additional dynamic data from
redux state, as well as refreshing currently displayed page.

This allows to show table rows specifically for currently logged-in account
with properly selected row buttons.
staking
goodsoft 5 years ago committed by Victor Baranov
parent cbb79679e0
commit 3b7e04c4b8
  1. 24
      apps/block_scout_web/assets/js/lib/async_listing_load.js
  2. 9
      apps/block_scout_web/assets/js/pages/stakes.js
  3. 26
      apps/block_scout_web/lib/block_scout_web/controllers/stakes_controller.ex
  4. 44
      apps/explorer/lib/explorer/chain.ex
  5. 6
      apps/explorer/test/explorer/chain_test.exs

@ -42,6 +42,8 @@ import '../app'
export const asyncInitialState = {
/* it will consider any query param in the current URI as paging */
beyondPageOne: (URI(window.location).query() !== ''),
/* will be sent along with { type: 'JSON' } to controller, useful for dynamically changing parameters */
additionalParams: {},
/* an array with every html element of the list being shown */
items: [],
/* the key for diffing the elements in the items array */
@ -52,6 +54,8 @@ export const asyncInitialState = {
requestError: false,
/* if response has no items */
emptyResponse: false,
/* link to the current page */
currentPagePath: null,
/* link to the next page */
nextPagePath: null,
/* link to the previous page */
@ -63,7 +67,10 @@ export const asyncInitialState = {
export function asyncReducer (state = asyncInitialState, action) {
switch (action.type) {
case 'ELEMENTS_LOAD': {
return Object.assign({}, state, { nextPagePath: action.nextPagePath })
return Object.assign({}, state, {
nextPagePath: action.nextPagePath,
currentPagePath: action.nextPagePath
})
}
case 'ADD_ITEM_KEY': {
return Object.assign({}, state, { itemKey: action.itemKey })
@ -71,7 +78,8 @@ export function asyncReducer (state = asyncInitialState, action) {
case 'START_REQUEST': {
return Object.assign({}, state, {
loading: true,
requestError: false
requestError: false,
currentPagePath: action.path
})
}
case 'REQUEST_ERROR': {
@ -277,6 +285,18 @@ export function createAsyncLoadStore (reducer, initialState, itemKey) {
return store
}
export function refreshPage (store) {
loadPage(store, store.getState().currentPagePath)
}
function loadPage (store, path) {
store.dispatch({type: 'START_REQUEST', path})
$.getJSON(path, merge({type: 'JSON'}, store.getState().additionalParams))
.done(response => store.dispatch(Object.assign({type: 'ITEMS_FETCHED'}, humps.camelizeKeys(response))))
.fail(() => store.dispatch({type: 'REQUEST_ERROR'}))
.always(() => store.dispatch({type: 'FINISH_REQUEST'}))
}
function firstPageLoad (store) {
const $element = $('[data-async-listing]')
function loadItemsNext () {

@ -4,7 +4,7 @@ import $ from 'jquery'
import _ from 'lodash'
import { subscribeChannel } from '../socket'
import { connectElements } from '../lib/redux_helpers.js'
import { createAsyncLoadStore } from '../lib/async_listing_load'
import { createAsyncLoadStore, refreshPage } from '../lib/async_listing_load'
import Web3 from 'web3'
export const initialState = {
@ -26,7 +26,11 @@ export function reducer (state = initialState, action) {
return Object.assign({}, state, { web3: action.web3 })
}
case 'ACCOUNT_UPDATED': {
return Object.assign({}, state, { account: action.account })
return Object.assign({}, state, {
account: action.account,
additionalParams: { account: action.account }
})
}
}
default:
return state
@ -75,6 +79,7 @@ function initializeWeb3 (store) {
function setAccount (account, store) {
store.dispatch({ type: 'ACCOUNT_UPDATED', account })
store.getState().channel.push('set_account', account)
refreshPage(store)
}
async function loginByMetamask (event) {

@ -48,7 +48,7 @@ defmodule BlockScoutWeb.StakesController do
|> Map.get("position", "0")
|> String.to_integer()
pools_plus_one = Chain.staking_pools(filter, options)
pools_plus_one = Chain.staking_pools(filter, options, params["account"])
{pools, next_page} = split_list_by_page(pools_plus_one)
@ -68,11 +68,12 @@ defmodule BlockScoutWeb.StakesController do
average_block_time = AverageBlockTime.average_block_time()
token = ContractState.get(:token, %Token{})
epoch_number = ContractState.get(:epoch_number, 0)
items =
pools
|> Enum.with_index(last_index + 1)
|> Enum.map(fn {pool, index} ->
|> Enum.map(fn {%{pool: pool, delegator: delegator}, index} ->
View.render_to_string(
StakesView,
"_rows.html",
@ -80,7 +81,12 @@ defmodule BlockScoutWeb.StakesController do
pool: pool,
index: index,
average_block_time: average_block_time,
pools_type: filter
pools_type: filter,
buttons: %{
stake: true,
move: move_allowed?(delegator),
withdraw: withdraw_allowed?(delegator, epoch_number)
}
)
end)
@ -113,4 +119,18 @@ defmodule BlockScoutWeb.StakesController do
defp next_page_path(:inactive, conn, params) do
inactive_pools_path(conn, :index, params)
end
defp move_allowed?(nil), do: false
defp move_allowed?(delegator) do
delegator.is_active and Decimal.positive?(delegator.max_withdraw_allowed)
end
defp withdraw_allowed?(nil, _epoch_number), do: false
defp withdraw_allowed?(delegator, epoch_number) do
(delegator.is_active and Decimal.positive?(delegator.max_withdraw_allowed)) or
(delegator.is_active and Decimal.positive?(delegator.max_ordered_withdraw_allowed)) or
(Decimal.positive?(delegator.ordered_withdraw) and delegator.ordered_withdraw_epoch < epoch_number)
end
end

@ -7,12 +7,14 @@ defmodule Explorer.Chain do
only: [
from: 2,
join: 4,
join: 5,
limit: 2,
lock: 2,
order_by: 2,
order_by: 3,
preload: 2,
select: 2,
select: 3,
subquery: 1,
union: 2,
union_all: 2,
@ -4721,34 +4723,50 @@ defmodule Explorer.Chain do
end
@doc "Get staking pools from the DB"
@spec staking_pools(filter :: :validator | :active | :inactive, options :: PagingOptions.t()) :: [map()]
def staking_pools(filter, paging_options \\ @default_paging_options) do
filter
|> staking_pools_query(paging_options)
|> Repo.all()
end
defp staking_pools_query(filter, paging_options) do
page_size = paging_options.page_size
@spec staking_pools(
filter :: :validator | :active | :inactive,
options :: PagingOptions.t(),
delegator_address_hash :: Hash.t() | nil
) :: [map()]
def staking_pools(filter, paging_options \\ @default_paging_options, delegator_address_hash \\ nil) do
base_query =
StakingPool
|> where(is_deleted: false)
|> staking_pool_filter(filter)
|> limit(^page_size)
|> staking_pools_paging_query(paging_options)
query =
if delegator_address_hash do
base_query
|> join(:left, [p], pd in StakingPoolsDelegator,
on: p.staking_address_hash == pd.pool_address_hash and pd.delegator_address_hash == ^delegator_address_hash
)
|> select([p, pd], %{pool: p, delegator: pd})
else
base_query
|> select([p], %{pool: p, delegator: nil})
end
Repo.all(query)
end
defp staking_pools_paging_query(base_query, paging_options) do
paging_query =
base_query
|> limit(^paging_options.page_size)
|> order_by(desc: :staked_ratio, asc: :staking_address_hash)
case paging_options.key do
{value, address_hash} ->
where(
base_query,
paging_query,
[p],
p.staked_ratio < ^value or
(p.staked_ratio == ^value and p.staking_address_hash > ^address_hash)
)
_ ->
base_query
paging_query
end
end

@ -4980,7 +4980,7 @@ defmodule Explorer.ChainTest do
options = %PagingOptions{page_size: 20, page_number: 1}
assert [gotten_validator] = Chain.staking_pools(:validator, options)
assert [%{pool: gotten_validator}] = Chain.staking_pools(:validator, options)
assert inserted_validator.staking_address_hash == gotten_validator.staking_address_hash
end
@ -4990,7 +4990,7 @@ defmodule Explorer.ChainTest do
options = %PagingOptions{page_size: 20, page_number: 1}
assert [gotten_pool] = Chain.staking_pools(:active, options)
assert [%{pool: gotten_pool}] = Chain.staking_pools(:active, options)
assert inserted_pool.staking_address_hash == gotten_pool.staking_address_hash
end
@ -5000,7 +5000,7 @@ defmodule Explorer.ChainTest do
options = %PagingOptions{page_size: 20, page_number: 1}
assert [gotten_pool] = Chain.staking_pools(:inactive, options)
assert [%{pool: gotten_pool}] = Chain.staking_pools(:inactive, options)
assert inserted_pool.staking_address_hash == gotten_pool.staking_address_hash
end
end

Loading…
Cancel
Save