posts: make post votes work the same way as comment votes.
Change post votes to work the same way as comment votes: * Make the upvote arrow blue if you've upvoted the post, or grey if you haven't. Likewise for the downvote arrow. * Make it so you can click the upvote or downvote arrows to undo the vote. * Don't show any notices when you vote on a post. Also fix it so that votes work the same way on the posts page, the comments page, and in the modqueue. Before it wasn't possible to undo votes on the comments page or in the modqueue.
This commit is contained in:
@@ -1,4 +1,8 @@
|
|||||||
class ApplicationComponent < ViewComponent::Base
|
class ApplicationComponent < ViewComponent::Base
|
||||||
|
delegate :link_to_user, :time_ago_in_words_tagged, :format_text, :edit_icon,
|
||||||
|
:delete_icon, :undelete_icon, :flag_icon, :upvote_icon, :downvote_icon,
|
||||||
|
:link_icon, to: :helpers
|
||||||
|
|
||||||
def policy(subject)
|
def policy(subject)
|
||||||
Pundit.policy!(current_user, subject)
|
Pundit.policy!(current_user, subject)
|
||||||
end
|
end
|
||||||
|
|||||||
27
app/components/post_votes_component.rb
Normal file
27
app/components/post_votes_component.rb
Normal file
@@ -0,0 +1,27 @@
|
|||||||
|
# frozen_string_literal: true
|
||||||
|
|
||||||
|
# This component represents the post score and upvote/downvote buttons ("🠉 5 🠋")
|
||||||
|
class PostVotesComponent < ApplicationComponent
|
||||||
|
attr_reader :post, :current_user
|
||||||
|
|
||||||
|
def initialize(post:, current_user:)
|
||||||
|
@post = post
|
||||||
|
@current_user = current_user
|
||||||
|
end
|
||||||
|
|
||||||
|
def can_vote?
|
||||||
|
policy(PostVote).create?
|
||||||
|
end
|
||||||
|
|
||||||
|
def current_vote
|
||||||
|
post.votes.find_by(user: current_user)
|
||||||
|
end
|
||||||
|
|
||||||
|
def upvoted?
|
||||||
|
can_vote? && current_vote&.is_positive?
|
||||||
|
end
|
||||||
|
|
||||||
|
def downvoted?
|
||||||
|
can_vote? && current_vote&.is_negative?
|
||||||
|
end
|
||||||
|
end
|
||||||
@@ -0,0 +1,19 @@
|
|||||||
|
<span class="post-votes" data-id="<%= post.id %>">
|
||||||
|
<% if can_vote? %>
|
||||||
|
<% if upvoted? %>
|
||||||
|
<%= link_to upvote_icon, post_post_votes_path(post_id: post.id), class: "post-upvote-link post-unvote-link active-link", method: :delete, remote: true %>
|
||||||
|
<% else %>
|
||||||
|
<%= link_to upvote_icon, post_post_votes_path(post_id: post.id, score: "up"), class: "post-upvote-link inactive-link", method: :post, remote: true %>
|
||||||
|
<% end %>
|
||||||
|
<% end %>
|
||||||
|
|
||||||
|
<span class="post-score"><%= post.score %></span>
|
||||||
|
|
||||||
|
<% if can_vote? %>
|
||||||
|
<% if downvoted? %>
|
||||||
|
<%= link_to downvote_icon, post_post_votes_path(post_id: post.id), class: "post-downvote-link post-unvote-link active-link", method: :delete, remote: true %>
|
||||||
|
<% else %>
|
||||||
|
<%= link_to downvote_icon, post_post_votes_path(post_id: post.id, score: "down"), class: "post-downvote-link inactive-link", method: :post, remote: true %>
|
||||||
|
<% end %>
|
||||||
|
<% end %>
|
||||||
|
</span>
|
||||||
@@ -0,0 +1,10 @@
|
|||||||
|
.post-votes {
|
||||||
|
// Fix it so that the vote buttons don't move when the score changes width.
|
||||||
|
// XXX duplicated from app/components/comment_component/comment_component.scss
|
||||||
|
.post-score {
|
||||||
|
display: inline-block;
|
||||||
|
text-align: center;
|
||||||
|
min-width: 1.25em;
|
||||||
|
white-space: nowrap;
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -14,4 +14,8 @@ module ComponentsHelper
|
|||||||
def render_comment_section(post, **options)
|
def render_comment_section(post, **options)
|
||||||
render CommentSectionComponent.new(post: post, **options)
|
render CommentSectionComponent.new(post: post, **options)
|
||||||
end
|
end
|
||||||
|
|
||||||
|
def render_post_votes(post, **options)
|
||||||
|
render PostVotesComponent.new(post: post, **options)
|
||||||
|
end
|
||||||
end
|
end
|
||||||
|
|||||||
@@ -33,6 +33,14 @@ class PostVote < ApplicationRecord
|
|||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
def is_positive?
|
||||||
|
score > 0
|
||||||
|
end
|
||||||
|
|
||||||
|
def is_negative?
|
||||||
|
score < 0
|
||||||
|
end
|
||||||
|
|
||||||
def update_post_on_create
|
def update_post_on_create
|
||||||
if score > 0
|
if score > 0
|
||||||
Post.where(:id => post_id).update_all("score = score + #{score}, up_score = up_score + #{score}")
|
Post.where(:id => post_id).update_all("score = score + #{score}, up_score = up_score + #{score}")
|
||||||
|
|||||||
@@ -14,12 +14,7 @@
|
|||||||
</span>
|
</span>
|
||||||
<span class="info">
|
<span class="info">
|
||||||
<strong>Score</strong>
|
<strong>Score</strong>
|
||||||
<span>
|
<%= render_post_votes post, current_user: CurrentUser.user %>
|
||||||
<span id="score-for-post-<%= post.id %>"><%= post.score %></span>
|
|
||||||
<% if policy(PostVote).create? %>
|
|
||||||
(vote <%= link_to upvote_icon, post_post_votes_path(score: "up", post_id: post.id), remote: true, method: :post %>/<%= link_to downvote_icon, post_post_votes_path(score: "down", post_id: post.id), remote: true, method: :post %>)
|
|
||||||
<% end %>
|
|
||||||
</span>
|
|
||||||
</span>
|
</span>
|
||||||
</div>
|
</div>
|
||||||
<div class="row list-of-tags">
|
<div class="row list-of-tags">
|
||||||
|
|||||||
@@ -1,17 +1,9 @@
|
|||||||
$("#add-to-favorites, #add-fav-button, #remove-from-favorites, #remove-fav-button").toggle();
|
$("#add-to-favorites, #add-fav-button, #remove-from-favorites, #remove-fav-button").toggle();
|
||||||
$("#remove-fav-button").addClass("animate");
|
$("#remove-fav-button").addClass("animate");
|
||||||
$("#score-for-post-<%= @post.id %>").text(<%= @post.score %>);
|
$("span.post-votes[data-id=<%= @post.id %>]").replaceWith("<%= j render_post_votes @post, current_user: CurrentUser.user %>");
|
||||||
$("#favcount-for-post-<%= @post.id %>").text(<%= @post.fav_count %>);
|
$("#favcount-for-post-<%= @post.id %>").text(<%= @post.fav_count %>);
|
||||||
$(".fav-buttons").toggleClass("fav-buttons-false").toggleClass("fav-buttons-true");
|
$(".fav-buttons").toggleClass("fav-buttons-false").toggleClass("fav-buttons-true");
|
||||||
|
|
||||||
<% if @post.can_be_voted_by?(CurrentUser.user) %>
|
|
||||||
$("#vote-links-for-post-<%= @post.id %>").show();
|
|
||||||
$("#unvote-link-for-post-<%= @post.id %>").hide();
|
|
||||||
<% else %>
|
|
||||||
$("#vote-links-for-post-<%= @post.id %>").hide();
|
|
||||||
$("#unvote-link-for-post-<%= @post.id %>").show();
|
|
||||||
<% end %>
|
|
||||||
|
|
||||||
<% if policy(@post).can_view_favlist? %>
|
<% if policy(@post).can_view_favlist? %>
|
||||||
var fav_count = <%= @post.fav_count %>;
|
var fav_count = <%= @post.fav_count %>;
|
||||||
$("#favlist").html("<%= j render "posts/partials/show/favorite_list", post: @post %>");
|
$("#favlist").html("<%= j render "posts/partials/show/favorite_list", post: @post %>");
|
||||||
|
|||||||
@@ -28,12 +28,7 @@
|
|||||||
|
|
||||||
<span class="info">
|
<span class="info">
|
||||||
<strong>Score</strong>
|
<strong>Score</strong>
|
||||||
<span>
|
<%= render_post_votes post, current_user: CurrentUser.user %>
|
||||||
<span id="score-for-post-<%= post.id %>"><%= post.score %></span>
|
|
||||||
<% if policy(PostVote).create? %>
|
|
||||||
(vote <%= link_to upvote_icon, post_post_votes_path(score: "up", post_id: post.id), remote: true, method: :post %>/<%= link_to downvote_icon, post_post_votes_path(score: "down", post_id: post.id), remote: true, method: :post %>)
|
|
||||||
<% end %>
|
|
||||||
</span>
|
|
||||||
</span>
|
</span>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
|||||||
@@ -1,5 +1 @@
|
|||||||
Danbooru.Utility.notice("Vote saved");
|
$("span.post-votes[data-id=<%= @post.id %>]").replaceWith("<%= j render_post_votes @post, current_user: CurrentUser.user %>");
|
||||||
$("#score-for-post-<%= @post.id %>").html(<%= @post.score %>);
|
|
||||||
|
|
||||||
$("#vote-links-for-post-<%= @post.id %>").hide();
|
|
||||||
$("#unvote-link-for-post-<%= @post.id %>").show();
|
|
||||||
|
|||||||
@@ -1,5 +0,0 @@
|
|||||||
Danbooru.Utility.notice("Unvoted successfully");
|
|
||||||
$("#score-for-post-<%= @post.id %>").html(<%= @post.score %>);
|
|
||||||
|
|
||||||
$("#vote-links-for-post-<%= @post.id %>").show();
|
|
||||||
$("#unvote-link-for-post-<%= @post.id %>").hide();
|
|
||||||
1
app/views/post_votes/destroy.js.erb
Symbolic link
1
app/views/post_votes/destroy.js.erb
Symbolic link
@@ -0,0 +1 @@
|
|||||||
|
create.js.erb
|
||||||
@@ -21,17 +21,8 @@
|
|||||||
</li>
|
</li>
|
||||||
<li id="post-info-source">Source: <%= post_source_tag(post.source, post.normalized_source) %></li>
|
<li id="post-info-source">Source: <%= post_source_tag(post.source, post.normalized_source) %></li>
|
||||||
<li id="post-info-rating">Rating: <%= post.pretty_rating %></li>
|
<li id="post-info-rating">Rating: <%= post.pretty_rating %></li>
|
||||||
<li id="post-info-score">Score: <span id="score-for-post-<%= post.id %>"><%= post.score %></span>
|
<li id="post-info-score">
|
||||||
<% if policy(PostVote).create? %>
|
Score: <%= render_post_votes post, current_user: CurrentUser.user %>
|
||||||
<%= tag.span id: "vote-links-for-post-#{post.id}", style: ("display: none;" if !@post.can_be_voted_by?(CurrentUser.user)) do %>
|
|
||||||
(vote
|
|
||||||
<%= link_to upvote_icon, post_post_votes_path(post_id: post.id, score: "up"), remote: true, method: :post %>
|
|
||||||
<%= link_to downvote_icon, post_post_votes_path(post_id: post.id, score: "down"), remote: true, method: :post %>)
|
|
||||||
<% end %>
|
|
||||||
<%= tag.span id: "unvote-link-for-post-#{post.id}", style: ("display: none;" if @post.can_be_voted_by?(CurrentUser.user)) do %>
|
|
||||||
(<%= link_to "undo vote", post_post_votes_path(post), remote: true, method: :delete, class: "unvote-post-link" %>)
|
|
||||||
<% end %>
|
|
||||||
<% end %>
|
|
||||||
</li>
|
</li>
|
||||||
<li id="post-info-favorites">Favorites: <span id="favcount-for-post-<%= post.id %>"><%= post.fav_count %></span>
|
<li id="post-info-favorites">Favorites: <span id="favcount-for-post-<%= post.id %>"><%= post.fav_count %></span>
|
||||||
<% if policy(post).can_view_favlist? %>
|
<% if policy(post).can_view_favlist? %>
|
||||||
|
|||||||
56
test/components/post_votes_component_test.rb
Normal file
56
test/components/post_votes_component_test.rb
Normal file
@@ -0,0 +1,56 @@
|
|||||||
|
require "test_helper"
|
||||||
|
|
||||||
|
class PostVotesComponentTest < ViewComponent::TestCase
|
||||||
|
def render_post_votes(post, current_user:)
|
||||||
|
render_inline(PostVotesComponent.new(post: post, current_user: current_user))
|
||||||
|
end
|
||||||
|
|
||||||
|
context "The PostVotesComponent" do
|
||||||
|
setup do
|
||||||
|
@post = as(create(:user)) { create(:post) }
|
||||||
|
end
|
||||||
|
|
||||||
|
context "for a user who can't vote" do
|
||||||
|
should "not show the vote buttons" do
|
||||||
|
render_post_votes(@post, current_user: User.anonymous)
|
||||||
|
|
||||||
|
assert_css(".post-score")
|
||||||
|
assert_no_css(".post-upvote-link")
|
||||||
|
assert_no_css(".post-downvote-link")
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
context "for a user who can vote" do
|
||||||
|
setup do
|
||||||
|
@user = create(:gold_user)
|
||||||
|
end
|
||||||
|
|
||||||
|
should "show the vote buttons" do
|
||||||
|
render_post_votes(@post, current_user: @user)
|
||||||
|
|
||||||
|
assert_css(".post-upvote-link.inactive-link")
|
||||||
|
assert_css(".post-downvote-link.inactive-link")
|
||||||
|
end
|
||||||
|
|
||||||
|
context "for a downvoted post" do
|
||||||
|
should "highlight the downvote button as active" do
|
||||||
|
@post.vote!("down", @user)
|
||||||
|
render_post_votes(@post, current_user: @user)
|
||||||
|
|
||||||
|
assert_css(".post-upvote-link.inactive-link")
|
||||||
|
assert_css(".post-downvote-link.active-link")
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
context "for an upvoted post" do
|
||||||
|
should "highlight the upvote button as active" do
|
||||||
|
@post.vote!("up", @user)
|
||||||
|
render_post_votes(@post, current_user: @user)
|
||||||
|
|
||||||
|
assert_css(".post-upvote-link.active-link")
|
||||||
|
assert_css(".post-downvote-link.inactive-link")
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
Reference in New Issue
Block a user