Merge pull request #2416 from r888888888/favorite-groups
Favorite groups
This commit is contained in:
@@ -52,7 +52,7 @@
|
|||||||
var prefixes = "-|~|general:|gen:|artist:|art:|copyright:|copy:|co:|character:|char:|ch:";
|
var prefixes = "-|~|general:|gen:|artist:|art:|copyright:|copy:|co:|character:|char:|ch:";
|
||||||
var metatags = "order|-status|status|-rating|rating|-locked|locked|child|" +
|
var metatags = "order|-status|status|-rating|rating|-locked|locked|child|" +
|
||||||
"-user|user|-approver|approver|commenter|comm|noter|noteupdater|artcomm|-fav|fav|ordfav|" +
|
"-user|user|-approver|approver|commenter|comm|noter|noteupdater|artcomm|-fav|fav|ordfav|" +
|
||||||
"sub|-pool|pool|ordpool";
|
"sub|-pool|pool|ordpool|favgroup";
|
||||||
|
|
||||||
$fields_multiple.autocomplete({
|
$fields_multiple.autocomplete({
|
||||||
delay: 100,
|
delay: 100,
|
||||||
@@ -140,6 +140,10 @@
|
|||||||
case "ordpool":
|
case "ordpool":
|
||||||
Danbooru.Autocomplete.pool_source(term, resp, metatag);
|
Danbooru.Autocomplete.pool_source(term, resp, metatag);
|
||||||
break;
|
break;
|
||||||
|
case "favgroup":
|
||||||
|
case "-favgroup":
|
||||||
|
Danbooru.Autocomplete.favorite_group_source(term, resp, metatag);
|
||||||
|
break;
|
||||||
default:
|
default:
|
||||||
Danbooru.Autocomplete.normal_source(term, resp);
|
Danbooru.Autocomplete.normal_source(term, resp);
|
||||||
break;
|
break;
|
||||||
@@ -370,6 +374,26 @@
|
|||||||
}
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Danbooru.Autocomplete.favorite_group_source = function(term, resp, metatag) {
|
||||||
|
$.ajax({
|
||||||
|
url: "/favorite_groups.json",
|
||||||
|
data: {
|
||||||
|
"search[name_matches]": term,
|
||||||
|
"limit": 10
|
||||||
|
},
|
||||||
|
method: "get",
|
||||||
|
success: function(data) {
|
||||||
|
resp($.map(data, function(favgroup) {
|
||||||
|
return {
|
||||||
|
label: favgroup.name.replace(/_/g, " "),
|
||||||
|
value: metatag + ":" + favgroup.name,
|
||||||
|
post_count: favgroup.post_count
|
||||||
|
};
|
||||||
|
}));
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
})();
|
})();
|
||||||
|
|
||||||
$(document).ready(function() {
|
$(document).ready(function() {
|
||||||
|
|||||||
@@ -148,7 +148,7 @@
|
|||||||
location.href = href;
|
location.href = href;
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
var href = $("#pool-nav a.active[rel=prev]").attr("href");
|
var href = $("#pool-nav a.active[rel=prev], #favgroup-nav a.active[rel=prev]").attr("href");
|
||||||
if (href) {
|
if (href) {
|
||||||
location.href = href;
|
location.href = href;
|
||||||
}
|
}
|
||||||
@@ -160,7 +160,7 @@
|
|||||||
var href = $("#search-seq-nav a[rel=next]").attr("href");
|
var href = $("#search-seq-nav a[rel=next]").attr("href");
|
||||||
location.href = href;
|
location.href = href;
|
||||||
} else {
|
} else {
|
||||||
var href = $("#pool-nav a.active[rel=next]").attr("href");
|
var href = $("#pool-nav a.active[rel=next], #favgroup-nav a.active[rel=next]").attr("href");
|
||||||
if (href) {
|
if (href) {
|
||||||
location.href = href;
|
location.href = href;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -37,3 +37,7 @@ kbd.key {
|
|||||||
span.inactive {
|
span.inactive {
|
||||||
color: #AAA;
|
color: #AAA;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
td a.last-page {
|
||||||
|
color: #666;
|
||||||
|
}
|
||||||
|
|||||||
5
app/assets/stylesheets/specific/favorite_groups.css.scss
Normal file
5
app/assets/stylesheets/specific/favorite_groups.css.scss
Normal file
@@ -0,0 +1,5 @@
|
|||||||
|
#c-favorite-groups #a-edit {
|
||||||
|
textarea {
|
||||||
|
height: 10em;
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -52,10 +52,6 @@ div#c-forum-topics {
|
|||||||
margin-right: 0.5em;
|
margin-right: 0.5em;
|
||||||
}
|
}
|
||||||
|
|
||||||
a.last-page {
|
|
||||||
color: #666;
|
|
||||||
}
|
|
||||||
|
|
||||||
span.locked-topic {
|
span.locked-topic {
|
||||||
color: #666;
|
color: #666;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -46,10 +46,6 @@ div#c-pools {
|
|||||||
height: 10em;
|
height: 10em;
|
||||||
}
|
}
|
||||||
|
|
||||||
a.last-page {
|
|
||||||
color: #666;
|
|
||||||
}
|
|
||||||
|
|
||||||
div#a-show {
|
div#a-show {
|
||||||
div#description {
|
div#description {
|
||||||
margin-bottom: 1em;
|
margin-bottom: 1em;
|
||||||
|
|||||||
@@ -368,11 +368,11 @@ div#c-posts {
|
|||||||
word-wrap: break-word;
|
word-wrap: break-word;
|
||||||
}
|
}
|
||||||
|
|
||||||
#search-seq-nav + #pool-nav {
|
#search-seq-nav + #pool-nav, #search-seq-nav + #favgroup-nav, #pool-nav + #favgroup-nav {
|
||||||
margin-top: 0.5em;
|
margin-top: 0.5em;
|
||||||
}
|
}
|
||||||
|
|
||||||
#pool-nav, #search-seq-nav {
|
#pool-nav, #search-seq-nav, #favgroup-nav {
|
||||||
li {
|
li {
|
||||||
position: relative;
|
position: relative;
|
||||||
text-align: center;
|
text-align: center;
|
||||||
|
|||||||
69
app/controllers/favorite_groups_controller.rb
Normal file
69
app/controllers/favorite_groups_controller.rb
Normal file
@@ -0,0 +1,69 @@
|
|||||||
|
class FavoriteGroupsController < ApplicationController
|
||||||
|
before_filter :member_only, :except => [:index, :show]
|
||||||
|
respond_to :html, :xml, :json
|
||||||
|
|
||||||
|
def index
|
||||||
|
@favorite_groups = FavoriteGroup.search(params[:search]).order("updated_at desc").paginate(params[:page], :limit => params[:limit], :search_count => params[:search])
|
||||||
|
respond_with(@favorite_groups) do |format|
|
||||||
|
format.xml do
|
||||||
|
render :xml => @favorite_groups.to_xml(:root => "favorite-groups")
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
def show
|
||||||
|
@favorite_group = FavoriteGroup.find(params[:id])
|
||||||
|
@post_set = PostSets::FavoriteGroup.new(@favorite_group, params[:page])
|
||||||
|
respond_with(@favorite_group)
|
||||||
|
end
|
||||||
|
|
||||||
|
def new
|
||||||
|
@favorite_group = FavoriteGroup.new
|
||||||
|
respond_with(@favorite_group)
|
||||||
|
end
|
||||||
|
|
||||||
|
def create
|
||||||
|
@favorite_group = FavoriteGroup.create(params[:favorite_group])
|
||||||
|
respond_with(@favorite_group) do |format|
|
||||||
|
format.html do
|
||||||
|
if @favorite_group.errors.any?
|
||||||
|
render :action => "new"
|
||||||
|
else
|
||||||
|
redirect_to favorite_groups_path
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
def edit
|
||||||
|
@favorite_group = FavoriteGroup.find(params[:id])
|
||||||
|
check_privilege(@favorite_group)
|
||||||
|
respond_with(@favorite_group)
|
||||||
|
end
|
||||||
|
|
||||||
|
def update
|
||||||
|
# need to do this in order for synchronize! to work correctly
|
||||||
|
@favorite_group = FavoriteGroup.find(params[:id])
|
||||||
|
check_privilege(@favorite_group)
|
||||||
|
@favorite_group.attributes = params[:favorite_group]
|
||||||
|
@favorite_group.synchronize
|
||||||
|
@favorite_group.save
|
||||||
|
unless @favorite_group.errors.any?
|
||||||
|
flash[:notice] = "Favorite group updated"
|
||||||
|
end
|
||||||
|
respond_with(@favorite_group)
|
||||||
|
end
|
||||||
|
|
||||||
|
def destroy
|
||||||
|
@favorite_group = FavoriteGroup.find(params[:id])
|
||||||
|
check_privilege(@favorite_group)
|
||||||
|
@favorite_group.destroy
|
||||||
|
flash[:notice] = "Favorite group deleted"
|
||||||
|
redirect_to favorite_groups_path
|
||||||
|
end
|
||||||
|
|
||||||
|
private
|
||||||
|
def check_privilege(favgroup)
|
||||||
|
raise User::PrivilegeError unless favgroup.editable_by?(CurrentUser.user)
|
||||||
|
end
|
||||||
|
end
|
||||||
@@ -130,14 +130,10 @@ private
|
|||||||
if post.errors.any?
|
if post.errors.any?
|
||||||
@error_message = post.errors.full_messages.join("; ")
|
@error_message = post.errors.full_messages.join("; ")
|
||||||
render :template => "static/error", :status => 500
|
render :template => "static/error", :status => 500
|
||||||
elsif params[:tags_query].present? && params[:pool_id].present?
|
|
||||||
redirect_to post_path(post, :tags => params[:tags_query], :pool_id => params[:pool_id])
|
|
||||||
elsif params[:tags_query].present?
|
|
||||||
redirect_to post_path(post, :tags => params[:tags_query])
|
|
||||||
elsif params[:pool_id].present?
|
|
||||||
redirect_to post_path(post, :pool_id => params[:pool_id])
|
|
||||||
else
|
else
|
||||||
redirect_to post_path(post)
|
response_params = {:tags => params[:tags_query], :pool_id => params[:pool_id], :favgroup_id => params[:favgroup_id]}
|
||||||
|
response_params.reject!{|key, value| value.blank?}
|
||||||
|
redirect_to post_path(post, response_params)
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|||||||
@@ -221,6 +221,10 @@ class AnonymousUser
|
|||||||
false
|
false
|
||||||
end
|
end
|
||||||
|
|
||||||
|
def favorite_groups
|
||||||
|
[]
|
||||||
|
end
|
||||||
|
|
||||||
%w(member banned gold builder platinum contributor janitor moderator admin).each do |name|
|
%w(member banned gold builder platinum contributor janitor moderator admin).each do |name|
|
||||||
define_method("is_#{name}?") do
|
define_method("is_#{name}?") do
|
||||||
false
|
false
|
||||||
|
|||||||
@@ -312,6 +312,12 @@ class PostQueryBuilder
|
|||||||
relation = relation.order("position(' '||posts.id||' ' in ' '||(select post_ids from pools where id = #{pool_id})||' ')")
|
relation = relation.order("position(' '||posts.id||' ' in ' '||(select post_ids from pools where id = #{pool_id})||' ')")
|
||||||
end
|
end
|
||||||
|
|
||||||
|
if q[:favgroup].present?
|
||||||
|
favgroup_id = q[:favgroup].to_i
|
||||||
|
post_ids = FavoriteGroup.find(favgroup_id).post_id_array
|
||||||
|
relation = relation.where("posts.id in (?)", post_ids)
|
||||||
|
end
|
||||||
|
|
||||||
if q[:ordfav].present?
|
if q[:ordfav].present?
|
||||||
user_id = q[:ordfav].to_i
|
user_id = q[:ordfav].to_i
|
||||||
relation = relation.joins("INNER JOIN favorites ON favorites.post_id = posts.id")
|
relation = relation.joins("INNER JOIN favorites ON favorites.post_id = posts.id")
|
||||||
|
|||||||
7
app/logical/post_sets/favorite_group.rb
Normal file
7
app/logical/post_sets/favorite_group.rb
Normal file
@@ -0,0 +1,7 @@
|
|||||||
|
module PostSets
|
||||||
|
class FavoriteGroup < PostSets::Pool
|
||||||
|
def presenter
|
||||||
|
@presenter ||= PostSetPresenters::FavoriteGroup.new(self)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
211
app/models/favorite_group.rb
Normal file
211
app/models/favorite_group.rb
Normal file
@@ -0,0 +1,211 @@
|
|||||||
|
require 'ostruct'
|
||||||
|
|
||||||
|
class FavoriteGroup < ActiveRecord::Base
|
||||||
|
validates_uniqueness_of :name, :case_sensitive => false, :scope => :creator_id
|
||||||
|
validates_format_of :name, :with => /\A[^,]+\Z/, :message => "cannot have commas"
|
||||||
|
belongs_to :creator, :class_name => "User"
|
||||||
|
before_validation :normalize_post_ids
|
||||||
|
before_validation :normalize_name
|
||||||
|
before_validation :initialize_creator, :on => :create
|
||||||
|
before_validation :strip_name
|
||||||
|
validate :creator_can_create_favorite_groups, :on => :create
|
||||||
|
validate :validate_number_of_posts
|
||||||
|
after_create :synchronize!
|
||||||
|
attr_accessible :name, :post_ids, :post_id_array, :as => [:member, :gold, :platinum, :builder, :contributor, :janitor, :moderator, :admin, :default]
|
||||||
|
|
||||||
|
module SearchMethods
|
||||||
|
def for_creator(user_id)
|
||||||
|
where("favorite_groups.creator_id = ?", user_id)
|
||||||
|
end
|
||||||
|
|
||||||
|
def named(name)
|
||||||
|
where("lower(name) = ?", name.to_s.mb_chars.downcase.strip)
|
||||||
|
end
|
||||||
|
|
||||||
|
def name_matches(name)
|
||||||
|
name = name.tr(" ", "_")
|
||||||
|
name = "*#{name}*" unless name =~ /\*/
|
||||||
|
where("name ilike ? escape E'\\\\'", name.to_escaped_for_sql_like)
|
||||||
|
end
|
||||||
|
|
||||||
|
def search(params)
|
||||||
|
q = where("true")
|
||||||
|
params = {} if params.blank?
|
||||||
|
|
||||||
|
if params[:creator_id].present?
|
||||||
|
q = q.where("creator_id = ?", params[:creator_id].to_i)
|
||||||
|
elsif params[:creator_name].present?
|
||||||
|
q = q.where("creator_id = (select _.id from users _ where lower(_.name) = ?)", params[:creator_name].tr(" ", "_").mb_chars.downcase)
|
||||||
|
else
|
||||||
|
q = q.where("creator_id = ?", CurrentUser.user.id)
|
||||||
|
end
|
||||||
|
|
||||||
|
if params[:name_matches].present?
|
||||||
|
q = q.name_matches(params[:name_matches])
|
||||||
|
end
|
||||||
|
|
||||||
|
q
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
extend SearchMethods
|
||||||
|
|
||||||
|
def self.name_to_id(name)
|
||||||
|
if name =~ /^\d+$/
|
||||||
|
name.to_i
|
||||||
|
else
|
||||||
|
select_value_sql("SELECT id FROM favorite_groups WHERE lower(name) = ? AND creator_id = ?", name.to_s.mb_chars.downcase.tr(" ", "_"), CurrentUser.user.id).to_i
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
def creator_can_create_favorite_groups
|
||||||
|
if creator.favorite_group_count >= creator.favorite_group_limit
|
||||||
|
error = "You can only keep up to #{creator.favorite_group_limit} favorite groups."
|
||||||
|
if !CurrentUser.user.is_platinum?
|
||||||
|
error += " Upgrade your account to create more."
|
||||||
|
end
|
||||||
|
self.errors.add(:base, error)
|
||||||
|
return false
|
||||||
|
else
|
||||||
|
return true
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
def validate_number_of_posts
|
||||||
|
if post_id_array.size > 10_000
|
||||||
|
self.errors.add(:base, "Favorite groups can have up to 10,000 posts each")
|
||||||
|
return false
|
||||||
|
else
|
||||||
|
return true
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
def normalize_post_ids
|
||||||
|
self.post_ids = post_ids.scan(/\d+/).uniq.join(" ")
|
||||||
|
end
|
||||||
|
|
||||||
|
def normalize_name
|
||||||
|
self.name = name.gsub(/\s+/, "_")
|
||||||
|
end
|
||||||
|
|
||||||
|
def initialize_creator
|
||||||
|
self.creator_id = CurrentUser.id
|
||||||
|
end
|
||||||
|
|
||||||
|
def strip_name
|
||||||
|
self.name = name.to_s.strip
|
||||||
|
end
|
||||||
|
|
||||||
|
def pretty_name
|
||||||
|
name.tr("_", " ")
|
||||||
|
end
|
||||||
|
|
||||||
|
def posts(options = {})
|
||||||
|
offset = options[:offset] || 0
|
||||||
|
limit = options[:limit] || Danbooru.config.posts_per_page
|
||||||
|
slice = post_id_array.slice(offset, limit)
|
||||||
|
if slice && slice.any?
|
||||||
|
slice.map do |id|
|
||||||
|
begin
|
||||||
|
Post.find(id)
|
||||||
|
rescue ActiveRecord::RecordNotFound
|
||||||
|
# swallow
|
||||||
|
end
|
||||||
|
end.compact
|
||||||
|
else
|
||||||
|
[]
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
def post_id_array
|
||||||
|
@post_id_array ||= post_ids.scan(/\d+/).map(&:to_i)
|
||||||
|
end
|
||||||
|
|
||||||
|
def post_id_array=(array)
|
||||||
|
self.post_ids = array.join(" ")
|
||||||
|
clear_post_id_array
|
||||||
|
end
|
||||||
|
|
||||||
|
def post_id_array_was
|
||||||
|
@post_id_array_was ||= post_ids_was.scan(/\d+/).map(&:to_i)
|
||||||
|
end
|
||||||
|
|
||||||
|
def clear_post_id_array
|
||||||
|
@post_id_array = nil
|
||||||
|
@post_id_array_was = nil
|
||||||
|
end
|
||||||
|
|
||||||
|
def synchronize
|
||||||
|
added = post_id_array - post_id_array_was
|
||||||
|
removed = post_id_array_was - post_id_array
|
||||||
|
|
||||||
|
normalize_post_ids
|
||||||
|
clear_post_id_array
|
||||||
|
self.post_count = post_id_array.size
|
||||||
|
end
|
||||||
|
|
||||||
|
def synchronize!
|
||||||
|
synchronize
|
||||||
|
save
|
||||||
|
end
|
||||||
|
|
||||||
|
def add!(post)
|
||||||
|
return if contains?(post.id)
|
||||||
|
|
||||||
|
update_attributes(:post_ids => add_number_to_string(post.id, post_ids), :post_count => post_count + 1)
|
||||||
|
clear_post_id_array
|
||||||
|
end
|
||||||
|
|
||||||
|
def remove!(post)
|
||||||
|
return unless contains?(post.id)
|
||||||
|
|
||||||
|
update_attributes(:post_ids => remove_number_from_string(post.id, post_ids), :post_count => post_count - 1)
|
||||||
|
clear_post_id_array
|
||||||
|
end
|
||||||
|
|
||||||
|
def add_number_to_string(number, string)
|
||||||
|
"#{string} #{number}"
|
||||||
|
end
|
||||||
|
|
||||||
|
def remove_number_from_string(number, string)
|
||||||
|
string.gsub(/(?:\A| )#{number}(?:\Z| )/, " ")
|
||||||
|
end
|
||||||
|
|
||||||
|
def neighbors(post)
|
||||||
|
@neighbor_posts ||= begin
|
||||||
|
post_ids =~ /\A#{post.id} (\d+)|(\d+) #{post.id} (\d+)|(\d+) #{post.id}\Z/
|
||||||
|
|
||||||
|
if $2 && $3
|
||||||
|
OpenStruct.new(:previous => $2.to_i, :next => $3.to_i)
|
||||||
|
elsif $1
|
||||||
|
OpenStruct.new(:next => $1.to_i)
|
||||||
|
elsif $4
|
||||||
|
OpenStruct.new(:previous => $4.to_i)
|
||||||
|
else
|
||||||
|
OpenStruct.new
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
def reload(options = {})
|
||||||
|
super
|
||||||
|
@neighbor_posts = nil
|
||||||
|
clear_post_id_array
|
||||||
|
end
|
||||||
|
|
||||||
|
def last_page
|
||||||
|
(post_count / CurrentUser.user.per_page.to_f).ceil
|
||||||
|
end
|
||||||
|
|
||||||
|
def strip_name
|
||||||
|
self.name = name.to_s.strip
|
||||||
|
end
|
||||||
|
|
||||||
|
def contains?(post_id)
|
||||||
|
post_ids =~ /(?:\A| )#{post_id}(?:\Z| )/
|
||||||
|
end
|
||||||
|
|
||||||
|
def editable_by?(user)
|
||||||
|
creator_id == user.id
|
||||||
|
end
|
||||||
|
end
|
||||||
@@ -629,7 +629,7 @@ class Post < ActiveRecord::Base
|
|||||||
|
|
||||||
def filter_metatags(tags)
|
def filter_metatags(tags)
|
||||||
@pre_metatags, tags = tags.partition {|x| x =~ /\A(?:rating|parent|-parent):/i}
|
@pre_metatags, tags = tags.partition {|x| x =~ /\A(?:rating|parent|-parent):/i}
|
||||||
@post_metatags, tags = tags.partition {|x| x =~ /\A(?:-pool|pool|newpool|fav|child):/i}
|
@post_metatags, tags = tags.partition {|x| x =~ /\A(?:-pool|pool|newpool|fav|child|-favgroup|favgroup):/i}
|
||||||
apply_pre_metatags
|
apply_pre_metatags
|
||||||
return tags
|
return tags
|
||||||
end
|
end
|
||||||
@@ -669,6 +669,22 @@ class Post < ActiveRecord::Base
|
|||||||
child = Post.find($1)
|
child = Post.find($1)
|
||||||
child.parent_id = id
|
child.parent_id = id
|
||||||
child.save
|
child.save
|
||||||
|
|
||||||
|
when /^-favgroup:(\d+)$/i
|
||||||
|
favgroup = FavoriteGroup.where("id = ?", $1.to_i).for_creator(CurrentUser.user.id).first
|
||||||
|
favgroup.remove!(self) if favgroup
|
||||||
|
|
||||||
|
when /^-favgroup:(.+)$/i
|
||||||
|
favgroup = FavoriteGroup.named($1).for_creator(CurrentUser.user.id).first
|
||||||
|
favgroup.remove!(self) if favgroup
|
||||||
|
|
||||||
|
when /^favgroup:(\d+)$/i
|
||||||
|
favgroup = FavoriteGroup.where("id = ?", $1.to_i).for_creator(CurrentUser.user.id).first
|
||||||
|
favgroup.add!(self) if favgroup
|
||||||
|
|
||||||
|
when /^favgroup:(.+)$/i
|
||||||
|
favgroup = FavoriteGroup.named($1).for_creator(CurrentUser.user.id).first
|
||||||
|
favgroup.add!(self) if favgroup
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
@@ -821,6 +837,14 @@ class Post < ActiveRecord::Base
|
|||||||
def favorited_users
|
def favorited_users
|
||||||
favorited_user_ids.map {|id| User.find(id)}
|
favorited_user_ids.map {|id| User.find(id)}
|
||||||
end
|
end
|
||||||
|
|
||||||
|
def favorite_groups
|
||||||
|
@favorite_groups ||= begin
|
||||||
|
CurrentUser.user.favorite_groups.select do |favgroup|
|
||||||
|
favgroup.contains?(self.id)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
module UploaderMethods
|
module UploaderMethods
|
||||||
@@ -1578,6 +1602,7 @@ class Post < ActiveRecord::Base
|
|||||||
super
|
super
|
||||||
reset_tag_array_cache
|
reset_tag_array_cache
|
||||||
@pools = nil
|
@pools = nil
|
||||||
|
@favorite_groups = nil
|
||||||
@tag_categories = nil
|
@tag_categories = nil
|
||||||
@typed_tags = nil
|
@typed_tags = nil
|
||||||
self
|
self
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
class Tag < ActiveRecord::Base
|
class Tag < ActiveRecord::Base
|
||||||
METATAGS = "-user|user|-approver|approver|commenter|comm|noter|noteupdater|artcomm|-pool|pool|ordpool|-fav|fav|ordfav|sub|md5|-rating|rating|-locked|locked|width|height|mpixels|ratio|score|favcount|filesize|source|-source|id|-id|date|age|order|limit|-status|status|tagcount|gentags|arttags|chartags|copytags|parent|-parent|child|pixiv_id|pixiv"
|
METATAGS = "-user|user|-approver|approver|commenter|comm|noter|noteupdater|artcomm|-pool|pool|ordpool|favgroup|-fav|fav|ordfav|sub|md5|-rating|rating|-locked|locked|width|height|mpixels|ratio|score|favcount|filesize|source|-source|id|-id|date|age|order|limit|-status|status|tagcount|gentags|arttags|chartags|copytags|parent|-parent|child|pixiv_id|pixiv"
|
||||||
SUBQUERY_METATAGS = "commenter|comm|noter|noteupdater|artcomm"
|
SUBQUERY_METATAGS = "commenter|comm|noter|noteupdater|artcomm"
|
||||||
attr_accessible :category, :as => [:moderator, :janitor, :contributor, :gold, :member, :anonymous, :default, :builder, :admin]
|
attr_accessible :category, :as => [:moderator, :janitor, :contributor, :gold, :member, :anonymous, :default, :builder, :admin]
|
||||||
attr_accessible :is_locked, :as => [:moderator, :janitor, :admin]
|
attr_accessible :is_locked, :as => [:moderator, :janitor, :admin]
|
||||||
@@ -460,6 +460,10 @@ class Tag < ActiveRecord::Base
|
|||||||
q[:tags][:related] << "pool:#{pool_id}"
|
q[:tags][:related] << "pool:#{pool_id}"
|
||||||
q[:ordpool] = pool_id
|
q[:ordpool] = pool_id
|
||||||
|
|
||||||
|
when "favgroup"
|
||||||
|
favgroup_id = FavoriteGroup.name_to_id($2)
|
||||||
|
q[:favgroup] = favgroup_id
|
||||||
|
|
||||||
when "-fav"
|
when "-fav"
|
||||||
q[:tags][:exclude] << "fav:#{User.name_to_id($2)}"
|
q[:tags][:exclude] << "fav:#{User.name_to_id($2)}"
|
||||||
|
|
||||||
|
|||||||
@@ -253,6 +253,10 @@ class User < ActiveRecord::Base
|
|||||||
def remove_favorite!(post)
|
def remove_favorite!(post)
|
||||||
Favorite.remove(post, self)
|
Favorite.remove(post, self)
|
||||||
end
|
end
|
||||||
|
|
||||||
|
def favorite_groups
|
||||||
|
FavoriteGroup.for_creator(CurrentUser.user.id)
|
||||||
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
module LevelMethods
|
module LevelMethods
|
||||||
@@ -541,7 +545,17 @@ class User < ActiveRecord::Base
|
|||||||
10_000
|
10_000
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
def favorite_group_limit
|
||||||
|
if is_platinum?
|
||||||
|
10
|
||||||
|
elsif is_gold?
|
||||||
|
5
|
||||||
|
else
|
||||||
|
3
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
def api_hourly_limit
|
def api_hourly_limit
|
||||||
if is_platinum? && api_key.present?
|
if is_platinum? && api_key.present?
|
||||||
20_000
|
20_000
|
||||||
@@ -634,6 +648,10 @@ class User < ActiveRecord::Base
|
|||||||
Comment.for_creator(id).count
|
Comment.for_creator(id).count
|
||||||
end
|
end
|
||||||
|
|
||||||
|
def favorite_group_count
|
||||||
|
FavoriteGroup.for_creator(id).count
|
||||||
|
end
|
||||||
|
|
||||||
def appeal_count
|
def appeal_count
|
||||||
PostAppeal.for_creator(id).count
|
PostAppeal.for_creator(id).count
|
||||||
end
|
end
|
||||||
|
|||||||
@@ -26,6 +26,8 @@ class PostPresenter < Presenter
|
|||||||
tag_param = "?tags=#{CGI::escape(options[:tags])}"
|
tag_param = "?tags=#{CGI::escape(options[:tags])}"
|
||||||
elsif options[:pool_id] || options[:pool]
|
elsif options[:pool_id] || options[:pool]
|
||||||
tag_param = "?pool_id=#{CGI::escape((options[:pool_id] || options[:pool].id).to_s)}"
|
tag_param = "?pool_id=#{CGI::escape((options[:pool_id] || options[:pool].id).to_s)}"
|
||||||
|
elsif options[:favgroup_id] || options[:favgroup]
|
||||||
|
tag_param = "?favgroup_id=#{CGI::escape((options[:favgroup_id] || options[:favgroup].id).to_s)}"
|
||||||
else
|
else
|
||||||
tag_param = nil
|
tag_param = nil
|
||||||
end
|
end
|
||||||
@@ -203,7 +205,7 @@ class PostPresenter < Presenter
|
|||||||
end
|
end
|
||||||
|
|
||||||
def has_nav_links?(template)
|
def has_nav_links?(template)
|
||||||
(CurrentUser.user.enable_sequential_post_navigation && template.params[:tags].present? && template.params[:tags] !~ /(?:^|\s)(?:order|ordfav|ordpool):/) || @post.pools.any?
|
(CurrentUser.user.enable_sequential_post_navigation && template.params[:tags].present? && template.params[:tags] !~ /(?:^|\s)(?:order|ordfav|ordpool):/) || @post.pools.any? || @post.favorite_groups.any?
|
||||||
end
|
end
|
||||||
|
|
||||||
def post_footer_for_pool_html(template)
|
def post_footer_for_pool_html(template)
|
||||||
@@ -233,7 +235,7 @@ class PostPresenter < Presenter
|
|||||||
first = true
|
first = true
|
||||||
pools = @post.pools.series_first
|
pools = @post.pools.series_first
|
||||||
pools.each do |pool|
|
pools.each do |pool|
|
||||||
if first && template.params[:tags].blank?
|
if first && template.params[:tags].blank? && template.params[:favgroup_id].blank?
|
||||||
html += pool_link_html(template, pool, :include_rel => true)
|
html += pool_link_html(template, pool, :include_rel => true)
|
||||||
first = false
|
first = false
|
||||||
else
|
else
|
||||||
|
|||||||
17
app/presenters/post_set_presenters/favorite_group.rb
Normal file
17
app/presenters/post_set_presenters/favorite_group.rb
Normal file
@@ -0,0 +1,17 @@
|
|||||||
|
module PostSetPresenters
|
||||||
|
class FavoriteGroup < PostSetPresenters::Pool
|
||||||
|
def post_previews_html(template)
|
||||||
|
html = ""
|
||||||
|
|
||||||
|
if posts.empty?
|
||||||
|
return template.render("post_sets/blank")
|
||||||
|
end
|
||||||
|
|
||||||
|
posts.each do |post|
|
||||||
|
html << PostPresenter.preview(post, :favgroup_id => post_set.pool.id)
|
||||||
|
end
|
||||||
|
|
||||||
|
html.html_safe
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
@@ -101,6 +101,10 @@ class UserPresenter
|
|||||||
template.link_to(user.favorite_count, template.favorites_path(:user_id => user.id))
|
template.link_to(user.favorite_count, template.favorites_path(:user_id => user.id))
|
||||||
end
|
end
|
||||||
|
|
||||||
|
def favorite_group_count(template)
|
||||||
|
template.link_to(user.favorite_group_count, template.favorite_groups_path(:search => {:creator_id => user.id}))
|
||||||
|
end
|
||||||
|
|
||||||
def comment_count(template)
|
def comment_count(template)
|
||||||
template.link_to(user.comment_count, template.comments_path(:search => {:creator_id => user.id}, :group_by => "comment"))
|
template.link_to(user.comment_count, template.comments_path(:search => {:creator_id => user.id}, :group_by => "comment"))
|
||||||
end
|
end
|
||||||
|
|||||||
19
app/views/favorite_groups/_secondary_links.html.erb
Normal file
19
app/views/favorite_groups/_secondary_links.html.erb
Normal file
@@ -0,0 +1,19 @@
|
|||||||
|
<% content_for(:secondary_links) do %>
|
||||||
|
<menu>
|
||||||
|
<li><%= link_to "Listing", favorite_groups_path %></li>
|
||||||
|
<% if CurrentUser.is_member? %>
|
||||||
|
<li><%= link_to "New", new_favorite_group_path %></li>
|
||||||
|
<% end %>
|
||||||
|
<li><%= link_to "Help", wiki_pages_path(:title => "help:favorite_groups") %></li>
|
||||||
|
|
||||||
|
<% if @favorite_group && !@favorite_group.new_record? %>
|
||||||
|
<li>|</li>
|
||||||
|
<li><%= link_to "Show", favorite_group_path(@favorite_group) %></li>
|
||||||
|
<li><%= link_to "Posts", posts_path(:tags => "favgroup:#{@favorite_group.id}") %></li>
|
||||||
|
<% if @favorite_group.editable_by?(CurrentUser.user) %>
|
||||||
|
<li><%= link_to "Edit", edit_favorite_group_path(@favorite_group) %></li>
|
||||||
|
<li><%= link_to "Delete", favorite_group_path(@favorite_group), :method => :delete, :data => {:confirm => "Are you sure you want to delete this favorite group?"} %></li>
|
||||||
|
<% end %>
|
||||||
|
<% end %>
|
||||||
|
</menu>
|
||||||
|
<% end %>
|
||||||
19
app/views/favorite_groups/edit.html.erb
Normal file
19
app/views/favorite_groups/edit.html.erb
Normal file
@@ -0,0 +1,19 @@
|
|||||||
|
<div id="c-favorite-groups">
|
||||||
|
<div id="a-edit">
|
||||||
|
<h1>Edit Favorite Group: <%= @favorite_group.pretty_name %></h1>
|
||||||
|
|
||||||
|
<%= error_messages_for "favorite_group" %>
|
||||||
|
|
||||||
|
<%= simple_form_for(@favorite_group) do |f| %>
|
||||||
|
<%= f.input :name, :as => :string, :input_html => { :value => @favorite_group.pretty_name } %>
|
||||||
|
<%= f.input :post_ids, :label => "Posts" %>
|
||||||
|
<%= f.button :submit, "Submit" %>
|
||||||
|
<% end %>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<%= render "secondary_links" %>
|
||||||
|
|
||||||
|
<% content_for(:page_title) do %>
|
||||||
|
Edit Favorite Group - <%= Danbooru.config.app_name %>
|
||||||
|
<% end %>
|
||||||
40
app/views/favorite_groups/index.html.erb
Normal file
40
app/views/favorite_groups/index.html.erb
Normal file
@@ -0,0 +1,40 @@
|
|||||||
|
<div id="c-favorite-groups">
|
||||||
|
<div id="a-index">
|
||||||
|
<table class="striped" width="100%">
|
||||||
|
<thead>
|
||||||
|
<tr>
|
||||||
|
<th width="5%"></th>
|
||||||
|
<th width="60%">Name</th>
|
||||||
|
<th width="10%">Count</th>
|
||||||
|
</tr>
|
||||||
|
</thead>
|
||||||
|
<tbody>
|
||||||
|
<% @favorite_groups.each do |favgroup| %>
|
||||||
|
<%= content_tag(:tr, :id => "favorite-group-#{favgroup.id}") do %>
|
||||||
|
<td>
|
||||||
|
|
||||||
|
</td>
|
||||||
|
<td>
|
||||||
|
<%= link_to favgroup.pretty_name, favorite_group_path(favgroup) %>
|
||||||
|
|
||||||
|
<% if favgroup.post_count > CurrentUser.user.per_page %>
|
||||||
|
<%= link_to "page #{favgroup.last_page}", favorite_group_path(favgroup, :page => favgroup.last_page), :class => "last-page" %>
|
||||||
|
<% end %>
|
||||||
|
</td>
|
||||||
|
<td>
|
||||||
|
<%= favgroup.post_count %>
|
||||||
|
</td>
|
||||||
|
<% end %>
|
||||||
|
<% end %>
|
||||||
|
</tbody>
|
||||||
|
</table>
|
||||||
|
|
||||||
|
<%= numbered_paginator(@favorite_groups) %>
|
||||||
|
|
||||||
|
<%= render "secondary_links" %>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<% content_for(:page_title) do %>
|
||||||
|
Favorite Groups - <%= Danbooru.config.app_name %>
|
||||||
|
<% end %>
|
||||||
19
app/views/favorite_groups/new.html.erb
Normal file
19
app/views/favorite_groups/new.html.erb
Normal file
@@ -0,0 +1,19 @@
|
|||||||
|
<div id="c-favorite-groups">
|
||||||
|
<div id="a-new">
|
||||||
|
<h1>New Favorite Group</h1>
|
||||||
|
|
||||||
|
<%= error_messages_for "favorite_group" %>
|
||||||
|
|
||||||
|
<%= simple_form_for(@favorite_group) do |f| %>
|
||||||
|
<%= f.input :name, :as => :string, :required => true %>
|
||||||
|
<%= f.input :post_ids, :label => "Posts" %>
|
||||||
|
<%= f.button :submit, "Submit" %>
|
||||||
|
<% end %>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<%= render "secondary_links" %>
|
||||||
|
|
||||||
|
<% content_for(:page_title) do %>
|
||||||
|
New Favorite Group - <%= Danbooru.config.app_name %>
|
||||||
|
<% end %>
|
||||||
22
app/views/favorite_groups/show.html.erb
Normal file
22
app/views/favorite_groups/show.html.erb
Normal file
@@ -0,0 +1,22 @@
|
|||||||
|
<div id="c-favorite-groups">
|
||||||
|
<div id="a-show">
|
||||||
|
<h1>
|
||||||
|
Favorite Group:
|
||||||
|
<%= link_to @favorite_group.pretty_name, posts_path(:tags => "favgroup:#{@favorite_group.id}") %>
|
||||||
|
</h1>
|
||||||
|
|
||||||
|
<%= render "posts/partials/common/inline_blacklist" %>
|
||||||
|
|
||||||
|
<section>
|
||||||
|
<%= @post_set.presenter.post_previews_html(self) %>
|
||||||
|
|
||||||
|
<%= numbered_paginator(@post_set) %>
|
||||||
|
</section>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<%= render "secondary_links" %>
|
||||||
|
|
||||||
|
<% content_for(:page_title) do %>
|
||||||
|
Favorite Group - <%= @favorite_group.pretty_name %> - <%= Danbooru.config.app_name %>
|
||||||
|
<% end %>
|
||||||
@@ -6,6 +6,7 @@
|
|||||||
<li><%= link_to "Hot", posts_path(:tags => "order:rank") %></li>
|
<li><%= link_to "Hot", posts_path(:tags => "order:rank") %></li>
|
||||||
<% unless CurrentUser.is_anonymous? %>
|
<% unless CurrentUser.is_anonymous? %>
|
||||||
<li><%= link_to "Favorites", favorites_path %></li>
|
<li><%= link_to "Favorites", favorites_path %></li>
|
||||||
|
<li><%= link_to "Favorite groups", favorite_groups_path %></li>
|
||||||
<% if CurrentUser.user.has_saved_searches? %>
|
<% if CurrentUser.user.has_saved_searches? %>
|
||||||
<li><%= link_to "Saved searches", saved_searches_path %></li>
|
<li><%= link_to "Saved searches", saved_searches_path %></li>
|
||||||
<% end %>
|
<% end %>
|
||||||
|
|||||||
@@ -9,6 +9,7 @@
|
|||||||
<%= form_for(post, :html => {:class => "simple_form", :id => "form"}) do |f| %>
|
<%= form_for(post, :html => {:class => "simple_form", :id => "form"}) do |f| %>
|
||||||
<%= hidden_field_tag :tags_query, params[:tags] %>
|
<%= hidden_field_tag :tags_query, params[:tags] %>
|
||||||
<%= hidden_field_tag :pool_id, params[:pool_id] %>
|
<%= hidden_field_tag :pool_id, params[:pool_id] %>
|
||||||
|
<%= hidden_field_tag :favgroup_id, params[:favgroup_id] %>
|
||||||
<%= f.hidden_field :old_tag_string, :value => post.tag_string %>
|
<%= f.hidden_field :old_tag_string, :value => post.tag_string %>
|
||||||
<%= f.hidden_field :old_parent_id, :value => post.parent_id %>
|
<%= f.hidden_field :old_parent_id, :value => post.parent_id %>
|
||||||
<%= f.hidden_field :old_source, :value => post.source %>
|
<%= f.hidden_field :old_source, :value => post.source %>
|
||||||
|
|||||||
25
app/views/posts/partials/show/_favorite_groups.html.erb
Normal file
25
app/views/posts/partials/show/_favorite_groups.html.erb
Normal file
@@ -0,0 +1,25 @@
|
|||||||
|
<div id="favgroup-nav">
|
||||||
|
<ul>
|
||||||
|
<% post.favorite_groups.each do |favgroup| %>
|
||||||
|
<li>
|
||||||
|
<% klass = "active" if favgroup.id == params[:favgroup_id].to_i %>
|
||||||
|
|
||||||
|
<% if favgroup.neighbors(post).previous %>
|
||||||
|
<%= link_to("‹ prev".html_safe, post_path(favgroup.neighbors(post).previous, :favgroup_id => favgroup.id), :rel => "prev", :class => "prev #{klass}") %>
|
||||||
|
<% else %>
|
||||||
|
<span class="prev">‹ prev</span>
|
||||||
|
<% end %>
|
||||||
|
|
||||||
|
<span class="favgroup-name <%= klass %>">
|
||||||
|
<%= link_to("Favorite group: #{favgroup.name}", favorite_group_path(favgroup)) %>
|
||||||
|
</span>
|
||||||
|
|
||||||
|
<% if favgroup.neighbors(post).next %>
|
||||||
|
<%= link_to("next ›".html_safe, post_path(favgroup.neighbors(post).next, :favgroup_id => favgroup.id), :rel => "next", :class => "next #{klass}") %>
|
||||||
|
<% else %>
|
||||||
|
<span class="next">next ›</span>
|
||||||
|
<% end %>
|
||||||
|
</li>
|
||||||
|
<% end %>
|
||||||
|
</ul>
|
||||||
|
</div>
|
||||||
@@ -7,5 +7,9 @@
|
|||||||
<% if post.pools.any? %>
|
<% if post.pools.any? %>
|
||||||
<%= render "posts/partials/show/pools", :post => post %>
|
<%= render "posts/partials/show/pools", :post => post %>
|
||||||
<% end %>
|
<% end %>
|
||||||
|
|
||||||
|
<% if post.favorite_groups.any? %>
|
||||||
|
<%= render "posts/partials/show/favorite_groups", :post => post %>
|
||||||
|
<% end %>
|
||||||
</div>
|
</div>
|
||||||
<% end %>
|
<% end %>
|
||||||
|
|||||||
@@ -44,6 +44,11 @@
|
|||||||
<td><%= presenter.favorite_count(self) %></td>
|
<td><%= presenter.favorite_count(self) %></td>
|
||||||
</tr>
|
</tr>
|
||||||
|
|
||||||
|
<tr>
|
||||||
|
<th>Favorite Groups</th>
|
||||||
|
<td><%= presenter.favorite_group_count(self) %></td>
|
||||||
|
</tr>
|
||||||
|
|
||||||
<tr>
|
<tr>
|
||||||
<th>Post Changes</th>
|
<th>Post Changes</th>
|
||||||
<td><%= presenter.post_version_count(self) %></td>
|
<td><%= presenter.post_version_count(self) %></td>
|
||||||
|
|||||||
@@ -109,6 +109,7 @@ Rails.application.routes.draw do
|
|||||||
end
|
end
|
||||||
resource :dtext_preview, :only => [:create]
|
resource :dtext_preview, :only => [:create]
|
||||||
resources :favorites
|
resources :favorites
|
||||||
|
resources :favorite_groups
|
||||||
resources :forum_posts do
|
resources :forum_posts do
|
||||||
member do
|
member do
|
||||||
post :undelete
|
post :undelete
|
||||||
|
|||||||
19
db/migrate/20150623191904_create_favorite_groups.rb
Normal file
19
db/migrate/20150623191904_create_favorite_groups.rb
Normal file
@@ -0,0 +1,19 @@
|
|||||||
|
class CreateFavoriteGroups < ActiveRecord::Migration
|
||||||
|
def self.up
|
||||||
|
create_table :favorite_groups do |t|
|
||||||
|
t.text :name, :null => false
|
||||||
|
t.integer :creator_id, :null => false
|
||||||
|
t.text :post_ids, :null => false, :default => ""
|
||||||
|
t.integer :post_count, :null => false, :default => 0
|
||||||
|
|
||||||
|
t.timestamps
|
||||||
|
end
|
||||||
|
|
||||||
|
execute "create index index_favorite_groups_on_lower_name on favorite_groups (lower(name))"
|
||||||
|
add_index :favorite_groups, :creator_id
|
||||||
|
end
|
||||||
|
|
||||||
|
def self.down
|
||||||
|
drop_table :favorite_groups
|
||||||
|
end
|
||||||
|
end
|
||||||
Reference in New Issue
Block a user