mirror of
https://github.com/discourse/discourse.git
synced 2025-05-22 22:43:33 +08:00
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:
@ -18,13 +18,18 @@ export default EmberObject.extend({
|
|||||||
|
|
||||||
@discourseComputed
|
@discourseComputed
|
||||||
sortIcon() {
|
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}`;
|
return `chevron-${asc}`;
|
||||||
},
|
},
|
||||||
|
|
||||||
@discourseComputed
|
@discourseComputed
|
||||||
isSorting() {
|
isSorting() {
|
||||||
return this.sortable && this.parent.order === this.order;
|
return (
|
||||||
|
this.sortable &&
|
||||||
|
(this.parent.order === this.order ||
|
||||||
|
this.parent.context?.order === this.order)
|
||||||
|
);
|
||||||
},
|
},
|
||||||
|
|
||||||
@discourseComputed
|
@discourseComputed
|
||||||
|
@ -664,9 +664,21 @@ class TopicQuery
|
|||||||
end
|
end
|
||||||
|
|
||||||
def apply_ordering(result, options = {})
|
def apply_ordering(result, options = {})
|
||||||
sort_column = SORTABLE_MAPPING[options[:order]] || "default"
|
order_option = options[:order]
|
||||||
sort_dir = (options[:ascending] == "true") ? "ASC" : "DESC"
|
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
|
# If we are sorting in the default order desc, we should consider including pinned
|
||||||
# topics. Otherwise, just use bumped_at.
|
# topics. Otherwise, just use bumped_at.
|
||||||
if sort_column == "default"
|
if sort_column == "default"
|
||||||
|
@ -2091,6 +2091,40 @@ RSpec.describe TopicQuery do
|
|||||||
end
|
end
|
||||||
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
|
describe "show_category_definitions_in_topic_lists setting" do
|
||||||
fab!(:category) { Fabricate(:category_with_definition) }
|
fab!(:category) { Fabricate(:category_with_definition) }
|
||||||
fab!(:subcategory) { Fabricate(:category_with_definition, parent_category: category) }
|
fab!(:subcategory) { Fabricate(:category_with_definition, parent_category: category) }
|
||||||
|
Reference in New Issue
Block a user