FEATURE: add liked and bookmarked classes to topic list item rows

This commit is contained in:
Sam 2015-01-08 14:35:56 +11:00
parent df7def6628
commit 3347a48275
7 changed files with 115 additions and 2 deletions

View File

@ -4,7 +4,12 @@ export default Discourse.View.extend(StringBuffer, {
rerenderTriggers: ['controller.bulkSelectEnabled', 'topic.pinned'], rerenderTriggers: ['controller.bulkSelectEnabled', 'topic.pinned'],
tagName: 'tr', tagName: 'tr',
rawTemplate: 'list/topic_list_item.raw', rawTemplate: 'list/topic_list_item.raw',
classNameBindings: ['controller.checked', 'content.archived', ':topic-list-item', 'content.hasExcerpt:has-excerpt'], classNameBindings: ['controller.checked',
'content.archived',
':topic-list-item',
'content.hasExcerpt:has-excerpt',
'content.liked:liked',
'content.bookmarked:bookmarked'],
attributeBindings: ['data-topic-id'], attributeBindings: ['data-topic-id'],
'data-topic-id': Em.computed.alias('content.id'), 'data-topic-id': Em.computed.alias('content.id'),
titleColSpan: function(){ titleColSpan: function(){

View File

@ -384,7 +384,16 @@ class PostAction < ActiveRecord::Base
Post.where(id: post_id).update_all ["#{column} = ?", count] Post.where(id: post_id).update_all ["#{column} = ?", count]
end end
topic_id = Post.with_deleted.where(id: post_id).pluck(:topic_id).first topic_id = Post.with_deleted.where(id: post_id).pluck(:topic_id).first
# topic_user
if [:like,:bookmark].include? post_action_type_key
TopicUser.update_post_action_cache(user_id: user_id,
topic_id: topic_id,
post_action_type: post_action_type_key)
end
topic_count = Post.where(topic_id: topic_id).sum(column) topic_count = Post.where(topic_id: topic_id).sum(column)
Topic.where(id: topic_id).update_all ["#{column} = ?", topic_count] Topic.where(id: topic_id).update_all ["#{column} = ?", topic_count]

View File

@ -229,7 +229,60 @@ class TopicUser < ActiveRecord::Base
end end
end end
def self.update_post_action_cache(opts={})
user_id = opts[:user_id]
topic_id = opts[:topic_id]
action_type = opts[:post_action_type]
action_type_name = "liked" if action_type == :like
action_type_name = "bookmarked" if action_type == :bookmark
raise ArgumentError, "action_type" if action_type && !action_type_name
unless action_type_name
update_post_action_cache(opts.merge(post_action_type: :like))
update_post_action_cache(opts.merge(post_action_type: :bookmark))
return
end
builder = SqlBuilder.new <<SQL
UPDATE topic_users tu
SET #{action_type_name} = x.state
FROM (
SELECT CASE WHEN EXISTS (
SELECT 1
FROM post_actions pa
JOIN posts p on p.id = pa.post_id
JOIN topics t ON t.id = p.topic_id
WHERE pa.deleted_at IS NULL AND
p.deleted_at IS NULL AND
t.deleted_at IS NULL AND
pa.post_action_type_id = :action_type_id AND
tu2.topic_id = t.id AND
tu2.user_id = pa.user_id
LIMIT 1
) THEN true ELSE false END state, tu2.topic_id, tu2.user_id
FROM topic_users tu2
/*where*/
) x
WHERE x.topic_id = tu.topic_id AND x.user_id = tu.user_id AND x.state != tu.#{action_type_name}
SQL
if user_id
builder.where("tu2.user_id = :user_id", user_id: user_id)
end
if topic_id
builder.where("tu2.topic_id = :topic_id", topic_id: topic_id)
end
builder.exec(action_type_id: PostActionType.types[action_type])
end
def self.ensure_consistency!(topic_id=nil) def self.ensure_consistency!(topic_id=nil)
update_post_action_cache
# TODO this needs some reworking, when we mark stuff skipped # TODO this needs some reworking, when we mark stuff skipped
# we up these numbers so they are not in-sync # we up these numbers so they are not in-sync
# the simple fix is to add a column here, but table is already quite big # the simple fix is to add a column here, but table is already quite big

View File

@ -20,10 +20,20 @@ class ListableTopicSerializer < BasicTopicSerializer
:closed, :closed,
:archived, :archived,
:is_warning, :is_warning,
:notification_level :notification_level,
:bookmarked,
:liked
has_one :last_poster, serializer: BasicUserSerializer, embed: :objects has_one :last_poster, serializer: BasicUserSerializer, embed: :objects
def liked
object.user_data && object.user_data.liked
end
def bookmarked
object.user_data && object.user_data.bookmarked
end
def include_last_poster? def include_last_poster?
object.include_last_poster object.include_last_poster
end end

View File

@ -0,0 +1,28 @@
class AddLikedAndBookmarkedToTopicUser < ActiveRecord::Migration
def up
add_column :topic_users, :liked, :boolean, default: false
add_column :topic_users, :bookmarked, :boolean, default: false
# likes and bookmarks PostActionType.types[:like] and :bookmark which should not be used in a migration
{liked: 1, bookmarked: 2}.each do |name, type|
execute "UPDATE topic_users
SET #{name} = true
WHERE EXISTS (SELECT 1 FROM post_actions pa
JOIN posts p ON p.id = pa.post_id
JOIN topics t ON t.id = p.topic_id
WHERE pa.deleted_at IS NULL AND
p.deleted_at IS NULL AND
t.deleted_at IS NULL AND
pa.user_id = topic_users.user_id AND
p.topic_id = topic_users.topic_id AND
post_action_type_id = #{type})
"
end
end
def down
remove_column :topic_users, :liked
remove_column :topic_users, :bookmarked
end
end

View File

@ -89,6 +89,7 @@ class PostDestroyer
end end
update_associated_category_latest_topic update_associated_category_latest_topic
update_user_counts update_user_counts
TopicUser.update_post_action_cache(topic_id: @post.topic_id)
end end
@post.publish_change_to_clients! :deleted if @post.topic @post.publish_change_to_clients! :deleted if @post.topic

View File

@ -140,11 +140,18 @@ describe PostAction do
describe "update_counters" do describe "update_counters" do
it "properly updates topic counters" do it "properly updates topic counters" do
# we need this to test it
TopicUser.change(codinghorror, post.topic, posted: true)
PostAction.act(moderator, post, PostActionType.types[:like]) PostAction.act(moderator, post, PostActionType.types[:like])
PostAction.act(codinghorror, second_post, PostActionType.types[:like]) PostAction.act(codinghorror, second_post, PostActionType.types[:like])
post.topic.reload post.topic.reload
expect(post.topic.like_count).to eq(2) expect(post.topic.like_count).to eq(2)
tu = TopicUser.get(post.topic, codinghorror)
expect(tu.liked).to be true
end end
end end