votes: add vote buttons beneath thumbnails.

Add upvote and downvote buttons beneath thumbnails on the post index page.

This is disabled by default. To enable it, click the "..." menu in the top
right of the page, then click "Show scores".

This is currently a per-search setting, not an account setting. If you
enable it in one tab, it won't be enabled in other tabs.
This commit is contained in:
evazion
2021-11-18 01:49:50 -06:00
parent 5585d1f7d6
commit bd8672681f
16 changed files with 61 additions and 30 deletions

View File

@@ -28,7 +28,7 @@ div.popup-menu {
li a {
display: block;
padding: 0.125em 2em 0.125em 0;
padding: 0.125em 0 0.125em 0;
.icon {
width: 1rem;

View File

@@ -3,18 +3,19 @@
class PostPreviewComponent < ApplicationComponent
with_collection_parameter :post
attr_reader :post, :tags, :show_deleted, :show_cropped, :link_target, :pool, :similarity, :recommended, :compact, :size, :current_user, :options
attr_reader :post, :tags, :show_deleted, :show_cropped, :link_target, :pool, :similarity, :recommended, :show_votes, :compact, :size, :current_user, :options
delegate :external_link_to, :time_ago_in_words_tagged, :duration_to_hhmmss, :empty_heart_icon, :sound_icon, to: :helpers
delegate :external_link_to, :time_ago_in_words_tagged, :duration_to_hhmmss, :render_post_votes, :empty_heart_icon, :sound_icon, to: :helpers
delegate :image_width, :image_height, :file_ext, :file_size, :duration, :is_animated?, to: :media_asset
delegate :media_asset, to: :post
def initialize(post:, tags: "", show_deleted: false, show_cropped: true, link_target: post, pool: nil, similarity: nil, recommended: nil, compact: nil, size: nil, current_user: CurrentUser.user, **options)
def initialize(post:, tags: "", show_deleted: false, show_cropped: true, show_votes: true, link_target: post, pool: nil, similarity: nil, recommended: nil, compact: nil, size: nil, current_user: CurrentUser.user, **options)
super
@post = post
@tags = tags.presence
@show_deleted = show_deleted
@show_cropped = show_cropped
@show_votes = show_votes
@link_target = link_target
@pool = pool
@similarity = similarity.round(1) if similarity.present?

View File

@@ -23,8 +23,7 @@
<p class="desc">
<%= link_to pool.pretty_name.truncate(80), pool %>
</p>
<% end -%>
<% if similarity -%>
<% elsif similarity -%>
<p class="desc">
<% if post.source =~ %r!\Ahttps?://!i %>
<%= external_link_to post.normalized_source, post.source_domain %>
@@ -33,20 +32,19 @@
<%= time_ago_in_words_tagged(post.created_at, compact: true) %>
<% end %>
</p>
<% end %>
<% if size -%>
<p class="desc">
<%= link_to number_to_human_size(size), post.file_url %>
(<%= post.image_width %>x<%= post.image_height %>)
</p>
<% end -%>
<% if similarity -%>
<p class="desc">
<%= link_to "#{similarity}%", iqdb_queries_path(post_id: post.id) %> similarity
</p>
<% end -%>
<% if recommended -%>
<% elsif size -%>
<p class="desc">
<%= link_to number_to_human_size(size), post.file_url %>
(<%= post.image_width %>x<%= post.image_height %>)
</p>
<% elsif recommended -%>
<p class="desc recommended">
<%= link_to recommended_posts_path(search: { post_id: post.id }), class: "more-recommended-posts", "data-post-id": post.id do %>
<%= post.fav_count %>
@@ -56,5 +54,9 @@
<br>more »
<% end %>
</p>
<% elsif show_votes -%>
<p class="desc">
<%= render_post_votes post, current_user: current_user %>
</p>
<% end -%>
<% end -%>

View File

@@ -1,7 +1,6 @@
@import "../../javascript/src/styles/base/000_vars.scss";
article.post-preview {
height: 154px;
width: 154px;
margin: 0 10px 10px 0;
text-align: center;

View File

@@ -15,7 +15,7 @@ class PostVotesComponent < ApplicationComponent
end
def current_vote
post.votes.find_by(user: current_user)
post.vote_by_current_user
end
def upvoted?

View File

@@ -1,15 +1,16 @@
# frozen_string_literal: true
class TagListComponent < ApplicationComponent
attr_reader :tags, :current_query, :show_extra_links
attr_reader :tags, :current_query, :show_extra_links, :search_params
delegate :humanized_number, to: :helpers
def initialize(tags: [], current_query: nil, show_extra_links: false)
def initialize(tags: [], current_query: nil, show_extra_links: false, search_params: {})
super
@tags = tags
@current_query = current_query
@show_extra_links = show_extra_links
@search_params = search_params
end
def self.tags_from_names(tag_names)

View File

@@ -11,11 +11,11 @@
<% end %>
<% if show_extra_links && current_query.present? %>
<%= link_to "+", posts_path(tags: "#{current_query} #{t.name}"), class: "search-inc-tag" %>
<%= link_to "-", posts_path(tags: "#{current_query} -#{t.name}"), class: "search-exl-tag" %>
<%= link_to "+", posts_path(tags: "#{current_query} #{t.name}", **search_params), class: "search-inc-tag" %>
<%= link_to "-", posts_path(tags: "#{current_query} -#{t.name}", **search_params), class: "search-exl-tag" %>
<% end %>
<%= link_to t.pretty_name, posts_path(tags: t.name), class: "search-tag" %>
<%= link_to t.pretty_name, posts_path(tags: t.name, **search_params), class: "search-tag" %>
<%= tag.span humanized_number(t.post_count), class: "post-count", title: t.post_count %>
</li>
<% end %>

View File

@@ -10,7 +10,7 @@ class PostsController < ApplicationController
end
else
tag_query = params[:tags] || params.dig(:post, :tags)
@post_set = PostSets::Post.new(tag_query, params[:page], params[:limit], random: params[:random], format: params[:format])
@post_set = PostSets::Post.new(tag_query, params[:page], params[:limit], random: params[:random], format: params[:format], view: params[:view])
@posts = authorize @post_set.posts, policy_class: PostPolicy
@post_set.log!
respond_with(@posts) do |format|

View File

@@ -98,7 +98,6 @@ menu {
> li {
margin: 0;
padding: 0 0.2em;
display: inline;
}
}

View File

@@ -82,6 +82,8 @@ $spacer: 0.25rem; /* 4px */
.items-center { align-items: center; }
.justify-center { justify-content: center; }
.float-right { float: right; }
.thin-scrollbar {
overflow-x: hidden;
overflow-y: auto;

View File

@@ -135,8 +135,6 @@ div#c-posts {
font-size: var(--text-lg);
li {
padding: 0 1em 0 0;
&.active {
font-weight: bold;
}

View File

@@ -7,10 +7,10 @@ module PostSets
MAX_PER_PAGE = 200
MAX_SIDEBAR_TAGS = 25
attr_reader :page, :random, :format, :tag_string, :query, :normalized_query
attr_reader :page, :random, :format, :tag_string, :query, :normalized_query, :view
delegate :post_count, to: :normalized_query
def initialize(tags, page = 1, per_page = nil, user: CurrentUser.user, random: false, format: "html")
def initialize(tags, page = 1, per_page = nil, user: CurrentUser.user, random: false, format: "html", view: "simple")
@query = PostQueryBuilder.new(tags, user, tag_limit: user.tag_query_limit, safe_mode: CurrentUser.safe_mode?, hide_deleted_posts: user.hide_deleted_posts?)
@normalized_query = query.normalized_query
@tag_string = tags
@@ -18,6 +18,7 @@ module PostSets
@per_page = per_page
@random = random.to_s.truthy?
@format = format.to_s
@view = view.presence || "simple"
end
def humanized_tag_string
@@ -107,7 +108,7 @@ module PostSets
if is_random?
get_random_posts.paginate(page, search_count: false, limit: per_page, max_limit: max_per_page).load
else
normalized_query.paginated_posts(page, includes: :media_asset, count: post_count, search_count: !post_count.nil?, limit: per_page, max_limit: max_per_page).load
normalized_query.paginated_posts(page, includes: includes, count: post_count, search_count: !post_count.nil?, limit: per_page, max_limit: max_per_page).load
end
end
end
@@ -139,6 +140,18 @@ module PostSets
end
end
def show_votes?
view == "score"
end
def includes
if show_votes?
[:media_asset, :vote_by_current_user]
else
[:media_asset]
end
end
def search_stats
{
query: normalized_query.to_s,

View File

@@ -40,6 +40,7 @@ class Post < ApplicationRecord
has_one :upload, :dependent => :destroy
has_one :artist_commentary, :dependent => :destroy
has_one :pixiv_ugoira_frame_data, class_name: "PixivUgoiraFrameData", foreign_key: :md5, primary_key: :md5
has_one :vote_by_current_user, -> { where(user_id: CurrentUser.id) }, class_name: "PostVote" # XXX using current user here is wrong
has_many :flags, :class_name => "PostFlag", :dependent => :destroy
has_many :appeals, :class_name => "PostAppeal", :dependent => :destroy
has_many :votes, :class_name => "PostVote", :dependent => :destroy

View File

@@ -7,7 +7,7 @@
<section id="tag-box">
<h2>Tags</h2>
<%= render_search_tag_list(@post_set.related_tags, current_query: params[:tags], show_extra_links: policy(Post).show_extra_links?) %>
<%= render_search_tag_list(@post_set.related_tags, current_query: params[:tags], show_extra_links: policy(Post).show_extra_links?, search_params: { view: params[:view] }) %>
</section>
<%= render "posts/partials/index/options" %>
@@ -16,7 +16,7 @@
<% end %>
<% content_for(:content) do %>
<menu id="post-sections" class="mb-4">
<menu id="post-sections" class="mb-4 space-x-2">
<li class="active"><a href="#" id="show-posts-link">Posts</a></li>
<% if @post_set.artist.present? %>
@@ -31,6 +31,18 @@
<li class="blank-wiki-excerpt-link"><%= link_to "Wiki", new_wiki_page_path(wiki_page: { title: @post_set.tag.name }), id: "show-excerpt-link" %></li>
<% end %>
<li class="float-right">
<%= render PopupMenuComponent.new do |menu| %>
<% menu.item do %>
<% if params[:view] == "score" %>
<%= link_to "Hide scores", posts_path(tags: params[:tags], view: nil) %>
<% else %>
<%= link_to "Show scores", posts_path(tags: params[:tags], view: "score") %>
<% end %>
<% end %>
<% end %>
</li>
<li id="searchbox-redirect-link" class="mobile-only"><a href="#search-box">Search &raquo;</a></li>
</menu>

View File

@@ -6,6 +6,9 @@
<% if params[:random] %>
<%= hidden_field_tag :random, params[:random] %>
<% end %>
<% if params[:view] %>
<%= hidden_field_tag :view, params[:view] %>
<% end %>
<%= text_field_tag("tags", tags, :id => tags_dom_id, :class => "flex-auto", :"data-shortcut" => "q", :"data-autocomplete" => "tag-query") %>
<button id="search-box-submit" type="submit"><%= search_icon %></button>
<% end %>

View File

@@ -3,7 +3,7 @@
<% if post_set.shown_posts.empty? %>
<%= render "post_sets/blank" %>
<% else %>
<%= post_previews_html(post_set.posts, show_deleted: post_set.show_deleted?, show_cropped: true, tags: post_set.tag_string) %>
<%= post_previews_html(post_set.posts, show_deleted: post_set.show_deleted?, show_cropped: true, tags: post_set.tag_string, show_votes: post_set.show_votes?) %>
<% end %>
</div>