From 2a3c085fef8ac23cfd3f63878740f51f58890de8 Mon Sep 17 00:00:00 2001 From: Shadowfacts Date: Mon, 1 Jun 2020 22:24:18 -0400 Subject: [PATCH] Add item pagination --- lib/frenzy/paginator.ex | 28 +++++++++++++++++++ lib/frenzy_web/controllers/feed_controller.ex | 15 ++++++++-- lib/frenzy_web/templates/feed/show.html.eex | 12 ++++++++ lib/frenzy_web/views/feed_view.ex | 27 +++++++++++++++++- 4 files changed, 78 insertions(+), 4 deletions(-) create mode 100644 lib/frenzy/paginator.ex diff --git a/lib/frenzy/paginator.ex b/lib/frenzy/paginator.ex new file mode 100644 index 0000000..088ba03 --- /dev/null +++ b/lib/frenzy/paginator.ex @@ -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 diff --git a/lib/frenzy_web/controllers/feed_controller.ex b/lib/frenzy_web/controllers/feed_controller.ex index 01d1628..c11818e 100644 --- a/lib/frenzy_web/controllers/feed_controller.ex +++ b/lib/frenzy_web/controllers/feed_controller.ex @@ -1,6 +1,6 @@ defmodule FrenzyWeb.FeedController do 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.Endpoint import Ecto.Query @@ -25,9 +25,18 @@ defmodule FrenzyWeb.FeedController do 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] - 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", %{ feed: feed, diff --git a/lib/frenzy_web/templates/feed/show.html.eex b/lib/frenzy_web/templates/feed/show.html.eex index d0e07a0..05e47aa 100644 --- a/lib/frenzy_web/templates/feed/show.html.eex +++ b/lib/frenzy_web/templates/feed/show.html.eex @@ -17,6 +17,12 @@

Items

+<%= unless is_nil(prev_page_path(@conn, @items)) do %> +

+ Newer +

+<% end %> + <%= for item <- @items do %> @@ -34,3 +40,9 @@ <% end %>
+ +<%= unless is_nil(next_page_path(@conn, @items)) do %> +

+ Older +

+<% end %> diff --git a/lib/frenzy_web/views/feed_view.ex b/lib/frenzy_web/views/feed_view.ex index c6e727b..bbd346f 100644 --- a/lib/frenzy_web/views/feed_view.ex +++ b/lib/frenzy_web/views/feed_view.ex @@ -1,3 +1,28 @@ defmodule FrenzyWeb.FeedView do use FrenzyWeb, :view -end \ No newline at end of file + 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