Refactor to replace any block that matches the new block received

pull/847/head
Stamates 6 years ago
parent 578f03a9e4
commit afe98f0c49
  1. 58
      apps/block_scout_web/assets/__tests__/pages/block.js
  2. 48
      apps/block_scout_web/assets/js/pages/block.js
  3. 5
      apps/block_scout_web/lib/block_scout_web/templates/block/_tile.html.eex
  4. 2
      apps/block_scout_web/test/block_scout_web/features/pages/block_list_page.ex

@ -23,7 +23,7 @@ describe('RECEIVED_NEW_BLOCK', () => {
const output = reducer(initialState, action) const output = reducer(initialState, action)
expect(output.newBlock).toBe('test') expect(output.newBlock).toBe('test')
expect(output.currentBlockNumber).toBe(1) expect(output.blockNumbers).toEqual([1])
}) })
test('on page 2+', () => { test('on page 2+', () => {
const state = Object.assign({}, initialState, { const state = Object.assign({}, initialState, {
@ -38,10 +38,12 @@ describe('RECEIVED_NEW_BLOCK', () => {
const output = reducer(state, action) const output = reducer(state, action)
expect(output.newBlock).toBe(null) expect(output.newBlock).toBe(null)
expect(output.blockNumbers).toEqual([])
expect(output.skippedBlockNumbers).toEqual([])
}) })
test('inserts place holders if block received out of order', () => { test('inserts place holders if block received out of order', () => {
const state = Object.assign({}, initialState, { const state = Object.assign({}, initialState, {
currentBlockNumber: 2 blockNumbers: [2]
}) })
const action = { const action = {
type: 'RECEIVED_NEW_BLOCK', type: 'RECEIVED_NEW_BLOCK',
@ -53,7 +55,57 @@ describe('RECEIVED_NEW_BLOCK', () => {
const output = reducer(state, action) const output = reducer(state, action)
expect(output.newBlock).toBe('test5') expect(output.newBlock).toBe('test5')
expect(output.currentBlockNumber).toBe(5) expect(output.blockNumbers).toEqual([5, 4, 3, 2])
expect(output.skippedBlockNumbers).toEqual([3, 4]) expect(output.skippedBlockNumbers).toEqual([3, 4])
}) })
test('replaces skipped block', () => {
const state = Object.assign({}, initialState, {
blockNumbers: [5, 4, 3, 2, 1],
skippedBlockNumbers: [1, 3, 4]
})
const action = {
type: 'RECEIVED_NEW_BLOCK',
msg: {
blockHtml: 'test3',
blockNumber: 3
}
}
const output = reducer(state, action)
expect(output.newBlock).toBe('test3')
expect(output.blockNumbers).toEqual([5, 4, 3, 2, 1])
expect(output.skippedBlockNumbers).toEqual([1, 4])
})
test('replaces duplicated block', () => {
const state = Object.assign({}, initialState, {
blockNumbers: [5, 4]
})
const action = {
type: 'RECEIVED_NEW_BLOCK',
msg: {
blockHtml: 'test5',
blockNumber: 5
}
}
const output = reducer(state, action)
expect(output.newBlock).toBe('test5')
expect(output.blockNumbers).toEqual([5, 4])
})
test('skips if new block height is lower than lowest on page', () => {
const state = Object.assign({}, initialState, {
blockNumbers: [5, 4, 3, 2]
})
const action = {
type: 'RECEIVED_NEW_BLOCK',
msg: {
blockHtml: 'test1',
blockNumber: 1
}
}
const output = reducer(state, action)
expect(output.newBlock).toBe(null)
expect(output.blockNumbers).toEqual([5, 4, 3, 2])
})
}) })

@ -7,9 +7,9 @@ import { updateAllAges } from '../lib/from_now'
import { initRedux, prependWithClingBottom } from '../utils' import { initRedux, prependWithClingBottom } from '../utils'
export const initialState = { export const initialState = {
blockNumbers: [],
beyondPageOne: null, beyondPageOne: null,
channelDisconnected: false, channelDisconnected: false,
currentBlockNumber: null,
newBlock: null, newBlock: null,
replaceBlock: null, replaceBlock: null,
skippedBlockNumbers: [] skippedBlockNumbers: []
@ -18,13 +18,9 @@ export const initialState = {
export function reducer (state = initialState, action) { export function reducer (state = initialState, action) {
switch (action.type) { switch (action.type) {
case 'PAGE_LOAD': { case 'PAGE_LOAD': {
let blockNumber = parseInt(state.currentBlockNumber)
if (!action.beyondPageOne) {
blockNumber = parseInt(action.highestBlockNumber)
}
return Object.assign({}, state, { return Object.assign({}, state, {
beyondPageOne: action.beyondPageOne, beyondPageOne: action.beyondPageOne,
currentBlockNumber: blockNumber blockNumbers: action.blockNumbers
}) })
} }
case 'CHANNEL_DISCONNECTED': { case 'CHANNEL_DISCONNECTED': {
@ -35,24 +31,30 @@ export function reducer (state = initialState, action) {
case 'RECEIVED_NEW_BLOCK': { case 'RECEIVED_NEW_BLOCK': {
if (state.channelDisconnected || state.beyondPageOne) return state if (state.channelDisconnected || state.beyondPageOne) return state
let skippedBlockNumbers = state.skippedBlockNumbers.slice(0)
let replaceBlock = null
const blockNumber = parseInt(action.msg.blockNumber) const blockNumber = parseInt(action.msg.blockNumber)
if (blockNumber > state.currentBlockNumber + 1) { if (_.includes(state.blockNumbers, blockNumber)) {
for (let i = state.currentBlockNumber + 1; i < action.msg.blockNumber; i++) { return Object.assign({}, state, {
newBlock: action.msg.blockHtml,
replaceBlock: blockNumber,
skippedBlockNumbers: _.without(state.skippedBlockNumbers, blockNumber)
})
} else if (blockNumber < _.last(state.blockNumbers)){
return state
} else {
let skippedBlockNumbers = state.skippedBlockNumbers.slice(0)
if (blockNumber > state.blockNumbers[0] + 1) {
for (let i = state.blockNumbers[0] + 1; i < blockNumber; i++) {
skippedBlockNumbers.push(i) skippedBlockNumbers.push(i)
} }
} else if (_.indexOf(skippedBlockNumbers, blockNumber) != -1) {
skippedBlockNumbers = _.without(skippedBlockNumbers, blockNumber)
replaceBlock = blockNumber
} }
return Object.assign({}, state, { return Object.assign({}, state, {
currentBlockNumber: blockNumber > state.currentBlockNumber ? blockNumber : state.currentBlockNumber, blockNumbers: _.chain([blockNumber]).union(skippedBlockNumbers, state.blockNumbers).orderBy([],['desc']).value(),
newBlock: action.msg.blockHtml, newBlock: action.msg.blockHtml,
replaceBlock, replaceBlock: null,
skippedBlockNumbers skippedBlockNumbers
}) })
} }
}
default: default:
return state return state
} }
@ -65,7 +67,7 @@ if ($blockListPage.length) {
const state = store.dispatch({ const state = store.dispatch({
type: 'PAGE_LOAD', type: 'PAGE_LOAD',
beyondPageOne: !!humps.camelizeKeys(URI(window.location).query(true)).blockNumber, beyondPageOne: !!humps.camelizeKeys(URI(window.location).query(true)).blockNumber,
highestBlockNumber: $('[data-selector="block-number"]').filter(':first').text() blockNumbers: $('[data-selector="block-number"]').map((index, el) => parseInt(el.innerText)).toArray()
}) })
if (!state.beyondPageOne) { if (!state.beyondPageOne) {
const blocksChannel = socket.channel(`blocks:new_block`, {}) const blocksChannel = socket.channel(`blocks:new_block`, {})
@ -81,20 +83,18 @@ if ($blockListPage.length) {
const $blocksList = $('[data-selector="blocks-list"]') const $blocksList = $('[data-selector="blocks-list"]')
if (state.channelDisconnected) $channelDisconnected.show() if (state.channelDisconnected) $channelDisconnected.show()
if (oldState.newBlock !== state.newBlock) { if (oldState.newBlock !== state.newBlock || (state.replaceBlock && oldState.replaceBlock !== state.replaceBlock)) {
if (state.replaceBlock && oldState.replaceBlock !== state.replaceBlock) {
const $replaceBlock = $(`[data-block-number="${state.replaceBlock}"]`)
$replaceBlock.addClass('shrink-out')
setTimeout(() => $replaceBlock.replaceWith(state.newBlock), 400)
} else {
if (oldState.skippedBlockNumbers !== state.skippedBlockNumbers) { if (oldState.skippedBlockNumbers !== state.skippedBlockNumbers) {
const newSkippedBlockNumbers = _.difference(state.skippedBlockNumbers, oldState.skippedBlockNumbers) const newSkippedBlockNumbers = _.difference(state.skippedBlockNumbers, oldState.skippedBlockNumbers)
if (state.replaceBlock) {
const $placeHolder = $(`[data-selector="place-holder"][data-block-number="${state.replaceBlock}"] div.tile`)
$placeHolder.addClass('shrink-out')
setTimeout(() => $placeHolder.replaceWith(state.newBlock), 400)
} else {
_.map(newSkippedBlockNumbers, (skippedBlockNumber) => { _.map(newSkippedBlockNumbers, (skippedBlockNumber) => {
prependWithClingBottom($blocksList, placeHolderBlock(skippedBlockNumber)) prependWithClingBottom($blocksList, placeHolderBlock(skippedBlockNumber))
}) })
prependWithClingBottom($blocksList, state.newBlock)
} }
} else {
prependWithClingBottom($blocksList, state.newBlock) prependWithClingBottom($blocksList, state.newBlock)
} }
updateAllAges() updateAllAges()

@ -1,4 +1,4 @@
<div class="tile tile-type-block fade-up"> <div class="tile tile-type-block fade-up" data-block-number="<%= to_string(@block.number) %>">
<div class="row"> <div class="row">
<div class="col-md-8 col-lg-9"> <div class="col-md-8 col-lg-9">
<!-- block height --> <!-- block height -->
@ -6,8 +6,7 @@
@block, @block,
class: "tile-title", class: "tile-title",
to: block_path(BlockScoutWeb.Endpoint, :show, @block), to: block_path(BlockScoutWeb.Endpoint, :show, @block),
"data-selector": "block-number", "data-selector": "block-number"
"data-block-number": to_string(@block.number)
) %> ) %>
<div> <div>
<!-- transactions --> <!-- transactions -->

@ -12,7 +12,7 @@ defmodule BlockScoutWeb.BlockListPage do
end end
def block(%Block{number: block_number}) do def block(%Block{number: block_number}) do
css("[data-selector='block-number'][data-block-number='#{block_number}']") css("[data-block-number='#{block_number}']")
end end
def place_holder_blocks(count) do def place_holder_blocks(count) do

Loading…
Cancel
Save