diff --git a/app/assets/javascripts/admin/controllers/admin-reports.js.es6 b/app/assets/javascripts/admin/controllers/admin-reports.js.es6 index 6bb36989b75..0430e8a1809 100644 --- a/app/assets/javascripts/admin/controllers/admin-reports.js.es6 +++ b/app/assets/javascripts/admin/controllers/admin-reports.js.es6 @@ -4,24 +4,26 @@ export default Ember.ObjectController.extend({ viewingBarChart: Em.computed.equal('viewMode', 'barChart'), startDate: null, endDate: null, + categoryId: null, refreshing: false, actions: { - refreshReport: function() { - var self = this; - this.set('refreshing', true); - Discourse.Report.find(this.get('type'), this.get('startDate'), this.get('endDate')).then(function(r) { - self.set('model', r); - }).finally(function() { - self.set('refreshing', false); - }); + refreshReport() { + this.set("refreshing", true); + Discourse.Report.find( + this.get("type"), + this.get("startDate"), + this.get("endDate"), + this.get("categoryId") + ).then(m => this.set("model", m) + ).finally(() => this.set("refreshing", false)); }, - viewAsTable: function() { + viewAsTable() { this.set('viewMode', 'table'); }, - viewAsBarChart: function() { + viewAsBarChart() { this.set('viewMode', 'barChart'); } } diff --git a/app/assets/javascripts/admin/models/report.js.es6 b/app/assets/javascripts/admin/models/report.js.es6 index d03e6d60532..ebb63486d2c 100644 --- a/app/assets/javascripts/admin/models/report.js.es6 +++ b/app/assets/javascripts/admin/models/report.js.es6 @@ -142,23 +142,24 @@ const Report = Discourse.Model.extend({ }); Report.reopenClass({ - find: function(type, startDate, endDate) { - return Discourse.ajax("/admin/reports/" + type, {data: { - start_date: startDate, - end_date: endDate - }}).then(function (json) { + find(type, startDate, endDate, categoryId) { + return Discourse.ajax("/admin/reports/" + type, { + data: { + start_date: startDate, + end_date: endDate, + category_id: categoryId + } + }).then(json => { // Add a percent field to each tuple - var maxY = 0; - json.report.data.forEach(function (row) { + let maxY = 0; + json.report.data.forEach(row => { if (row.y > maxY) maxY = row.y; }); if (maxY > 0) { - json.report.data.forEach(function (row) { - row.percentage = Math.round((row.y / maxY) * 100); - }); + json.report.data.forEach(row => row.percentage = Math.round((row.y / maxY) * 100)); } - var model = Discourse.Report.create({type: type}); + const model = Discourse.Report.create({ type: type }); model.setProperties(json.report); return model; }); diff --git a/app/assets/javascripts/admin/templates/reports.hbs b/app/assets/javascripts/admin/templates/reports.hbs index 0bc26a87399..2bbc04b1876 100644 --- a/app/assets/javascripts/admin/templates/reports.hbs +++ b/app/assets/javascripts/admin/templates/reports.hbs @@ -3,6 +3,7 @@
{{i18n 'admin.dashboard.reports.start_date'}} {{input type="date" value=startDate}} {{i18n 'admin.dashboard.reports.end_date'}} {{input type="date" value=endDate}} + {{category-chooser valueAttribute="id" value=categoryId source=categoryId}} {{d-button action="refreshReport" class="btn-primary" label="admin.dashboard.reports.refresh_report" icon="refresh"}}
diff --git a/app/controllers/admin/reports_controller.rb b/app/controllers/admin/reports_controller.rb index cd9b7c85418..e4416b13094 100644 --- a/app/controllers/admin/reports_controller.rb +++ b/app/controllers/admin/reports_controller.rb @@ -13,7 +13,12 @@ class Admin::ReportsController < Admin::AdminController end_date = start_date + 1.month end_date = Time.parse(params[:end_date]) if params[:end_date].present? - report = Report.find(report_type, {start_date: start_date, end_date: end_date}) + category_id = if params.has_key?(:category_id) + params[:category_id].blank? ? SiteSetting.uncategorized_category_id : params[:category_id].to_i + end + + report = Report.find(report_type, start_date: start_date, end_date: end_date, category_id: category_id) + raise Discourse::NotFound if report.blank? render_json_dump(report: report) diff --git a/app/models/post.rb b/app/models/post.rb index 0dbe2c6c3b4..22fbea3ec9f 100644 --- a/app/models/post.rb +++ b/app/models/post.rb @@ -493,15 +493,16 @@ class Post < ActiveRecord::Base Jobs.enqueue(:process_post, args) end - def self.public_posts_count_per_day(start_date, end_date) - public_posts.where('posts.created_at >= ? AND posts.created_at <= ?', start_date, end_date).group('date(posts.created_at)').order('date(posts.created_at)').count + def self.public_posts_count_per_day(start_date, end_date, category_id=nil) + result = public_posts.where('posts.created_at >= ? AND posts.created_at <= ?', start_date, end_date) + result = result.where('topics.category_id = ?', category_id) if category_id + result.group('date(posts.created_at)').order('date(posts.created_at)').count end def self.private_messages_count_per_day(since_days_ago, topic_subtype) private_posts.with_topic_subtype(topic_subtype).where('posts.created_at > ?', since_days_ago.days.ago).group('date(posts.created_at)').order('date(posts.created_at)').count end - def reply_history(max_replies=100) post_ids = Post.exec_sql("WITH RECURSIVE breadcrumb(id, reply_to_post_number) AS ( SELECT p.id, p.reply_to_post_number FROM posts AS p diff --git a/app/models/post_action.rb b/app/models/post_action.rb index 5fc13301268..f1746196a99 100644 --- a/app/models/post_action.rb +++ b/app/models/post_action.rb @@ -39,11 +39,13 @@ class PostAction < ActiveRecord::Base nil end - def self.flag_count_by_date(start_date, end_date) - where('created_at >= ? and created_at <= ?', start_date, end_date) - .where(post_action_type_id: PostActionType.flag_types.values) - .group('date(created_at)').order('date(created_at)') - .count + def self.flag_count_by_date(start_date, end_date, category_id=nil) + result = where('post_actions.created_at >= ? AND post_actions.created_at <= ?', start_date, end_date) + result = result.where(post_action_type_id: PostActionType.flag_types.values) + result = result.joins(post: :topic).where("topics.category_id = ?", category_id) if category_id + result.group('date(post_actions.created_at)') + .order('date(post_actions.created_at)') + .count end def self.update_flagged_posts_count @@ -122,12 +124,15 @@ SQL user_actions end - def self.count_per_day_for_type(post_action_type, since_days_ago=30) - unscoped.where(post_action_type_id: post_action_type) - .where('created_at >= ?', since_days_ago.days.ago) - .group('date(created_at)') - .order('date(created_at)') - .count + def self.count_per_day_for_type(post_action_type, opts=nil) + opts ||= {} + opts[:since_days_ago] ||= 30 + result = unscoped.where(post_action_type_id: post_action_type) + result = result.where('post_actions.created_at >= ?', opts[:since_days_ago].days.ago) + result = result.joins(post: :topic).where('topics.category_id = ?', opts[:category_id]) if opts[:category_id] + result.group('date(post_actions.created_at)') + .order('date(post_actions.created_at)') + .count end def self.agree_flags!(post, moderator, delete_post=false) diff --git a/app/models/report.rb b/app/models/report.rb index 5c6c9ad9dbf..d97a97057aa 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 + attr_accessor :type, :data, :total, :prev30Days, :start_date, :end_date, :category_id def self.default_days 30 @@ -10,14 +10,11 @@ class Report def initialize(type) @type = type - @data = nil - @total = nil - @prev30Days = nil @start_date ||= 1.month.ago.beginning_of_day @end_date ||= Time.zone.now.end_of_day end - def as_json(options = nil) + def as_json(options=nil) { type: type, title: I18n.t("reports.#{type}.title"), @@ -27,6 +24,7 @@ class Report total: total, start_date: start_date, end_date: end_date, + category_id: category_id, prev30Days: self.prev30Days } end @@ -37,6 +35,7 @@ class Report report = Report.new(type) 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_method = :"report_#{type}" if respond_to?(report_method) @@ -46,6 +45,7 @@ class Report else return nil end + report end @@ -60,13 +60,14 @@ class Report end filtered_results = data.where('date >= ? AND date <= ?', report.start_date.to_date, report.end_date.to_date) + filtered_results = filtered_results.where(category_id: report.category_id) if report.category_id report.data = [] filtered_results.order(date: :asc) .group(:date) .sum(:count) .each do |date, count| - report.data << {x: date, y: count} + report.data << { x: date, y: count } end report.total = data.sum(:count) @@ -84,28 +85,32 @@ class Report end def self.report_topics(report) - basic_report_about report, Topic, :listable_count_per_day, report.start_date, report.end_date - add_counts report, Topic.listable_topics, 'topics.created_at' + basic_report_about report, Topic, :listable_count_per_day, report.start_date, report.end_date, report.category_id + countable = Topic.listable_topics + countable = countable.where(category_id: report.category_id) if report.category_id + add_counts report, countable, 'topics.created_at' end def self.report_posts(report) - basic_report_about report, Post, :public_posts_count_per_day, report.start_date, report.end_date - add_counts report, Post.public_posts, 'posts.created_at' + basic_report_about report, Post, :public_posts_count_per_day, report.start_date, report.end_date, report.category_id + countable = Post.public_posts + countable = countable.joins(:topic).where("topics.category_id = ?", report.category_id) if report.category_id + add_counts report, countable, 'posts.created_at' end def self.report_time_to_first_response(report) report.data = [] - Topic.time_to_first_response_per_day(report.start_date, report.end_date).each do |r| + Topic.time_to_first_response_per_day(report.start_date, report.end_date, report.category_id).each do |r| report.data << { x: Date.parse(r["date"]), y: r["hours"].to_f.round(2) } end - report.total = Topic.time_to_first_response_total - report.prev30Days = Topic.time_to_first_response_total(report.start_date - 30.days, report.start_date) + report.total = Topic.time_to_first_response_total(category_id: report.category_id) + report.prev30Days = Topic.time_to_first_response_total(start_date: report.start_date - 30.days, end_date: report.start_date, category_id: report.category_id) end def self.report_topics_with_no_response(report) - basic_report_about report, Topic, :with_no_response_per_day, report.start_date, report.end_date - report.total = Topic.with_no_response_total - report.prev30Days = Topic.with_no_response_total(report.start_date - 30.days, report.start_date) + basic_report_about report, Topic, :with_no_response_per_day, report.start_date, report.end_date, report.category_id + report.total = Topic.with_no_response_total(category_id: report.category_id) + report.prev30Days = Topic.with_no_response_total(start_date: report.start_date - 30.days, end_date: report.start_date, category_id: report.category_id) end def self.report_emails(report) @@ -120,7 +125,7 @@ class Report def self.basic_report_about(report, subject_class, report_method, *args) report.data = [] subject_class.send(report_method, *args).each do |date, count| - report.data << {x: date, y: count} + report.data << { x: date, y: count } end end @@ -132,14 +137,16 @@ class Report def self.report_users_by_trust_level(report) report.data = [] User.real.group('trust_level').count.each do |level, count| - report.data << {x: level.to_i, y: count} + report.data << { x: level.to_i, y: count } end end # Post action counts: def self.report_flags(report) - basic_report_about report, PostAction, :flag_count_by_date, report.start_date, report.end_date - add_counts report, PostAction.where(post_action_type_id: PostActionType.flag_types.values), 'post_actions.created_at' + basic_report_about report, PostAction, :flag_count_by_date, report.start_date, report.end_date, report.category_id + countable = PostAction.where(post_action_type_id: PostActionType.flag_types.values) + countable = countable.joins(post: :topic).where("topics.category_id = ?", report.category_id) if report.category_id + add_counts report, countable, 'post_actions.created_at' end def self.report_likes(report) @@ -152,10 +159,12 @@ class Report def self.post_action_report(report, post_action_type) report.data = [] - PostAction.count_per_day_for_type(post_action_type).each do |date, count| + PostAction.count_per_day_for_type(post_action_type, category_id: report.category_id).each do |date, count| report.data << { x: date, y: count } end - add_counts report, PostAction.unscoped.where(post_action_type_id: post_action_type), 'post_actions.created_at' + countable = PostAction.unscoped.where(post_action_type_id: post_action_type) + countable = countable.joins(post: :topic).where("topics.category_id = ?", report.category_id) if report.category_id + add_counts report, countable, 'post_actions.created_at' end # Private messages counts: diff --git a/app/models/topic.rb b/app/models/topic.rb index cfdae5d20cf..1ee7926e724 100644 --- a/app/models/topic.rb +++ b/app/models/topic.rb @@ -359,8 +359,10 @@ class Topic < ActiveRecord::Base custom_fields[key.to_s] end - def self.listable_count_per_day(start_date, end_date) - listable_topics.where('created_at >= ? and created_at <= ?', start_date, end_date).group('date(created_at)').order('date(created_at)').count + def self.listable_count_per_day(start_date, end_date, category_id=nil) + result = listable_topics.where('created_at >= ? and created_at <= ?', start_date, end_date) + result = result.where(category_id: category_id) if category_id + result.group('date(created_at)').order('date(created_at)').count end def private_message? @@ -872,10 +874,12 @@ class Topic < ActiveRecord::Base ) t SQL - def self.time_to_first_response(sql, start_date=nil, end_date=nil) + def self.time_to_first_response(sql, opts=nil) + opts ||= {} builder = SqlBuilder.new(sql) - builder.where("t.created_at >= :start_date", start_date: start_date) if start_date - builder.where("t.created_at <= :end_date", end_date: end_date) if end_date + builder.where("t.created_at >= :start_date", start_date: opts[:start_date]) if opts[:start_date] + builder.where("t.created_at <= :end_date", end_date: opts[:end_date]) if opts[:end_date] + builder.where("t.category_id = :category_id", category_id: opts[:category_id]) if opts[:category_id] builder.where("t.archetype <> '#{Archetype.private_message}'") builder.where("t.deleted_at IS NULL") builder.where("p.deleted_at IS NULL") @@ -884,27 +888,30 @@ class Topic < ActiveRecord::Base builder.exec end - def self.time_to_first_response_per_day(start_date, end_date) - time_to_first_response(TIME_TO_FIRST_RESPONSE_SQL, start_date, end_date) + def self.time_to_first_response_per_day(start_date, end_date, category_id=nil) + time_to_first_response(TIME_TO_FIRST_RESPONSE_SQL, start_date: start_date, end_date: end_date, category_id: category_id) end - def self.time_to_first_response_total(start_date=nil, end_date=nil) - result = time_to_first_response(TIME_TO_FIRST_RESPONSE_TOTAL_SQL, start_date, end_date) - result.first["hours"].to_f.round(2) + def self.time_to_first_response_total(opts=nil) + total = time_to_first_response(TIME_TO_FIRST_RESPONSE_TOTAL_SQL, opts) + total.first["hours"].to_f.round(2) end - def self.with_no_response_per_day(start_date, end_date) - listable_topics.where(highest_post_number: 1) - .where("created_at BETWEEN ? AND ?", start_date, end_date) - .group("created_at::date") - .order("created_at::date") - .count + def self.with_no_response_per_day(start_date, end_date, category_id=nil) + result = listable_topics.where(highest_post_number: 1) + result = result.where("created_at BETWEEN ? AND ?", start_date, end_date) + result = result.where(category_id: category_id) if category_id + result.group("created_at::date") + .order("created_at::date") + .count end - def self.with_no_response_total(start_date=nil, end_date=nil) + def self.with_no_response_total(opts=nil) + opts ||= {} total = listable_topics.where(highest_post_number: 1) - total = total.where("created_at >= ?", start_date) if start_date - total = total.where("created_at <= ?", end_date) if end_date + total = total.where("created_at >= ?", opts[:start_date]) if opts[:start_date] + total = total.where("created_at <= ?", opts[:end_date]) if opts[:end_date] + total = total.where(category_id: opts[:category_id]) if opts[:category_id] total.count end