diff --git a/app/assets/javascripts/discourse/app/controllers/review-index.js b/app/assets/javascripts/discourse/app/controllers/review-index.js
index 7ea2523e87e..e1e003870dc 100644
--- a/app/assets/javascripts/discourse/app/controllers/review-index.js
+++ b/app/assets/javascripts/discourse/app/controllers/review-index.js
@@ -11,6 +11,7 @@ export default Controller.extend({
"category_id",
"topic_id",
"username",
+ "reviewed_by",
"from_date",
"to_date",
"sort_order",
@@ -24,6 +25,7 @@ export default Controller.extend({
topic_id: null,
filtersExpanded: false,
username: "",
+ reviewed_by: "",
from_date: null,
to_date: null,
sort_order: null,
@@ -147,6 +149,7 @@ export default Controller.extend({
status: this.filterStatus,
category_id: this.filterCategoryId,
username: this.filterUsername,
+ reviewed_by: this.filterReviewedBy,
from_date: isPresent(this.filterFromDate)
? this.filterFromDate.toISOString(true).split("T")[0]
: null,
diff --git a/app/assets/javascripts/discourse/app/routes/review-index.js b/app/assets/javascripts/discourse/app/routes/review-index.js
index 13d10724f2e..b4d15e68e1e 100644
--- a/app/assets/javascripts/discourse/app/routes/review-index.js
+++ b/app/assets/javascripts/discourse/app/routes/review-index.js
@@ -32,6 +32,7 @@ export default DiscourseRoute.extend({
filterPriority: meta.priority,
reviewableTypes: meta.reviewable_types,
filterUsername: meta.username,
+ filterReviewedBy: meta.reviewed_by,
filterFromDate: isPresent(meta.from_date) ? moment(meta.from_date) : null,
filterToDate: isPresent(meta.to_date) ? moment(meta.to_date) : null,
filterSortOrder: meta.sort_order,
diff --git a/app/assets/javascripts/discourse/app/templates/review-index.hbs b/app/assets/javascripts/discourse/app/templates/review-index.hbs
index c5a0fad8891..322ba824c21 100644
--- a/app/assets/javascripts/discourse/app/templates/review-index.hbs
+++ b/app/assets/javascripts/discourse/app/templates/review-index.hbs
@@ -58,6 +58,17 @@
}}
+
+ {{i18n "review.filtered_reviewed_by"}}
+ {{user-selector
+ excludeCurrentUser=false
+ usernames=filterReviewedBy
+ fullWidthWrap=true
+ single=true
+ class="user-selector"
+ canReceiveUpdates=true}}
+
+
{{i18n "review.filtered_user"}}
{{user-selector
diff --git a/app/controllers/reviewables_controller.rb b/app/controllers/reviewables_controller.rb
index 65de25b429f..874a678c32a 100644
--- a/app/controllers/reviewables_controller.rb
+++ b/app/controllers/reviewables_controller.rb
@@ -30,7 +30,7 @@ class ReviewablesController < ApplicationController
additional_filters: additional_filters.reject { |_, v| v.blank? }
}
- %i[priority username from_date to_date type sort_order].each do |filter_key|
+ %i[priority username reviewed_by from_date to_date type sort_order].each do |filter_key|
filters[filter_key] = params[filter_key]
end
diff --git a/app/models/reviewable.rb b/app/models/reviewable.rb
index c26efaedb4b..6adcb6ae422 100644
--- a/app/models/reviewable.rb
+++ b/app/models/reviewable.rb
@@ -437,6 +437,7 @@ class Reviewable < ActiveRecord::Base
offset: nil,
priority: nil,
username: nil,
+ reviewed_by: nil,
sort_order: nil,
from_date: nil,
to_date: nil,
@@ -470,6 +471,21 @@ class Reviewable < ActiveRecord::Base
result = result.where("reviewables.created_at >= ?", from_date) if from_date
result = result.where("reviewables.created_at <= ?", to_date) if to_date
+ if reviewed_by
+ reviewed_by_id = User.find_by_username(reviewed_by)&.id
+ return [] if reviewed_by_id.nil?
+
+ result = result.joins(<<~SQL
+ INNER JOIN(
+ SELECT reviewable_id
+ FROM reviewable_histories
+ WHERE reviewable_history_type = #{ReviewableHistory.types[:transitioned]} AND
+ status <> #{Reviewable.statuses[:pending]} AND created_by_id = #{reviewed_by_id}
+ ) AS rh ON rh.reviewable_id = reviewables.id
+ SQL
+ )
+ end
+
if min_score > 0 && status == :pending
result = result.where("reviewables.score >= ? OR reviewables.force_review", min_score)
elsif min_score > 0
diff --git a/config/locales/client.en.yml b/config/locales/client.en.yml
index 7a81c069845..b1fcd40bc91 100644
--- a/config/locales/client.en.yml
+++ b/config/locales/client.en.yml
@@ -457,6 +457,7 @@ en:
topic: "Topic:"
filtered_topic: "You have filtered to reviewable content in a single topic."
filtered_user: "User"
+ filtered_reviewed_by: "Reviewed By"
show_all_topics: "show all topics"
deleted_post: "(post deleted)"
deleted_user: "(user deleted)"
diff --git a/spec/models/reviewable_spec.rb b/spec/models/reviewable_spec.rb
index e5246ef05dd..2572da5e906 100644
--- a/spec/models/reviewable_spec.rb
+++ b/spec/models/reviewable_spec.rb
@@ -149,6 +149,18 @@ RSpec.describe Reviewable, type: :model do
expect(reviewables).not_to include(qp)
end
+ it 'can filter by who reviewed the flag' do
+ reviewable = Fabricate(:reviewable_flagged_post)
+ admin = Fabricate(:admin)
+ reviewable.perform(admin, :ignore)
+
+ reviewables = Reviewable.list_for(
+ user, status: :all, reviewed_by: admin.username
+ )
+
+ expect(reviewables).to contain_exactly(reviewable)
+ end
+
it 'Does not filter by status when status parameter is set to all' do
rejected_reviewable = Fabricate(:reviewable, target: post, status: Reviewable.statuses[:rejected])
reviewables = Reviewable.list_for(user, status: :all)