Add total users report; restructure dashboard reports js

This commit is contained in:
Neil Lalonde 2013-03-12 11:57:33 -04:00
parent b97a3c8d34
commit 4eda422cdf
15 changed files with 111 additions and 24 deletions

View File

@ -31,7 +31,7 @@ Discourse.AdminDashboardRoute = Discourse.Route.extend({
if( !c.get('reportsCheckedAt') || Date.create('1 hour ago') > c.get('reportsCheckedAt') ) { if( !c.get('reportsCheckedAt') || Date.create('1 hour ago') > c.get('reportsCheckedAt') ) {
// TODO: use one request to get all reports, or maybe one request for all dashboard data including version check. // TODO: use one request to get all reports, or maybe one request for all dashboard data including version check.
c.set('reportsCheckedAt', new Date()); c.set('reportsCheckedAt', new Date());
['visits', 'signups', 'topics', 'posts'].each(function(reportType){ ['visits', 'signups', 'topics', 'posts', 'total_users'].each(function(reportType){
c.set(reportType, Discourse.Report.find(reportType)); c.set(reportType, Discourse.Report.find(reportType));
}); });
} }

View File

@ -54,9 +54,26 @@
<th>{{i18n admin.dashboard.reports.last_30_days}}</th> <th>{{i18n admin.dashboard.reports.last_30_days}}</th>
</tr> </tr>
</thead> </thead>
{{ render 'admin_signups' signups }} {{ render 'admin_report_signups' signups }}
{{ render 'admin_visits' visits }} {{ render 'admin_report_topics' topics }}
{{ render 'admin_topics' topics }} {{ render 'admin_report_posts' posts }}
{{ render 'admin_posts' posts }}
</table> </table>
</div> </div>
<div class="dashboard-stats">
<table class="table table-condensed table-hover">
<thead>
<tr>
<th>&nbsp;</th>
<th>{{i18n admin.dashboard.reports.today}}</th>
<th>{{i18n admin.dashboard.reports.yesterday}}</th>
<th>{{i18n admin.dashboard.reports.7_days_ago}}</th>
<th>{{i18n admin.dashboard.reports.30_days_ago}}</th>
</tr>
</thead>
{{ render 'admin_report_total_users' total_users }}
{{ render 'admin_report_visits' visits }}
</table>
</div>
<div class="clearfix"></div>

View File

@ -0,0 +1,9 @@
{{#if loaded}}
<tr>
<td class="title">{{title}}</td>
<td class="value">{{valueAtDaysAgo data 0}}</td>
<td class="value">{{valueAtDaysAgo data 1}}</td>
<td class="value">{{valueAtDaysAgo data 7}}</td>
<td class="value">{{valueAtDaysAgo data 30}}</td>
</tr>
{{/if}}

View File

@ -0,0 +1,9 @@
{{#if loaded}}
<tr>
<td class="title">{{title}}</td>
<td class="value">{{valueAtDaysAgo data 0}}</td>
<td class="value">{{valueAtDaysAgo data 1}}</td>
<td class="value">{{sumLast data 7}}</td>
<td class="value">{{sumLast data 30}}</td>
</tr>
{{/if}}

View File

@ -0,0 +1,4 @@
Discourse.AdminReportPostsView = Discourse.View.extend({
templateName: 'admin/templates/reports/summed_counts_report',
tagName: 'tbody'
});

View File

@ -0,0 +1,4 @@
Discourse.AdminReportSignupsView = Discourse.View.extend({
templateName: 'admin/templates/reports/summed_counts_report',
tagName: 'tbody'
});

View File

@ -0,0 +1,4 @@
Discourse.AdminReportTopicsView = Discourse.View.extend({
templateName: 'admin/templates/reports/summed_counts_report',
tagName: 'tbody'
});

View File

@ -0,0 +1,4 @@
Discourse.AdminReportTotalUsersView = Discourse.View.extend({
templateName: 'admin/templates/reports/per_day_counts_report',
tagName: 'tbody'
});

View File

@ -0,0 +1,4 @@
Discourse.AdminReportVisitsView = Discourse.View.extend({
templateName: 'admin/templates/reports/per_day_counts_report',
tagName: 'tbody'
});

View File

@ -1,9 +0,0 @@
/**
These views are needed so we can render the same template multiple times on
the admin dashboard.
**/
var opts = { templateName: 'admin/templates/report', tagName: 'tbody' };
Discourse.AdminSignupsView = Discourse.View.extend(opts);
Discourse.AdminVisitsView = Discourse.View.extend(opts);
Discourse.AdminTopicsView = Discourse.View.extend(opts);
Discourse.AdminPostsView = Discourse.View.extend(opts);

View File

@ -304,10 +304,13 @@ table {
} }
.dashboard-stats { .dashboard-stats {
margin-top: 10px; margin-top: 30px;
width: 450px;
float: left;
margin-left: 40px;
table { table {
width: 450px; width: 100%;
th { th {
font-weight: normal; font-weight: normal;

View File

@ -69,6 +69,17 @@ class Report
end end
end end
def self.report_total_users(report)
report.data = []
fetch report do
(0..30).each do |i|
if (count = User.where('created_at < ?', i.days.ago).count) > 0
report.data << {x: i.days.ago.to_date.to_s, y: count}
end
end
end
end
private private

View File

@ -689,6 +689,8 @@ en:
last_7_days: "Last 7 Days" last_7_days: "Last 7 Days"
last_30_days: "Last 30 Days" last_30_days: "Last 30 Days"
all_time: "All Time" all_time: "All Time"
7_days_ago: "7 Days Ago"
30_days_ago: "30 Days Ago"
flags: flags:
title: "Flags" title: "Flags"

View File

@ -244,7 +244,7 @@ en:
reports: reports:
visits: visits:
title: "Users Visits" title: "User Visits"
xaxis: "Day" xaxis: "Day"
yaxis: "Number of visits" yaxis: "Number of visits"
signups: signups:
@ -259,6 +259,8 @@ en:
title: "New Posts" title: "New Posts"
xaxis: "Day" xaxis: "Day"
yaxis: "Number of new posts" yaxis: "Number of new posts"
total_users:
title: "Total Users"
site_settings: site_settings:
default_locale: "The default language of this Discourse instance (ISO 639-1 Code)" default_locale: "The default language of this Discourse instance (ISO 639-1 Code)"

View File

@ -45,9 +45,9 @@ describe Report do
context "with #{pluralized}" do context "with #{pluralized}" do
before do before do
fabricator = (arg == :signup ? :user : arg) fabricator = (arg == :signup ? :user : arg)
Fabricate(fabricator, created_at: 2.days.ago) Fabricate(fabricator, created_at: 25.hours.ago)
Fabricate(fabricator, created_at: 1.day.ago) Fabricate(fabricator, created_at: 1.hours.ago)
Fabricate(fabricator, created_at: 1.day.ago) Fabricate(fabricator, created_at: 1.hours.ago)
end end
it 'returns correct data' do it 'returns correct data' do
@ -58,6 +58,29 @@ describe Report do
end end
end end
describe "total_users report" do
let(:report) { Report.find("total_users", cache: false) }
context "no total_users" do
it 'returns an empty report' do
report.data.should be_blank
end
end
context "with users" do
before do
Fabricate(:user, created_at: 25.hours.ago)
Fabricate(:user, created_at: 1.hours.ago)
Fabricate(:user, created_at: 1.hours.ago)
end
it 'returns correct data' do
report.data[0][:y].should == 3
report.data[1][:y].should == 1
end
end
end
describe '#fetch' do describe '#fetch' do
context 'signups' do context 'signups' do
let(:report) { Report.find('signups', cache: true) } let(:report) { Report.find('signups', cache: true) }
@ -90,9 +113,9 @@ describe Report do
context 'with data' do context 'with data' do
before do before do
Fabricate(:user, created_at: 2.days.ago) Fabricate(:user, created_at: 25.hours.ago)
Fabricate(:user, created_at: 1.day.ago) Fabricate(:user, created_at: 1.hour.ago)
Fabricate(:user, created_at: 1.day.ago) Fabricate(:user, created_at: 1.hour.ago)
end end
context 'cache miss' do context 'cache miss' do