analytics/lib/plausible_web/live/components/pagination.ex
Adrian Gruntkowski 07cab27fef
Implement new sites view (#3463)
* Implement complete basics of LV sites

* Reimplement everything in LV except pagination

* Implement basic search capability

* PoC: plot visitors on sites index

* Add rudimentary clipped gradient in minicharts

* Fix clipping gradient, define once

* Format

* Add moduledoc to visitors component

* Move paginator helpers to the top core namespace

* Fix typespec of `Plausible.Sites.list`

* Split sites component into subcomponents

* Add function to uniformly calculate 24h intervals
and visitor totals across multiple sites.

* Integrate batch 24h interval query with plots on sites view

* Don't confuse heex compiler with alpine @ shorthands

* Make linear gradient svg definition truly invisible

* Implement basic pagination

* Extract `site_stats` from site and invitation cards

* Improve pagination

* Tweak css

* Improve filtering on pagination and make WSS fail graceful

* Test `last_24h_visitors_hourly_intervals/2`

* Replace /sites with LV implementation

* Add debounce to search filter

* Fix typespecs

* Fix styling

* Fix mini graph scaling factor calculation

* Fix search consuming itself

* Minimal tweaks to the plots

* Fixup

* Remove magic numbers from the plot

* Create `site_pins` table

* Add `SitePin` schema

* Implement listing invitations, sites and pins in a single query

* Add FIXME note

* Remove site pins for now

* Add tests for `Plausible.Sites.list/3`

* Add a couple more tests to sites dead view

* Remove unnecessary FIXME

* Add LV tests for Sites

* Calculate and display 24h visitors change

* Render the change in bold

* Add clarfying comment on virtual field in `Site` schema

* Remove unnecessary function from Invitations API

* Remove unused list opt from type definition in `Sites`

* Improve joins in list query slightly

* Add comment on manually computing sites list total

* Start searching from a singly character in domain field

* Add typespec to `last_24h_visitors_hourly_intervals`

* Extend moduledoc in visitors component

* Simplify loading sites in LV

* Simplify assigns in LV

* Add missing group for shadow under site card

* Make invitation modal render

* Make HTML in sites LV semantically correct

* Remove autofocus and focus search on `/`

* Remove shadow from search input

* Make search cancel on escape

* Fix tests relying on outdated HTML structure

* Make visitor chart color scheme consistent with dashboard chart

* Update styling of trend labels

* Fix empty state and improve search blur/focus handling

* Use live navigation for pagination

* Implement spinner on load from search

* Remove unused `Plausible.Stats.Clickhouse.last_24h_visitors/1`

* Calculate uniques correctly across hour boundaries

* Swap inlined svg for Heroicons component in invitation modal

* Add order by to base query in 24h hourly intervals

* Revert "Add order by to base query in 24h hourly intervals"

This reverts commit a6be5e3026.

* Query clickhouse 24h visitors only on second mount

* Remove redundant sign from percentage change when negative

* Switch to offset-based pagination

  - offset seems easier to deal with for when actions on
    paginated list will be performed such as site pinning;
    tracking cursor data makes some entries disappear in
    edge cases. The data set is still fairly small and
    static, even for large customers.
  - we're removing Phoenix.Pagination as it doesn't really
    fir any use case, and it was only used to limit the number
    of sites in the site picker
  - site picker is now limited to 9 sites (future: pinned
    sites will be prioritized there)
  - no need to re-query for total count any more
  - BTW, the old /sites template was removed

* Refine the plot queries; Tests pass snapshot

* Add PromEx plugin for LiveView

* Fix tiny plot cut-off at the top

---------

Co-authored-by: Adam Rutkowski <hq@mtod.org>
2023-11-02 13:18:11 +01:00

79 lines
2.3 KiB
Elixir

defmodule PlausibleWeb.Live.Components.Pagination do
@moduledoc """
Pagination components for LiveViews.
"""
use Phoenix.Component
def pagination(assigns) do
~H"""
<nav
class="px-4 py-3 flex items-center justify-between border-t border-gray-200 dark:border-gray-500 sm:px-6"
aria-label="Pagination"
>
<div class="hidden sm:block">
<p class="text-sm text-gray-700 dark:text-gray-300">
<%= render_slot(@inner_block) %>
</p>
</div>
<div class="flex-1 flex justify-between sm:justify-end">
<.pagination_link
page_number={@page_number}
total_pages={@total_pages}
uri={@uri}
type={:prev}
/>
<.pagination_link
page_number={@page_number}
total_pages={@total_pages}
class="ml-4"
uri={@uri}
type={:next}
/>
</div>
</nav>
"""
end
attr :class, :string, default: nil
attr :uri, URI, required: true
attr :type, :atom, required: true
attr :page_number, :integer, required: true
attr :total_pages, :integer, required: true
defp pagination_link(assigns) do
{active?, uri} =
case {assigns.type, assigns.page_number, assigns.total_pages} do
{:next, n, total} when n < total ->
params = URI.decode_query(assigns.uri.query, %{"page" => n + 1})
{true, %{assigns.uri | query: URI.encode_query(params)}}
{:prev, n, _total} when n > 1 ->
params = URI.decode_query(assigns.uri.query, %{"page" => n - 1})
{true, %{assigns.uri | query: URI.encode_query(params)}}
{_, _, _} ->
{false, nil}
end
assigns = assign(assigns, uri: active? && URI.to_string(uri), active?: active?)
~H"""
<.link
navigate={@uri}
class={[
"pagination-link relative inline-flex items-center px-4 py-2 border text-sm font-medium rounded-md",
if @active? do
"active button "
else
"inactive border-gray-300 text-gray-300 dark:border-gray-500 dark:bg-gray-800 dark:text-gray-600 hover:shadow-none hover:bg-gray-300 cursor-not-allowed"
end,
@class
]}
>
<span :if={@type == :prev}>← Previous</span>
<span :if={@type == :next}>Next →</span>
</.link>
"""
end
end