mirror of
https://github.com/discourse/discourse.git
synced 2024-11-26 11:03:40 +08:00
DEV: Use ResultSet with staff action logs. (#7661)
This commit is contained in:
parent
296cdc53ee
commit
ba396a5384
|
@ -0,0 +1,7 @@
|
|||
import RestAdapter from "discourse/adapters/rest";
|
||||
|
||||
export default RestAdapter.extend({
|
||||
basePath() {
|
||||
return "/admin/logs/";
|
||||
}
|
||||
});
|
|
@ -1,21 +1,15 @@
|
|||
import { exportEntity } from "discourse/lib/export-csv";
|
||||
import { outputExportResult } from "discourse/lib/export-result";
|
||||
import StaffActionLog from "admin/models/staff-action-log";
|
||||
import {
|
||||
default as computed,
|
||||
on
|
||||
} from "ember-addons/ember-computed-decorators";
|
||||
|
||||
export default Ember.Controller.extend({
|
||||
loading: false,
|
||||
filters: null,
|
||||
userHistoryActions: [],
|
||||
model: null,
|
||||
nextPage: 0,
|
||||
lastPage: null,
|
||||
|
||||
filters: null,
|
||||
filtersExists: Ember.computed.gt("filterCount", 0),
|
||||
showTable: Ember.computed.gt("model.length", 0),
|
||||
userHistoryActions: null,
|
||||
|
||||
@computed("filters.action_name")
|
||||
actionFilter(name) {
|
||||
|
@ -25,34 +19,21 @@ export default Ember.Controller.extend({
|
|||
@on("init")
|
||||
resetFilters() {
|
||||
this.setProperties({
|
||||
filters: Ember.Object.create(),
|
||||
model: [],
|
||||
nextPage: 0,
|
||||
lastPage: null
|
||||
model: Ember.Object.create({ loadingMore: true }),
|
||||
filters: Ember.Object.create()
|
||||
});
|
||||
this.scheduleRefresh();
|
||||
},
|
||||
|
||||
_changeFilters(props) {
|
||||
this.set("model", Ember.Object.create({ loadingMore: true }));
|
||||
this.filters.setProperties(props);
|
||||
this.setProperties({
|
||||
model: [],
|
||||
nextPage: 0,
|
||||
lastPage: null
|
||||
});
|
||||
this.scheduleRefresh();
|
||||
},
|
||||
|
||||
_refresh() {
|
||||
if (this.lastPage && this.nextPage >= this.lastPage) {
|
||||
return;
|
||||
}
|
||||
|
||||
this.set("loading", true);
|
||||
|
||||
const page = this.nextPage;
|
||||
let filters = this.filters;
|
||||
let params = { page };
|
||||
let params = {};
|
||||
let count = 0;
|
||||
|
||||
// Don't send null values
|
||||
|
@ -65,32 +46,23 @@ export default Ember.Controller.extend({
|
|||
});
|
||||
this.set("filterCount", count);
|
||||
|
||||
StaffActionLog.findAll(params)
|
||||
.then(result => {
|
||||
this.setProperties({
|
||||
model: this.model.concat(result.staff_action_logs),
|
||||
nextPage: page + 1
|
||||
});
|
||||
this.store.findAll("staff-action-log", params).then(result => {
|
||||
this.set("model", result);
|
||||
|
||||
if (result.staff_action_logs.length === 0) {
|
||||
this.set("lastPage", page);
|
||||
}
|
||||
|
||||
if (this.userHistoryActions.length === 0) {
|
||||
this.set(
|
||||
"userHistoryActions",
|
||||
result.user_history_actions
|
||||
.map(action => ({
|
||||
id: action.id,
|
||||
action_id: action.action_id,
|
||||
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));
|
||||
if (!this.userHistoryActions) {
|
||||
this.set(
|
||||
"userHistoryActions",
|
||||
result.extras.user_history_actions
|
||||
.map(action => ({
|
||||
id: action.id,
|
||||
action_id: action.action_id,
|
||||
name: I18n.t("admin.logs.staff_actions.actions." + action.id),
|
||||
name_raw: action.id
|
||||
}))
|
||||
.sort((a, b) => a.name.localeCompare(b.name))
|
||||
);
|
||||
}
|
||||
});
|
||||
},
|
||||
|
||||
scheduleRefresh() {
|
||||
|
@ -153,7 +125,7 @@ export default Ember.Controller.extend({
|
|||
},
|
||||
|
||||
loadMore() {
|
||||
this._refresh();
|
||||
this.model.loadMore();
|
||||
}
|
||||
}
|
||||
});
|
||||
|
|
|
@ -2,6 +2,7 @@ import computed from "ember-addons/ember-computed-decorators";
|
|||
import { ajax } from "discourse/lib/ajax";
|
||||
import AdminUser from "admin/models/admin-user";
|
||||
import { escapeExpression } from "discourse/lib/utilities";
|
||||
import RestModel from "discourse/models/rest";
|
||||
|
||||
function format(label, value, escape = true) {
|
||||
return value
|
||||
|
@ -9,7 +10,7 @@ function format(label, value, escape = true) {
|
|||
: "";
|
||||
}
|
||||
|
||||
const StaffActionLog = Discourse.Model.extend({
|
||||
const StaffActionLog = RestModel.extend({
|
||||
showFullDetails: false,
|
||||
|
||||
@computed("action_name")
|
||||
|
@ -80,16 +81,14 @@ const StaffActionLog = Discourse.Model.extend({
|
|||
});
|
||||
|
||||
StaffActionLog.reopenClass({
|
||||
create(attrs) {
|
||||
attrs = attrs || {};
|
||||
|
||||
if (attrs.acting_user) {
|
||||
attrs.acting_user = AdminUser.create(attrs.acting_user);
|
||||
munge(json) {
|
||||
if (json.acting_user) {
|
||||
json.acting_user = AdminUser.create(json.acting_user);
|
||||
}
|
||||
if (attrs.target_user) {
|
||||
attrs.target_user = AdminUser.create(attrs.target_user);
|
||||
if (json.target_user) {
|
||||
json.target_user = AdminUser.create(json.target_user);
|
||||
}
|
||||
return this._super(attrs);
|
||||
return json;
|
||||
},
|
||||
|
||||
findAll(data) {
|
||||
|
|
|
@ -39,70 +39,66 @@
|
|||
|
||||
{{#staff-actions}}
|
||||
|
||||
{{#load-more selector=".staff-logs tr" action=(action "loadMore")}}
|
||||
{{#if showTable}}
|
||||
<table class='table staff-logs grid'>
|
||||
|
||||
<thead>
|
||||
<th>{{i18n 'admin.logs.staff_actions.staff_user'}}</th>
|
||||
<th>{{i18n 'admin.logs.action'}}</th>
|
||||
<th>{{i18n 'admin.logs.staff_actions.subject'}}</th>
|
||||
<th>{{i18n 'admin.logs.staff_actions.when'}}</th>
|
||||
<th>{{i18n 'admin.logs.staff_actions.details'}}</th>
|
||||
<th>{{i18n 'admin.logs.staff_actions.context'}}</th>
|
||||
</thead>
|
||||
|
||||
<tbody>
|
||||
{{#each model as |item|}}
|
||||
<tr class='admin-list-item'>
|
||||
<td class="staff-users">
|
||||
<div class="staff-user">
|
||||
{{#if item.acting_user}}
|
||||
{{#link-to 'adminUser' item.acting_user}}{{avatar item.acting_user imageSize="tiny"}}{{/link-to}}
|
||||
<a {{action "filterByStaffUser" item.acting_user}}>{{item.acting_user.username}}</a>
|
||||
{{else}}
|
||||
<span class="deleted-user" title="{{i18n 'admin.user.deleted'}}">
|
||||
{{d-icon "far-trash-alt"}}
|
||||
</span>
|
||||
{{#load-more selector=".staff-logs tr" action=(action "loadMore")}}
|
||||
{{#if model.content}}
|
||||
<table class='table staff-logs grid'>
|
||||
<thead>
|
||||
<th>{{i18n 'admin.logs.staff_actions.staff_user'}}</th>
|
||||
<th>{{i18n 'admin.logs.action'}}</th>
|
||||
<th>{{i18n 'admin.logs.staff_actions.subject'}}</th>
|
||||
<th>{{i18n 'admin.logs.staff_actions.when'}}</th>
|
||||
<th>{{i18n 'admin.logs.staff_actions.details'}}</th>
|
||||
<th>{{i18n 'admin.logs.staff_actions.context'}}</th>
|
||||
</thead>
|
||||
<tbody>
|
||||
{{#each model.content as |item|}}
|
||||
<tr class='admin-list-item'>
|
||||
<td class="staff-users">
|
||||
<div class="staff-user">
|
||||
{{#if item.acting_user}}
|
||||
{{#link-to 'adminUser' item.acting_user}}{{avatar item.acting_user imageSize="tiny"}}{{/link-to}}
|
||||
<a {{action "filterByStaffUser" item.acting_user}}>{{item.acting_user.username}}</a>
|
||||
{{else}}
|
||||
<span class="deleted-user" title="{{i18n 'admin.user.deleted'}}">
|
||||
{{d-icon "far-trash-alt"}}
|
||||
</span>
|
||||
{{/if}}
|
||||
</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}}
|
||||
</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 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}}
|
||||
{{#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 if model.loadingMore}}
|
||||
{{conditional-loading-spinner condition=model.loadingMore}}
|
||||
{{else}}
|
||||
{{i18n 'search.no_results'}}
|
||||
{{/if}}
|
||||
{{/load-more}}
|
||||
|
||||
{{/staff-actions}}
|
||||
|
|
|
@ -5,11 +5,24 @@ class Admin::StaffActionLogsController < Admin::AdminController
|
|||
def index
|
||||
filters = params.slice(*UserHistory.staff_filters + [:page, :limit])
|
||||
|
||||
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: staff_available_actions
|
||||
}, root: false)
|
||||
page = (params[:page] || 0).to_i
|
||||
page_size = (params[:limit] || 200).to_i.clamp(1, 200)
|
||||
|
||||
staff_action_logs = UserHistory.staff_action_records(current_user, filters)
|
||||
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
|
||||
|
||||
def diff
|
||||
|
|
|
@ -222,14 +222,9 @@ class UserHistory < ActiveRecord::Base
|
|||
opts[:action_id] = self.actions[opts[:action_name].to_sym] if opts[:action_name]
|
||||
end
|
||||
|
||||
page = (opts[:page] || 0).to_i
|
||||
page_size = (opts[:limit] || 200).to_i
|
||||
|
||||
query = self
|
||||
.with_filters(opts.slice(*staff_filters))
|
||||
.only_staff_actions
|
||||
.limit(page_size)
|
||||
.offset(page * page_size)
|
||||
.order('id DESC')
|
||||
.includes(:acting_user, :target_user)
|
||||
query = query.where(admin_only: false) unless viewer && viewer.admin?
|
||||
|
|
|
@ -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
|
|
@ -26,7 +26,7 @@ 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(
|
||||
expect(json["extras"]["user_history_actions"]).to include(
|
||||
"id" => 'delete_topic', "action_id" => UserHistory.actions[:delete_topic]
|
||||
)
|
||||
end
|
||||
|
@ -60,7 +60,7 @@ describe Admin::StaffActionLogsController do
|
|||
get "/admin/logs/staff_action_logs.json", params: {}
|
||||
|
||||
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['action_id']).to eq UserHistory.actions[:custom_staff]
|
||||
|
|
|
@ -604,7 +604,10 @@ export default function() {
|
|||
this.delete("/admin/badges/:id", success);
|
||||
|
||||
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", () => {
|
||||
|
|
Loading…
Reference in New Issue
Block a user