diff --git a/app/assets/javascripts/admin/controllers/admin-reports.js.es6 b/app/assets/javascripts/admin/controllers/admin-reports.js.es6
index bdafff9f0ac..9ceb1b0b093 100644
--- a/app/assets/javascripts/admin/controllers/admin-reports.js.es6
+++ b/app/assets/javascripts/admin/controllers/admin-reports.js.es6
@@ -1,6 +1,7 @@
import { exportEntity } from 'discourse/lib/export-csv';
import { outputExportResult } from 'discourse/lib/export-result';
import Report from 'admin/models/report';
+import computed from 'ember-addons/ember-computed-decorators';
export default Ember.Controller.extend({
viewMode: 'table',
@@ -9,22 +10,32 @@ export default Ember.Controller.extend({
startDate: null,
endDate: null,
categoryId: null,
+ groupId: null,
refreshing: false,
- categoryOptions: function() {
- var arr = [{name: I18n.t('category.all'), value: 'all'}];
- return arr.concat( Discourse.Site.currentProp('sortedCategories').map(function(i) { return {name: i.get('name'), value: i.get('id') }; }) );
- }.property(),
+ @computed()
+ categoryOptions() {
+ const arr = [{name: I18n.t('category.all'), value: 'all'}];
+ return arr.concat(Discourse.Site.currentProp('sortedCategories').map((i) => {return {name: i.get('name'), value: i.get('id')};}));
+ },
+
+ @computed()
+ groupOptions() {
+ const arr = [{name: I18n.t('admin.dashboard.reports.groups'), value: 'all'}];
+ return arr.concat(this.site.groups.map((i) => {return {name: i['name'], value: i['id']};}));
+ },
+
+ @computed('model.type')
+ showGroupOptions(modelType) {
+ return modelType === "visits" || modelType === "signups" || modelType === "profile_views";
+ },
actions: {
refreshReport() {
var q;
this.set("refreshing", true);
- if (this.get('categoryId') === "all") {
- q = Report.find(this.get("model.type"), this.get("startDate"), this.get("endDate"));
- } else {
- q = Report.find(this.get("model.type"), this.get("startDate"), this.get("endDate"), this.get("categoryId"));
- }
+
+ q = Report.find(this.get("model.type"), this.get("startDate"), this.get("endDate"), this.get("categoryId"), this.get("groupId"));
q.then(m => this.set("model", m)).finally(() => this.set("refreshing", false));
},
@@ -41,7 +52,8 @@ export default Ember.Controller.extend({
name: this.get("model.type"),
start_date: this.get('startDate'),
end_date: this.get('endDate'),
- category_id: this.get('categoryId') === 'all' ? undefined : this.get('categoryId')
+ category_id: this.get('categoryId') === 'all' ? undefined : this.get('categoryId'),
+ group_id: this.get('groupId') === 'all' ? undefined : this.get('groupId')
}).then(outputExportResult);
}
}
diff --git a/app/assets/javascripts/admin/models/report.js.es6 b/app/assets/javascripts/admin/models/report.js.es6
index b4b5912eec9..1891984b47e 100644
--- a/app/assets/javascripts/admin/models/report.js.es6
+++ b/app/assets/javascripts/admin/models/report.js.es6
@@ -131,12 +131,13 @@ const Report = Discourse.Model.extend({
Report.reopenClass({
- find(type, startDate, endDate, categoryId) {
+ find(type, startDate, endDate, categoryId, groupId) {
return Discourse.ajax("/admin/reports/" + type, {
data: {
start_date: startDate,
end_date: endDate,
- category_id: categoryId
+ category_id: categoryId,
+ group_id: groupId
}
}).then(json => {
// Add a percent field to each tuple
diff --git a/app/assets/javascripts/admin/templates/reports.hbs b/app/assets/javascripts/admin/templates/reports.hbs
index 718a61a2c1d..1f5360a8af0 100644
--- a/app/assets/javascripts/admin/templates/reports.hbs
+++ b/app/assets/javascripts/admin/templates/reports.hbs
@@ -1,9 +1,12 @@
+
{{i18n 'admin.dashboard.reports.start_date'}} {{input type="date" value=startDate}}
{{i18n 'admin.dashboard.reports.end_date'}} {{input type="date" value=endDate}}
{{combo-box valueAttribute="value" content=categoryOptions value=categoryId}}
+ {{#if showGroupOptions}}
+ {{combo-box valueAttribute="value" content=groupOptions value=groupId}}
+ {{/if}}
{{d-button action="refreshReport" class="btn-primary" label="admin.dashboard.reports.refresh_report" icon="refresh"}}
{{d-button action="exportCsv" label="admin.export_csv.button_text" icon="download"}}
diff --git a/app/assets/stylesheets/common/admin/admin_base.scss b/app/assets/stylesheets/common/admin/admin_base.scss
index 85e9ac30e94..5a5df3b7381 100644
--- a/app/assets/stylesheets/common/admin/admin_base.scss
+++ b/app/assets/stylesheets/common/admin/admin_base.scss
@@ -38,6 +38,12 @@ $mobile-breakpoint: 700px;
.filters input { margin-bottom: 0; }
}
+.admin-contents .admin-reports-filter {
+ input[type="date"] {
+ width: 140px;
+ }
+}
+
td.flaggers td {
border-bottom: none;
border-top: none;
diff --git a/app/controllers/admin/reports_controller.rb b/app/controllers/admin/reports_controller.rb
index e4416b13094..f24ee3f5287 100644
--- a/app/controllers/admin/reports_controller.rb
+++ b/app/controllers/admin/reports_controller.rb
@@ -13,11 +13,19 @@ class Admin::ReportsController < Admin::AdminController
end_date = start_date + 1.month
end_date = Time.parse(params[:end_date]) if params[:end_date].present?
- category_id = if params.has_key?(:category_id)
- params[:category_id].blank? ? SiteSetting.uncategorized_category_id : params[:category_id].to_i
+ if params.has_key?(:category_id) && params[:category_id].to_i > 0
+ category_id = params[:category_id].to_i
+ else
+ category_id = nil
end
- report = Report.find(report_type, start_date: start_date, end_date: end_date, category_id: category_id)
+ if params.has_key?(:group_id) && params[:group_id].to_i > 0
+ group_id = params[:group_id].to_i
+ else
+ group_id = nil
+ end
+
+ report = Report.find(report_type, start_date: start_date, end_date: end_date, category_id: category_id, group_id: group_id)
raise Discourse::NotFound if report.blank?
diff --git a/app/controllers/export_csv_controller.rb b/app/controllers/export_csv_controller.rb
index f632b93bee6..cbb6399acb3 100644
--- a/app/controllers/export_csv_controller.rb
+++ b/app/controllers/export_csv_controller.rb
@@ -30,7 +30,7 @@ class ExportCsvController < ApplicationController
@_export_params ||= begin
params.require(:entity)
params.require(:entity_type)
- params.permit(:entity, :entity_type, args: [:name, :start_date, :end_date, :category_id])
+ params.permit(:entity, :entity_type, args: [:name, :start_date, :end_date, :category_id, :group_id])
end
end
end
diff --git a/app/jobs/regular/export_csv_file.rb b/app/jobs/regular/export_csv_file.rb
index d32f1a3f782..bacf8c6f700 100644
--- a/app/jobs/regular/export_csv_file.rb
+++ b/app/jobs/regular/export_csv_file.rb
@@ -151,6 +151,7 @@ module Jobs
@extra[:start_date] = @extra[:start_date].to_date if @extra[:start_date].is_a?(String)
@extra[:end_date] = @extra[:end_date].to_date if @extra[:end_date].is_a?(String)
@extra[:category_id] = @extra[:category_id].to_i if @extra[:category_id]
+ @extra[:group_id] = @extra[:group_id].to_i if @extra[:group_id]
r = Report.find(@extra[:name], @extra)
r.data.map do |row|
[row[:x].to_s(:db), row[:y].to_s(:db)]
diff --git a/app/models/report.rb b/app/models/report.rb
index 1da7954015e..e5135dcacf2 100644
--- a/app/models/report.rb
+++ b/app/models/report.rb
@@ -2,7 +2,7 @@ require_dependency 'topic_subtype'
class Report
- attr_accessor :type, :data, :total, :prev30Days, :start_date, :end_date, :category_id
+ attr_accessor :type, :data, :total, :prev30Days, :start_date, :end_date, :category_id, :group_id
def self.default_days
30
@@ -25,6 +25,7 @@ class Report
start_date: start_date,
end_date: end_date,
category_id: category_id,
+ group_id: group_id,
prev30Days: self.prev30Days
}
end
@@ -41,6 +42,7 @@ class Report
report.start_date = opts[:start_date] if opts[:start_date]
report.end_date = opts[:end_date] if opts[:end_date]
report.category_id = opts[:category_id] if opts[:category_id]
+ report.group_id = opts[:group_id] if opts[:group_id]
report_method = :"report_#{type}"
if respond_to?(report_method)
@@ -85,7 +87,8 @@ class Report
def self.report_visits(report)
- basic_report_about report, UserVisit, :by_day, report.start_date, report.end_date
+ basic_report_about report, UserVisit, :by_day, report.start_date, report.end_date, report.group_id
+
add_counts report, UserVisit, 'visited_at'
end
@@ -96,13 +99,19 @@ class Report
end
def self.report_signups(report)
- report_about report, User.real, :count_by_signup_date
+ if report.group_id
+ basic_report_about report, User.real, :count_by_signup_date, report.start_date, report.end_date, report.group_id
+ add_counts report, User.real, 'users.created_at'
+ else
+ report_about report, User.real, :count_by_signup_date
+ end
end
def self.report_profile_views(report)
start_date = report.start_date.to_date
end_date = report.end_date.to_date
- basic_report_about report, UserProfileView, :profile_views_by_day, start_date, end_date
+ basic_report_about report, UserProfileView, :profile_views_by_day, start_date, end_date, report.group_id
+
report.total = UserProfile.sum(:views)
report.prev30Days = UserProfileView.where("viewed_at >= ? AND viewed_at < ?", start_date - 30.days, start_date + 1).count
end
diff --git a/app/models/user.rb b/app/models/user.rb
index 6a74a641e7a..639846ee265 100644
--- a/app/models/user.rb
+++ b/app/models/user.rb
@@ -110,7 +110,7 @@ class User < ActiveRecord::Base
attr_accessor :import_mode
# excluding fake users like the system user or anonymous users
- scope :real, -> { where('id > 0').where('NOT EXISTS(
+ scope :real, -> { where('users.id > 0').where('NOT EXISTS(
SELECT 1
FROM user_custom_fields ucf
WHERE
@@ -637,8 +637,14 @@ class User < ActiveRecord::Base
.limit(limit)
end
- def self.count_by_signup_date(start_date, end_date)
- where('created_at >= ? and created_at <= ?', start_date, end_date).group('date(created_at)').order('date(created_at)').count
+ def self.count_by_signup_date(start_date, end_date, group_id=nil)
+ result = where('users.created_at >= ? and users.created_at <= ?', start_date, end_date)
+
+ if group_id
+ result = result.joins("INNER JOIN group_users ON group_users.user_id = users.id")
+ result = result.where("group_users.group_id = ?", group_id)
+ end
+ result.group('date(users.created_at)').order('date(users.created_at)').count
end
diff --git a/app/models/user_profile_view.rb b/app/models/user_profile_view.rb
index 0a62a426d1c..2fd3cd1c209 100644
--- a/app/models/user_profile_view.rb
+++ b/app/models/user_profile_view.rb
@@ -40,8 +40,13 @@ class UserProfileView < ActiveRecord::Base
end
end
- def self.profile_views_by_day(start_date, end_date)
+ def self.profile_views_by_day(start_date, end_date, group_id=nil)
profile_views = self.where("viewed_at >= ? AND viewed_at < ?", start_date, end_date + 1.day)
+ if group_id
+ profile_views = profile_views.joins("INNER JOIN users ON users.id = user_profile_views.user_id")
+ profile_views = profile_views.joins("INNER JOIN group_users ON group_users.user_id = users.id")
+ profile_views = profile_views.where("group_users.group_id = ?", group_id)
+ end
profile_views.group("date(viewed_at)").order("date(viewed_at)").count
end
end
diff --git a/app/models/user_visit.rb b/app/models/user_visit.rb
index 551361586e1..5ebe059167b 100644
--- a/app/models/user_visit.rb
+++ b/app/models/user_visit.rb
@@ -1,16 +1,23 @@
class UserVisit < ActiveRecord::Base
- def self.counts_by_day_query(start_date, end_date)
- where('visited_at >= ? and visited_at <= ?', start_date.to_date, end_date.to_date).group(:visited_at).order(:visited_at)
+ def self.counts_by_day_query(start_date, end_date, group_id=nil)
+ result = where('visited_at >= ? and visited_at <= ?', start_date.to_date, end_date.to_date)
+
+ if group_id
+ result = result.joins("INNER JOIN users ON users.id = user_visits.user_id")
+ result = result.joins("INNER JOIN group_users ON group_users.user_id = users.id")
+ result = result.where("group_users.group_id = ?", group_id)
+ end
+ result.group(:visited_at).order(:visited_at)
end
# A count of visits in a date range by day
- def self.by_day(start_date, end_date)
- counts_by_day_query(start_date, end_date).count
+ def self.by_day(start_date, end_date, group_id=nil)
+ counts_by_day_query(start_date, end_date, group_id).count
end
- def self.mobile_by_day(start_date, end_date)
- counts_by_day_query(start_date, end_date).where(mobile: true).count
+ def self.mobile_by_day(start_date, end_date, group_id=nil)
+ counts_by_day_query(start_date, end_date, group_id).where(mobile: true).count
end
def self.ensure_consistency!
diff --git a/config/locales/client.en.yml b/config/locales/client.en.yml
index 4feee950c7f..d98e1eb65ef 100644
--- a/config/locales/client.en.yml
+++ b/config/locales/client.en.yml
@@ -1929,6 +1929,7 @@ en:
refresh_report: "Refresh Report"
start_date: "Start Date"
end_date: "End Date"
+ groups: "All groups"
commits:
latest_changes: "Latest changes: please update often!"