FEATURE: support for filter=bookmarked and filter=liked in topic list

This commit is contained in:
Sam 2015-01-07 18:20:10 +11:00
parent da3da6feee
commit ea87f5fd8a
7 changed files with 85 additions and 8 deletions

View File

@ -260,7 +260,7 @@ class ListController < ApplicationController
min_posts: params[:min_posts],
max_posts: params[:max_posts],
status: params[:status],
bookmarked: params[:bookmarked].present?,
filter: params[:filter],
state: params[:state],
search: params[:search]
}

View File

@ -80,6 +80,23 @@ class PostAction < ActiveRecord::Base
user_actions
end
def self.lookup_for(user, topics, post_action_type_id)
return if topics.blank?
map = {}
PostAction.where(user_id: user.id, post_action_type_id: post_action_type_id, deleted_at: nil)
.references(:post)
.includes(:post)
.where('posts.topic_id in (?)', topics.map(&:id))
.order('posts.topic_id, posts.post_number')
.pluck('posts.topic_id, posts.post_number')
.each do |topic_id, post_number|
(map[topic_id] ||= []) << post_number
end
map
end
def self.active_flags_counts_for(collection)
return {} if collection.blank?

View File

@ -46,6 +46,20 @@ class TopicList
# Attach some data for serialization to each topic
@topic_lookup = TopicUser.lookup_for(@current_user, @topics) if @current_user.present?
post_action_type =
if @current_user.present?
if @opts[:filter].present?
if @opts[:filter] == "bookmarked"
PostActionType.types[:bookmark]
elsif @opts[:filter] == "liked"
PostActionType.types[:like]
end
end
end
# Data for bookmarks or likes
post_action_lookup = PostAction.lookup_for(@current_user, @topics, post_action_type) if post_action_type
# Create a lookup for all the user ids we need
user_ids = []
@topics.each do |ft|
@ -56,6 +70,11 @@ class TopicList
@topics.each do |ft|
ft.user_data = @topic_lookup[ft.id] if @topic_lookup.present?
if ft.user_data && post_action_lookup && actions = post_action_lookup[ft.id]
ft.user_data.post_action_data = {post_action_type => actions}
end
ft.posters = ft.posters_summary(avatar_lookup: avatar_lookup)
ft.participants = ft.participants_summary(avatar_lookup: avatar_lookup, user: @current_user)
ft.topic_list = self

View File

@ -2,6 +2,9 @@ class TopicUser < ActiveRecord::Base
belongs_to :user
belongs_to :topic
# used for serialization
attr_accessor :post_action_data
scope :tracking, lambda { |topic_id|
where(topic_id: topic_id)
.where("COALESCE(topic_users.notification_level, :regular) >= :tracking",

View File

@ -7,7 +7,8 @@ class TopicListItemSerializer < ListableTopicSerializer
:last_poster_username,
:category_id,
:op_like_count,
:pinned_globally
:pinned_globally,
:bookmarked_post_numbers
has_many :posters, serializer: TopicPosterSerializer, embed: :objects
has_many :participants, serializer: TopicPosterSerializer, embed: :objects
@ -28,6 +29,16 @@ class TopicListItemSerializer < ListableTopicSerializer
object.participants_summary || []
end
def include_bookmarked_post_numbers?
object.user_data &&
object.user_data.post_action_data &&
object.user_data.post_action_data.key?(PostActionType.types[:bookmark])
end
def bookmarked_post_numbers
object.user_data.post_action_data[PostActionType.types[:bookmark]]
end
def include_participants?
object.private_message?
end

View File

@ -26,7 +26,7 @@ class TopicQuery
state
search
slow_platform
bookmarked
filter
).map(&:to_sym)
# Maps `order` to a columns in `topics`
@ -311,17 +311,25 @@ class TopicQuery
end
end
if options[:bookmarked] && @user
if (filter=options[:filter]) && @user
action =
if filter == "bookmarked"
PostActionType.types[:bookmark]
elsif filter == "liked"
PostActionType.types[:like]
end
if action
result = result.where('topics.id IN (SELECT pp.topic_id
FROM post_actions pa
JOIN posts pp ON pp.id = pa.post_id
WHERE pa.user_id = :user_id AND
pa.post_action_type_id = :bookmarked AND
pa.post_action_type_id = :action AND
pa.deleted_at IS NULL
)', user_id: @user.id,
bookmarked: PostActionType.types[:bookmark]
action: action
)
end
end
result = result.where('topics.deleted_at IS NULL') if require_deleted_clause
result = result.where('topics.posts_count <= ?', options[:max_posts]) if options[:max_posts].present?

View File

@ -40,9 +40,28 @@ describe TopicQuery do
end
context 'bookmarks' do
it "filters and returns bookmarks correctly" do
post = Fabricate(:post)
reply = Fabricate(:post, topic_id: post.topic_id)
post2 = Fabricate(:post)
PostAction.act(user, post, PostActionType.types[:bookmark])
PostAction.act(user, reply, PostActionType.types[:bookmark])
TopicUser.change(user, post.topic, notification_level: 1)
TopicUser.change(user, post2.topic, notification_level: 1)
query = TopicQuery.new(user, filter: 'bookmarked').list_latest
query.topics.length.should == 1
query.topics.first.user_data.post_action_data.should == {PostActionType.types[:bookmark] => [1,2]}
end
end
context 'deleted filter' do
it "filters deleted topics correctly" do
topic = Fabricate(:topic, deleted_at: 1.year.ago)
_topic = Fabricate(:topic, deleted_at: 1.year.ago)
TopicQuery.new(admin, status: 'deleted').list_latest.topics.size.should == 1
TopicQuery.new(moderator, status: 'deleted').list_latest.topics.size.should == 1