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:
parent
32e2a1fd4a
commit
ecb7fb0481
|
@ -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
|
||||
|
|
|
@ -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"
|
||||
|
|
|
@ -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) }
|
||||
|
|
Loading…
Reference in New Issue