From 5780ed57689339542e756787b8770b73f78a94eb Mon Sep 17 00:00:00 2001 From: evazion Date: Wed, 20 Jan 2021 03:10:59 -0600 Subject: [PATCH] comments: add scores, rework comment menu. * Add comment scores. * Rework voting buttons so that you can click the upvote/downvote buttons to toggle votes. * Hide the edit, delete, undelete, and report buttons behind a popup menu. * Show the upvote/downvote/reply buttons to logged out users. Redirect them to the login page instead. --- CHANGELOG.md | 2 + app/components/comment_component.rb | 16 ++- .../comment_component.html.erb | 112 ++++++++++++------ .../comment_component/comment_component.scss | 29 ++++- app/components/comment_section_component.rb | 2 +- .../forum_post_component.html.erb | 2 +- .../popup_menu_component.js | 9 ++ .../popup_menu_component.scss | 13 +- app/javascript/src/javascripts/utility.js | 4 + app/javascript/src/styles/base/020_base.scss | 2 +- .../src/styles/common/messages.scss | 2 +- app/models/comment.rb | 5 - app/policies/comment_policy.rb | 7 +- app/views/comment_votes/create.js.erb | 4 +- app/views/comment_votes/destroy.js.erb | 4 +- 15 files changed, 149 insertions(+), 64 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 0b080a19b..10c9e0938 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -15,6 +15,8 @@ * You can now see the list of comments and forum posts you've reported to the moderators at . +* Comment scores are now visible and the vote buttons have been reworked. + * You can now see when a post has deleted comments. Deleted comments are now replaced with the word `[deleted]`, instead of being completely hidden. diff --git a/app/components/comment_component.rb b/app/components/comment_component.rb index fbae1fadf..d4a9427cb 100644 --- a/app/components/comment_component.rb +++ b/app/components/comment_component.rb @@ -23,7 +23,21 @@ class CommentComponent < ApplicationComponent comment.is_deleted? && !policy(comment).can_see_deleted? end - def has_moderation_reports? + def votable? + !comment.is_deleted? || current_user.is_moderator? + end + + def upvoted? + return false if current_user.is_anonymous? + comment.votes.select(&:is_positive?).map(&:user_id).include?(current_user.id) + end + + def downvoted? + return false if current_user.is_anonymous? + comment.votes.select(&:is_negative?).map(&:user_id).include?(current_user.id) + end + + def reported? policy(ModerationReport).can_see_moderation_reports? && comment.moderation_reports.present? end end diff --git a/app/components/comment_component/comment_component.html.erb b/app/components/comment_component/comment_component.html.erb index 1267e9a29..f15579acd 100644 --- a/app/components/comment_component/comment_component.html.erb +++ b/app/components/comment_component/comment_component.html.erb @@ -10,8 +10,10 @@ data-is-sticky="<%= comment.is_sticky? %>" data-is-dimmed="<%= dimmed? %>" data-is-thresholded="<%= thresholded? %>" - data-is-reported="<%= has_moderation_reports? %>" - data-is-voted="<%= comment.voted_by?(current_user) %>"> + data-is-reported="<%= reported? %>" + data-is-upvoted="<%= upvoted? %>" + data-is-downvoted="<%= downvoted? %>"> +
<% if redact_deleted? %> @@ -25,6 +27,7 @@
<%= link_to time_ago_in_words_tagged(comment.created_at), post_path(comment.post, anchor: "comment_#{comment.id}"), class: "message-timestamp" %>
+
<% if thresholded? %> <%= link_to "[hidden]", "javascript:void(0)", class: "unhide-comment-link" %> @@ -41,42 +44,81 @@ <% end %> + <% if votable? %> +
  • + <% if current_user.is_anonymous? %> + <%= link_to "🡹", login_path(url: request.fullpath), class: "comment-upvote-link" %> + <% elsif upvoted? %> + <%= link_to "🡹", comment_comment_votes_path(comment_id: comment.id), class: "comment-upvote-link comment-unvote-link", method: :delete, remote: true %> + <% else %> + <%= link_to "🡹", comment_comment_votes_path(comment_id: comment.id, score: "up"), class: "comment-upvote-link", method: :post, remote: true %> + <% end %> + + <%= comment.score %> + + <% if current_user.is_anonymous? %> + <%= link_to "🡻", login_path(url: request.fullpath), class: "comment-downvote-link" %> + <% elsif downvoted? %> + <%= link_to "🡻", comment_comment_votes_path(comment_id: comment.id), class: "comment-downvote-link comment-unvote-link", method: :delete, remote: true %> + <% else %> + <%= link_to "🡻", comment_comment_votes_path(comment_id: comment.id, score: "down"), class: "comment-downvote-link", method: :post, remote: true %> + <% end %> +
  • + <% end %> + <% if policy(comment).reply? %> - <% if context == :index_by_comment %> -
  • <%= link_to "Reply", new_comment_path(id: comment, comment: { post_id: comment.post_id }), class: "reply-link" %>
  • - <% else %> -
  • <%= link_to "Reply", new_comment_path(id: comment, comment: { post_id: comment.post_id }), class: "reply-link", remote: true %>
  • +
  • + <% if current_user.is_anonymous? %> + <%= link_to "Reply", login_path(url: request.fullpath) %> + <% elsif context == :index_by_comment %> + <%= link_to "Reply", new_comment_path(id: comment, comment: { post_id: comment.post_id }) %> + <% else %> + <%= link_to "Reply", new_comment_path(id: comment, comment: { post_id: comment.post_id }), remote: true %> + <% end %> +
  • + <% end %> + + <% if reported? %> +
  • + Reported (<%= link_to pluralize(comment.moderation_reports.length, "report"), moderation_reports_path(search: { model_type: "Comment", model_id: comment.id }) %>) +
  • + <% end %> + + <% if policy(comment).update? || policy(comment).reportable? %> + <%= render PopupMenuComponent.new do |menu| %> + <% if policy(comment).update? %> + <%= menu.item do %> + <%= link_to edit_comment_path(comment.id), id: "edit_comment_link_#{comment.id}", class: "edit_comment_link" do %> + + Edit + <% end %> + <% end %> + + <%= menu.item do %> + <% if comment.is_deleted? %> + <%= link_to undelete_comment_path(comment.id), method: :post, remote: true do %> + + Undelete + <% end %> + <% else %> + <%= link_to comment_path(comment.id), "data-confirm": "Are you sure you want to delete this comment?", method: :delete, remote: true do %> + + Delete + <% end %> + <% end %> + <% end %> + <% end %> + + <% if policy(comment).reportable? %> + <%= menu.item do %> + <%= link_to new_moderation_report_path(moderation_report: { model_type: "Comment", model_id: comment.id }), remote: true do %> + + Report + <% end %> + <% end %> + <% end %> <% end %> <% end %> - - <% if policy(comment).update? %> - <% if comment.is_deleted? %> -
  • <%= link_to "Undelete", undelete_comment_path(comment.id), method: :post, remote: true %>
  • - <% else %> -
  • <%= link_to "Delete", comment_path(comment.id), "data-confirm": "Are you sure you want to delete this comment?", method: :delete, remote: true %>
  • - <% end %> -
  • <%= link_to "Edit", edit_comment_path(comment.id), id: "edit_comment_link_#{comment.id}", class: "edit_comment_link" %>
  • - <% end %> - - <% if policy(comment).vote? %> - - - - <% end %> - - <% if policy(comment).reportable? %> -
  • <%= link_to "Report", new_moderation_report_path(moderation_report: { model_type: "Comment", model_id: comment.id }), remote: true %>
  • - <% end %> - - <% if has_moderation_reports? %> -
  • This comment has been reported! (<%= link_to pluralize(comment.moderation_reports.length, "report"), moderation_reports_path(search: { model_type: "Comment", model_id: comment.id }) %>)
  • - <% end %>
    <% if policy(comment).update? %> diff --git a/app/components/comment_component/comment_component.scss b/app/components/comment_component/comment_component.scss index edb5ce61f..a685f355b 100644 --- a/app/components/comment_component/comment_component.scss +++ b/app/components/comment_component/comment_component.scss @@ -9,15 +9,15 @@ article.comment { background-color: var(--moderation-report-background-color); } - &[data-is-voted="true"] { - .comment-vote-up-link, .comment-vote-down-link { - display: none; + &[data-is-upvoted="true"] { + a.comment-upvote-link { + color: var(--link-color); } } - &[data-is-voted="false"] { - .comment-unvote-link { - display: none; + &[data-is-downvoted="true"] { + a.comment-downvote-link { + color: var(--link-color); } } @@ -38,4 +38,21 @@ article.comment { font-weight: bold; color: var(--moderation-report-text-color); } + + .comment-votes { + color: var(--muted-text-color); + + a { + color: var(--muted-text-color); + + &:hover { + color: var(--link-color); + } + } + } + + .popup-menu { + width: 1.5em; + height: 1.5em; + } } diff --git a/app/components/comment_section_component.rb b/app/components/comment_section_component.rb index 341ea6c8e..cc8bf85d0 100644 --- a/app/components/comment_section_component.rb +++ b/app/components/comment_section_component.rb @@ -11,7 +11,7 @@ class CommentSectionComponent < ApplicationComponent @comments = @post.comments.order(id: :asc) @comments = @comments.includes(:creator) @comments = @comments.includes(:votes) if !current_user.is_anonymous? - @comments = @comments.includes(:moderation_reports) if policy(ModerationReport).show? + @comments = @comments.includes(:moderation_reports) if policy(ModerationReport).can_see_moderation_reports? @comments = @comments.last(limit) if limit.present? @dtext_data = DText.preprocess(@comments.map(&:body)) diff --git a/app/components/forum_post_component/forum_post_component.html.erb b/app/components/forum_post_component/forum_post_component.html.erb index 46eb19f5b..343bedce6 100644 --- a/app/components/forum_post_component/forum_post_component.html.erb +++ b/app/components/forum_post_component/forum_post_component.html.erb @@ -41,7 +41,7 @@
  • <%= link_to "Report", new_moderation_report_path(moderation_report: { model_type: "ForumPost", model_id: forum_post.id }), remote: true, title: "Report this forum post to the moderators" %>
  • <% end %> <% if has_moderation_reports? %> -
  • This post has been reported! (<%= link_to pluralize(forum_post.moderation_reports.length, "report"), moderation_reports_path(search: { model_type: "ForumPost", model_id: forum_post.id }) %>)
  • +
  • Reported (<%= link_to pluralize(forum_post.moderation_reports.length, "report"), moderation_reports_path(search: { model_type: "ForumPost", model_id: forum_post.id }) %>)
  • <% end %> <% if forum_post.bulk_update_request.present? %>
      diff --git a/app/components/popup_menu_component/popup_menu_component.js b/app/components/popup_menu_component/popup_menu_component.js index 272e1ddc3..59cfcfd11 100644 --- a/app/components/popup_menu_component/popup_menu_component.js +++ b/app/components/popup_menu_component/popup_menu_component.js @@ -10,8 +10,11 @@ class PopupMenuComponent { target: "a.popup-menu-button", placement: "bottom-start", trigger: "click", + animation: null, content: PopupMenuComponent.content, }); + + $(document).on("click.danbooru", ".popup-menu-content", PopupMenuComponent.onMenuItemClicked); } static content(element) { @@ -19,6 +22,12 @@ class PopupMenuComponent { $content.show(); return $content.get(0); } + + // Hides the menu when a menu item is clicked. + static onMenuItemClicked(event) { + let tippy = $(event.target).parents("[data-tippy-root]").get(0)._tippy; + tippy.hide(); + } } $(document).ready(PopupMenuComponent.initialize); diff --git a/app/components/popup_menu_component/popup_menu_component.scss b/app/components/popup_menu_component/popup_menu_component.scss index 684973d3c..03460647b 100644 --- a/app/components/popup_menu_component/popup_menu_component.scss +++ b/app/components/popup_menu_component/popup_menu_component.scss @@ -1,4 +1,6 @@ div.popup-menu { + display: inline-block; + a.popup-menu-button { display: flex; align-items: center; @@ -8,7 +10,8 @@ div.popup-menu { border-radius: 50%; color: var(--muted-text-color); - &:hover { + &:focus, &:hover { + color: var(--link-color); background-color: var(--subnav-menu-background-color); } } @@ -16,8 +19,12 @@ div.popup-menu { ul.popup-menu-content { display: none; - .icon { - width: 1.5em; + li { + margin: 0 2em 0.25em 0; + + i.icon { + width: 2em; + } } } } diff --git a/app/javascript/src/javascripts/utility.js b/app/javascript/src/javascripts/utility.js index 03e831858..9c77f25a3 100644 --- a/app/javascript/src/javascripts/utility.js +++ b/app/javascript/src/javascripts/utility.js @@ -1,4 +1,5 @@ import Rails from '@rails/ujs'; +import { hideAll } from 'tippy.js'; let Utility = {}; @@ -70,6 +71,9 @@ Utility.dialog = function(title, html) { $dialog.find("form").on("submit.danbooru", function() { $dialog.dialog("close"); }); + + // XXX hides the popup menu when the Report comment button is clicked. + hideAll({ duration: 0 }); } Utility.keydown = function(keys, namespace, handler, selector = document) { diff --git a/app/javascript/src/styles/base/020_base.scss b/app/javascript/src/styles/base/020_base.scss index 3230c5db2..91b380a10 100644 --- a/app/javascript/src/styles/base/020_base.scss +++ b/app/javascript/src/styles/base/020_base.scss @@ -103,7 +103,7 @@ menu { padding: 0; } - li { + > li { margin: 0; padding: 0 0.2em; display: inline; diff --git a/app/javascript/src/styles/common/messages.scss b/app/javascript/src/styles/common/messages.scss index b38857027..4a612c418 100644 --- a/app/javascript/src/styles/common/messages.scss +++ b/app/javascript/src/styles/common/messages.scss @@ -31,7 +31,7 @@ div.list-of-messages { flex: 1; menu { - li { + > li { padding: 0; margin-right: 1.5em; } diff --git a/app/models/comment.rb b/app/models/comment.rb index 041b47ee5..8d260fa28 100644 --- a/app/models/comment.rb +++ b/app/models/comment.rb @@ -113,11 +113,6 @@ class Comment < ApplicationRecord end end - def voted_by?(user) - return false if user.is_anonymous? - user.id.in?(votes.map(&:user_id)) - end - def quoted_response DText.quote(body, creator.name) end diff --git a/app/policies/comment_policy.rb b/app/policies/comment_policy.rb index fc5faa8b8..b832ee294 100644 --- a/app/policies/comment_policy.rb +++ b/app/policies/comment_policy.rb @@ -20,12 +20,7 @@ class CommentPolicy < ApplicationPolicy end def reply? - create? && !record.is_deleted? - end - - def vote? - # XXX should use CommentVotePolicy - unbanned? && !record.is_deleted? + !record.is_deleted? end def permitted_attributes_for_create diff --git a/app/views/comment_votes/create.js.erb b/app/views/comment_votes/create.js.erb index b8f2b29bb..b8a438cd5 100644 --- a/app/views/comment_votes/create.js.erb +++ b/app/views/comment_votes/create.js.erb @@ -1,2 +1,2 @@ -Danbooru.Utility.notice("Vote saved"); -$(".comment[data-id=<%= @comment.id %>]").attr("data-is-voted", "true"); +var $comment = $("article#comment_<%= @comment.id %>"); +$comment.replaceWith("<%= j render_comment(@comment, current_user: CurrentUser.user) %>"); diff --git a/app/views/comment_votes/destroy.js.erb b/app/views/comment_votes/destroy.js.erb index bc00c5721..b8a438cd5 100644 --- a/app/views/comment_votes/destroy.js.erb +++ b/app/views/comment_votes/destroy.js.erb @@ -1,2 +1,2 @@ -Danbooru.Utility.notice("Removed vote"); -$(".comment[data-id=<%= @comment.id %>]").attr("data-is-voted", "false"); +var $comment = $("article#comment_<%= @comment.id %>"); +$comment.replaceWith("<%= j render_comment(@comment, current_user: CurrentUser.user) %>");