FEATURE: reorder participants in topic so always chronological

FEATURE: tie breaker for same number of posts is last post date
UX: highlight for latest poster when it is OP
This commit is contained in:
Sam 2015-04-06 17:27:05 +10:00
parent 0fcb98c80a
commit c6a5081763
7 changed files with 33 additions and 43 deletions

View File

@ -108,7 +108,16 @@
}
}
}
.posters a:first-child .avatar.latest:not(.single) {
box-shadow: 0 0 3px 1px desaturate(scale-color($tertiary, $lightness: 65%), 35%);
border: 2px solid desaturate(scale-color($tertiary, $lightness: 50%), 40%);
position: relative;
top: -2px;
left: -2px;
}
.sortable {
cursor: pointer;
&:hover {

View File

@ -43,6 +43,7 @@ class PostMover
update_user_actions
set_last_post_user_id(destination_topic)
destination_topic.reload
destination_topic
end

View File

@ -11,10 +11,8 @@ class TopicFeaturedUsers
# Chooses which topic users to feature
def choose(args={})
clear
update keys(args)
self.class.ensure_consistency!(topic.id.to_i)
update_participant_count
topic.save
end
def user_ids
@ -24,19 +22,29 @@ class TopicFeaturedUsers
topic.featured_user4_id].uniq.compact
end
def self.ensure_consistency!
def self.ensure_consistency!(topic_id=nil)
sql = <<SQL
WITH cte as (
SELECT
t.id, p.user_id,
ROW_NUMBER() OVER(PARTITION BY t.id ORDER BY COUNT(*) DESC) as rank
t.id,
p.user_id,
MAX(p.created_at) last_post_date,
ROW_NUMBER() OVER(PARTITION BY t.id ORDER BY COUNT(*) DESC, MAX(p.created_at) DESC) as rank
FROM topics t
JOIN posts p ON p.topic_id = t.id
WHERE p.deleted_at IS NULL AND NOT p.hidden AND p.user_id <> t.user_id AND
WHERE p.deleted_at IS NULL AND
NOT p.hidden AND
p.user_id <> t.user_id AND
p.user_id <> t.last_post_user_id
GROUP BY t.id, p.user_id
),
cte2 as (
SELECT id, user_id, ROW_NUMBER() OVER(PARTITION BY id ORDER BY last_post_date ASC) as rank
FROM cte
WHERE rank <= #{count}
)
UPDATE topics tt
@ -52,8 +60,7 @@ FROM (
MAX(case when c.rank = 2 then c.user_id end) featured_user2,
MAX(case when c.rank = 3 then c.user_id end) featured_user3,
MAX(case when c.rank = 4 then c.user_id end) featured_user4
FROM cte as c
WHERE c.rank <= 4
FROM cte2 as c
GROUP BY c.id
) x
WHERE x.id = tt.id AND
@ -62,7 +69,7 @@ WHERE x.id = tt.id AND
COALESCE(featured_user2_id,-99) <> COALESCE(featured_user2,-99) OR
COALESCE(featured_user3_id,-99) <> COALESCE(featured_user3,-99) OR
COALESCE(featured_user4_id,-99) <> COALESCE(featured_user4,-99)
)
) #{"AND x.id = #{topic_id.to_i}" if topic_id}
SQL
Topic.exec_sql(sql)
@ -70,30 +77,7 @@ SQL
private
def keys(args)
# Don't include the OP or the last poster
to_feature = topic.posts.where('user_id NOT IN (?, ?)', topic.user_id, topic.last_post_user_id)
# Exclude a given post if supplied (in the case of deletes)
to_feature = to_feature.where("id <> ?", args[:except_post_id]) if args[:except_post_id].present?
# Assign the featured_user{x} columns
to_feature.group(:user_id).order('count_all desc').limit(TopicFeaturedUsers.count).count.keys
end
def clear
TopicFeaturedUsers.count.times do |i|
topic.send("featured_user#{i+1}_id=", nil)
end
end
def update(user_keys)
user_keys.each_with_index do |user_id, i|
topic.send("featured_user#{i+1}_id=", user_id)
end
end
def update_participant_count
topic.participant_count = topic.posts.count('distinct user_id')
topic.update_columns(participant_count: topic.posts.count('distinct user_id'))
end
end

View File

@ -19,6 +19,7 @@ class PostOwnerChanger
@topic.update_statistics
@new_owner.user_stat.update(first_post_created_at: @new_owner.posts(true).order('created_at ASC').first.try(:created_at))
@topic.save!
end
end
end

View File

@ -72,7 +72,6 @@ class PostDestroyer
if @post.topic
make_previous_post_the_last_one
clear_user_posted_flag
feature_users_in_the_topic
Topic.reset_highest(@post.topic_id)
end
trash_public_post_actions
@ -92,6 +91,7 @@ class PostDestroyer
TopicUser.update_post_action_cache(topic_id: @post.topic_id)
end
feature_users_in_the_topic if @post.topic
@post.publish_change_to_clients! :deleted if @post.topic
end
@ -136,7 +136,7 @@ class PostDestroyer
end
def feature_users_in_the_topic
Jobs.enqueue(:feature_topic_users, topic_id: @post.topic_id, except_post_id: @post.id)
Jobs.enqueue(:feature_topic_users, topic_id: @post.topic_id)
end
def trash_public_post_actions

View File

@ -291,7 +291,7 @@ describe PostDestroyer do
let!(:post) { Fabricate(:post, raw: "Hello @CodingHorror") }
it "should feature the users again (in case they've changed)" do
Jobs.expects(:enqueue).with(:feature_topic_users, has_entries(topic_id: post.topic_id, except_post_id: post.id))
Jobs.expects(:enqueue).with(:feature_topic_users, has_entries(topic_id: post.topic_id))
PostDestroyer.new(moderator, post).destroy
end

View File

@ -30,11 +30,6 @@ describe Jobs::FeatureTopicUsers do
expect(topic.reload.featured_user_ids.include?(coding_horror.id)).to eq(true)
end
it "will not feature the second poster if we supply their post to be ignored" do
Jobs::FeatureTopicUsers.new.execute(topic_id: topic.id, except_post_id: second_post.id)
expect(topic.reload.featured_user_ids.include?(coding_horror.id)).to eq(false)
end
it "won't feature the last poster" do
Jobs::FeatureTopicUsers.new.execute(topic_id: topic.id)
expect(topic.reload.featured_user_ids.include?(evil_trout.id)).to eq(false)