admin mod notes

This commit is contained in:
byte[] 2019-12-15 17:52:51 -05:00
parent e37ab2849e
commit 299e0cf923
12 changed files with 197 additions and 8 deletions

View file

@ -49,8 +49,8 @@ defmodule Philomena.ModNotes do
{:error, %Ecto.Changeset{}}
"""
def create_mod_note(attrs \\ %{}) do
%ModNote{}
def create_mod_note(creator, attrs \\ %{}) do
%ModNote{moderator_id: creator.id}
|> ModNote.changeset(attrs)
|> Repo.insert()
end

View file

@ -12,7 +12,8 @@ defmodule Philomena.ModNotes.ModNote do
field :notable_type, :string
field :body, :string
field :deleted, :boolean, default: false
field :notable, :any, virtual: true
timestamps(inserted_at: :created_at)
end
@ -20,7 +21,8 @@ defmodule Philomena.ModNotes.ModNote do
@doc false
def changeset(mod_note, attrs) do
mod_note
|> cast(attrs, [])
|> validate_required([])
|> cast(attrs, [:notable_id, :notable_type, :body])
|> validate_required([:notable_id, :notable_type, :body])
|> validate_inclusion(:notable_type, ["User", "Report", "DnpEntry"])
end
end

View file

@ -7,12 +7,14 @@ defmodule Philomena.Polymorphic do
"Comment" => Philomena.Comments.Comment,
"Commission" => Philomena.Commissions.Commission,
"Conversation" => Philomena.Conversations.Conversation,
"DnpEntry" => Philomena.DnpEntries.DnpEntry,
"Filter" => Philomena.Filters.Filter,
"Forum" => Philomena.Forums.Forum,
"Gallery" => Philomena.Galleries.Gallery,
"Image" => Philomena.Images.Image,
"LivestreamChannel" => Philomena.Channels.Channel,
"Post" => Philomena.Posts.Post,
"Report" => Philomena.Reports.Report,
"Topic" => Philomena.Topics.Topic,
"User" => Philomena.Users.User
}
@ -21,10 +23,12 @@ defmodule Philomena.Polymorphic do
"Comment" => [:user, image: :tags],
"Commission" => [:user],
"Conversation" => [:from, :to],
"DnpEntry" => [:requesting_user],
"Gallery" => [:creator],
"Image" => [:user, :tags],
"Post" => [:user, topic: :forum],
"Topic" => [:forum, :user]
"Topic" => [:forum, :user],
"Report" => [:user]
}
# Deal with Rails polymorphism BS
@ -64,4 +68,4 @@ defmodule Philomena.Polymorphic do
%{struct | name => row}
end)
end
end
end

View file

@ -9,6 +9,7 @@ defimpl Canada.Can, for: [Atom, Philomena.Users.User] do
alias Philomena.Images.Image
alias Philomena.Forums.Forum
alias Philomena.Topics.Topic
alias Philomena.ModNotes.ModNote
alias Philomena.Posts.Post
alias Philomena.Filters.Filter
alias Philomena.Galleries.Gallery
@ -97,6 +98,9 @@ defimpl Canada.Can, for: [Atom, Philomena.Users.User] do
# Award badges
def can?(%User{role: "moderator"}, :create, %Award{}), do: true
# Create mod notes
def can?(%User{role: "moderator"}, :index, ModNote), do: true
#
# Assistants can...
#

View file

@ -0,0 +1,92 @@
defmodule PhilomenaWeb.Admin.ModNoteController do
use PhilomenaWeb, :controller
alias Philomena.Textile.Renderer
alias Philomena.ModNotes.ModNote
alias Philomena.Polymorphic
alias Philomena.ModNotes
alias Philomena.Repo
import Ecto.Query
plug :verify_authorized
plug :load_resource, model: ModNote, only: [:edit, :update, :delete]
plug :preload_association when action in [:edit, :update, :delete]
def index(conn, %{"q" => q}) do
ModNote
|> where([m], ilike(m.body, ^"%#{q}%"))
|> load_mod_notes(conn)
end
def index(conn, _params) do
load_mod_notes(ModNote, conn)
end
defp load_mod_notes(queryable, conn) do
mod_notes =
queryable
|> preload(:moderator)
|> Repo.paginate(conn.assigns.scrivener)
bodies = Renderer.render_collection(mod_notes, conn)
preloaded = Polymorphic.load_polymorphic(mod_notes, notable: [notable_id: :notable_type])
mod_notes = %{mod_notes | entries: Enum.zip(bodies, preloaded)}
render(conn, "index.html", mod_notes: mod_notes)
end
def new(conn, %{"notable_type" => type, "notable_id" => id}) do
changeset = ModNotes.change_mod_note(%ModNote{notable_type: type, notable_id: id})
render(conn, "new.html", changeset: changeset)
end
def create(conn, %{"mod_note" => mod_note_params}) do
case ModNotes.create_mod_note(conn.assigns.current_user, mod_note_params) do
{:ok, _mod_note} ->
conn
|> put_flash(:info, "Successfully created mod note.")
|> redirect(to: Routes.admin_mod_note_path(conn, :index))
{:error, changeset} ->
render(conn, "new.html", changeset: changeset)
end
end
def edit(conn, _params) do
changeset = ModNotes.change_mod_note(conn.assigns.mod_note)
render(conn, "edit.html", changeset: changeset)
end
def update(conn, %{"mod_note" => mod_note_params}) do
case ModNotes.update_mod_note(conn.assigns.mod_note, mod_note_params) do
{:ok, _mod_note} ->
conn
|> put_flash(:info, "Successfully updated mod note.")
|> redirect(to: Routes.admin_mod_note_path(conn, :index))
{:error, changeset} ->
render(conn, "edit.html", changeset: changeset)
end
end
def delete(conn, _params) do
{:ok, _mod_note} = ModNotes.delete_mod_note(conn.assigns.mod_note)
conn
|> put_flash(:info, "Successfully deleted mod note.")
|> redirect(to: Routes.admin_mod_note_path(conn, :index))
end
defp verify_authorized(conn, _opts) do
case Canada.Can.can?(conn.assigns.current_user, :index, ModNote) do
true -> conn
_false -> PhilomenaWeb.NotAuthorizedPlug.call(conn)
end
end
def preload_association(%{assigns: %{mod_note: mod_note}} = conn, _opts) do
[mod_note] = Polymorphic.load_polymorphic([mod_note], notable: [notable_id: :notable_type])
assign(conn, :mod_note, mod_note)
end
end

View file

@ -205,6 +205,7 @@ defmodule PhilomenaWeb.Router do
resources "/forums", ForumController, except: [:show, :delete]
resources "/badges", BadgeController, except: [:show, :delete]
resources "/mod_notes", ModNoteController, except: [:show]
end
resources "/duplicate_reports", DuplicateReportController, only: [] do

View file

@ -0,0 +1,15 @@
= form_for @changeset, @action, fn f ->
= if @changeset.action do
.alert.alert-danger
p Oops, something went wrong! Please check the errors below.
.field
=> label f, :body, "Note"
= text_input f, :body, class: "input input--wide", required: true
= error_tag f, :body
= hidden_input f, :notable_id
= hidden_input f, :notable_type
.field
= submit "Save", class: "button"

View file

@ -0,0 +1,6 @@
h2
' Editing mod note for
=> @mod_note.notable_type
=> @mod_note.notable_id
= render PhilomenaWeb.Admin.ModNoteView, "_form.html", changeset: @changeset, action: Routes.admin_mod_note_path(@conn, :update, @mod_note), conn: @conn

View file

@ -0,0 +1,38 @@
- route = fn p -> Routes.admin_mod_note_path(@conn, :index, p) end
- pagination = render PhilomenaWeb.PaginationView, "_pagination.html", page: @mod_notes, route: route, conn: @conn
h2 Mod Notes
.block
.block__header
span.block__header__title Mod Notes
= pagination
.block__content
table.table
thead
tr
td Object
td Note
td Time
td Moderator
td Actions
tbody
= for {body, note} <- @mod_notes do
tr
td
= link_to_noted_thing(@conn, note.notable)
td
== body
td
= pretty_time note.created_at
td
= link note.moderator.name, to: Routes.profile_path(@conn, :show, note.moderator)
td
=> link "Edit", to: Routes.admin_mod_note_path(@conn, :edit, note)
' &bull;
=> link "Delete", to: Routes.admin_mod_note_path(@conn, :delete, note), data: [confirm: "Are you really, really sure?", method: "delete"]

View file

@ -0,0 +1,6 @@
h2
' New mod note for
=> @conn.params["notable_type"]
=> @conn.params["notable_id"]
= render PhilomenaWeb.Admin.ModNoteView, "_form.html", changeset: @changeset, action: Routes.admin_mod_note_path(@conn, :create), conn: @conn

View file

@ -37,7 +37,7 @@
' Pages
= if manages_mod_notes?(@conn) do
= link to: "#", class: "header__link" do
= link to: Routes.admin_mod_note_path(@conn, :index), class: "header__link" do
i.fa.fa-fw.fa-sticky-note>
' Mod Notes

View file

@ -0,0 +1,21 @@
defmodule PhilomenaWeb.Admin.ModNoteView do
use PhilomenaWeb, :view
alias Philomena.Users.User
alias Philomena.Reports.Report
alias Philomena.DnpEntries.DnpEntry
def link_to_noted_thing(conn, %DnpEntry{requesting_user: user} = dnp_entry),
do: link("#{user.name}'s DNP entry", to: Routes.dnp_entry_path(conn, :show, dnp_entry))
def link_to_noted_thing(conn, %Report{user: nil} = report),
do: link("Report #{report.id}", to: Routes.admin_report_path(conn, :show, report))
def link_to_noted_thing(conn, %Report{user: user} = report),
do: link("Report #{report.id} by #{user.name}", to: Routes.admin_report_path(conn, :show, report))
def link_to_noted_thing(conn, %User{} = user),
do: link("User #{user.name}", to: Routes.profile_path(conn, :show, user))
def link_to_noted_thing(_conn, notable), do: "Item permanently deleted"
end