FEATURE: add option to sort topic query result via plugin. (#25349)

Previously, it was not possible to modify the sorting order of the `TopicQuery` result from a plugin. This feature adds support to specify custom sorting functionality in a plugin. We're using the `apply_modifier` method in the `DiscoursePluginRegistry` module to achieve it.

Co-authored-by: Alan Guo Xiang Tan <gxtan1990@gmail.com>
This commit is contained in:
Vinoth Kannan 2024-01-24 12:58:12 +05:30 committed by GitHub
parent 32e2a1fd4a
commit ecb7fb0481
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
3 changed files with 54 additions and 3 deletions

View File

@ -18,13 +18,18 @@ export default EmberObject.extend({
@discourseComputed
sortIcon() {
const asc = this.parent.ascending ? "up" : "down";
const isAscending = this.parent.ascending || this.parent.context?.ascending;
const asc = isAscending ? "up" : "down";
return `chevron-${asc}`;
},
@discourseComputed
isSorting() {
return this.sortable && this.parent.order === this.order;
return (
this.sortable &&
(this.parent.order === this.order ||
this.parent.context?.order === this.order)
);
},
@discourseComputed

View File

@ -664,9 +664,21 @@ class TopicQuery
end
def apply_ordering(result, options = {})
sort_column = SORTABLE_MAPPING[options[:order]] || "default"
order_option = options[:order]
sort_dir = (options[:ascending] == "true") ? "ASC" : "DESC"
new_result =
DiscoursePluginRegistry.apply_modifier(
:topic_query_apply_ordering_result,
result,
order_option,
sort_dir,
options,
self,
)
return new_result if !new_result.nil? && new_result != result
sort_column = SORTABLE_MAPPING[order_option] || "default"
# If we are sorting in the default order desc, we should consider including pinned
# topics. Otherwise, just use bumped_at.
if sort_column == "default"

View File

@ -2091,6 +2091,40 @@ RSpec.describe TopicQuery do
end
end
describe "#apply_ordering" do
fab!(:topic1) { Fabricate(:topic, spam_count: 3, bumped_at: 3.hours.ago) }
fab!(:topic2) { Fabricate(:topic, spam_count: 2, bumped_at: 3.minutes.ago) }
fab!(:topic3) { Fabricate(:topic, spam_count: 3, bumped_at: 1.hour.ago) }
let(:modifier_block) do
Proc.new do |result, sort_column, sort_dir, options, topic_query|
if sort_column == "spam"
sort_column = "spam_count"
result.order("topics.#{sort_column} #{sort_dir}, bumped_at DESC")
end
end
end
it "returns the result of topic_query_apply_ordering_result modifier" do
plugin_instance = Plugin::Instance.new
plugin_instance.register_modifier(:topic_query_apply_ordering_result, &modifier_block)
topics = TopicQuery.new(nil, order: "spam", ascending: "false").list_latest.topics
expect(topics.map(&:id)).to eq([topic3.id, topic1.id, topic2.id])
ensure
DiscoursePluginRegistry.unregister_modifier(
plugin_instance,
:topic_query_apply_ordering_result,
&modifier_block
)
end
it "ignores the result of topic_query_apply_ordering_result if modifier not registered" do
topics = TopicQuery.new(nil, order: "spam", ascending: "false").list_latest.topics
expect(topics.map(&:id)).to eq([topic2.id, topic3.id, topic1.id])
end
end
describe "show_category_definitions_in_topic_lists setting" do
fab!(:category) { Fabricate(:category_with_definition) }
fab!(:subcategory) { Fabricate(:category_with_definition, parent_category: category) }