Change to last seen paging and hide paging button on last page for block_transactions

pull/306/head
Stamates 7 years ago
parent f7df4971f7
commit ef6a478741
  1. 24
      apps/explorer/lib/explorer/chain.ex
  2. 48
      apps/explorer/test/explorer/chain_test.exs
  3. 46
      apps/explorer_web/lib/explorer_web/controllers/block_transaction_controller.ex
  4. 28
      apps/explorer_web/lib/explorer_web/templates/block_transaction/index.html.eex
  5. 11
      apps/explorer_web/test/explorer_web/controllers/address_transaction_controller_test.exs
  6. 30
      apps/explorer_web/test/explorer_web/controllers/block_transaction_controller_test.exs

@ -419,22 +419,21 @@ defmodule Explorer.Chain do
end
@doc """
Finds all `t:Explorer.Chain.Transaction.t/0` in the `t:Explorer.Chain.Block.t/0`.
Finds all `t:Explorer.Chain.Transaction.t/0`s in the `t:Explorer.Chain.Block.t/0`.
## Options
* `:necessity_by_association` - use to load `t:association/0` as `:required` or `:optional`. If an association is
`:required`, and the `t:Explorer.Chain.Transaction.t/0` has no associated record for that association, then the
`t:Explorer.Chain.Transaction.t/0` will not be included in the page `entries`.
* `:pagination` - pagination params to pass to scrivener.
* `:paging_options` - a `t:Explorer.PagingOptions.t/0` used to specify the `:page_size` and
`:key` (a tuple of the lowest/oldest {index}) and. Results will be the transactions older than
the index that are passed.
"""
@spec block_to_transactions(Block.t()) :: %Scrivener.Page{entries: [Transaction.t()]}
@spec block_to_transactions(Block.t(), [necessity_by_association_option | pagination_option]) :: %Scrivener.Page{
entries: [Transaction.t()]
}
@spec block_to_transactions(Block.t(), [paging_options | necessity_by_association_option]) :: [Transaction.t()]
def block_to_transactions(%Block{hash: block_hash}, options \\ []) when is_list(options) do
necessity_by_association = Keyword.get(options, :necessity_by_association, %{})
pagination = Keyword.get(options, :pagination, %{})
paging_options = Keyword.get(options, :paging_options, %PagingOptions{page_size: 50})
Transaction
|> load_contract_creation()
@ -443,9 +442,11 @@ defmodule Explorer.Chain do
})
|> join(:inner, [transaction], block in assoc(transaction, :block))
|> where([_, _, block], block.hash == ^block_hash)
|> order_by([transaction], desc: transaction.inserted_at, desc: transaction.hash)
|> page_transaction(paging_options)
|> limit(^paging_options.page_size)
|> order_by([transaction], desc: transaction.index)
|> join_associations(necessity_by_association)
|> Repo.paginate(pagination)
|> Repo.all()
end
@doc """
@ -2550,6 +2551,11 @@ defmodule Explorer.Chain do
)
end
defp page_transaction(query, %PagingOptions{key: {index}}) do
query
|> where([transaction], transaction.index < ^index)
end
defp run_addresses(multi, ecto_schema_module_to_changes_list, options)
when is_map(ecto_schema_module_to_changes_list) and is_list(options) do
case ecto_schema_module_to_changes_list do

@ -122,11 +122,7 @@ defmodule Explorer.ChainTest do
assert Repo.aggregate(Transaction, :count, :hash) == 0
assert %Scrivener.Page{
entries: [],
page_number: 1,
total_entries: 0
} = Chain.block_to_transactions(block)
assert [] = Chain.block_to_transactions(block)
end
test "with transactions" do
@ -135,40 +131,28 @@ defmodule Explorer.ChainTest do
|> insert()
|> with_block()
assert %Scrivener.Page{
entries: [%Transaction{hash: ^transaction_hash}],
page_number: 1,
total_entries: 1
} = Chain.block_to_transactions(block)
assert [%Transaction{hash: ^transaction_hash}] = Chain.block_to_transactions(block)
end
test "with transactions can be paginated" do
block = insert(:block)
transactions =
Enum.map(0..1, fn _ ->
:transaction
|> insert()
|> with_block(block)
end)
[%Transaction{hash: first_transaction_hash}, %Transaction{hash: second_transaction_hash}] = transactions
second_page_hashes =
50
|> insert_list(:transaction)
|> with_block(block)
|> Enum.map(& &1.hash)
assert %Scrivener.Page{
entries: [%Transaction{hash: ^second_transaction_hash}],
page_number: 1,
page_size: 1,
total_entries: 2,
total_pages: 2
} = Chain.block_to_transactions(block, pagination: %{page_size: 1})
%Transaction{block_number: block_number, index: index} =
:transaction
|> insert()
|> with_block(block)
assert %Scrivener.Page{
entries: [%Transaction{hash: ^first_transaction_hash}],
page_number: 2,
page_size: 1,
total_entries: 2,
total_pages: 2
} = Chain.block_to_transactions(block, pagination: %{page: 2, page_size: 1})
assert second_page_hashes ==
block
|> Chain.block_to_transactions(paging_options: %PagingOptions{key: {block_number, index}, page_size: 50})
|> Enum.map(& &1.hash)
|> Enum.reverse()
end
end

@ -3,24 +3,37 @@ defmodule ExplorerWeb.BlockTransactionController do
import ExplorerWeb.Chain, only: [param_to_block_number: 1]
alias Explorer.Chain
alias Explorer.{Chain, PagingOptions}
@page_size 50
@default_paging_options %PagingOptions{page_size: @page_size + 1}
def index(conn, %{"block_id" => formatted_block_number} = params) do
with {:ok, block_number} <- param_to_block_number(formatted_block_number),
{:ok, block} <- Chain.number_to_block(block_number, necessity_by_association: %{miner: :required}),
block_transaction_count <- Chain.block_to_transaction_count(block) do
page =
Chain.block_to_transactions(
block,
full_options =
[
necessity_by_association: %{
block: :required,
from_address: :required,
to_address: :optional
},
pagination: params
)
}
]
|> Keyword.merge(paging_options(params))
transactions_plus_one = Chain.block_to_transactions(block, full_options)
{transactions, next_page} = Enum.split(transactions_plus_one, @page_size)
render(conn, "index.html", block: block, block_transaction_count: block_transaction_count, page: page)
render(
conn,
"index.html",
block: block,
block_transaction_count: block_transaction_count,
next_page_params: next_page_params(next_page, transactions),
transactions: transactions
)
else
{:error, :invalid} ->
not_found(conn)
@ -29,4 +42,21 @@ defmodule ExplorerWeb.BlockTransactionController do
not_found(conn)
end
end
defp next_page_params([], _transactions), do: nil
defp next_page_params(_, transactions) do
last = List.last(transactions)
%{block_number: last.block_number, index: last.index}
end
defp paging_options(params) do
with %{"index" => index_string} <- params,
{index, ""} <- Integer.parse(index_string) do
[paging_options: %{@default_paging_options | key: {index}}]
else
_ ->
[paging_options: @default_paging_options]
end
end
end

@ -129,7 +129,7 @@
</ul>
</div>
<div class="card-body">
<%= if Enum.count(@page) > 0 do %>
<%= if Enum.count(@transactions) > 0 do %>
<table class="table table-responsive-sm table-font">
<thead>
<tr>
@ -146,7 +146,7 @@
</tr>
</thead>
<tbody>
<%= for transaction <- @page do %>
<%= for transaction <- @transactions do %>
<tr>
<td>
<div class="transaction__dot transaction__dot--<%= status(transaction) %>"></div>
@ -195,21 +195,17 @@
<% end %>
</div>
</div>
<%= if Enum.count(@page) > 0 do %>
<div class="blocks__pagination">
<%= pagination_links(
<%= if @next_page_params do %>
<%= link(
gettext("Older"),
class: "button button--secondary button--sm u-float-right mt-3",
to: transaction_path(
@conn,
@page,
["en", @conn.params["block_id"]],
distance: 1,
first: true,
next: Phoenix.HTML.raw("&rsaquo;"),
path: &block_transaction_path/5,
previous: Phoenix.HTML.raw("&lsaquo;"),
view_style: :bulma
) %>
</div>
:index,
@conn.assigns.locale,
@next_page_params
)
) %>
<% end %>
</section>
</section>

@ -114,16 +114,7 @@ defmodule ExplorerWeb.AddressTransactionControllerTest do
|> insert(from_address_hash: address.hash)
|> with_block()
%Transaction{block_number: block_number, index: index} =
:transaction
|> insert(from_address_hash: address.hash)
|> with_block()
conn =
get(conn, address_transaction_path(ExplorerWeb.Endpoint, :index, :en, address.hash), %{
"block_number" => Integer.to_string(block_number),
"index" => Integer.to_string(index)
})
conn = get(conn, address_transaction_path(ExplorerWeb.Endpoint, :index, :en, address.hash))
refute conn.assigns.next_page_params
end

@ -25,7 +25,7 @@ defmodule ExplorerWeb.BlockTransactionControllerTest do
conn = get(conn, block_transaction_path(ExplorerWeb.Endpoint, :index, :en, block.number))
assert html_response(conn, 200)
assert 2 == Enum.count(conn.assigns.page)
assert 2 == Enum.count(conn.assigns.transactions)
end
test "does not return unrelated transactions", %{conn: conn} do
@ -35,7 +35,7 @@ defmodule ExplorerWeb.BlockTransactionControllerTest do
conn = get(conn, block_transaction_path(ExplorerWeb.Endpoint, :index, :en, block))
assert html_response(conn, 200)
assert Enum.empty?(conn.assigns.page)
assert Enum.empty?(conn.assigns.transactions)
end
test "does not return related transactions without a block", %{conn: conn} do
@ -45,7 +45,31 @@ defmodule ExplorerWeb.BlockTransactionControllerTest do
conn = get(conn, block_transaction_path(ExplorerWeb.Endpoint, :index, :en, block))
assert html_response(conn, 200)
assert Enum.empty?(conn.assigns.page)
assert Enum.empty?(conn.assigns.transactions)
end
test "next_page_params exist if not on last page", %{conn: conn} do
block = insert(:block)
60
|> insert_list(:transaction)
|> with_block(block)
conn = get(conn, block_transaction_path(ExplorerWeb.Endpoint, :index, :en, block))
assert conn.assigns.next_page_params
end
test "next_page_params are empty if on last page", %{conn: conn} do
block = insert(:block)
:transaction
|> insert()
|> with_block(block)
conn = get(conn, block_transaction_path(ExplorerWeb.Endpoint, :index, :en, block))
refute conn.assigns.next_page_params
end
end
end

Loading…
Cancel
Save