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