FEATURE: Support searching custom staff actions (#7346)

FEATURE: Support searching custom staff actions (#7346)

diff --git a/app/assets/javascripts/admin/controllers/admin-logs-staff-action-logs.js.es6 b/app/assets/javascripts/admin/controllers/admin-logs-staff-action-logs.js.es6
index 0747597..16ed12e 100644
--- a/app/assets/javascripts/admin/controllers/admin-logs-staff-action-logs.js.es6
+++ b/app/assets/javascripts/admin/controllers/admin-logs-staff-action-logs.js.es6
@@ -13,11 +13,9 @@ export default Ember.Controller.extend({
     const filterActionId = this.get("filterActionId");
     if (filterActionId) {
       this._changeFilters({
-        action_name: this.get("userHistoryActions").findBy(
-          "id",
-          parseInt(filterActionId, 10)
-        ).name_raw,
-        action_id: filterActionId
+        action_name: filterActionId,
+        action_id: this.get("userHistoryActions").findBy("id", filterActionId)
+          .action_id
       });
     }
   }.observes("filterActionId"),
@@ -54,11 +52,12 @@ export default Ember.Controller.extend({
       .then(result => {
         this.set("model", result.staff_action_logs);
         if (this.get("userHistoryActions").length === 0) {
-          let actionTypes = result.user_history_actions.map(pair => {
+          let actionTypes = result.user_history_actions.map(action => {
             return {
-              id: pair.id,
-              name: I18n.t("admin.logs.staff_actions.actions." + pair.name),
-              name_raw: pair.name
+              id: action.id,
+              action_id: action.action_id,
+              name: I18n.t("admin.logs.staff_actions.actions." + action.id),
+              name_raw: action.id
             };
           });
           actionTypes = _.sortBy(actionTypes, row => row.name);
diff --git a/app/controllers/admin/staff_action_logs_controller.rb b/app/controllers/admin/staff_action_logs_controller.rb
index 2e72e2b..46ad493 100644
--- a/app/controllers/admin/staff_action_logs_controller.rb
+++ b/app/controllers/admin/staff_action_logs_controller.rb
@@ -6,7 +6,7 @@ class Admin::StaffActionLogsController < Admin::AdminController
     staff_action_logs = UserHistory.staff_action_records(current_user, filters).to_a
     render json: StaffActionLogsSerializer.new({
       staff_action_logs: staff_action_logs,
-      user_history_actions: UserHistory.staff_actions.sort.map { |name| { id: UserHistory.actions[name], name: name } }
+      user_history_actions: staff_available_actions
     }, root: false)
   end
 
@@ -77,4 +77,14 @@ class Admin::StaffActionLogsController < Admin::AdminController
     end
   end
 
+  private
+
+  def staff_available_actions
+    UserHistory.staff_actions.sort.map do |name|
+      {
+        id: name,
+        action_id: UserHistory.actions[name] || UserHistory.actions[:custom_staff],
+      }
+    end
+  end
 end
diff --git a/app/models/user_history.rb b/app/models/user_history.rb
index be0f2fa..af847f1 100644
--- a/app/models/user_history.rb
+++ b/app/models/user_history.rb
@@ -204,7 +204,14 @@ class UserHistory < ActiveRecord::Base
 
   def self.staff_action_records(viewer, opts = nil)
     opts ||= {}
-    opts[:action_id] = self.actions[opts[:action_name].to_sym] if opts[:action_name]
+    custom_staff = opts[:action_id].to_i == actions[:custom_staff]
+
+    if custom_staff
+      opts[:custom_type] = opts[:action_name]
+    else
+      opts[:action_id] = self.actions[opts[:action_name].to_sym] if opts[:action_name]
+    end
+
     query = self.with_filters(opts.slice(*staff_filters)).only_staff_actions.limit(200).order('id DESC').includes(:acting_user, :target_user)
     query = query.where(admin_only: false) unless viewer && viewer.admin?
     query
diff --git a/spec/models/user_history_spec.rb b/spec/models/user_history_spec.rb
index 8aa547b..b5c8a6b 100644
--- a/spec/models/user_history_spec.rb
+++ b/spec/models/user_history_spec.rb
@@ -20,33 +20,45 @@ describe UserHistory do
 
   describe '#staff_action_records' do
     context "with some records" do
+      let(:admin) { Fabricate(:admin) }
+      let(:custom_type) { 'confirmed_ham' }
+
       before do
         @change_site_setting = UserHistory.create!(action: UserHistory.actions[:change_site_setting], subject: "title", previous_value: "Old", new_value: "New")
         @change_trust_level  = UserHistory.create!(action: UserHistory.actions[:change_trust_level], target_user_id: Fabricate(:user).id, details: "stuff happened")
+        @custom_history = StaffActionLogger.new(admin).log_custom('confirmed_ham', admin_only: true)
       end
 
       it "returns all records for admins" do
-        records = described_class.staff_action_records(Fabricate(:admin)).to_a
-        expect(records.size).to eq(2)
+        records = described_class.staff_action_records(admin).to_a
+        expect(records.size).to eq(3)
       end
 
       it "doesn't return records to moderators that only admins should see" do
         records = described_class.staff_action_records(Fabricate(:moderator)).to_a
-        expect(records).to eq([@change_trust_level])
+        expect(records).not_to include([@change_site_setting])
       end
 
       it 'filters by action' do
-        records = described_class.staff_action_records(Fabricate(:admin), action_id: @change_site_setting.action_before_type_cast).to_a
+        records = described_class.staff_action_records(admin, action_id: @change_site_setting.action_before_type_cast).to_a
         expect(records.size).to eq(1)
         expect(records.first).to eq(@change_site_setting)
       end
 
       it 'filters by action_name' do
-        records = described_class.staff_action_records(Fabricate(:admin), action_name: "change_site_setting").to_a
+        records = described_class.staff_action_records(admin, action_name: "change_site_setting").to_a
         expect(records.size).to eq(1)
         expect(records.first).to eq(@change_site_setting)
       end
+
+      it 'Uses action_name as custom_type when searching for custom_staff logs' do
+        records = described_class.staff_action_records(
+          admin, action_name: custom_type, action_id: described_class.actions[:custom_staff]
+        ).to_a
+
+        expect(records.size).to eq(1)
+        expect(records.first).to eq(@custom_history)
+      end
     end
   end
-
 end
diff --git a/spec/requests/admin/staff_action_logs_controller_spec.rb b/spec/requests/admin/staff_action_logs_controller_spec.rb
index f970be1..68d4369 100644
--- a/spec/requests/admin/staff_action_logs_controller_spec.rb
+++ b/spec/requests/admin/staff_action_logs_controller_spec.rb
@@ -24,7 +24,25 @@ describe Admin::StaffActionLogsController do
       expect(json["staff_action_logs"].length).to eq(1)
       expect(json["staff_action_logs"][0]["action_name"]).to eq("delete_topic")
 
-      expect(json["user_history_actions"]).to include("id" => UserHistory.actions[:delete_topic], "name" => 'delete_topic')
+      expect(json["user_history_actions"]).to include(
+        "id" => 'delete_topic', "action_id" => UserHistory.actions[:delete_topic]
+      )
+    end
+
+    context 'When staff actions are extended' do
+      let(:plugin_extended_action) { :confirmed_ham }
+      before { UserHistory.stubs(:staff_actions).returns([plugin_extended_action]) }
+      after { UserHistory.unstub(:staff_actions) }
+
+      it 'Uses the custom_staff id' do
+        get "/admin/logs/staff_action_logs.json", params: {}
+
+        json = JSON.parse(response.body)
+        action = json['user_history_actions'].first
+
+        expect(action['id']).to eq plugin_extended_action.to_s
+        expect(action['action_id']).to eq UserHistory.actions[:custom_staff]
+      end
     end
   end

GitHub sha: 536b90e0