diff --git a/assets/css/common/global.scss b/assets/css/common/global.scss index 3985ee9a..b33377bd 100644 --- a/assets/css/common/global.scss +++ b/assets/css/common/global.scss @@ -30,6 +30,8 @@ $vote_up_color: #67af2b !default; $vote_down_color: #cf0001 !default; $hide_color: #cf0001 !default; +$destroyed_content_color: #ffdcdc !default; + $assistant_color: #eeceed !default; $tag_normal_color: #6f8f0e !default; diff --git a/assets/css/common/header.scss b/assets/css/common/header.scss index 717bcc6b..b92b9624 100644 --- a/assets/css/common/header.scss +++ b/assets/css/common/header.scss @@ -74,6 +74,7 @@ a.header__link:hover, .header__dropdown:hover > a { background: $header_field_color; color: $text_light_color; + -webkit-text-fill-color: $text_light_color; text-overflow: ellipsis; diff --git a/assets/css/themes/dark.scss b/assets/css/themes/dark.scss index 215b9eda..f1017115 100644 --- a/assets/css/themes/dark.scss +++ b/assets/css/themes/dark.scss @@ -17,6 +17,8 @@ $success_light_color: #144714 !default; $danger_light_color: #66211f !default; $warning_light_color: #7d4825 !default; +$destroyed_content_color: #382c2f !default; + $meta_color: #191f2a !default; $header_color: #284371 !default; diff --git a/assets/css/themes/red.scss b/assets/css/themes/red.scss index adc8d267..b3c7d138 100644 --- a/assets/css/themes/red.scss +++ b/assets/css/themes/red.scss @@ -22,6 +22,8 @@ $success_light_color: #2e4e2e !default; $danger_light_color: #7b3b00 !default; $warning_light_color: #5b5b00 !default; +$destroyed_content_color: #412f2f !default; + $meta_color: #411d1d !default; $header_color: #923131 !default; diff --git a/assets/css/views/communications.scss b/assets/css/views/communications.scss index d0a3b512..5809534f 100644 --- a/assets/css/views/communications.scss +++ b/assets/css/views/communications.scss @@ -97,3 +97,7 @@ span.communication__sender__stats, display: inline-block; margin-right: 2em; } + +.communication--destroyed { + background-color: $destroyed_content_color; +} diff --git a/lib/philomena/comments.ex b/lib/philomena/comments.ex index ae55ae10..dc8171d9 100644 --- a/lib/philomena/comments.ex +++ b/lib/philomena/comments.ex @@ -134,6 +134,24 @@ defmodule Philomena.Comments do Repo.delete(comment) end + def hide_comment(%Comment{} = comment, attrs, user) do + comment + |> Comment.hide_changeset(attrs, user) + |> Repo.update() + end + + def unhide_comment(%Comment{} = comment) do + comment + |> Comment.unhide_changeset() + |> Repo.update() + end + + def destroy_comment(%Comment{} = comment) do + comment + |> Comment.destroy_changeset() + |> Repo.update() + end + @doc """ Returns an `%Ecto.Changeset{}` for tracking comment changes. diff --git a/lib/philomena/comments/comment.ex b/lib/philomena/comments/comment.ex index 987ee79f..01cf2e72 100644 --- a/lib/philomena/comments/comment.ex +++ b/lib/philomena/comments/comment.ex @@ -50,6 +50,26 @@ defmodule Philomena.Comments.Comment do |> validate_length(:edit_reason, max: 70, count: :bytes) end + def hide_changeset(comment, attrs, user) do + comment + |> cast(attrs, [:deletion_reason]) + |> put_change(:hidden_from_users, true) + |> put_change(:deleted_by_id, user.id) + |> validate_required([:deletion_reason]) + end + + def unhide_changeset(comment) do + change(comment) + |> put_change(:hidden_from_users, false) + |> put_change(:deletion_reason, "") + end + + def destroy_changeset(comment) do + change(comment) + |> put_change(:destroyed_content, true) + |> put_change(:body, "") + end + defp put_name_at_post_time(changeset, nil), do: changeset defp put_name_at_post_time(changeset, user), do: change(changeset, name_at_post_time: user.name) end diff --git a/lib/philomena/posts.ex b/lib/philomena/posts.ex index 2c39ca7c..35345ce7 100644 --- a/lib/philomena/posts.ex +++ b/lib/philomena/posts.ex @@ -160,6 +160,24 @@ defmodule Philomena.Posts do Repo.delete(post) end + def hide_post(%Post{} = post, attrs, user) do + post + |> Post.hide_changeset(attrs, user) + |> Repo.update() + end + + def unhide_post(%Post{} = post) do + post + |> Post.unhide_changeset() + |> Repo.update() + end + + def destroy_post(%Post{} = post) do + post + |> Post.destroy_changeset() + |> Repo.update() + end + @doc """ Returns an `%Ecto.Changeset{}` for tracking post changes. diff --git a/lib/philomena/posts/post.ex b/lib/philomena/posts/post.ex index 393906e7..f2df618d 100644 --- a/lib/philomena/posts/post.ex +++ b/lib/philomena/posts/post.ex @@ -64,6 +64,26 @@ defmodule Philomena.Posts.Post do |> put_name_at_post_time(attribution[:user]) end + def hide_changeset(post, attrs, user) do + post + |> cast(attrs, [:deletion_reason]) + |> put_change(:hidden_from_users, true) + |> put_change(:deleted_by_id, user.id) + |> validate_required([:deletion_reason]) + end + + def unhide_changeset(post) do + change(post) + |> put_change(:hidden_from_users, false) + |> put_change(:deletion_reason, "") + end + + def destroy_changeset(post) do + change(post) + |> put_change(:destroyed_content, true) + |> put_change(:body, "") + end + defp put_name_at_post_time(changeset, nil), do: changeset defp put_name_at_post_time(changeset, user), do: change(changeset, name_at_post_time: user.name) end diff --git a/lib/philomena/users/ability.ex b/lib/philomena/users/ability.ex index 81b7bd67..a68286d0 100644 --- a/lib/philomena/users/ability.ex +++ b/lib/philomena/users/ability.ex @@ -57,6 +57,9 @@ defimpl Canada.Can, for: [Atom, Philomena.Users.User] do def can?(%User{role: "moderator"}, :edit, %UserLink{}), do: true def can?(%User{role: "moderator"}, :index, UserLink), do: true + # Reveal anon users + def can?(%User{role: "moderator"}, :reveal_anon, _object), do: true + # # Assistants can... # diff --git a/lib/philomena_web/controllers/image/comment/delete_controller.ex b/lib/philomena_web/controllers/image/comment/delete_controller.ex new file mode 100644 index 00000000..76c428e0 --- /dev/null +++ b/lib/philomena_web/controllers/image/comment/delete_controller.ex @@ -0,0 +1,26 @@ +defmodule PhilomenaWeb.Image.Comment.DeleteController do + use PhilomenaWeb, :controller + + alias Philomena.Comments.Comment + alias Philomena.Comments + + plug PhilomenaWeb.CanaryMapPlug, create: :hide, delete: :hide + plug :load_and_authorize_resource, model: Comment, id_name: "comment_id", persisted: true + + def delete(conn, _params) do + comment = conn.assigns.comment + + case Comments.destroy_comment(comment) do + {:ok, comment} -> + Comments.reindex_comment(comment) + + conn + |> put_flash(:info, "Comment successfully destroyed!") + |> redirect(to: Routes.image_path(conn, :show, comment.image_id) <> "#comment_#{comment.id}") + {:error, _changeset} -> + conn + |> put_flash(:error, "Unable to destroy comment!") + |> redirect(to: Routes.image_path(conn, :show, comment.image_id) <> "#comment_#{comment.id}") + end + end +end diff --git a/lib/philomena_web/controllers/image/comment/hide_controller.ex b/lib/philomena_web/controllers/image/comment/hide_controller.ex new file mode 100644 index 00000000..d1aecb24 --- /dev/null +++ b/lib/philomena_web/controllers/image/comment/hide_controller.ex @@ -0,0 +1,44 @@ +defmodule PhilomenaWeb.Image.Comment.HideController do + use PhilomenaWeb, :controller + + alias Philomena.Comments.Comment + alias Philomena.Comments + + plug PhilomenaWeb.CanaryMapPlug, create: :hide, delete: :hide + plug :load_and_authorize_resource, model: Comment, id_name: "comment_id", persisted: true + + def create(conn, %{"comment" => comment_params}) do + comment = conn.assigns.comment + user = conn.assigns.current_user + + case Comments.hide_comment(comment, comment_params, user) do + {:ok, comment} -> + Comments.reindex_comment(comment) + + conn + |> put_flash(:info, "Comment successfully hidden!") + |> redirect(to: Routes.image_path(conn, :show, comment.image_id) <> "#comment_#{comment.id}") + {:error, _changeset} -> + conn + |> put_flash(:error, "Unable to hide comment!") + |> redirect(to: Routes.image_path(conn, :show, comment.image_id) <> "#comment_#{comment.id}") + end + end + + def delete(conn, _params) do + comment = conn.assigns.comment + + case Comments.unhide_comment(comment) do + {:ok, comment} -> + Comments.reindex_comment(comment) + + conn + |> put_flash(:info, "Comment successfully unhidden!") + |> redirect(to: Routes.image_path(conn, :show, comment.image_id) <> "#comment_#{comment.id}") + {:error, _changeset} -> + conn + |> put_flash(:error, "Unable to unhide comment!") + |> redirect(to: Routes.image_path(conn, :show, comment.image_id) <> "#comment_#{comment.id}") + end + end +end diff --git a/lib/philomena_web/controllers/image_controller.ex b/lib/philomena_web/controllers/image_controller.ex index 646b4818..0032afc2 100644 --- a/lib/philomena_web/controllers/image_controller.ex +++ b/lib/philomena_web/controllers/image_controller.ex @@ -41,7 +41,7 @@ defmodule PhilomenaWeb.ImageController do comments = Comment |> where(image_id: ^image.id) - |> preload([:image, user: [awards: :badge]]) + |> preload([:image, :deleted_by, user: [awards: :badge]]) |> order_by(desc: :created_at) |> limit(25) |> Repo.paginate(conn.assigns.comment_scrivener) diff --git a/lib/philomena_web/controllers/topic/post/delete_controller.ex b/lib/philomena_web/controllers/topic/post/delete_controller.ex new file mode 100644 index 00000000..64334018 --- /dev/null +++ b/lib/philomena_web/controllers/topic/post/delete_controller.ex @@ -0,0 +1,26 @@ +defmodule PhilomenaWeb.Topic.Post.DeleteController do + use PhilomenaWeb, :controller + + alias Philomena.Posts.Post + alias Philomena.Posts + + plug PhilomenaWeb.CanaryMapPlug, create: :hide, delete: :hide + plug :load_and_authorize_resource, model: Post, id_name: "post_id", persisted: true, preload: [:topic] + + def delete(conn, _params) do + post = conn.assigns.post + + case Posts.destroy_post(post) do + {:ok, post} -> + Posts.reindex_post(post) + + conn + |> put_flash(:info, "Post successfully destroyed!") + |> redirect(to: Routes.forum_topic_path(conn, :show, post.topic.forum_id, post.topic_id) <> "#post_#{post.id}") + {:error, _changeset} -> + conn + |> put_flash(:error, "Unable to destroy post!") + |> redirect(to: Routes.forum_topic_path(conn, :show, post.topic.forum_id, post.topic_id) <> "#post_#{post.id}") + end + end +end diff --git a/lib/philomena_web/controllers/topic/post/hide_controller.ex b/lib/philomena_web/controllers/topic/post/hide_controller.ex new file mode 100644 index 00000000..11b9b193 --- /dev/null +++ b/lib/philomena_web/controllers/topic/post/hide_controller.ex @@ -0,0 +1,44 @@ +defmodule PhilomenaWeb.Topic.Post.HideController do + use PhilomenaWeb, :controller + + alias Philomena.Posts.Post + alias Philomena.Posts + + plug PhilomenaWeb.CanaryMapPlug, create: :hide, delete: :hide + plug :load_and_authorize_resource, model: Post, id_name: "post_id", persisted: true, preload: [:topic] + + def create(conn, %{"post" => post_params}) do + post = conn.assigns.post + user = conn.assigns.current_user + + case Posts.hide_post(post, post_params, user) do + {:ok, post} -> + Posts.reindex_post(post) + + conn + |> put_flash(:info, "Post successfully hidden!") + |> redirect(to: Routes.forum_topic_path(conn, :show, post.topic.forum_id, post.topic_id) <> "#post_#{post.id}") + {:error, _changeset} -> + conn + |> put_flash(:error, "Unable to hide post!") + |> redirect(to: Routes.forum_topic_path(conn, :show, post.topic.forum_id, post.topic_id) <> "#post_#{post.id}") + end + end + + def delete(conn, _params) do + post = conn.assigns.post + + case Posts.unhide_post(post) do + {:ok, post} -> + Posts.reindex_post(post) + + conn + |> put_flash(:info, "Post successfully unhidden!") + |> redirect(to: Routes.forum_topic_path(conn, :show, post.topic.forum_id, post.topic_id) <> "#post_#{post.id}") + {:error, _changeset} -> + conn + |> put_flash(:error, "Unable to unhide post!") + |> redirect(to: Routes.forum_topic_path(conn, :show, post.topic.forum_id, post.topic_id) <> "#post_#{post.id}") + end + end +end diff --git a/lib/philomena_web/controllers/topic_controller.ex b/lib/philomena_web/controllers/topic_controller.ex index ccb7949f..99083c6a 100644 --- a/lib/philomena_web/controllers/topic_controller.ex +++ b/lib/philomena_web/controllers/topic_controller.ex @@ -49,7 +49,7 @@ defmodule PhilomenaWeb.TopicController do |> where(topic_id: ^conn.assigns.topic.id) |> where([p], p.topic_position >= ^(25 * (page - 1)) and p.topic_position < ^(25 * page)) |> order_by(asc: :created_at) - |> preload([topic: :forum, user: [awards: :badge]]) + |> preload([:deleted_by, :topic, topic: :forum, user: [awards: :badge]]) |> Repo.all() rendered = diff --git a/lib/philomena_web/router.ex b/lib/philomena_web/router.ex index f355b67a..7eef54a1 100644 --- a/lib/philomena_web/router.ex +++ b/lib/philomena_web/router.ex @@ -115,7 +115,10 @@ defmodule PhilomenaWeb.Router do resources "/hide", Image.HideController, only: [:create, :delete], singleton: true resources "/subscription", Image.SubscriptionController, only: [:create, :delete], singleton: true resources "/read", Image.ReadController, only: [:create], singleton: true - resources "/comments", Image.CommentController, only: [:edit, :update] + resources "/comments", Image.CommentController, only: [:edit, :update] do + resources "/hide", Image.Comment.HideController, only: [:create, :delete], singleton: true + resources "/delete", Image.Comment.DeleteController, only: [:delete], singleton: true + end resources "/delete", Image.DeleteController, only: [:create, :delete], singleton: true end @@ -123,7 +126,10 @@ defmodule PhilomenaWeb.Router do resources "/topics", TopicController, only: [:new, :create] do resources "/subscription", Topic.SubscriptionController, only: [:create, :delete], singleton: true resources "/read", Topic.ReadController, only: [:create], singleton: true - resources "/posts", Topic.PostController, only: [:edit, :update] + resources "/posts", Topic.PostController, only: [:edit, :update] do + resources "/hide", Topic.Post.HideController, only: [:create, :delete], singleton: true + resources "/delete", Topic.Post.DeleteController, only: [:delete], singleton: true + end end resources "/subscription", Forum.SubscriptionController, only: [:create, :delete], singleton: true diff --git a/lib/philomena_web/templates/comment/_comment.html.slime b/lib/philomena_web/templates/comment/_comment.html.slime index 38ae6ee8..1b61f1b1 100644 --- a/lib/philomena_web/templates/comment/_comment.html.slime +++ b/lib/philomena_web/templates/comment/_comment.html.slime @@ -1,5 +1,5 @@ article.block.communication id="comment_#{@comment.id}" - .block__content.flex.flex--no-wrap + .block__content.flex.flex--no-wrap class=communication_body_class(@comment) .flex__fixed.spacing-right = render PhilomenaWeb.UserAttributionView, "_anon_user_avatar.html", object: @comment, conn: @conn .flex__grow.communication__body @@ -10,7 +10,19 @@ article.block.communication id="comment_#{@comment.id}" = if @comment.hidden_from_users do strong.comment_deleted ' Deletion reason: - => @comment.deletion_reason + =<> @comment.deletion_reason + = if can?(@conn, :hide, @comment) do + | ( + = @comment.deleted_by.name + | ) + = if can?(@conn, :hide, @comment) do + = if @comment.destroyed_content do + br + strong.comment_deleted> + | This comment's contents have been destroyed. + - else + br + ==<> @body - else ==<> @body .block__content.communication__options @@ -18,34 +30,25 @@ article.block.communication id="comment_#{@comment.id}" = render PhilomenaWeb.CommentView, "_comment_options.html", comment: @comment, conn: @conn = if can?(@conn, :hide, @comment) do .js-staff-action - / todo: make delete button work - a.communication__interaction.togglable-delete-form-link href="#" - i.fa.fa-times - =<> "Delete" - = if can?(@conn, :manage, @comment) do + = cond do + - @comment.hidden_from_users and not @comment.destroyed_content -> + = link(to: Routes.image_comment_hide_path(@conn, :delete, @comment.image_id, @comment), data: [confirm: "Are you sure?"], method: :delete, class: "communication__interaction") do + i.fas.fa-check> + ' Restore + = if can?(@conn, :delete, @comment) do + = link(to: Routes.image_comment_delete_path(@conn, :delete, @comment.image_id, @comment), data: [confirm: "Are you sure?"], method: :delete, class: "communication__interaction") do + i.fas.fa-times> + ' Delete Contents + - not @comment.hidden_from_users and not @comment.destroyed_content -> + a.communication__interaction.togglable-delete-form-link href="#" data-click-toggle="#inline-del-form-comment-#{@comment.id}" + i.fas.fa-times> + ' Delete + - true -> + = if can?(@conn, :show, :ip_address) do .communication__info =<> link_to_ip(@conn, @comment.ip) .communication__info =<> link_to_fingerprint(@conn, @comment.fingerprint) - /- if can?(:hide, Comment) - / .js-staff-action - / - if !comment.hidden_from_users && !comment.destroyed_content - / =<> link_to '#', class: 'communication__interaction togglable-delete-form-link', 'data-click-toggle': "#inline-del-form-comment-#{comment.id}" do - / i.fa.fa-times - / =<> 'Delete' - / - elsif comment.hidden_from_users && !comment.destroyed_content - / =<> link_to image_comment_hide_path(comment.image, comment), data: { confirm: t('are_you_sure') }, method: :delete, class: 'communication__interaction' do - / i.fa.fa-check - / =<> 'Restore' - / - if can?(:manage, Comment) - / =<> link_to image_comment_path(comment.image, comment), method: :delete, data: { confirm: t('are_you_sure') }, class: 'communication__interaction' do - / i.fa.fa-times - / =<> 'Delete Contents' - / - if can?(:manage, Comment) - / .communication__info - / =<> link_to_ip(comment.ip) - / .communication__info - / =<> link_to_fingerprint(comment.fingerprint, comment.user_agent) - / = form_tag image_comment_hide_path(comment.image, comment), class: 'togglable-delete-form hidden flex', id: "inline-del-form-comment-#{comment.id}" - / = text_field_tag :deletion_reason, nil, class: 'input input--wide', placeholder: 'Deletion Reason', id: "inline-del-reason-comment-#{comment.id}", required: true - / = submit_tag 'Delete', class: 'button' + = form_for :comment, Routes.image_comment_hide_path(@conn, :create, @comment.image_id, @comment), [class: "togglable-delete-form hidden flex", id: "inline-del-form-comment-#{@comment.id}"], fn f -> + = text_input f, :deletion_reason, class: "input input--wide", placeholder: "Deletion Reason", id: "inline-del-reason-comment-#{@comment.id}", required: true + = submit "Delete", class: "button" diff --git a/lib/philomena_web/templates/comment/_comment_options.html.slime b/lib/philomena_web/templates/comment/_comment_options.html.slime index 2a42210b..d6e17f3f 100644 --- a/lib/philomena_web/templates/comment/_comment_options.html.slime +++ b/lib/philomena_web/templates/comment/_comment_options.html.slime @@ -37,5 +37,5 @@ div span.owner-options strong a.communication__interaction href=Routes.image_comment_path(@conn, :edit, @comment.image, @comment) - i.fa.fa-pencil> + i.fas.fa-edit> ' Edit diff --git a/lib/philomena_web/templates/comment/_comment_with_image.html.slime b/lib/philomena_web/templates/comment/_comment_with_image.html.slime index 61092f6a..315ac8fd 100644 --- a/lib/philomena_web/templates/comment/_comment_with_image.html.slime +++ b/lib/philomena_web/templates/comment/_comment_with_image.html.slime @@ -1,5 +1,5 @@ article.block.communication id="comment_#{@comment.id}" - .block__content.flex.flex--no-wrap + .block__content.flex.flex--no-wrap class=communication_body_class(@comment) .flex__fixed.spacing-right .post-image-container = render PhilomenaWeb.ImageView, "_image_container.html", image: @comment.image, size: :thumb_tiny, conn: @conn @@ -14,10 +14,44 @@ article.block.communication id="comment_#{@comment.id}" = if @comment.hidden_from_users do strong.comment_deleted ' Deletion reason: - => @comment.deletion_reason - - else - ==<> @body + =<> @comment.deletion_reason + = if can?(@conn, :hide, @comment) do + | ( + = @comment.deleted_by.name + | ) + = if can?(@conn, :hide, @comment) do + = if @comment.destroyed_content do + br + strong.comment_deleted> + | This comment's contents have been destroyed. + - else + br + ==<> @body .block__content.communication__options .flex.flex--wrap.flex--spaced-out - = render PhilomenaWeb.CommentView, "_comment_options.html", comment: @comment, conn: @conn \ No newline at end of file + = render PhilomenaWeb.CommentView, "_comment_options.html", comment: @comment, conn: @conn + = if can?(@conn, :hide, @comment) do + .js-staff-action + = cond do + - @comment.hidden_from_users and not @comment.destroyed_content -> + = link(to: Routes.image_comment_hide_path(@conn, :delete, @comment.image_id, @comment), data: [confirm: "Are you sure?"], method: :delete, class: "communication__interaction") do + i.fas.fa-check> + ' Restore + = if can?(@conn, :delete, @comment) do + = link(to: Routes.image_comment_delete_path(@conn, :delete, @comment.image_id, @comment), data: [confirm: "Are you sure?"], method: :delete, class: "communication__interaction") do + i.fas.fa-times> + ' Delete Contents + - not @comment.hidden_from_users and not @comment.destroyed_content -> + a.communication__interaction.togglable-delete-form-link href="#" data-click-toggle="#inline-del-form-comment-#{@comment.id}" + i.fas.fa-times> + ' Delete + - true -> + = if can?(@conn, :show, :ip_address) do + .communication__info + =<> link_to_ip(@conn, @comment.ip) + .communication__info + =<> link_to_fingerprint(@conn, @comment.fingerprint) + = form_for :comment, Routes.image_comment_hide_path(@conn, :create, @comment.image_id, @comment), [class: "togglable-delete-form hidden flex", id: "inline-del-form-comment-#{@comment.id}"], fn f -> + = text_input f, :deletion_reason, class: "input input--wide", placeholder: "Deletion Reason", id: "inline-del-reason-comment-#{@comment.id}", required: true + = submit "Delete", class: "button" diff --git a/lib/philomena_web/templates/image/_image_meta.html.slime b/lib/philomena_web/templates/image/_image_meta.html.slime index b6cc461d..b8d82f38 100644 --- a/lib/philomena_web/templates/image/_image_meta.html.slime +++ b/lib/philomena_web/templates/image/_image_meta.html.slime @@ -54,7 +54,7 @@ span.image_uploader ' by => render PhilomenaWeb.UserAttributionView, "_anon_user.html", object: @image, awards: true, conn: @conn - = if can?(@conn, :manage, @image) do + = if can?(@conn, :show, :ip_address) do => link_to_ip(@conn, @image.ip) => link_to_fingerprint(@conn, @image.fingerprint) a href="#" diff --git a/lib/philomena_web/templates/post/_post.html.slime b/lib/philomena_web/templates/post/_post.html.slime index f626f117..f2add634 100644 --- a/lib/philomena_web/templates/post/_post.html.slime +++ b/lib/philomena_web/templates/post/_post.html.slime @@ -1,5 +1,5 @@ article.block.communication id="post_#{@post.id}" - .block__content.flex.flex--no-wrap + .block__content.flex.flex--no-wrap class=communication_body_class(@post) .flex__fixed.spacing-right = render PhilomenaWeb.UserAttributionView, "_anon_user_avatar.html", object: @post, conn: @conn .flex__grow.communication__body @@ -11,40 +11,43 @@ article.block.communication id="post_#{@post.id}" strong.comment_deleted ' Deletion reason: => @post.deletion_reason + = if can?(@conn, :hide, @post) do + | ( + = @post.deleted_by.name + | ) + = if can?(@conn, :hide, @post) do + = if @post.destroyed_content do + br + strong.comment_deleted> + | This post's contents have been destroyed. + - else + br + ==<> @body - else ==<> @body .block__content.communication__options .flex.flex--wrap.flex--spaced-out = render PhilomenaWeb.PostView, "_post_options.html", conn: @conn, post: @post = if can?(@conn, :hide, @post) do - / todo: make post deletion work - a.communication__interaction.togglable-delete-form-link href="#" - i.fa.fa-times - =<> "Delete" - = if can?(@conn, :manage, @post) do + = cond do + - @post.hidden_from_users and not @post.destroyed_content -> + = link(to: Routes.forum_topic_post_hide_path(@conn, :delete, @post.topic.forum, @post.topic, @post), data: [confirm: "Are you sure?"], method: :delete, class: "communication__interaction") do + i.fas.fa-check> + ' Restore + = if can?(@conn, :delete, @post) do + = link(to: Routes.forum_topic_post_delete_path(@conn, :delete, @post.topic.forum, @post.topic, @post), data: [confirm: "Are you sure?"], method: :delete, class: "communication__interaction") do + i.fas.fa-times> + ' Delete Contents + - not @post.hidden_from_users and not @post.destroyed_content -> + a.communication__interaction.togglable-delete-form-link href="#" data-click-toggle="#inline-del-form-post-#{@post.id}" + i.fa.fa-times> + ' Delete + - true -> + = if can?(@conn, :show, :ip_address) do .communication__info =<> link_to_ip(@conn, @post.ip) .communication__info =<> link_to_fingerprint(@conn, @post.fingerprint) - /- if can?(:hide, Post) - / .js-staff-action - / - if !post.hidden_from_users && !post.destroyed_content - / =<> link_to '#', class: 'communication__interaction togglable-delete-form-link', 'data-click-toggle': "#inline-del-form-post-#{post.id}" do - / i.fa.fa-times - / =<> 'Delete' - / - elsif post.hidden_from_users && !post.destroyed_content - / =<> link_to forum_topic_post_hide_path(post.topic.forum, post.topic, post), data: { confirm: t('are_you_sure') }, method: :delete, class: 'communication__interaction' do - / i.fa.fa-check - / =<> 'Restore' - / - if can?(:manage, Post) - / =<> link_to forum_topic_post_path(post.topic.forum, post.topic, post, deletion_reason: post.deletion_reason), method: :delete, data: { confirm: t('are_you_sure') }, class: 'communication__interaction' do - / i.fa.fa-times - / =<> 'Delete Contents' - / - if can?(:manage, Post) - / .communication__info - / =<> link_to_ip(post.ip) - / .communication__info - / =<> link_to_fingerprint(post.fingerprint, post.user_agent) - / = form_tag forum_topic_post_hide_path(post.topic.forum, post.topic, post), class: 'togglable-delete-form hidden flex', id: "inline-del-form-post-#{post.id}" - / = text_field_tag :deletion_reason, nil, class: 'input input--wide', placeholder: 'Deletion Reason', id: "inline-del-reason-post-#{post.id}", required: true - / = submit_tag 'Delete', class: 'button' + = form_for :post, Routes.forum_topic_post_hide_path(@conn, :create, @post.topic.forum, @post.topic, @post), [class: "togglable-delete-form hidden flex", id: "inline-del-form-post-#{@post.id}"], fn f -> + = text_input f, :deletion_reason, class: "input input--wide", placeholder: "Deletion Reason", id: "inline-del-reason-post-#{@post.id}", required: true + = submit "Delete", class: "button" diff --git a/lib/philomena_web/templates/post/_post_options.html.slime b/lib/philomena_web/templates/post/_post_options.html.slime index cd83745c..08ea46b7 100644 --- a/lib/philomena_web/templates/post/_post_options.html.slime +++ b/lib/philomena_web/templates/post/_post_options.html.slime @@ -37,5 +37,5 @@ div span.owner-options strong a.communication__interaction href=Routes.forum_topic_post_path(@conn, :edit, @post.topic.forum, @post.topic, @post) - i.fa.fa-pencil> + i.fa.fa-edit> ' Edit diff --git a/lib/philomena_web/templates/topic/show.html.slime b/lib/philomena_web/templates/topic/show.html.slime index 7ad43354..6458dc66 100644 --- a/lib/philomena_web/templates/topic/show.html.slime +++ b/lib/philomena_web/templates/topic/show.html.slime @@ -35,7 +35,7 @@ h1 = @topic.title / The actual posts .posts-area .post-list - = for {post, body} <- @posts, !post.destroyed_content do + = for {post, body} <- @posts, (!post.destroyed_content or can?(@conn, :hide, post)) do = render PhilomenaWeb.PostView, "_post.html", conn: @conn, post: post, body: body = if @conn.assigns.advert do diff --git a/lib/philomena_web/templates/user_attribution/_anon_user.html.slime b/lib/philomena_web/templates/user_attribution/_anon_user.html.slime index 92ec0b37..d02c1a6b 100644 --- a/lib/philomena_web/templates/user_attribution/_anon_user.html.slime +++ b/lib/philomena_web/templates/user_attribution/_anon_user.html.slime @@ -5,4 +5,7 @@ = render PhilomenaWeb.ProfileView, "_awards.html", awards: @object.user.awards - else strong<> - = anonymous_name(@object) \ No newline at end of file + = if can?(@conn, :reveal_anon, @object) do + = link(anonymous_name(@object, true), to: Routes.profile_path(@conn, :show, @object.user)) + - else + = anonymous_name(@object) diff --git a/lib/philomena_web/templates/user_attribution/_anon_user_avatar.html.slime b/lib/philomena_web/templates/user_attribution/_anon_user_avatar.html.slime index d411abaa..dccab704 100644 --- a/lib/philomena_web/templates/user_attribution/_anon_user_avatar.html.slime +++ b/lib/philomena_web/templates/user_attribution/_anon_user_avatar.html.slime @@ -1,4 +1,4 @@ = if !!@object.user and !anonymous?(@object) do = user_avatar(@object, assigns[:class] || "avatar--100px") - else - = anonymous_avatar(@object, assigns[:class] || "avatar--100px") \ No newline at end of file + = anonymous_avatar(@object, assigns[:class] || "avatar--100px") diff --git a/lib/philomena_web/views/app_view.ex b/lib/philomena_web/views/app_view.ex index b3b5ff3c..58537281 100644 --- a/lib/philomena_web/views/app_view.ex +++ b/lib/philomena_web/views/app_view.ex @@ -127,16 +127,31 @@ defmodule PhilomenaWeb.AppView do end defp text_or_na(nil), do: "N/A" - defp text_or_na(text), do: text + defp text_or_na(text), do: to_string(text) def link_to_ip(conn, ip) do - link(text_or_na(ip), to: Routes.ip_profile_path(conn, :show, to_string(ip))) + link(to: Routes.ip_profile_path(conn, :show, to_string(ip))) do + [ + content_tag(:i, "", class: "fas fa-network-wired"), + " ", + text_or_na(ip) + ] + end end def link_to_fingerprint(conn, fp) do - link(String.slice(text_or_na(fp), 0..6), to: Routes.fingerprint_profile_path(conn, :show, fp)) + link(to: Routes.fingerprint_profile_path(conn, :show, fp)) do + [ + content_tag(:i, "", class: "fas fa-desktop"), + " ", + String.slice(text_or_na(fp), 0..6) + ] + end end + def communication_body_class(%{destroyed_content: true}), do: "communication--destroyed" + def communication_body_class(_communication), do: nil + def blank?(nil), do: true def blank?(""), do: true def blank?([]), do: true diff --git a/lib/philomena_web/views/user_attribution_view.ex b/lib/philomena_web/views/user_attribution_view.ex index 49d12748..b05ebef1 100644 --- a/lib/philomena_web/views/user_attribution_view.ex +++ b/lib/philomena_web/views/user_attribution_view.ex @@ -7,7 +7,7 @@ defmodule PhilomenaWeb.UserAttributionView do Attribution.anonymous?(object) end - def anonymous_name(object) do + def anonymous_name(object, reveal_anon? \\ false) do salt = anonymous_name_salt() id = Attribution.object_identifier(object) user_id = Attribution.best_user_identifier(object) @@ -17,7 +17,10 @@ defmodule PhilomenaWeb.UserAttributionView do |> Integer.to_string(16) |> String.pad_leading(4, "0") - "Background Pony ##{hash}" + case reveal_anon? do + true -> "#{object.user.name} (##{hash}, hidden)" + false -> "Background Pony ##{hash}" + end end def anonymous_avatar(_object, class \\ "avatar--100px") do