diff --git a/lib/philomena/users/ability.ex b/lib/philomena/users/ability.ex index a8f2c9e9..579b584d 100644 --- a/lib/philomena/users/ability.ex +++ b/lib/philomena/users/ability.ex @@ -6,6 +6,7 @@ defimpl Canada.Can, for: [Atom, Philomena.Users.User] do alias Philomena.Forums.Forum alias Philomena.Topics.Topic alias Philomena.Filters.Filter + alias Philomena.DnpEntries.DnpEntry # Admins can do anything def can?(%User{role: "admin"}, _action, _model), do: true @@ -84,6 +85,15 @@ defimpl Canada.Can, for: [Atom, Philomena.Users.User] do # View profile pages def can?(_user, :show, %User{}), do: true + # View and create DNP entries + def can?(%User{}, action, DnpEntry) when action in [:new, :create, :index], do: true + def can?(%User{id: id}, :show, %DnpEntry{requesting_user_id: id}), do: true + def can?(%User{id: id}, :show_reason, %DnpEntry{requesting_user_id: id}), do: true + def can?(%User{id: id}, :show_feedback, %DnpEntry{requesting_user_id: id}), do: true + + def can?(_user, :show, %DnpEntry{aasm_state: "listed"}), do: true + def can?(_user, :show_reason, %DnpEntry{aasm_state: "listed", hide_reason: false}), do: true + # Otherwise... def can?(_user, _action, _model), do: false end diff --git a/lib/philomena_web/controllers/dnp_entry_controller.ex b/lib/philomena_web/controllers/dnp_entry_controller.ex new file mode 100644 index 00000000..91b858e1 --- /dev/null +++ b/lib/philomena_web/controllers/dnp_entry_controller.ex @@ -0,0 +1,45 @@ +defmodule PhilomenaWeb.DnpEntryController do + use PhilomenaWeb, :controller + + # alias Philomena.DnpEntries + alias Philomena.DnpEntries.DnpEntry + alias Philomena.Textile.Renderer + alias Philomena.Tags.Tag + alias Philomena.Repo + import Ecto.Query + + plug :load_and_authorize_resource, model: DnpEntry, only: [:show] + + def index(conn, _params) do + dnp_entries = + DnpEntry + |> where(aasm_state: "listed") + |> join(:inner, [d], t in Tag, on: d.tag_id == t.id) + |> preload([:tag]) + |> order_by([d, t], asc: t.name_in_namespace) + |> Repo.paginate(conn.assigns.scrivener) + + bodies = + dnp_entries + |> Enum.map(&%{body: &1.conditions || "-"}) + |> Renderer.render_collection() + + dnp_entries = + %{dnp_entries | entries: Enum.zip(bodies, dnp_entries.entries)} + + render(conn, "index.html", layout_class: "layout--medium", dnp_entries: dnp_entries) + end + + def show(conn, _params) do + dnp_entry = conn.assigns.dnp_entry + + [conditions, reason, instructions] = + Renderer.render_collection([ + %{body: dnp_entry.conditions || "-"}, + %{body: dnp_entry.reason || "-"}, + %{body: dnp_entry.instructions || "-"} + ]) + + render(conn, "show.html", dnp_entry: dnp_entry, conditions: conditions, reason: reason, instructions: instructions) + end +end diff --git a/lib/philomena_web/router.ex b/lib/philomena_web/router.ex index eca4caf9..073ad65f 100644 --- a/lib/philomena_web/router.ex +++ b/lib/philomena_web/router.ex @@ -129,6 +129,7 @@ defmodule PhilomenaWeb.Router do resources "/galleries", GalleryController, only: [:index, :show] resources "/adverts", AdvertController, only: [:show] resources "/pages", PageController, only: [:show] + resources "/dnp", DnpEntryController, only: [:index, :show] get "/:id", ImageController, :show # get "/:forum_id", ForumController, :show # impossible to do without constraints diff --git a/lib/philomena_web/templates/dnp_entry/index.html.slime b/lib/philomena_web/templates/dnp_entry/index.html.slime new file mode 100644 index 00000000..ef83c603 --- /dev/null +++ b/lib/philomena_web/templates/dnp_entry/index.html.slime @@ -0,0 +1,43 @@ +h2 The Do-Not-Post (DNP) List + +/ Information block +h3 Information +.block + .block__header + span.block__header__title About + .block__content + p This is a list of artists who have asked us to place a restriction on the uploading of their artwork. These restructions can include anything from requesting that no edits of their work be allowed, to requesting that no uploads be allowed unless uploaded by the artists themselves. + p We ask that you please respect the wishes of artists in regards to their artworks, and check the list before uploading. Note that just because an artist is not listed may not mean that their artwork is ok to post, especially if they have a note at their "source" that they do not wish for their artwork to be reposted. +br + +h3 The List +.block + - route = fn p -> Routes.dnp_entry_path(@conn, :index, p) end + - pagination = render PhilomenaWeb.PaginationView, "_pagination.html", page: @dnp_entries, route: route, conn: @conn + + .block__header + span.block__header__title The DNP List + = pagination + + .block__content + table.table + thead + tr + th Tag + th Restriction + th Conditions + th Options + tbody + = for {body, entry} <- @dnp_entries do + tr + td + = render PhilomenaWeb.TagView, "_tag.html", tag: entry.tag, conn: @conn + td + = entry.dnp_type + td + == body + td + = link "More Info", to: Routes.dnp_entry_path(@conn, :show, entry) + + .block__header + = pagination diff --git a/lib/philomena_web/templates/dnp_entry/show.html.slime b/lib/philomena_web/templates/dnp_entry/show.html.slime new file mode 100644 index 00000000..b57a1b58 --- /dev/null +++ b/lib/philomena_web/templates/dnp_entry/show.html.slime @@ -0,0 +1,48 @@ +h2 + ' DNP Listing for Tag + = @dnp_entry.tag.name + +.block + .block__header + span.block__header__title DNP Information + = link "Back to DNP List", to: Routes.dnp_entry_path(@conn, :index) + + .block__content + table.table + tbody + tr + td Created: + td + = pretty_time(@dnp_entry.created_at) + tr + td Tag: + td + = render PhilomenaWeb.TagView, "_tag.html", tag: @dnp_entry.tag, conn: @conn + tr + td Restriction Type: + td + = @dnp_entry.dnp_type + tr + td Conditions: + td + == @conditions + + = if can?(@conn, :show_reason, @dnp_entry) do + tr + td Reason: + td + == @reason + + = if can?(@conn, :show_feedback, @dnp_entry) do + tr + td Instructions: + td + == @instructions + tr + td Feedback: + td + = @dnp_entry.feedback + tr + td Status: + td + = String.capitalize(@dnp_entry.aasm_state) \ No newline at end of file diff --git a/lib/philomena_web/views/dnp_entry_view.ex b/lib/philomena_web/views/dnp_entry_view.ex new file mode 100644 index 00000000..24a1077d --- /dev/null +++ b/lib/philomena_web/views/dnp_entry_view.ex @@ -0,0 +1,3 @@ +defmodule PhilomenaWeb.DnpEntryView do + use PhilomenaWeb, :view +end diff --git a/test/philomena_web/controllers/dnp_entry_controller_test.exs b/test/philomena_web/controllers/dnp_entry_controller_test.exs new file mode 100644 index 00000000..cd004a1d --- /dev/null +++ b/test/philomena_web/controllers/dnp_entry_controller_test.exs @@ -0,0 +1,88 @@ +defmodule PhilomenaWeb.DnpEntryControllerTest do + use PhilomenaWeb.ConnCase + + alias Philomena.DnpEntries + + @create_attrs %{} + @update_attrs %{} + @invalid_attrs %{} + + def fixture(:dnp_entry) do + {:ok, dnp_entry} = DnpEntries.create_dnp_entry(@create_attrs) + dnp_entry + end + + describe "index" do + test "lists all dnp_entries", %{conn: conn} do + conn = get(conn, Routes.dnp_entry_path(conn, :index)) + assert html_response(conn, 200) =~ "Listing Dnp entries" + end + end + + describe "new dnp_entry" do + test "renders form", %{conn: conn} do + conn = get(conn, Routes.dnp_entry_path(conn, :new)) + assert html_response(conn, 200) =~ "New Dnp entry" + end + end + + describe "create dnp_entry" do + test "redirects to show when data is valid", %{conn: conn} do + conn = post(conn, Routes.dnp_entry_path(conn, :create), dnp_entry: @create_attrs) + + assert %{id: id} = redirected_params(conn) + assert redirected_to(conn) == Routes.dnp_entry_path(conn, :show, id) + + conn = get(conn, Routes.dnp_entry_path(conn, :show, id)) + assert html_response(conn, 200) =~ "Show Dnp entry" + end + + test "renders errors when data is invalid", %{conn: conn} do + conn = post(conn, Routes.dnp_entry_path(conn, :create), dnp_entry: @invalid_attrs) + assert html_response(conn, 200) =~ "New Dnp entry" + end + end + + describe "edit dnp_entry" do + setup [:create_dnp_entry] + + test "renders form for editing chosen dnp_entry", %{conn: conn, dnp_entry: dnp_entry} do + conn = get(conn, Routes.dnp_entry_path(conn, :edit, dnp_entry)) + assert html_response(conn, 200) =~ "Edit Dnp entry" + end + end + + describe "update dnp_entry" do + setup [:create_dnp_entry] + + test "redirects when data is valid", %{conn: conn, dnp_entry: dnp_entry} do + conn = put(conn, Routes.dnp_entry_path(conn, :update, dnp_entry), dnp_entry: @update_attrs) + assert redirected_to(conn) == Routes.dnp_entry_path(conn, :show, dnp_entry) + + conn = get(conn, Routes.dnp_entry_path(conn, :show, dnp_entry)) + assert html_response(conn, 200) + end + + test "renders errors when data is invalid", %{conn: conn, dnp_entry: dnp_entry} do + conn = put(conn, Routes.dnp_entry_path(conn, :update, dnp_entry), dnp_entry: @invalid_attrs) + assert html_response(conn, 200) =~ "Edit Dnp entry" + end + end + + describe "delete dnp_entry" do + setup [:create_dnp_entry] + + test "deletes chosen dnp_entry", %{conn: conn, dnp_entry: dnp_entry} do + conn = delete(conn, Routes.dnp_entry_path(conn, :delete, dnp_entry)) + assert redirected_to(conn) == Routes.dnp_entry_path(conn, :index) + assert_error_sent 404, fn -> + get(conn, Routes.dnp_entry_path(conn, :show, dnp_entry)) + end + end + end + + defp create_dnp_entry(_) do + dnp_entry = fixture(:dnp_entry) + {:ok, dnp_entry: dnp_entry} + end +end