- Bug #12: Lower rate limit to 15/min - Bug #13: Wrap model loading in Task.start - Bug #14: Fix classify_time_period guard gap at -3.0 - Bug #15: Not applicable (Elixir has no ?? operator) - Bug #16: Remove fallback Repo.get for station preload - Bug #17: Extract cache_key() in ContactMapController - Bug #18: Add has_many :contacts and :beacons to User schema - A&D #4: Move serve_markdown_if_requested after secure headers - Config #1: Move signing_salt to runtime.exs env var - Config #2: Use --check-unused instead of --unused - Config #3: Re-enable UnsafeToAtom Credo check - Config #5: Re-enable LeakyEnvironment Credo check - Add @spec annotations to fix re-enabled Specs violations - Replace String.to_atom with to_existing_atom where guarded
105 lines
3.1 KiB
Elixir
105 lines
3.1 KiB
Elixir
defmodule MicrowavepropWeb.LiveTableFooter do
|
|
@moduledoc false
|
|
use Phoenix.Component
|
|
|
|
@spec render(map()) :: Phoenix.LiveView.Rendered.t()
|
|
def render(assigns) do
|
|
options = assigns.options
|
|
table_options = assigns.table_options
|
|
paginate? = get_in(options, ["pagination", "paginate?"])
|
|
mode = get_in(table_options, [:pagination, :mode])
|
|
page = parse_page(get_in(options, ["pagination", "page"]))
|
|
has_next? = get_in(options, ["pagination", :has_next_page]) || false
|
|
|
|
assigns =
|
|
assigns
|
|
|> assign(:show_pagination?, paginate? && mode != :infinite_scroll)
|
|
|> assign(:page, page)
|
|
|> assign(:has_next_page?, has_next?)
|
|
|> assign(:page_items, page_items(page, has_next?))
|
|
|
|
~H"""
|
|
<nav
|
|
:if={@show_pagination?}
|
|
class="flex items-center justify-between px-4 py-3 sm:px-6"
|
|
aria-label="Pagination"
|
|
>
|
|
<p class="hidden sm:block text-sm opacity-60">
|
|
Page <span class="font-medium text-base-content">{@page}</span>
|
|
</p>
|
|
|
|
<div class="join">
|
|
<button
|
|
type="button"
|
|
class="btn btn-sm join-item"
|
|
phx-click="sort"
|
|
phx-value-page={@page - 1}
|
|
disabled={@page == 1}
|
|
aria-label="Previous page"
|
|
>
|
|
«
|
|
</button>
|
|
<%= for item <- @page_items do %>
|
|
<%= if item == :ellipsis do %>
|
|
<button type="button" class="btn btn-sm join-item btn-disabled pointer-events-none">
|
|
…
|
|
</button>
|
|
<% else %>
|
|
<button
|
|
type="button"
|
|
class={[
|
|
"btn btn-sm join-item",
|
|
item == @page && "btn-active pointer-events-none"
|
|
]}
|
|
phx-click="sort"
|
|
phx-value-page={item}
|
|
aria-label={"Page #{item}"}
|
|
aria-current={item == @page && "page"}
|
|
>
|
|
{item}
|
|
</button>
|
|
<% end %>
|
|
<% end %>
|
|
<button
|
|
type="button"
|
|
class="btn btn-sm join-item"
|
|
phx-click="sort"
|
|
phx-value-page={@page + 1}
|
|
disabled={!@has_next_page?}
|
|
aria-label="Next page"
|
|
>
|
|
»
|
|
</button>
|
|
</div>
|
|
</nav>
|
|
"""
|
|
end
|
|
|
|
# Without a total count from live_table we can only show pages we know exist:
|
|
# everything up to and including `page` (we got here), plus `page + 1` when
|
|
# `has_next?` is true. Collapses a gap to "…" once we're past page 4.
|
|
@doc false
|
|
@spec page_items(pos_integer(), boolean()) :: [pos_integer() | :ellipsis]
|
|
def page_items(page, has_next?) when page >= 1 do
|
|
window_start = max(1, page - 2)
|
|
window_end = if has_next?, do: page + 1, else: page
|
|
window = Enum.to_list(window_start..window_end)
|
|
|
|
cond do
|
|
window_start == 1 -> window
|
|
window_start == 2 -> [1 | window]
|
|
true -> [1, :ellipsis | window]
|
|
end
|
|
end
|
|
|
|
defp parse_page(page) when is_integer(page) and page >= 1, do: page
|
|
|
|
defp parse_page(page) when is_binary(page) do
|
|
case Integer.parse(page) do
|
|
{n, ""} when n >= 1 -> n
|
|
_ -> 1
|
|
end
|
|
end
|
|
|
|
defp parse_page(_), do: 1
|
|
end
|