defmodule FrenzyWeb.GroupController do use FrenzyWeb, :controller alias Frenzy.{Repo, Group, Feed, Item, Paginator} alias FrenzyWeb.Endpoint import Ecto.Query plug :user_owns_group defp user_owns_group(%Plug.Conn{path_params: %{"id" => id}} = conn, _opts) do user = conn.assigns[:user] group = Repo.get(Group, id) if Enum.any?(user.groups, fn g -> g.id == group.id end) do conn |> assign(:group, group) else conn |> put_flash(:error, "You do not have permission to acess that resource.") |> redirect(to: Routes.group_path(Endpoint, :index)) |> halt() end end defp user_owns_group(conn, _opts), do: conn def index(conn, _params) do groups = conn.assigns[:user].groups render(conn, "index.html", groups: groups) end def show(conn, _params) do group = conn.assigns[:group] |> Repo.preload(:feeds) create_feed_changeset = Feed.changeset( %Feed{ group_id: group.id }, %{} ) render(conn, "show.html", %{ group: group, create_feed_changeset: create_feed_changeset }) end def new(conn, _params) do changeset = Group.changeset(%Group{}, %{}) render(conn, "new.html", changeset: changeset) end def create(conn, %{"group" => %{"title" => title}}) do user = conn.assigns[:user] title = title |> String.trim() if String.length(title) > 0 do changeset = Ecto.build_assoc(user, :groups, %{ title: title }) {:ok, group} = Repo.insert(changeset) redirect(conn, to: Routes.group_path(Endpoint, :show, group.id)) else conn |> put_flash(:error, "Group title must not be empty") |> redirect(to: Routes.group_path(Endpoint, :new)) end end def edit(conn, _params) do group = conn.assigns[:group] edit_changeset = Group.changeset(group, %{}) render(conn, "edit.html", %{ group: group, changeset: edit_changeset }) end def update(conn, %{"group" => group_params}) do group = conn.assigns[:group] changeset = Group.changeset(group, group_params) {:ok, group} = Repo.update(changeset) redirect(conn, to: Routes.group_path(Endpoint, :show, group.id)) end def delete(conn, _params) do group = conn.assigns[:group] {:ok, _} = Repo.delete(group) redirect(conn, to: Routes.group_path(Endpoint, :index)) end def read(conn, params) do group = conn.assigns[:group] |> Repo.preload(:feeds) feed_ids = Enum.map(group.feeds, fn feed -> feed.id end) items = Item |> where([i], not i.tombstone and i.feed_id in ^feed_ids) |> Paginator.paginate(params) |> limit(50) |> preload(:feed) |> Repo.all() |> Enum.sort_by(fn item -> item.date end, fn a, b -> DateTime.compare(a, b) == :gt end) first_item = List.first(items) last_item = List.last(items) prev_page_path = if !is_nil(first_item) && Repo.exists?( from i in Item, where: not i.tombstone and i.date > ^first_item.date and i.feed_id in ^feed_ids ) do current_path(conn, %{after: first_item.id}) else nil end next_page_path = if !is_nil(last_item) && Repo.exists?( from i in Item, where: not i.tombstone and i.date < ^last_item.date and i.feed_id in ^feed_ids ) do current_path(conn, %{before: last_item.id}) else nil end render(conn, "read.html", %{ group: group, items: items, prev_page_path: prev_page_path, next_page_path: next_page_path }) end end