mirror of
https://github.com/discourse/discourse.git
synced 2025-02-25 18:55:32 -06:00
DEV: Support ordering filters on /filter route (#21275)
This commit adds support for the following ordering filters: 1. `order:activity` which orders the topics by `Topic#bumped_at` in descending order 2. `order:activity-asc` which orders the topics by `Topic#bumped_at` in ascending order 3. `order:latest-post` which orders the topics by `Topic#last_posted_at` in descending order 4. `order:latest-post-asc` which orders the topics by `Topic#last_posted_at` in ascending order 5. `order:created` which orders the topics by `Topic#created_at` in descending order 6. `order:created-asc` which orders the topics by `Topic#created_at` in ascending order 7. `order:views` which orders the topics by `Topic#views` in descending order 8. `order:views-asc` which orders the topics by `Topic#views` in ascending order 9. `order:likes` which orders the topics by `Topic#likes` in descending order 10. `order:likes-asc` which orders the topics by `Topic#likes` in ascending order 11. `order:likes-op` which orders the topics by `Post#like_count` of the first post in the topic in descending order 12. `order:likes-op-asc` which orders the topics by `Post#like_count` of the first post in the topic in ascending order 13. `order:posters` which orders the topics by `Topic#participant_count` in descending order 14. `order:posters-asc` which orders the topics by `Topic#participant_count` in ascending order 15. `order:category` which orders the topics by `Category#name` of the topic's category in descending order 16. `order:category-asc` which orders the topics by `Category#name` of the topic's category in ascending order Multiple order filters can be composed together and the order of ordering is applied based on the position of the filter in the query string. For example, `order:views order:created` will order the topics by `Topic#views` in descending order and then order the topics by `Topics#created_at` in descending order.
This commit is contained in:
committed by
GitHub
parent
141555136a
commit
6e5e607072
@@ -62,6 +62,8 @@ class TopicsFilter
|
||||
filter_by_number_of_likes_in_first_post(min: filter_values)
|
||||
when "likes-op-max"
|
||||
filter_by_number_of_likes_in_first_post(max: filter_values)
|
||||
when "order"
|
||||
order_by(values: filter_values)
|
||||
when "posts-min"
|
||||
filter_by_number_of_posts(min: filter_values)
|
||||
when "posts-max"
|
||||
@@ -171,10 +173,7 @@ class TopicsFilter
|
||||
column_name: "first_posts.like_count",
|
||||
min:,
|
||||
max:,
|
||||
scope:
|
||||
@scope.joins(
|
||||
"INNER JOIN posts AS first_posts ON first_posts.topic_id = topics.id AND first_posts.post_number = 1",
|
||||
),
|
||||
scope: self.joins_first_posts(@scope),
|
||||
)
|
||||
end
|
||||
|
||||
@@ -426,4 +425,57 @@ class TopicsFilter
|
||||
def include_topics_with_any_tags(tag_ids)
|
||||
@scope = @scope.joins(:topic_tags).where("topic_tags.tag_id IN (?)", tag_ids).distinct(:id)
|
||||
end
|
||||
|
||||
ORDER_BY_MAPPINGS = {
|
||||
"activity" => {
|
||||
column: "topics.bumped_at",
|
||||
},
|
||||
"category" => {
|
||||
column: "categories.name",
|
||||
scope: -> { @scope.joins(:category) },
|
||||
},
|
||||
"created" => {
|
||||
column: "topics.created_at",
|
||||
},
|
||||
"latest-post" => {
|
||||
column: "topics.last_posted_at",
|
||||
},
|
||||
"likes" => {
|
||||
column: "topics.like_count",
|
||||
},
|
||||
"likes-op" => {
|
||||
column: "first_posts.like_count",
|
||||
scope: -> { joins_first_posts(@scope) },
|
||||
},
|
||||
"posters" => {
|
||||
column: "topics.participant_count",
|
||||
},
|
||||
"views" => {
|
||||
column: "topics.views",
|
||||
},
|
||||
}
|
||||
private_constant :ORDER_BY_MAPPINGS
|
||||
|
||||
ORDER_BY_REGEXP = /^(?<order_by>#{ORDER_BY_MAPPINGS.keys.join("|")})(?<asc>-asc)?$/
|
||||
private_constant :ORDER_BY_REGEXP
|
||||
|
||||
def order_by(values:)
|
||||
values.each do |value|
|
||||
match_data = value.match(ORDER_BY_REGEXP)
|
||||
|
||||
if match_data && column_name = ORDER_BY_MAPPINGS.dig(match_data[:order_by], :column)
|
||||
if scope = ORDER_BY_MAPPINGS.dig(match_data[:order_by], :scope)
|
||||
@scope = instance_exec(&scope)
|
||||
end
|
||||
|
||||
@scope = @scope.order(column_name => match_data[:asc] ? :asc : :desc)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
def joins_first_posts(scope)
|
||||
scope.joins(
|
||||
"INNER JOIN posts AS first_posts ON first_posts.topic_id = topics.id AND first_posts.post_number = 1",
|
||||
)
|
||||
end
|
||||
end
|
||||
|
||||
Reference in New Issue
Block a user