Skip to content

Commit

Permalink
relay style pagination
Browse files Browse the repository at this point in the history
  • Loading branch information
ericsullivan committed Jan 4, 2022
1 parent 4d7dadd commit 06a773b
Show file tree
Hide file tree
Showing 3 changed files with 60 additions and 5 deletions.
53 changes: 52 additions & 1 deletion lib/paginator.ex
Original file line number Diff line number Diff line change
Expand Up @@ -88,6 +88,9 @@ defmodule Paginator do
* `:total_count_limit` - Running count queries on tables with a large number
of records is expensive so it is capped by default. Can be set to `:infinity`
in order to count all the records. Defaults to `10,000`.
* `:page_booleans` - populates `:has_next_page` and `:has_previous_page` booleans.
Always returns an `:after` and `:before` cursor (if available). This mimics
[relay style pagination](https://relay.dev/graphql/connections.htm#sec-undefined.PageInfo)
## Repo options
Expand Down Expand Up @@ -187,7 +190,9 @@ defmodule Paginator do
after: after_cursor(paginated_entries, sorted_entries, config),
limit: config.limit,
total_count: total_count,
total_count_cap_exceeded: total_count_cap_exceeded
total_count_cap_exceeded: total_count_cap_exceeded,
has_next_page: has_next_page(paginated_entries, sorted_entries, config),
has_previous_page: has_previous_page(paginated_entries, sorted_entries, config),
}
}
end
Expand Down Expand Up @@ -260,6 +265,10 @@ defmodule Paginator do
first_or_nil(paginated_entries, config)
end

defp before_cursor(paginated_entries, _sorted_entries, %Config{page_booleans: true} = config) do
first_or_nil(paginated_entries, config)
end

defp before_cursor(paginated_entries, sorted_entries, config) do
if first_page?(sorted_entries, config) do
nil
Expand All @@ -283,6 +292,10 @@ defmodule Paginator do
last_or_nil(paginated_entries, config)
end

defp after_cursor(paginated_entries, _sorted_entries, %Config{page_booleans: true} = config) do
last_or_nil(paginated_entries, config)
end

defp after_cursor(paginated_entries, sorted_entries, config) do
if last_page?(sorted_entries, config) do
nil
Expand All @@ -299,6 +312,44 @@ defmodule Paginator do
end
end

defp has_next_page(_paginated_entries, _sorted_entries, %Config{page_booleans: false}) do
nil
end

defp has_next_page([], [], _config) do
false
end

defp has_next_page(_paginated_entries, _sorted_entries, %Config{before: c_before})
when not is_nil(c_before) do
true
end

defp has_next_page(_paginated_entries, sorted_entries, config) do
!last_page?(sorted_entries, config)
end

defp has_previous_page(_paginated_entries, _sorted_entries, %Config{page_booleans: false}) do
nil
end

defp has_previous_page([], [], _config) do
false
end

defp has_previous_page(_paginated_entries, _sorted_entries, %Config{after: nil, before: nil}) do
false
end

defp has_previous_page(_paginated_entries, _sorted_entries, %Config{after: c_after})
when not is_nil(c_after) do
true
end

defp has_previous_page(_paginated_entries, sorted_entries, config) do
!first_page?(sorted_entries, config)
end

defp fetch_cursor_value(schema, %Config{
cursor_fields: cursor_fields,
fetch_cursor_value_fun: fetch_cursor_value_fun
Expand Down
6 changes: 4 additions & 2 deletions lib/paginator/config.ex
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,8 @@ defmodule Paginator.Config do
:limit,
:maximum_limit,
:sort_direction,
:total_count_limit
:total_count_limit,
:page_booleans
]

@default_total_count_primary_key_field :id
Expand All @@ -41,7 +42,8 @@ defmodule Paginator.Config do
opts[:total_count_primary_key_field] || @default_total_count_primary_key_field,
limit: limit(opts),
sort_direction: opts[:sort_direction],
total_count_limit: opts[:total_count_limit] || @default_total_count_limit
total_count_limit: opts[:total_count_limit] || @default_total_count_limit,
page_booleans: opts[:page_booleans] || false
}
|> convert_deprecated_config()
end
Expand Down
6 changes: 4 additions & 2 deletions lib/paginator/page/metadata.ex
Original file line number Diff line number Diff line change
Expand Up @@ -19,8 +19,10 @@ defmodule Paginator.Page.Metadata do
before: opaque_cursor() | nil,
limit: integer(),
total_count: integer() | nil,
total_count_cap_exceeded: boolean() | nil
total_count_cap_exceeded: boolean() | nil,
has_next_page: boolean() | nil,
has_previous_page: boolean() | nil
}

defstruct [:after, :before, :limit, :total_count, :total_count_cap_exceeded]
defstruct [:after, :before, :limit, :total_count, :total_count_cap_exceeded, :has_next_page, :has_previous_page]
end

0 comments on commit 06a773b

Please sign in to comment.