From 23c0cb552969ecf3de6a6cfb050f8d047c0c5738 Mon Sep 17 00:00:00 2001 From: albert Date: Thu, 21 Feb 2013 18:18:08 -0500 Subject: [PATCH] add post previews to user profile, improved ui for tag subscriptions --- .../stylesheets/specific/users.css.scss | 22 +++ app/models/tag_subscription.rb | 14 +- app/presenters/user_presenter.rb | 72 ++++++---- app/views/posts/index.html.erb | 2 +- .../posts/partials/index/_related.html.erb | 8 +- app/views/users/show.html.erb | 130 ++++++++++++------ ...1_add_index_updated_at_on_pool_versions.rb | 4 +- db/structure.sql | 11 +- test/unit/tag_subscription_test.rb | 67 ++++++--- 9 files changed, 234 insertions(+), 96 deletions(-) diff --git a/app/assets/stylesheets/specific/users.css.scss b/app/assets/stylesheets/specific/users.css.scss index 8a3e0d519..5a82d54bf 100644 --- a/app/assets/stylesheets/specific/users.css.scss +++ b/app/assets/stylesheets/specific/users.css.scss @@ -2,6 +2,28 @@ div#c-users { div#a-show { + div.grid { + div.col { + float: left; + width: 50%; + } + + div.box { + clear: both; + margin-bottom: 2em; + } + + /* clearfix hacks */ + div.box:before, div.box:after { + content: ""; + display: table; + } + + div.box:after { + clear: both; + } + } + dl { dt { width: 12em; diff --git a/app/models/tag_subscription.rb b/app/models/tag_subscription.rb index 2cd211256..270b3774a 100644 --- a/app/models/tag_subscription.rb +++ b/app/models/tag_subscription.rb @@ -6,6 +6,7 @@ class TagSubscription < ActiveRecord::Base before_save :limit_tag_count attr_accessible :name, :tag_query, :post_ids, :is_public, :is_visible_on_profile validates_presence_of :name, :tag_query, :is_public, :creator_id + validate :creator_can_create_subscriptions def normalize_name self.name = name.gsub(/\W/, "_") @@ -18,6 +19,15 @@ class TagSubscription < ActiveRecord::Base def initialize_post_ids process end + + def creator_can_create_subscriptions + if TagSubscription.owned_by(creator).count >= Danbooru.config.max_tag_subscriptions + self.errors.add(:creator, "can subscribe up to #{Danbooru.config.max_tag_subscriptions} tags") + return false + else + return true + end + end def tag_query_array Tag.scan_query(tag_query) @@ -94,10 +104,10 @@ class TagSubscription < ActiveRecord::Base end def self.find_post_ids(user_id, name = nil, limit = Danbooru.config.tag_subscription_post_limit) - relation = where(["creator_id = ?", user_id]) + relation = where("creator_id = ?", user_id) if name - relation = relation.where(["name ILIKE ? ESCAPE E'\\\\'", name.to_escaped_for_sql_like]) + relation = relation.where("name ILIKE ? ESCAPE E'\\\\'", name.to_escaped_for_sql_like) end relation.each do |tag_sub| diff --git a/app/presenters/user_presenter.rb b/app/presenters/user_presenter.rb index 038676ed1..da920b395 100644 --- a/app/presenters/user_presenter.rb +++ b/app/presenters/user_presenter.rb @@ -25,10 +25,16 @@ class UserPresenter end end - def tag_subscriptions(template) - user.subscriptions.map do |subscription| - template.link_to(subscription.name, template.tag_subscription_path(subscription)) - end.join("; ") + def tag_subscriptions + if CurrentUser.user.id == user.id + user.subscriptions + else + user.subscriptions.select {|x| x.is_public?} + end + end + + def posts_for_subscription(subscription) + Post.where("id in (?)", subscription.post_id_array.slice(0, 6).map(&:to_i)) end def upload_limit @@ -57,39 +63,55 @@ class UserPresenter return string end - def uploads(template) + def uploads + @uploads ||= Post.where("uploader_id = ?", user.id).order("id desc").limit(6) + end + + def has_uploads? + user.post_upload_count > 0 + end + + def favorites + @favorites ||= user.favorites.limit(6).includes(:post).map(&:post) + end + + def has_favorites? + user.favorite_count > 0 + end + + def upload_count(template) template.link_to(user.post_upload_count, template.posts_path(:tags => "user:#{user.name}")) end - def deleted_uploads(template) + def deleted_upload_count(template) template.link_to(Post.for_user(user.id).deleted.count, template.posts_path(:tags => "status:deleted user:#{user.name}")) end - def favorites(template) + def favorite_count(template) template.link_to(user.favorite_count, template.posts_path(:tags => "fav:#{user.name}")) end - def comments(template) + def comment_count(template) template.link_to(Comment.for_creator(user.id).count, template.comments_path(:search => {:creator_id => user.id})) end - def post_versions(template) + def post_version_count(template) template.link_to(user.post_update_count, template.post_versions_path(:search => {:updater_id => user.id})) end - def note_versions(template) + def note_version_count(template) template.link_to(user.note_update_count, template.note_versions_path(:search => {:updater_id => user.id})) end - def wiki_page_versions(template) + def wiki_page_version_count(template) template.link_to(WikiPageVersion.for_user(user.id).count, template.wiki_page_versions_path(:search => {:updater_id => user.id})) end - def forum_posts(template) + def forum_post_count(template) template.link_to(ForumPost.for_user(user.id).count, template.forum_posts_path(:search => {:creator_id => user.id})) end - def pool_versions(template) + def pool_version_count(template) template.link_to(PoolVersion.for_user(user.id).count, template.pool_versions_path(:search => {:updater_id => user.id})) end @@ -101,7 +123,7 @@ class UserPresenter end end - def approvals(template) + def approval_count(template) template.link_to(Post.where("approver_id = ?", user.id).count, template.posts_path(:tags => "approver:#{user.name}")) end @@ -113,15 +135,17 @@ class UserPresenter template.link_to("positive:#{positive} neutral:#{neutral} negative:#{negative}", template.user_feedbacks_path(:search => {:user_id => user.id})) end - def subscriptions(template) - if user.subscriptions.any? - str = user.subscriptions.map do |subscription| - template.link_to(subscription.name, template.posts_path(:tags => "sub:#{user.name}:#{subscription.name}")) - end.join(", ") - str += " [" + template.link_to("edit", template.tag_subscriptions_path) + "]" - str.html_safe - else - "None" - end + def subscriptions + user.subscriptions + # + # if user.subscriptions.any? + # str = user.subscriptions.map do |subscription| + # template.link_to(subscription.name, template.posts_path(:tags => "sub:#{user.name}:#{subscription.name}")) + # end.join(", ") + # str += " [" + template.link_to("edit", template.tag_subscriptions_path) + "]" + # str.html_safe + # else + # "None" + # end end end diff --git a/app/views/posts/index.html.erb b/app/views/posts/index.html.erb index eefcd18d7..8c74db2ae 100644 --- a/app/views/posts/index.html.erb +++ b/app/views/posts/index.html.erb @@ -11,7 +11,7 @@

Tags

<%= @post_set.presenter.tag_list_html(self) %> - + <%= render "posts/partials/index/blacklist" %> <%= render "posts/partials/index/related" %> diff --git a/app/views/posts/partials/index/_related.html.erb b/app/views/posts/partials/index/_related.html.erb index 0d9083206..76aeb1d25 100644 --- a/app/views/posts/partials/index/_related.html.erb +++ b/app/views/posts/partials/index/_related.html.erb @@ -1,8 +1,12 @@ diff --git a/app/views/users/show.html.erb b/app/views/users/show.html.erb index f1e99af1a..2f80b6a7e 100644 --- a/app/views/users/show.html.erb +++ b/app/views/users/show.html.erb @@ -2,60 +2,106 @@

<%= @presenter.name %>

-
-
Join Date
-
<%= @presenter.join_date %>
+
+
+
+

<%= link_to "Uploads", posts_path(:tags => "user:#{@user.name}") %>

+ <% if @presenter.has_uploads? %> +
+ <% @presenter.uploads.each do |post| %> + <%= PostPresenter.preview(post) %> + <% end %> +
+ <% else %> +

None

+ <% end %> +
+ +
+

<%= link_to "Favorites", posts_path(:tags => "fav:#{@user.name}") %>

+ <% if @presenter.has_favorites? %> +
+ <% @presenter.favorites.each do |post| %> + <%= PostPresenter.preview(post) %> + <% end %> +
+ <% else %> +

None

+ <% end %> +
+ +
+

Subscriptions

+ <% @presenter.subscriptions.each do |subscription| %> +
+

<%= link_to subscription.name, posts_path(:tags => "sub:#{@user.name}:#{subscription.name}") %>

+ +
+ <% @presenter.posts_for_subscription(subscription).each do |post| %> + <%= PostPresenter.preview(post) %> + <% end %> +
+
+ + <% end %> +
+
-
Inviter
-
<%= @presenter.inviter(self) %>
- -
Level
-
<%= @presenter.level %>
- - <% if @user.is_banned? %> -
Ban reason
-
<%= @presenter.ban_reason %>
- <% end %> - -
Upload Limit
-
<%= @presenter.upload_limit %>
+
+

Statistics

+
+
Join Date
+
<%= @presenter.join_date %>
-
Uploads
-
<%= @presenter.uploads(self) %>
+
Inviter
+
<%= @presenter.inviter(self) %>
-
Deleted Uploads
-
<%= @presenter.deleted_uploads(self) %>
+
Level
+
<%= @presenter.level %>
-
Favorites
-
<%= @presenter.favorites(self) %>
+ <% if @user.is_banned? %> +
Ban reason
+
<%= @presenter.ban_reason %>
+ <% end %> -
Subscriptions
-
<%= @presenter.subscriptions(self) %>
+
Upload Limit
+
<%= @presenter.upload_limit %>
-
Post Changes
-
<%= @presenter.post_versions(self) %>
+
Uploads
+
<%= @presenter.upload_count(self) %>
-
Note Changes
-
<%= @presenter.note_versions(self) %>
+
Deleted Uploads
+
<%= @presenter.deleted_upload_count(self) %>
-
Wiki Page Changes
-
<%= @presenter.wiki_page_versions(self) %>
+
Favorites
+
<%= @presenter.favorite_count(self) %>
-
Pool Changes
-
<%= @presenter.pool_versions(self) %>
+
Post Changes
+
<%= @presenter.post_version_count(self) %>
-
Forum Posts
-
<%= @presenter.forum_posts(self) %>
+
Note Changes
+
<%= @presenter.note_version_count(self) %>
-
Approvals
-
<%= @presenter.approvals(self) %>
- -
Comments
-
<%= @presenter.comments(self) %>
+
Wiki Page Changes
+
<%= @presenter.wiki_page_version_count(self) %>
-
Feedback
-
<%= @presenter.feedbacks(self) %>
-
+
Pool Changes
+
<%= @presenter.pool_version_count(self) %>
+ +
Forum Posts
+
<%= @presenter.forum_post_count(self) %>
+ +
Approvals
+
<%= @presenter.approval_count(self) %>
+ +
Comments
+
<%= @presenter.comment_count(self) %>
+ +
Feedback
+
<%= @presenter.feedbacks(self) %>
+
+
+ diff --git a/db/migrate/20130221214811_add_index_updated_at_on_pool_versions.rb b/db/migrate/20130221214811_add_index_updated_at_on_pool_versions.rb index 4d3dff3a2..01bca170e 100644 --- a/db/migrate/20130221214811_add_index_updated_at_on_pool_versions.rb +++ b/db/migrate/20130221214811_add_index_updated_at_on_pool_versions.rb @@ -1,11 +1,11 @@ class AddIndexUpdatedAtOnPoolVersions < ActiveRecord::Migration def up execute "set statement_timeout = 0" - add_index :post_versions, :updated_at + add_index :pool_versions, :updated_at end def down execute "set statement_timeout = 0" - remove_index :post_versions, :updated_at + remove_index :pool_versions, :updated_at end end diff --git a/db/structure.sql b/db/structure.sql index 183187111..32f8a2cb7 100644 --- a/db/structure.sql +++ b/db/structure.sql @@ -5647,6 +5647,13 @@ CREATE INDEX index_notes_on_post_id ON notes USING btree (post_id); CREATE INDEX index_pool_versions_on_pool_id ON pool_versions USING btree (pool_id); +-- +-- Name: index_pool_versions_on_updated_at; Type: INDEX; Schema: public; Owner: -; Tablespace: +-- + +CREATE INDEX index_pool_versions_on_updated_at ON pool_versions USING btree (updated_at); + + -- -- Name: index_pool_versions_on_updater_id; Type: INDEX; Schema: public; Owner: -; Tablespace: -- @@ -6198,4 +6205,6 @@ INSERT INTO schema_migrations (version) VALUES ('20130219184743'); INSERT INTO schema_migrations (version) VALUES ('20130221032344'); -INSERT INTO schema_migrations (version) VALUES ('20130221035518'); \ No newline at end of file +INSERT INTO schema_migrations (version) VALUES ('20130221035518'); + +INSERT INTO schema_migrations (version) VALUES ('20130221214811'); \ No newline at end of file diff --git a/test/unit/tag_subscription_test.rb b/test/unit/tag_subscription_test.rb index 9ebee0de8..939718e33 100644 --- a/test/unit/tag_subscription_test.rb +++ b/test/unit/tag_subscription_test.rb @@ -14,6 +14,19 @@ class TagSubscriptionTest < ActiveSupport::TestCase end context "A tag subscription" do + context "for a user with too many subscriptions" do + setup do + Danbooru.config.stubs(:max_tag_subscriptions).returns(0) + @user = FactoryGirl.create(:user) + end + + should "fail" do + sub = FactoryGirl.build(:tag_subscription, :tag_query => "aaa bbb", :creator => @user, :name => "zzz") + sub.save + assert_equal(["Creator can subscribe up to 0 tags"], sub.errors.full_messages) + end + end + should "find the union of all posts for each tag in its tag query" do posts = [] user = FactoryGirl.create(:user) @@ -21,10 +34,12 @@ class TagSubscriptionTest < ActiveSupport::TestCase posts << FactoryGirl.create(:post, :tag_string => "bbb") posts << FactoryGirl.create(:post, :tag_string => "ccc") posts << FactoryGirl.create(:post, :tag_string => "ddd") - sub_1 = FactoryGirl.create(:tag_subscription, :tag_query => "aaa bbb", :creator => user, :name => "zzz") - sub_2 = FactoryGirl.create(:tag_subscription, :tag_query => "ccc", :creator => user, :name => "yyy") - assert_equal([posts[1].id, posts[0].id], TagSubscription.find_posts(user.id, "zzz").map(&:id)) - assert_equal([posts[2].id, posts[1].id, posts[0].id], TagSubscription.find_posts(user.id).map(&:id)) + CurrentUser.scoped(user, "127.0.0.1") do + sub_1 = FactoryGirl.create(:tag_subscription, :tag_query => "aaa bbb", :name => "zzz") + sub_2 = FactoryGirl.create(:tag_subscription, :tag_query => "ccc", :name => "yyy") + assert_equal([posts[1].id, posts[0].id], TagSubscription.find_posts(user.id, "zzz").map(&:id)) + assert_equal([posts[2].id, posts[1].id, posts[0].id], TagSubscription.find_posts(user.id).map(&:id)) + end end should "cache its tag query results" do @@ -33,26 +48,30 @@ class TagSubscriptionTest < ActiveSupport::TestCase posts << FactoryGirl.create(:post, :tag_string => "aaa") posts << FactoryGirl.create(:post, :tag_string => "bbb") posts << FactoryGirl.create(:post, :tag_string => "ccc") - sub = FactoryGirl.create(:tag_subscription, :tag_query => "aaa bbb", :creator => user, :name => "zzz") - assert_equal("#{posts[1].id},#{posts[0].id}", sub.post_ids) + CurrentUser.scoped(user, "127.0.0.1") do + sub = FactoryGirl.create(:tag_subscription, :tag_query => "aaa bbb", :name => "zzz") + assert_equal("#{posts[1].id},#{posts[0].id}", sub.post_ids) + end end should "find posts based on its cached post ids" do user = FactoryGirl.create(:user) - subs = [] - subs << FactoryGirl.create(:tag_subscription, :tag_query => "aaa", :creator => user, :name => "zzz") - subs << FactoryGirl.create(:tag_subscription, :tag_query => "bbb", :creator => user, :name => "yyy") - assert_equal([], TagSubscription.find_posts(user.id)) - assert_equal([], TagSubscription.find_posts(user.id, "zzz")) - assert_equal([], TagSubscription.find_posts(user.id, "yyy")) - posts = [] - posts << FactoryGirl.create(:post, :tag_string => "aaa") - posts << FactoryGirl.create(:post, :tag_string => "bbb") - posts << FactoryGirl.create(:post, :tag_string => "ccc") - subs.each {|x| x.process; x.save} - assert_equal([posts[1].id, posts[0].id], TagSubscription.find_posts(user.id).map(&:id)) - assert_equal([posts[0].id], TagSubscription.find_posts(user.id, "zzz").map(&:id)) - assert_equal([posts[1].id], TagSubscription.find_posts(user.id, "yyy").map(&:id)) + CurrentUser.scoped(user, "127.0.0.1") do + subs = [] + subs << FactoryGirl.create(:tag_subscription, :tag_query => "aaa", :name => "zzz") + subs << FactoryGirl.create(:tag_subscription, :tag_query => "bbb", :name => "yyy") + assert_equal([], TagSubscription.find_posts(user.id)) + assert_equal([], TagSubscription.find_posts(user.id, "zzz")) + assert_equal([], TagSubscription.find_posts(user.id, "yyy")) + posts = [] + posts << FactoryGirl.create(:post, :tag_string => "aaa") + posts << FactoryGirl.create(:post, :tag_string => "bbb") + posts << FactoryGirl.create(:post, :tag_string => "ccc") + subs.each {|x| x.process; x.save} + assert_equal([posts[1].id, posts[0].id], TagSubscription.find_posts(user.id).map(&:id)) + assert_equal([posts[0].id], TagSubscription.find_posts(user.id, "zzz").map(&:id)) + assert_equal([posts[1].id], TagSubscription.find_posts(user.id, "yyy").map(&:id)) + end end end @@ -66,8 +85,12 @@ class TagSubscriptionTest < ActiveSupport::TestCase posts << FactoryGirl.create(:post, :tag_string => "bbb") posts << FactoryGirl.create(:post, :tag_string => "ccc") subscriptions = [] - subscriptions << FactoryGirl.create(:tag_subscription, :tag_query => "aaa", :creator => users[0]) - subscriptions << FactoryGirl.create(:tag_subscription, :tag_query => "bbb", :creator => users[1]) + CurrentUser.scoped(users[0], "127.0.0.1") do + subscriptions << FactoryGirl.create(:tag_subscription, :tag_query => "aaa") + end + CurrentUser.scoped(users[1], "127.0.0.1") do + subscriptions << FactoryGirl.create(:tag_subscription, :tag_query => "bbb") + end TagSubscription.process_all subscriptions.each {|x| x.reload} assert_equal("#{posts[0].id}", subscriptions[0].post_ids)