FEATURE: filter admin reports via user group
This commit is contained in:
parent
7d992cb4c5
commit
eec8436cfe
|
@ -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);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -1,9 +1,12 @@
|
|||
<h3>{{model.title}}</h3>
|
||||
|
||||
<div>
|
||||
<div class="admin-reports-filter">
|
||||
{{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"}}
|
||||
</div>
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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?
|
||||
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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)]
|
||||
|
|
|
@ -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)
|
||||
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
|
||||
|
|
|
@ -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
|
||||
|
||||
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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!
|
||||
|
|
|
@ -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!"
|
||||
|
|
Loading…
Reference in New Issue