DEV: Use ResultSet with staff action logs. (#7661)

This commit is contained in:
Bianca Nenciu 2019-08-13 20:55:05 +03:00 committed by GitHub
parent 296cdc53ee
commit ba396a5384
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
9 changed files with 122 additions and 151 deletions

View File

@ -0,0 +1,7 @@
import RestAdapter from "discourse/adapters/rest";
export default RestAdapter.extend({
basePath() {
return "/admin/logs/";
}
});

View File

@ -1,21 +1,15 @@
import { exportEntity } from "discourse/lib/export-csv"; import { exportEntity } from "discourse/lib/export-csv";
import { outputExportResult } from "discourse/lib/export-result"; import { outputExportResult } from "discourse/lib/export-result";
import StaffActionLog from "admin/models/staff-action-log";
import { import {
default as computed, default as computed,
on on
} from "ember-addons/ember-computed-decorators"; } from "ember-addons/ember-computed-decorators";
export default Ember.Controller.extend({ export default Ember.Controller.extend({
loading: false,
filters: null,
userHistoryActions: [],
model: null, model: null,
nextPage: 0, filters: null,
lastPage: null,
filtersExists: Ember.computed.gt("filterCount", 0), filtersExists: Ember.computed.gt("filterCount", 0),
showTable: Ember.computed.gt("model.length", 0), userHistoryActions: null,
@computed("filters.action_name") @computed("filters.action_name")
actionFilter(name) { actionFilter(name) {
@ -25,34 +19,21 @@ export default Ember.Controller.extend({
@on("init") @on("init")
resetFilters() { resetFilters() {
this.setProperties({ this.setProperties({
filters: Ember.Object.create(), model: Ember.Object.create({ loadingMore: true }),
model: [], filters: Ember.Object.create()
nextPage: 0,
lastPage: null
}); });
this.scheduleRefresh(); this.scheduleRefresh();
}, },
_changeFilters(props) { _changeFilters(props) {
this.set("model", Ember.Object.create({ loadingMore: true }));
this.filters.setProperties(props); this.filters.setProperties(props);
this.setProperties({
model: [],
nextPage: 0,
lastPage: null
});
this.scheduleRefresh(); this.scheduleRefresh();
}, },
_refresh() { _refresh() {
if (this.lastPage && this.nextPage >= this.lastPage) {
return;
}
this.set("loading", true);
const page = this.nextPage;
let filters = this.filters; let filters = this.filters;
let params = { page }; let params = {};
let count = 0; let count = 0;
// Don't send null values // Don't send null values
@ -65,32 +46,23 @@ export default Ember.Controller.extend({
}); });
this.set("filterCount", count); this.set("filterCount", count);
StaffActionLog.findAll(params) this.store.findAll("staff-action-log", params).then(result => {
.then(result => { this.set("model", result);
this.setProperties({
model: this.model.concat(result.staff_action_logs),
nextPage: page + 1
});
if (result.staff_action_logs.length === 0) { if (!this.userHistoryActions) {
this.set("lastPage", page); this.set(
} "userHistoryActions",
result.extras.user_history_actions
if (this.userHistoryActions.length === 0) { .map(action => ({
this.set( id: action.id,
"userHistoryActions", action_id: action.action_id,
result.user_history_actions name: I18n.t("admin.logs.staff_actions.actions." + action.id),
.map(action => ({ name_raw: action.id
id: action.id, }))
action_id: action.action_id, .sort((a, b) => a.name.localeCompare(b.name))
name: I18n.t("admin.logs.staff_actions.actions." + action.id), );
name_raw: action.id }
})) });
.sort((a, b) => (a.name > b.name ? 1 : -1))
);
}
})
.finally(() => this.set("loading", false));
}, },
scheduleRefresh() { scheduleRefresh() {
@ -153,7 +125,7 @@ export default Ember.Controller.extend({
}, },
loadMore() { loadMore() {
this._refresh(); this.model.loadMore();
} }
} }
}); });

View File

@ -2,6 +2,7 @@ import computed from "ember-addons/ember-computed-decorators";
import { ajax } from "discourse/lib/ajax"; import { ajax } from "discourse/lib/ajax";
import AdminUser from "admin/models/admin-user"; import AdminUser from "admin/models/admin-user";
import { escapeExpression } from "discourse/lib/utilities"; import { escapeExpression } from "discourse/lib/utilities";
import RestModel from "discourse/models/rest";
function format(label, value, escape = true) { function format(label, value, escape = true) {
return value return value
@ -9,7 +10,7 @@ function format(label, value, escape = true) {
: ""; : "";
} }
const StaffActionLog = Discourse.Model.extend({ const StaffActionLog = RestModel.extend({
showFullDetails: false, showFullDetails: false,
@computed("action_name") @computed("action_name")
@ -80,16 +81,14 @@ const StaffActionLog = Discourse.Model.extend({
}); });
StaffActionLog.reopenClass({ StaffActionLog.reopenClass({
create(attrs) { munge(json) {
attrs = attrs || {}; if (json.acting_user) {
json.acting_user = AdminUser.create(json.acting_user);
if (attrs.acting_user) {
attrs.acting_user = AdminUser.create(attrs.acting_user);
} }
if (attrs.target_user) { if (json.target_user) {
attrs.target_user = AdminUser.create(attrs.target_user); json.target_user = AdminUser.create(json.target_user);
} }
return this._super(attrs); return json;
}, },
findAll(data) { findAll(data) {

View File

@ -39,70 +39,66 @@
{{#staff-actions}} {{#staff-actions}}
{{#load-more selector=".staff-logs tr" action=(action "loadMore")}} {{#load-more selector=".staff-logs tr" action=(action "loadMore")}}
{{#if showTable}} {{#if model.content}}
<table class='table staff-logs grid'> <table class='table staff-logs grid'>
<thead>
<thead> <th>{{i18n 'admin.logs.staff_actions.staff_user'}}</th>
<th>{{i18n 'admin.logs.staff_actions.staff_user'}}</th> <th>{{i18n 'admin.logs.action'}}</th>
<th>{{i18n 'admin.logs.action'}}</th> <th>{{i18n 'admin.logs.staff_actions.subject'}}</th>
<th>{{i18n 'admin.logs.staff_actions.subject'}}</th> <th>{{i18n 'admin.logs.staff_actions.when'}}</th>
<th>{{i18n 'admin.logs.staff_actions.when'}}</th> <th>{{i18n 'admin.logs.staff_actions.details'}}</th>
<th>{{i18n 'admin.logs.staff_actions.details'}}</th> <th>{{i18n 'admin.logs.staff_actions.context'}}</th>
<th>{{i18n 'admin.logs.staff_actions.context'}}</th> </thead>
</thead> <tbody>
{{#each model.content as |item|}}
<tbody> <tr class='admin-list-item'>
{{#each model as |item|}} <td class="staff-users">
<tr class='admin-list-item'> <div class="staff-user">
<td class="staff-users"> {{#if item.acting_user}}
<div class="staff-user"> {{#link-to 'adminUser' item.acting_user}}{{avatar item.acting_user imageSize="tiny"}}{{/link-to}}
{{#if item.acting_user}} <a {{action "filterByStaffUser" item.acting_user}}>{{item.acting_user.username}}</a>
{{#link-to 'adminUser' item.acting_user}}{{avatar item.acting_user imageSize="tiny"}}{{/link-to}} {{else}}
<a {{action "filterByStaffUser" item.acting_user}}>{{item.acting_user.username}}</a> <span class="deleted-user" title="{{i18n 'admin.user.deleted'}}">
{{else}} {{d-icon "far-trash-alt"}}
<span class="deleted-user" title="{{i18n 'admin.user.deleted'}}"> </span>
{{d-icon "far-trash-alt"}} {{/if}}
</span> </div>
</td>
<td class="col value action">
<a {{action "filterByAction" item}}>{{item.actionName}}</a>
</td>
<td class="col value subject">
<div class="subject">
{{#if item.target_user}}
{{#link-to 'adminUser' item.target_user}}{{avatar item.target_user imageSize="tiny"}}{{/link-to}}
<a {{action "filterByTargetUser" item.target_user}}>{{item.target_user.username}}</a>
{{/if}}
{{#if item.subject}}
<a {{action "filterBySubject" item.subject}} title={{item.subject}}>{{item.subject}}</a>
{{/if}}
</div>
</td>
<td class="col value created-at">{{age-with-tooltip item.created_at}}</td>
<td class="col value details">
{{{item.formattedDetails}}}
{{#if item.useCustomModalForDetails}}
<a {{action "showCustomDetailsModal" item}}>{{d-icon "info-circle"}} {{i18n 'admin.logs.staff_actions.show'}}</a>
{{/if}} {{/if}}
</div> {{#if item.useModalForDetails}}
</td> <a {{action "showDetailsModal" item}}>{{d-icon "info-circle"}} {{i18n 'admin.logs.staff_actions.show'}}</a>
<td class="col value action"> {{/if}}
<a {{action "filterByAction" item}}>{{item.actionName}}</a> </td>
</td> <td class="col value context">{{item.context}}</td>
<td class="col value subject"> </tr>
<div class="subject"> {{/each}}
</tbody>
{{#if item.target_user}} </table>
{{#link-to 'adminUser' item.target_user}}{{avatar item.target_user imageSize="tiny"}}{{/link-to}} {{else if model.loadingMore}}
<a {{action "filterByTargetUser" item.target_user}}>{{item.target_user.username}}</a> {{conditional-loading-spinner condition=model.loadingMore}}
{{/if}} {{else}}
{{#if item.subject}} {{i18n 'search.no_results'}}
<a {{action "filterBySubject" item.subject}} title={{item.subject}}>{{item.subject}}</a> {{/if}}
{{/if}} {{/load-more}}
</div>
</td>
<td class="col value created-at">{{age-with-tooltip item.created_at}}</td>
<td class="col value details">
{{{item.formattedDetails}}}
{{#if item.useCustomModalForDetails}}
<a {{action "showCustomDetailsModal" item}}>{{d-icon "info-circle"}} {{i18n 'admin.logs.staff_actions.show'}}</a>
{{/if}}
{{#if item.useModalForDetails}}
<a {{action "showDetailsModal" item}}>{{d-icon "info-circle"}} {{i18n 'admin.logs.staff_actions.show'}}</a>
{{/if}}
</td>
<td class="col value context">{{item.context}}</td>
</tr>
{{/each}}
</tbody>
</table>
{{else}}
{{i18n 'search.no_results'}}
{{/if}}
{{conditional-loading-spinner condition=loading}}
{{/load-more}}
{{/staff-actions}} {{/staff-actions}}

View File

@ -5,11 +5,24 @@ class Admin::StaffActionLogsController < Admin::AdminController
def index def index
filters = params.slice(*UserHistory.staff_filters + [:page, :limit]) filters = params.slice(*UserHistory.staff_filters + [:page, :limit])
staff_action_logs = UserHistory.staff_action_records(current_user, filters).to_a page = (params[:page] || 0).to_i
render json: StaffActionLogsSerializer.new({ page_size = (params[:limit] || 200).to_i.clamp(1, 200)
staff_action_logs: staff_action_logs,
user_history_actions: staff_available_actions staff_action_logs = UserHistory.staff_action_records(current_user, filters)
}, root: false) count = staff_action_logs.count
staff_action_logs = staff_action_logs.offset(page * page_size).limit(page_size).to_a
load_more_params = params.permit(UserHistory.staff_filters)
load_more_params.merge!(page: page + 1, page_size: page_size)
render_json_dump(
staff_action_logs: serialize_data(staff_action_logs, UserHistorySerializer),
total_rows_staff_action_logs: count,
load_more_staff_action_logs: admin_staff_action_logs_path(load_more_params),
extras: {
user_history_actions: staff_available_actions
}
)
end end
def diff def diff

View File

@ -222,14 +222,9 @@ class UserHistory < ActiveRecord::Base
opts[:action_id] = self.actions[opts[:action_name].to_sym] if opts[:action_name] opts[:action_id] = self.actions[opts[:action_name].to_sym] if opts[:action_name]
end end
page = (opts[:page] || 0).to_i
page_size = (opts[:limit] || 200).to_i
query = self query = self
.with_filters(opts.slice(*staff_filters)) .with_filters(opts.slice(*staff_filters))
.only_staff_actions .only_staff_actions
.limit(page_size)
.offset(page * page_size)
.order('id DESC') .order('id DESC')
.includes(:acting_user, :target_user) .includes(:acting_user, :target_user)
query = query.where(admin_only: false) unless viewer && viewer.admin? query = query.where(admin_only: false) unless viewer && viewer.admin?

View File

@ -1,14 +0,0 @@
# frozen_string_literal: true
class StaffActionLogsSerializer < ApplicationSerializer
attributes :user_history_actions
has_many :staff_action_logs, serializer: UserHistorySerializer, embed: :objects
def staff_action_logs
object[:staff_action_logs]
end
def user_history_actions
object[:user_history_actions]
end
end

View File

@ -26,7 +26,7 @@ describe Admin::StaffActionLogsController do
expect(json["staff_action_logs"].length).to eq(1) expect(json["staff_action_logs"].length).to eq(1)
expect(json["staff_action_logs"][0]["action_name"]).to eq("delete_topic") expect(json["staff_action_logs"][0]["action_name"]).to eq("delete_topic")
expect(json["user_history_actions"]).to include( expect(json["extras"]["user_history_actions"]).to include(
"id" => 'delete_topic', "action_id" => UserHistory.actions[:delete_topic] "id" => 'delete_topic', "action_id" => UserHistory.actions[:delete_topic]
) )
end end
@ -60,7 +60,7 @@ describe Admin::StaffActionLogsController do
get "/admin/logs/staff_action_logs.json", params: {} get "/admin/logs/staff_action_logs.json", params: {}
json = JSON.parse(response.body) json = JSON.parse(response.body)
action = json['user_history_actions'].first action = json['extras']['user_history_actions'].first
expect(action['id']).to eq plugin_extended_action.to_s expect(action['id']).to eq plugin_extended_action.to_s
expect(action['action_id']).to eq UserHistory.actions[:custom_staff] expect(action['action_id']).to eq UserHistory.actions[:custom_staff]

View File

@ -604,7 +604,10 @@ export default function() {
this.delete("/admin/badges/:id", success); this.delete("/admin/badges/:id", success);
this.get("/admin/logs/staff_action_logs.json", () => { this.get("/admin/logs/staff_action_logs.json", () => {
return response(200, { staff_action_logs: [], user_history_actions: [] }); return response(200, {
staff_action_logs: [],
extras: { user_history_actions: [] }
});
}); });
this.get("/admin/logs/watched_words", () => { this.get("/admin/logs/watched_words", () => {