From 04fa5596e2c4326a991ecfa395d9572babf33873 Mon Sep 17 00:00:00 2001 From: Toks Date: Tue, 23 Jun 2015 15:25:54 -0400 Subject: [PATCH] Favorite groups --- app/assets/javascripts/autocomplete.js | 26 ++- app/assets/stylesheets/common/inline.css.scss | 4 + .../stylesheets/specific/forum.css.scss | 4 - .../stylesheets/specific/pools.css.scss | 4 - .../stylesheets/specific/posts.css.scss | 4 +- app/controllers/favorite_groups_controller.rb | 69 ++++++ app/logical/anonymous_user.rb | 4 + app/logical/post_query_builder.rb | 6 + app/logical/post_sets/favorite_group.rb | 7 + app/models/favorite_group.rb | 211 ++++++++++++++++++ app/models/post.rb | 27 ++- app/models/tag.rb | 6 +- app/models/user.rb | 20 +- app/presenters/post_presenter.rb | 4 +- .../post_set_presenters/favorite_group.rb | 17 ++ app/presenters/user_presenter.rb | 4 + .../favorite_groups/_secondary_links.html.erb | 19 ++ app/views/favorite_groups/edit.html.erb | 19 ++ app/views/favorite_groups/index.html.erb | 40 ++++ app/views/favorite_groups/new.html.erb | 19 ++ app/views/favorite_groups/show.html.erb | 22 ++ .../partials/common/_secondary_links.html.erb | 1 + .../partials/show/_favorite_groups.html.erb | 23 ++ .../posts/partials/show/_nav_links.html.erb | 4 + app/views/users/_statistics.html.erb | 5 + config/routes.rb | 1 + .../20150623191904_create_favorite_groups.rb | 19 ++ 27 files changed, 574 insertions(+), 15 deletions(-) create mode 100644 app/controllers/favorite_groups_controller.rb create mode 100644 app/logical/post_sets/favorite_group.rb create mode 100644 app/models/favorite_group.rb create mode 100644 app/presenters/post_set_presenters/favorite_group.rb create mode 100644 app/views/favorite_groups/_secondary_links.html.erb create mode 100644 app/views/favorite_groups/edit.html.erb create mode 100644 app/views/favorite_groups/index.html.erb create mode 100644 app/views/favorite_groups/new.html.erb create mode 100644 app/views/favorite_groups/show.html.erb create mode 100644 app/views/posts/partials/show/_favorite_groups.html.erb create mode 100644 db/migrate/20150623191904_create_favorite_groups.rb diff --git a/app/assets/javascripts/autocomplete.js b/app/assets/javascripts/autocomplete.js index 9fb1b7405..2ece773bf 100644 --- a/app/assets/javascripts/autocomplete.js +++ b/app/assets/javascripts/autocomplete.js @@ -52,7 +52,7 @@ var prefixes = "-|~|general:|gen:|artist:|art:|copyright:|copy:|co:|character:|char:|ch:"; var metatags = "order|-status|status|-rating|rating|-locked|locked|child|" + "-user|user|-approver|approver|commenter|comm|noter|noteupdater|artcomm|-fav|fav|ordfav|" + - "sub|-pool|pool|ordpool"; + "sub|-pool|pool|ordpool|favgroup"; $fields_multiple.autocomplete({ delay: 100, @@ -140,6 +140,10 @@ case "ordpool": Danbooru.Autocomplete.pool_source(term, resp, metatag); break; + case "favgroup": + case "-favgroup": + Danbooru.Autocomplete.favorite_group_source(term, resp, metatag); + break; default: Danbooru.Autocomplete.normal_source(term, resp); 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() { diff --git a/app/assets/stylesheets/common/inline.css.scss b/app/assets/stylesheets/common/inline.css.scss index fe76fceec..b87e9351b 100644 --- a/app/assets/stylesheets/common/inline.css.scss +++ b/app/assets/stylesheets/common/inline.css.scss @@ -37,3 +37,7 @@ kbd.key { span.inactive { color: #AAA; } + +td a.last-page { + color: #666; +} diff --git a/app/assets/stylesheets/specific/forum.css.scss b/app/assets/stylesheets/specific/forum.css.scss index 656219336..86396853a 100644 --- a/app/assets/stylesheets/specific/forum.css.scss +++ b/app/assets/stylesheets/specific/forum.css.scss @@ -52,10 +52,6 @@ div#c-forum-topics { margin-right: 0.5em; } - a.last-page { - color: #666; - } - span.locked-topic { color: #666; } diff --git a/app/assets/stylesheets/specific/pools.css.scss b/app/assets/stylesheets/specific/pools.css.scss index f0c91bac3..95b771235 100644 --- a/app/assets/stylesheets/specific/pools.css.scss +++ b/app/assets/stylesheets/specific/pools.css.scss @@ -46,10 +46,6 @@ div#c-pools { height: 10em; } - a.last-page { - color: #666; - } - div#a-show { div#description { margin-bottom: 1em; diff --git a/app/assets/stylesheets/specific/posts.css.scss b/app/assets/stylesheets/specific/posts.css.scss index 680c96463..c294d8d3a 100644 --- a/app/assets/stylesheets/specific/posts.css.scss +++ b/app/assets/stylesheets/specific/posts.css.scss @@ -368,11 +368,11 @@ div#c-posts { 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; } - #pool-nav, #search-seq-nav { + #pool-nav, #search-seq-nav, #favgroup-nav { li { position: relative; text-align: center; diff --git a/app/controllers/favorite_groups_controller.rb b/app/controllers/favorite_groups_controller.rb new file mode 100644 index 000000000..4a5a1799f --- /dev/null +++ b/app/controllers/favorite_groups_controller.rb @@ -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 diff --git a/app/logical/anonymous_user.rb b/app/logical/anonymous_user.rb index 6e3fa00e3..91f1d6260 100644 --- a/app/logical/anonymous_user.rb +++ b/app/logical/anonymous_user.rb @@ -221,6 +221,10 @@ class AnonymousUser false end + def favorite_groups + [] + end + %w(member banned gold builder platinum contributor janitor moderator admin).each do |name| define_method("is_#{name}?") do false diff --git a/app/logical/post_query_builder.rb b/app/logical/post_query_builder.rb index 470e60ecb..32d4bf962 100644 --- a/app/logical/post_query_builder.rb +++ b/app/logical/post_query_builder.rb @@ -312,6 +312,12 @@ class PostQueryBuilder relation = relation.order("position(' '||posts.id||' ' in ' '||(select post_ids from pools where id = #{pool_id})||' ')") 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? user_id = q[:ordfav].to_i relation = relation.joins("INNER JOIN favorites ON favorites.post_id = posts.id") diff --git a/app/logical/post_sets/favorite_group.rb b/app/logical/post_sets/favorite_group.rb new file mode 100644 index 000000000..ea571ef70 --- /dev/null +++ b/app/logical/post_sets/favorite_group.rb @@ -0,0 +1,7 @@ +module PostSets + class FavoriteGroup < PostSets::Pool + def presenter + @presenter ||= PostSetPresenters::FavoriteGroup.new(self) + end + end +end diff --git a/app/models/favorite_group.rb b/app/models/favorite_group.rb new file mode 100644 index 000000000..d68bae5d2 --- /dev/null +++ b/app/models/favorite_group.rb @@ -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 diff --git a/app/models/post.rb b/app/models/post.rb index 3a757caa9..a8e8fbc40 100644 --- a/app/models/post.rb +++ b/app/models/post.rb @@ -629,7 +629,7 @@ class Post < ActiveRecord::Base def filter_metatags(tags) @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 return tags end @@ -669,6 +669,22 @@ class Post < ActiveRecord::Base child = Post.find($1) child.parent_id = id 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 @@ -821,6 +837,14 @@ class Post < ActiveRecord::Base def favorited_users favorited_user_ids.map {|id| User.find(id)} end + + def favorite_groups + @favorite_groups ||= begin + CurrentUser.user.favorite_groups.select do |favgroup| + favgroup.contains?(self.id) + end + end + end end module UploaderMethods @@ -1578,6 +1602,7 @@ class Post < ActiveRecord::Base super reset_tag_array_cache @pools = nil + @favorite_groups = nil @tag_categories = nil @typed_tags = nil self diff --git a/app/models/tag.rb b/app/models/tag.rb index 7ccd92ca4..7435c7498 100644 --- a/app/models/tag.rb +++ b/app/models/tag.rb @@ -1,5 +1,5 @@ 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" attr_accessible :category, :as => [:moderator, :janitor, :contributor, :gold, :member, :anonymous, :default, :builder, :admin] attr_accessible :is_locked, :as => [:moderator, :janitor, :admin] @@ -460,6 +460,10 @@ class Tag < ActiveRecord::Base q[:tags][:related] << "pool:#{pool_id}" q[:ordpool] = pool_id + when "favgroup" + favgroup_id = FavoriteGroup.name_to_id($2) + q[:favgroup] = favgroup_id + when "-fav" q[:tags][:exclude] << "fav:#{User.name_to_id($2)}" diff --git a/app/models/user.rb b/app/models/user.rb index c4f083b53..fcb9aacdf 100644 --- a/app/models/user.rb +++ b/app/models/user.rb @@ -253,6 +253,10 @@ class User < ActiveRecord::Base def remove_favorite!(post) Favorite.remove(post, self) end + + def favorite_groups + FavoriteGroup.for_creator(CurrentUser.user.id) + end end module LevelMethods @@ -541,7 +545,17 @@ class User < ActiveRecord::Base 10_000 end end - + + def favorite_group_limit + if is_platinum? + 10 + elsif is_gold? + 5 + else + 3 + end + end + def api_hourly_limit if is_platinum? && api_key.present? 20_000 @@ -634,6 +648,10 @@ class User < ActiveRecord::Base Comment.for_creator(id).count end + def favorite_group_count + FavoriteGroup.for_creator(id).count + end + def appeal_count PostAppeal.for_creator(id).count end diff --git a/app/presenters/post_presenter.rb b/app/presenters/post_presenter.rb index a2d5478b9..6c29a1e87 100644 --- a/app/presenters/post_presenter.rb +++ b/app/presenters/post_presenter.rb @@ -26,6 +26,8 @@ class PostPresenter < Presenter tag_param = "?tags=#{CGI::escape(options[:tags])}" elsif options[:pool_id] || options[:pool] 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 tag_param = nil end @@ -203,7 +205,7 @@ class PostPresenter < Presenter end 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 def post_footer_for_pool_html(template) diff --git a/app/presenters/post_set_presenters/favorite_group.rb b/app/presenters/post_set_presenters/favorite_group.rb new file mode 100644 index 000000000..701bd6483 --- /dev/null +++ b/app/presenters/post_set_presenters/favorite_group.rb @@ -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 diff --git a/app/presenters/user_presenter.rb b/app/presenters/user_presenter.rb index 26a641373..7b2adb823 100644 --- a/app/presenters/user_presenter.rb +++ b/app/presenters/user_presenter.rb @@ -101,6 +101,10 @@ class UserPresenter template.link_to(user.favorite_count, template.favorites_path(:user_id => user.id)) 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) template.link_to(user.comment_count, template.comments_path(:search => {:creator_id => user.id}, :group_by => "comment")) end diff --git a/app/views/favorite_groups/_secondary_links.html.erb b/app/views/favorite_groups/_secondary_links.html.erb new file mode 100644 index 000000000..909f984ee --- /dev/null +++ b/app/views/favorite_groups/_secondary_links.html.erb @@ -0,0 +1,19 @@ +<% content_for(:secondary_links) do %> + +
  • <%= link_to "Listing", favorite_groups_path %>
  • + <% if CurrentUser.is_member? %> +
  • <%= link_to "New", new_favorite_group_path %>
  • + <% end %> +
  • <%= link_to "Help", wiki_pages_path(:title => "help:favorite_groups") %>
  • + + <% if @favorite_group && !@favorite_group.new_record? %> +
  • |
  • +
  • <%= link_to "Show", favorite_group_path(@favorite_group) %>
  • +
  • <%= link_to "Posts", posts_path(:tags => "favgroup:#{@favorite_group.id}") %>
  • + <% if @favorite_group.editable_by?(CurrentUser.user) %> +
  • <%= link_to "Edit", edit_favorite_group_path(@favorite_group) %>
  • +
  • <%= link_to "Delete", favorite_group_path(@favorite_group), :method => :delete, :data => {:confirm => "Are you sure you want to delete this favorite group?"} %>
  • + <% end %> + <% end %> +
    +<% end %> diff --git a/app/views/favorite_groups/edit.html.erb b/app/views/favorite_groups/edit.html.erb new file mode 100644 index 000000000..93b5d8c59 --- /dev/null +++ b/app/views/favorite_groups/edit.html.erb @@ -0,0 +1,19 @@ +
    +
    +

    Edit Favorite Group: <%= @favorite_group.pretty_name %>

    + + <%= 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 %> +
    +
    + +<%= render "secondary_links" %> + +<% content_for(:page_title) do %> + Edit Favorite Group - <%= Danbooru.config.app_name %> +<% end %> diff --git a/app/views/favorite_groups/index.html.erb b/app/views/favorite_groups/index.html.erb new file mode 100644 index 000000000..317c9fcce --- /dev/null +++ b/app/views/favorite_groups/index.html.erb @@ -0,0 +1,40 @@ +
    +
    + + + + + + + + + + <% @favorite_groups.each do |favgroup| %> + <%= content_tag(:tr, :id => "favorite-group-#{favgroup.id}") do %> + + + + <% end %> + <% end %> + +
    NameCount
    + + + <%= 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 %> + + <%= favgroup.post_count %> +
    + + <%= numbered_paginator(@favorite_groups) %> + + <%= render "secondary_links" %> +
    +
    + +<% content_for(:page_title) do %> + Favorite Groups - <%= Danbooru.config.app_name %> +<% end %> diff --git a/app/views/favorite_groups/new.html.erb b/app/views/favorite_groups/new.html.erb new file mode 100644 index 000000000..91013659c --- /dev/null +++ b/app/views/favorite_groups/new.html.erb @@ -0,0 +1,19 @@ +
    +
    +

    New Favorite Group

    + + <%= 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 %> +
    +
    + +<%= render "secondary_links" %> + +<% content_for(:page_title) do %> + New Favorite Group - <%= Danbooru.config.app_name %> +<% end %> diff --git a/app/views/favorite_groups/show.html.erb b/app/views/favorite_groups/show.html.erb new file mode 100644 index 000000000..c37d9e848 --- /dev/null +++ b/app/views/favorite_groups/show.html.erb @@ -0,0 +1,22 @@ +
    +
    +

    + Favorite Group: + <%= link_to @favorite_group.pretty_name, posts_path(:tags => "favgroup:#{@favorite_group.id}") %> +

    + + <%= render "posts/partials/common/inline_blacklist" %> + +
    + <%= @post_set.presenter.post_previews_html(self) %> + + <%= numbered_paginator(@post_set) %> +
    +
    +
    + +<%= render "secondary_links" %> + +<% content_for(:page_title) do %> + Favorite Group - <%= @favorite_group.pretty_name %> - <%= Danbooru.config.app_name %> +<% end %> diff --git a/app/views/posts/partials/common/_secondary_links.html.erb b/app/views/posts/partials/common/_secondary_links.html.erb index b4c41409f..e55bb1541 100644 --- a/app/views/posts/partials/common/_secondary_links.html.erb +++ b/app/views/posts/partials/common/_secondary_links.html.erb @@ -6,6 +6,7 @@
  • <%= link_to "Hot", posts_path(:tags => "order:rank") %>
  • <% unless CurrentUser.is_anonymous? %>
  • <%= link_to "Favorites", favorites_path %>
  • +
  • <%= link_to "Favorite groups", favorite_groups_path %>
  • <% if CurrentUser.user.has_saved_searches? %>
  • <%= link_to "Saved searches", saved_searches_path %>
  • <% end %> diff --git a/app/views/posts/partials/show/_favorite_groups.html.erb b/app/views/posts/partials/show/_favorite_groups.html.erb new file mode 100644 index 000000000..738979b88 --- /dev/null +++ b/app/views/posts/partials/show/_favorite_groups.html.erb @@ -0,0 +1,23 @@ +
    + +
    diff --git a/app/views/posts/partials/show/_nav_links.html.erb b/app/views/posts/partials/show/_nav_links.html.erb index bf8576811..64cd03560 100644 --- a/app/views/posts/partials/show/_nav_links.html.erb +++ b/app/views/posts/partials/show/_nav_links.html.erb @@ -7,5 +7,9 @@ <% if post.pools.any? %> <%= render "posts/partials/show/pools", :post => post %> <% end %> + + <% if post.favorite_groups.any? %> + <%= render "posts/partials/show/favorite_groups", :post => post %> + <% end %> <% end %> diff --git a/app/views/users/_statistics.html.erb b/app/views/users/_statistics.html.erb index 37707a64f..7d46769c8 100644 --- a/app/views/users/_statistics.html.erb +++ b/app/views/users/_statistics.html.erb @@ -44,6 +44,11 @@ <%= presenter.favorite_count(self) %> + + Favorite Groups + <%= presenter.favorite_group_count(self) %> + + Post Changes <%= presenter.post_version_count(self) %> diff --git a/config/routes.rb b/config/routes.rb index 1b168509c..923cd3ce4 100644 --- a/config/routes.rb +++ b/config/routes.rb @@ -109,6 +109,7 @@ Rails.application.routes.draw do end resource :dtext_preview, :only => [:create] resources :favorites + resources :favorite_groups resources :forum_posts do member do post :undelete diff --git a/db/migrate/20150623191904_create_favorite_groups.rb b/db/migrate/20150623191904_create_favorite_groups.rb new file mode 100644 index 000000000..5662fa4d1 --- /dev/null +++ b/db/migrate/20150623191904_create_favorite_groups.rb @@ -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