FEATURE: allow plugins to add custom admin reports
This commit is contained in:
parent
28a8b886c0
commit
18f887772d
|
@ -12,8 +12,9 @@ export default Discourse.Route.extend({
|
|||
if (versionChecks) {
|
||||
c.set('versionCheck', Discourse.VersionCheck.create(d.version_check));
|
||||
}
|
||||
_.each(d.reports,function(report){
|
||||
c.set(report.type, Discourse.Report.create(report));
|
||||
|
||||
['global_reports', 'page_view_reports', 'private_message_reports', 'http_reports', 'user_reports'].forEach(name => {
|
||||
c.set(name, d[name].map(r => Discourse.Report.create(r)));
|
||||
});
|
||||
|
||||
var topReferrers = d.top_referrers;
|
||||
|
|
|
@ -17,7 +17,9 @@
|
|||
</thead>
|
||||
<tbody>
|
||||
{{#unless loading}}
|
||||
{{admin-report-trust-level-counts report=users_by_trust_level}}
|
||||
{{#each r in user_reports}}
|
||||
{{admin-report-trust-level-counts report=r}}
|
||||
{{/each}}
|
||||
{{/unless}}
|
||||
</tbody>
|
||||
</table>
|
||||
|
@ -26,15 +28,15 @@
|
|||
<div class="dashboard-stats totals">
|
||||
<table>
|
||||
<tr>
|
||||
<td class="title"><i class='fa fa-shield'></i> {{i18n 'admin.dashboard.admins'}}</td>
|
||||
<td class="title">{{fa-icon "shield"}} {{i18n 'admin.dashboard.admins'}}</td>
|
||||
<td class="value">{{#link-to 'adminUsersList.show' 'admins'}}{{admins}}{{/link-to}}</td>
|
||||
<td class="title"><i class='fa fa-ban'></i> {{i18n 'admin.dashboard.suspended'}}</td>
|
||||
<td class="title">{{fa-icon "ban"}} {{i18n 'admin.dashboard.suspended'}}</td>
|
||||
<td class="value">{{#link-to 'adminUsersList.show' 'suspended'}}{{suspended}}{{/link-to}}</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td class="title"><i class='fa fa-shield'></i> {{i18n 'admin.dashboard.moderators'}}</td>
|
||||
<td class="title">{{fa-icon "shield"}} {{i18n 'admin.dashboard.moderators'}}</td>
|
||||
<td class="value">{{#link-to 'adminUsersList.show' 'moderators'}}{{moderators}}{{/link-to}}</td>
|
||||
<td class="title"><i class='fa fa-ban'></i> {{i18n 'admin.dashboard.blocked'}}</td>
|
||||
<td class="title">{{fa-icon "ban"}} {{i18n 'admin.dashboard.blocked'}}</td>
|
||||
<td class="value">{{#link-to 'adminUsersList.show' 'blocked'}}{{blocked}}{{/link-to}}</td>
|
||||
</tr>
|
||||
</table>
|
||||
|
@ -54,16 +56,9 @@
|
|||
</thead>
|
||||
<tbody>
|
||||
{{#unless loading}}
|
||||
{{admin-report-counts report=visits}}
|
||||
{{admin-report-counts report=signups}}
|
||||
{{admin-report-counts report=topics}}
|
||||
{{admin-report-counts report=posts}}
|
||||
{{admin-report-counts report=time_to_first_response}}
|
||||
{{admin-report-counts report=topics_with_no_response}}
|
||||
{{admin-report-counts report=likes}}
|
||||
{{admin-report-counts report=flags}}
|
||||
{{admin-report-counts report=bookmarks}}
|
||||
{{admin-report-counts report=emails}}
|
||||
{{#each r in global_reports}}
|
||||
{{admin-report-counts report=r}}
|
||||
{{/each}}
|
||||
{{/unless}}
|
||||
</tbody>
|
||||
</table>
|
||||
|
@ -83,21 +78,19 @@
|
|||
</thead>
|
||||
<tbody>
|
||||
{{#unless loading}}
|
||||
{{admin-report-counts report=page_view_anon_reqs}}
|
||||
{{admin-report-counts report=page_view_logged_in_reqs}}
|
||||
{{admin-report-counts report=page_view_crawler_reqs}}
|
||||
{{admin-report-counts report=page_view_total_reqs}}
|
||||
{{#each r in page_view_reports}}
|
||||
{{admin-report-counts report=r}}
|
||||
{{/each}}
|
||||
{{/unless}}
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
|
||||
|
||||
<div class="dashboard-stats">
|
||||
<table class="table table-condensed table-hover">
|
||||
<thead>
|
||||
<tr>
|
||||
<th class="title" title="{{i18n 'admin.dashboard.private_messages_title'}}"><i class="fa fa-envelope"></i> {{i18n 'admin.dashboard.private_messages_short'}}</th>
|
||||
<th class="title" title="{{i18n 'admin.dashboard.private_messages_title'}}">{{fa-icon "enveloppe"}} {{i18n 'admin.dashboard.private_messages_short'}}</th>
|
||||
<th>{{i18n 'admin.dashboard.reports.today'}}</th>
|
||||
<th>{{i18n 'admin.dashboard.reports.yesterday'}}</th>
|
||||
<th>{{i18n 'admin.dashboard.reports.last_7_days'}}</th>
|
||||
|
@ -107,11 +100,9 @@
|
|||
</thead>
|
||||
<tbody>
|
||||
{{#unless loading}}
|
||||
{{admin-report-counts report=user_to_user_private_messages}}
|
||||
{{admin-report-counts report=system_private_messages}}
|
||||
{{admin-report-counts report=notify_moderators_private_messages}}
|
||||
{{admin-report-counts report=notify_user_private_messages}}
|
||||
{{admin-report-counts report=moderator_warning_private_messages}}
|
||||
{{#each r in private_message_reports}}
|
||||
{{admin-report-counts report=r}}
|
||||
{{/each}}
|
||||
{{/unless}}
|
||||
</tbody>
|
||||
</table>
|
||||
|
@ -156,12 +147,9 @@
|
|||
</thead>
|
||||
<tbody>
|
||||
{{#unless loading}}
|
||||
{{admin-report-counts report=http_2xx_reqs}}
|
||||
{{admin-report-counts report=http_3xx_reqs}}
|
||||
{{admin-report-counts report=http_4xx_reqs}}
|
||||
{{admin-report-counts report=http_5xx_reqs}}
|
||||
{{admin-report-counts report=http_background_reqs}}
|
||||
{{admin-report-counts report=http_total_reqs}}
|
||||
{{#each r in http_reports}}
|
||||
{{admin-report-counts report=r}}
|
||||
{{/each}}
|
||||
{{/unless}}
|
||||
</tbody>
|
||||
</table>
|
||||
|
@ -178,7 +166,7 @@
|
|||
|
||||
{{#if foundProblems}}
|
||||
<div class="dashboard-stats detected-problems">
|
||||
<div class="look-here"><i class="fa fa-exclamation-triangle"></i></div>
|
||||
<div class="look-here">{{fa-icon "exclamation-triangle"}}</div>
|
||||
<div class="problem-messages">
|
||||
<p {{bind-attr class="loadingProblems:invisible"}}>
|
||||
{{i18n 'admin.dashboard.problems_found'}}
|
||||
|
|
|
@ -3,13 +3,13 @@ module Jobs
|
|||
every 30.minutes
|
||||
|
||||
def execute(args)
|
||||
stats_json = AdminDashboardData.fetch_stats.as_json
|
||||
stats = AdminDashboardData.fetch_stats.as_json
|
||||
|
||||
# Add some extra time to the expiry so that the next job run has plenty of time to
|
||||
# finish before previous cached value expires.
|
||||
$redis.setex AdminDashboardData.stats_cache_key, (AdminDashboardData.recalculate_interval + 5).minutes, stats_json.to_json
|
||||
$redis.setex AdminDashboardData.stats_cache_key, (AdminDashboardData.recalculate_interval + 5).minutes, stats.to_json
|
||||
|
||||
stats_json
|
||||
stats
|
||||
end
|
||||
|
||||
end
|
||||
|
|
|
@ -2,25 +2,34 @@ require_dependency 'mem_info'
|
|||
|
||||
class AdminDashboardData
|
||||
|
||||
REPORTS = [
|
||||
GLOBAL_REPORTS ||= [
|
||||
'visits',
|
||||
'signups',
|
||||
'topics',
|
||||
'posts',
|
||||
'time_to_first_response',
|
||||
'topics_with_no_response',
|
||||
'flags',
|
||||
'users_by_trust_level',
|
||||
'likes',
|
||||
'flags',
|
||||
'bookmarks',
|
||||
'emails',
|
||||
]
|
||||
|
||||
PAGE_VIEW_REPORTS ||= ['page_view_total_reqs'] + ApplicationRequest.req_types.keys.select { |r| r =~ /^page_view_/ }.map { |r| r + "_reqs" }
|
||||
|
||||
PRIVATE_MESSAGE_REPORTS ||= [
|
||||
'user_to_user_private_messages',
|
||||
'system_private_messages',
|
||||
'moderator_warning_private_messages',
|
||||
'notify_moderators_private_messages',
|
||||
'notify_user_private_messages',
|
||||
'page_view_total_reqs'
|
||||
] + ApplicationRequest.req_types.keys.map{|r| r + "_reqs"}
|
||||
'moderator_warning_private_messages',
|
||||
]
|
||||
|
||||
HTTP_REPORTS ||= ApplicationRequest.req_types.keys.select { |r| r =~ /^http_/ }.map { |r| r + "_reqs" }.sort
|
||||
|
||||
USER_REPORTS ||= ['users_by_trust_level']
|
||||
|
||||
# TODO: MOBILE_REPORTS
|
||||
|
||||
def problems
|
||||
[ rails_env_check,
|
||||
|
@ -50,11 +59,13 @@ class AdminDashboardData
|
|||
def self.fetch_stats
|
||||
AdminDashboardData.new
|
||||
end
|
||||
|
||||
def self.fetch_cached_stats
|
||||
# The DashboardStats job is responsible for generating and caching this.
|
||||
stats = $redis.get(stats_cache_key)
|
||||
stats ? JSON.parse(stats) : nil
|
||||
end
|
||||
|
||||
def self.stats_cache_key
|
||||
'dash-stats'
|
||||
end
|
||||
|
@ -65,7 +76,11 @@ class AdminDashboardData
|
|||
|
||||
def as_json(_options = nil)
|
||||
@json ||= {
|
||||
reports: REPORTS.map { |type| Report.find(type).as_json },
|
||||
global_reports: AdminDashboardData.reports(GLOBAL_REPORTS),
|
||||
page_view_reports: AdminDashboardData.reports(PAGE_VIEW_REPORTS),
|
||||
private_message_reports: AdminDashboardData.reports(PRIVATE_MESSAGE_REPORTS),
|
||||
http_reports: AdminDashboardData.reports(HTTP_REPORTS),
|
||||
user_reports: AdminDashboardData.reports(USER_REPORTS),
|
||||
admins: User.admins.count,
|
||||
moderators: User.moderators.count,
|
||||
suspended: User.suspended.count,
|
||||
|
@ -77,8 +92,12 @@ class AdminDashboardData
|
|||
}
|
||||
end
|
||||
|
||||
def self.reports(source)
|
||||
source.map { |type| Report.find(type).as_json }
|
||||
end
|
||||
|
||||
# Could be configurable, multisite need to support it.
|
||||
def self.recalculate_interval
|
||||
# Could be configurable, multisite need to support it.
|
||||
30 # minutes
|
||||
end
|
||||
|
||||
|
|
|
@ -29,6 +29,10 @@ class Report
|
|||
}
|
||||
end
|
||||
|
||||
def Report.add_report(name, &block)
|
||||
singleton_class.instance_eval { define_method("report_#{name}", &block) }
|
||||
end
|
||||
|
||||
def self.find(type, opts=nil)
|
||||
opts ||= {}
|
||||
# Load the report
|
||||
|
|
Loading…
Reference in New Issue