Add item pagination

This commit is contained in:
Shadowfacts 2020-06-01 22:24:18 -04:00
parent 3eeef799ad
commit 2a3c085fef
Signed by: shadowfacts
GPG Key ID: 94A5AB95422746E5
4 changed files with 78 additions and 4 deletions

28
lib/frenzy/paginator.ex Normal file
View File

@ -0,0 +1,28 @@
defmodule Frenzy.Paginator do
import Ecto.Query
alias Frenzy.{Repo, Item}
@spec paginate(query :: Ecto.Queryable.t(), params :: map()) :: Ecto.Query.t()
def paginate(query, %{"before" => before_id}) do
before = Repo.get(Item, before_id)
query
# |> where([o], o.id < ^before_id)
|> where([i], i.date < ^before.date)
|> order_by(desc: :date)
end
def paginate(query, %{"after" => after_id}) do
after_item = Repo.get(Item, after_id)
query
|> where([i], i.date > ^after_item.date)
|> order_by(asc: :date)
end
def paginate(query, _) do
query
|> order_by(desc: :date)
end
end

View File

@ -1,6 +1,6 @@
defmodule FrenzyWeb.FeedController do defmodule FrenzyWeb.FeedController do
use FrenzyWeb, :controller use FrenzyWeb, :controller
alias Frenzy.{Repo, Group, Feed, Item, Pipeline} alias Frenzy.{Repo, Group, Feed, Item, Pipeline, Paginator}
alias FrenzyWeb.Router.Helpers, as: Routes alias FrenzyWeb.Router.Helpers, as: Routes
alias FrenzyWeb.Endpoint alias FrenzyWeb.Endpoint
import Ecto.Query import Ecto.Query
@ -25,9 +25,18 @@ defmodule FrenzyWeb.FeedController do
defp user_owns_feed(conn, _opts), do: conn defp user_owns_feed(conn, _opts), do: conn
def show(conn, %{"id" => id}) do def show(conn, %{"id" => id} = params) do
feed = conn.assigns[:feed] feed = conn.assigns[:feed]
items = Repo.all(from Item, where: [feed_id: ^id, tombstone: false], order_by: [desc: :date])
items =
Item
|> where([i], i.feed_id == ^id)
|> Paginator.paginate(params)
|> limit(50)
|> Repo.all()
|> Enum.sort_by(fn item -> item.date end, fn a, b ->
DateTime.compare(a, b) == :gt
end)
render(conn, "show.html", %{ render(conn, "show.html", %{
feed: feed, feed: feed,

View File

@ -17,6 +17,12 @@
<h3 class="mt-4">Items</h3> <h3 class="mt-4">Items</h3>
<%= unless is_nil(prev_page_path(@conn, @items)) do %>
<p class="text-center">
<a href="<%= prev_page_path(@conn, @items) %>" class="pagination-link">Newer</a>
</p>
<% end %>
<table class="table table-striped"> <table class="table table-striped">
<tbody> <tbody>
<%= for item <- @items do %> <%= for item <- @items do %>
@ -34,3 +40,9 @@
<% end %> <% end %>
</tbody> </tbody>
</table> </table>
<%= unless is_nil(next_page_path(@conn, @items)) do %>
<p class="text-center">
<a href="<%= next_page_path(@conn, @items) %>" class="pagination-link">Older</a>
</p>
<% end %>

View File

@ -1,3 +1,28 @@
defmodule FrenzyWeb.FeedView do defmodule FrenzyWeb.FeedView do
use FrenzyWeb, :view use FrenzyWeb, :view
alias Frenzy.{Repo, Item}
import Ecto.Query
@spec next_page_path(Plug.Conn.t(), [Frenzy.Item.t()]) :: String.t()
defp next_page_path(conn, items) do
%Item{id: id, date: date} = List.last(items)
has_older = Repo.exists?(from i in Item, where: i.date < ^date)
if has_older do
Phoenix.Controller.current_path(conn, %{before: id})
else
nil
end
end
@spec prev_page_path(Plug.Conn.t(), [Frenzy.Item.t()]) :: String.t()
defp prev_page_path(conn, [%Item{id: id, date: date} | _]) do
has_newer = Repo.exists?(from i in Item, where: i.date > ^date)
if has_newer do
Phoenix.Controller.current_path(conn, %{after: id})
else
nil
end
end
end end