defmodule PlausibleWeb.Plugins.API.Views.Pagination do @moduledoc """ A view capable of rendering pagination metadata included in responses containing lists of objects. """ use Phoenix.View, namespace: PlausibleWeb.Plugins.API, root: "" alias PlausibleWeb.Router.Helpers def render_metadata_links(meta, helper_fn, helper_fn_args, existing_params \\ %{}) do render(__MODULE__, "pagination.json", %{ meta: meta, url_helper: fn query_params -> existing_params = Map.drop(existing_params, ["before", "after"]) query_params = query_params |> Enum.into(%{}) |> Map.merge(existing_params) args = [ PlausibleWeb.Endpoint | List.wrap(helper_fn_args) ++ [query_params] ] apply(Helpers, helper_fn, args) end }) end @spec render(binary(), map()) :: binary() def render("pagination.json", %{meta: meta, url_helper: url_helper_fn}) do pagination = [ {:after, :next, :has_next_page}, {:before, :prev, :has_prev_page} ] |> Enum.reduce(%{}, fn {meta_key, url_key, sibling_key}, acc -> meta_value = Map.get(meta, meta_key) if meta_value do url = url_helper_fn.([{meta_key, meta_value}]) acc |> Map.update( :links, %{url_key => %{url: url}}, &Map.put(&1, url_key, %{url: url}) ) |> Map.put(sibling_key, true) else acc |> Map.update(:links, %{}, & &1) |> Map.put(sibling_key, false) end end) %{ pagination: pagination } end end