FEATURE: A low priority filter for the review queue. (#12822)
This filter hides reviewables with a score lower than the "reviewable_low_priority_threshold" setting. We only use reviewables that already met this threshold to calculate the Medium and High priority filters.
This commit is contained in:
parent
4ccbecf480
commit
60059a7190
|
@ -49,7 +49,7 @@ export default Controller.extend({
|
||||||
|
|
||||||
@discourseComputed
|
@discourseComputed
|
||||||
priorities() {
|
priorities() {
|
||||||
return ["low", "medium", "high"].map((priority) => {
|
return ["any", "low", "medium", "high"].map((priority) => {
|
||||||
return {
|
return {
|
||||||
id: priority,
|
id: priority,
|
||||||
name: I18n.t(`review.filters.priority.${priority}`),
|
name: I18n.t(`review.filters.priority.${priority}`),
|
||||||
|
|
|
@ -16,13 +16,16 @@ class Jobs::ReviewablePriorities < ::Jobs::Scheduled
|
||||||
def execute(args)
|
def execute(args)
|
||||||
return unless Reviewable.where('score > 0').count >= self.class.min_reviewables
|
return unless Reviewable.where('score > 0').count >= self.class.min_reviewables
|
||||||
|
|
||||||
res = DB.query_single(<<~SQL, target_count: self.class.target_count)
|
min_priority_threshold = SiteSetting.reviewable_low_priority_threshold
|
||||||
|
|
||||||
|
res = DB.query_single(<<~SQL, target_count: self.class.target_count, min_priority: min_priority_threshold)
|
||||||
SELECT COALESCE(PERCENTILE_DISC(0.5) WITHIN GROUP (ORDER BY score), 0.0) AS medium,
|
SELECT COALESCE(PERCENTILE_DISC(0.5) WITHIN GROUP (ORDER BY score), 0.0) AS medium,
|
||||||
COALESCE(PERCENTILE_DISC(0.85) WITHIN GROUP (ORDER BY score), 0.0) AS high
|
COALESCE(PERCENTILE_DISC(0.85) WITHIN GROUP (ORDER BY score), 0.0) AS high
|
||||||
FROM (
|
FROM (
|
||||||
SELECT r.score
|
SELECT r.score
|
||||||
FROM reviewables AS r
|
FROM reviewables AS r
|
||||||
INNER JOIN reviewable_scores AS rs ON rs.reviewable_id = r.id
|
INNER JOIN reviewable_scores AS rs ON rs.reviewable_id = r.id
|
||||||
|
WHERE r.score >= :min_priority
|
||||||
GROUP BY r.id
|
GROUP BY r.id
|
||||||
HAVING COUNT(*) >= :target_count
|
HAVING COUNT(*) >= :target_count
|
||||||
) AS x
|
) AS x
|
||||||
|
@ -32,6 +35,10 @@ class Jobs::ReviewablePriorities < ::Jobs::Scheduled
|
||||||
|
|
||||||
medium, high = res
|
medium, high = res
|
||||||
|
|
||||||
Reviewable.set_priorities(medium: medium, high: high)
|
Reviewable.set_priorities(
|
||||||
|
low: min_priority_threshold,
|
||||||
|
medium: medium,
|
||||||
|
high: high
|
||||||
|
)
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
|
@ -444,8 +444,6 @@ class Reviewable < ActiveRecord::Base
|
||||||
to_date: nil,
|
to_date: nil,
|
||||||
additional_filters: {}
|
additional_filters: {}
|
||||||
)
|
)
|
||||||
min_score = Reviewable.min_score_for_priority(priority)
|
|
||||||
|
|
||||||
order = case sort_order
|
order = case sort_order
|
||||||
when 'score_asc'
|
when 'score_asc'
|
||||||
'reviewables.score ASC, reviewables.created_at DESC'
|
'reviewables.score ASC, reviewables.created_at DESC'
|
||||||
|
@ -488,6 +486,8 @@ class Reviewable < ActiveRecord::Base
|
||||||
)
|
)
|
||||||
end
|
end
|
||||||
|
|
||||||
|
min_score = Reviewable.min_score_for_priority(priority)
|
||||||
|
|
||||||
if min_score > 0 && status == :pending
|
if min_score > 0 && status == :pending
|
||||||
result = result.where("reviewables.score >= ? OR reviewables.force_review", min_score)
|
result = result.where("reviewables.score >= ? OR reviewables.force_review", min_score)
|
||||||
elsif min_score > 0
|
elsif min_score > 0
|
||||||
|
|
|
@ -48,4 +48,9 @@ DiscourseEvent.on(:site_setting_changed) do |name, old_value, new_value|
|
||||||
if SiteSetting::WATCHED_SETTINGS.include?(name)
|
if SiteSetting::WATCHED_SETTINGS.include?(name)
|
||||||
SiteSetting.reset_cached_settings!
|
SiteSetting.reset_cached_settings!
|
||||||
end
|
end
|
||||||
|
|
||||||
|
# Make sure medium and high priority thresholds were calculated.
|
||||||
|
if name == :reviewable_low_priority_threshold && Reviewable.min_score_for_priority(:medium) > 0
|
||||||
|
Reviewable.set_priorities(low: new_value)
|
||||||
|
end
|
||||||
end
|
end
|
||||||
|
|
|
@ -516,7 +516,8 @@ en:
|
||||||
|
|
||||||
priority:
|
priority:
|
||||||
title: "Minimum Priority"
|
title: "Minimum Priority"
|
||||||
low: "(any)"
|
any: "(any)"
|
||||||
|
low: "Low"
|
||||||
medium: "Medium"
|
medium: "Medium"
|
||||||
high: "High"
|
high: "High"
|
||||||
|
|
||||||
|
|
|
@ -1956,6 +1956,7 @@ en:
|
||||||
reviewable_claiming: "Does reviewable content need to be claimed before it can be acted upon?"
|
reviewable_claiming: "Does reviewable content need to be claimed before it can be acted upon?"
|
||||||
reviewable_default_topics: "Show reviewable content grouped by topic by default"
|
reviewable_default_topics: "Show reviewable content grouped by topic by default"
|
||||||
reviewable_default_visibility: "Don't show reviewable items unless they meet this priority"
|
reviewable_default_visibility: "Don't show reviewable items unless they meet this priority"
|
||||||
|
reviewable_low_priority_threshold: "The priority filter hides reviewable that doesn't meet this score unless the '(any)' filter is used."
|
||||||
high_trust_flaggers_auto_hide_posts: "New user posts are automatically hidden after being flagged as spam by a TL3+ user"
|
high_trust_flaggers_auto_hide_posts: "New user posts are automatically hidden after being flagged as spam by a TL3+ user"
|
||||||
cooldown_hours_until_reflag: "How much time users will have to wait until they are able to reflag a post"
|
cooldown_hours_until_reflag: "How much time users will have to wait until they are able to reflag a post"
|
||||||
|
|
||||||
|
|
|
@ -1710,6 +1710,10 @@ spam:
|
||||||
type: enum
|
type: enum
|
||||||
default: low
|
default: low
|
||||||
enum: "ReviewablePrioritySetting"
|
enum: "ReviewablePrioritySetting"
|
||||||
|
reviewable_low_priority_threshold:
|
||||||
|
default: 1
|
||||||
|
min: 1
|
||||||
|
|
||||||
|
|
||||||
rate_limits:
|
rate_limits:
|
||||||
unique_posts_mins: 5
|
unique_posts_mins: 5
|
||||||
|
|
|
@ -22,4 +22,27 @@ describe 'Setting changes' do
|
||||||
expect(non_approved_user.reload.approved?).to eq(true)
|
expect(non_approved_user.reload.approved?).to eq(true)
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
describe '#reviewable_low_priority_threshold' do
|
||||||
|
let(:new_threshold) { 5 }
|
||||||
|
|
||||||
|
it 'sets the low priority value' do
|
||||||
|
medium_threshold = 10
|
||||||
|
Reviewable.set_priorities(medium: medium_threshold)
|
||||||
|
|
||||||
|
expect(Reviewable.min_score_for_priority(:low)).not_to eq(new_threshold)
|
||||||
|
|
||||||
|
SiteSetting.reviewable_low_priority_threshold = new_threshold
|
||||||
|
|
||||||
|
expect(Reviewable.min_score_for_priority(:low)).to eq(new_threshold)
|
||||||
|
end
|
||||||
|
|
||||||
|
it "does nothing if the other thresholds were not calculated" do
|
||||||
|
Reviewable.set_priorities(medium: 0.0)
|
||||||
|
|
||||||
|
SiteSetting.reviewable_low_priority_threshold = new_threshold
|
||||||
|
|
||||||
|
expect(Reviewable.min_score_for_priority(:low)).not_to eq(new_threshold)
|
||||||
|
end
|
||||||
|
end
|
||||||
end
|
end
|
||||||
|
|
|
@ -6,42 +6,65 @@ describe Jobs::ReviewablePriorities do
|
||||||
|
|
||||||
it "needs returns 0s with no existing reviewables" do
|
it "needs returns 0s with no existing reviewables" do
|
||||||
Jobs::ReviewablePriorities.new.execute({})
|
Jobs::ReviewablePriorities.new.execute({})
|
||||||
expect(Reviewable.min_score_for_priority(:low)).to eq(0.0)
|
|
||||||
expect(Reviewable.min_score_for_priority(:medium)).to eq(0.0)
|
expect_min_score(:low, 0.0)
|
||||||
expect(Reviewable.min_score_for_priority(:high)).to eq(0.0)
|
expect_min_score(:medium, 0.0)
|
||||||
|
expect_min_score(:high, 0.0)
|
||||||
expect(Reviewable.score_required_to_hide_post).to eq(8.33)
|
expect(Reviewable.score_required_to_hide_post).to eq(8.33)
|
||||||
end
|
end
|
||||||
|
|
||||||
fab!(:u0) { Fabricate(:user) }
|
fab!(:user_0) { Fabricate(:user) }
|
||||||
fab!(:u1) { Fabricate(:user) }
|
fab!(:user_1) { Fabricate(:user) }
|
||||||
|
|
||||||
def create_reviewables(count)
|
def create_reviewables(count)
|
||||||
(1..count).each do |i|
|
(1..count).each { |i| create_with_score(i) }
|
||||||
r = Fabricate(:reviewable_flagged_post)
|
end
|
||||||
r.add_score(u0, PostActionType.types[:off_topic])
|
|
||||||
r.add_score(u1, PostActionType.types[:off_topic])
|
def create_with_score(score)
|
||||||
r.update!(score: i)
|
Fabricate(:reviewable_flagged_post).tap do |reviewable|
|
||||||
|
reviewable.add_score(user_0, PostActionType.types[:off_topic])
|
||||||
|
reviewable.add_score(user_1, PostActionType.types[:off_topic])
|
||||||
|
reviewable.update!(score: score)
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
it "needs a minimum amount of reviewables before it calculates anything" do
|
it "needs a minimum amount of reviewables before it calculates anything" do
|
||||||
create_reviewables(5)
|
create_reviewables(5)
|
||||||
|
|
||||||
Jobs::ReviewablePriorities.new.execute({})
|
Jobs::ReviewablePriorities.new.execute({})
|
||||||
expect(Reviewable.min_score_for_priority(:low)).to eq(0.0)
|
|
||||||
expect(Reviewable.min_score_for_priority(:medium)).to eq(0.0)
|
expect_min_score(:low, 0.0)
|
||||||
expect(Reviewable.min_score_for_priority(:high)).to eq(0.0)
|
expect_min_score(:medium, 0.0)
|
||||||
|
expect_min_score(:high, 0.0)
|
||||||
expect(Reviewable.score_required_to_hide_post).to eq(8.33)
|
expect(Reviewable.score_required_to_hide_post).to eq(8.33)
|
||||||
end
|
end
|
||||||
|
|
||||||
it "will set priorities based on the maximum score" do
|
it "will set priorities based on the maximum score" do
|
||||||
create_reviewables(Jobs::ReviewablePriorities.min_reviewables)
|
create_reviewables(Jobs::ReviewablePriorities.min_reviewables)
|
||||||
|
|
||||||
Jobs::ReviewablePriorities.new.execute({})
|
Jobs::ReviewablePriorities.new.execute({})
|
||||||
|
|
||||||
expect(Reviewable.min_score_for_priority(:low)).to eq(0.0)
|
expect_min_score(:low, SiteSetting.reviewable_low_priority_threshold)
|
||||||
expect(Reviewable.min_score_for_priority(:medium)).to eq(8.0)
|
expect_min_score(:medium, 8.0)
|
||||||
expect(Reviewable.min_score_for_priority('medium')).to eq(8.0)
|
expect_min_score('medium', 8.0)
|
||||||
expect(Reviewable.min_score_for_priority(:high)).to eq(13.0)
|
expect_min_score(:high, 13.0)
|
||||||
expect(Reviewable.score_required_to_hide_post).to eq(8.66)
|
expect(Reviewable.score_required_to_hide_post).to eq(8.66)
|
||||||
end
|
end
|
||||||
|
|
||||||
|
it 'ignore negative scores when calculating priorities' do
|
||||||
|
create_reviewables(Jobs::ReviewablePriorities.min_reviewables)
|
||||||
|
negative_score = -9
|
||||||
|
10.times { create_with_score(negative_score) }
|
||||||
|
|
||||||
|
Jobs::ReviewablePriorities.new.execute({})
|
||||||
|
|
||||||
|
expect_min_score(:low, SiteSetting.reviewable_low_priority_threshold)
|
||||||
|
expect_min_score(:medium, 8.0)
|
||||||
|
expect_min_score(:high, 13.0)
|
||||||
|
expect(Reviewable.score_required_to_hide_post).to eq(8.66)
|
||||||
|
end
|
||||||
|
|
||||||
|
def expect_min_score(priority, score)
|
||||||
|
expect(Reviewable.min_score_for_priority(priority)).to eq(score)
|
||||||
|
end
|
||||||
end
|
end
|
||||||
|
|
Loading…
Reference in New Issue