diff --git a/app/assets/javascripts/admin/components/dashboard-inline-table.js.es6 b/app/assets/javascripts/admin/components/dashboard-inline-table.js.es6
index 22443906acb..7a1720db3e7 100644
--- a/app/assets/javascripts/admin/components/dashboard-inline-table.js.es6
+++ b/app/assets/javascripts/admin/components/dashboard-inline-table.js.es6
@@ -8,12 +8,31 @@ export default Ember.Component.extend(AsyncReport, {
help: null,
helpPage: null,
+ loadReport(report_json) {
+ this._setPropertiesFromReport(Report.create(report_json));
+ },
+
fetchReport() {
this.set("isLoading", true);
- ajax(this.get("dataSource"))
+ let payload = { data: { async: true } };
+
+ if (this.get("startDate")) {
+ payload.data.start_date = this.get("startDate").format("YYYY-MM-DD[T]HH:mm:ss.SSSZZ");
+ }
+
+ if (this.get("endDate")) {
+ payload.data.end_date = this.get("endDate").format("YYYY-MM-DD[T]HH:mm:ss.SSSZZ");
+ }
+
+ if (this.get("limit")) {
+ payload.data.limit = this.get("limit");
+ }
+
+ ajax(this.get("dataSource"), payload)
.then((response) => {
- this._setPropertiesFromReport(Report.create(response.report));
+ this.set('reportKey', response.report.report_key);
+ this.loadReport(response.report);
}).finally(() => {
if (!Ember.isEmpty(this.get("report.data"))) {
this.set("isLoading", false);
diff --git a/app/assets/javascripts/admin/components/dashboard-table-trending-search.js.es6 b/app/assets/javascripts/admin/components/dashboard-table-trending-search.js.es6
deleted file mode 100644
index f6523f6841b..00000000000
--- a/app/assets/javascripts/admin/components/dashboard-table-trending-search.js.es6
+++ /dev/null
@@ -1,8 +0,0 @@
-import DashboardTable from "admin/components/dashboard-table";
-import AsyncReport from "admin/mixins/async-report";
-
-export default DashboardTable.extend(AsyncReport, {
- layoutName: "admin/templates/components/dashboard-table",
-
- classNames: ["dashboard-table", "dashboard-table-trending-search"]
-});
diff --git a/app/assets/javascripts/admin/components/dashboard-table.js.es6 b/app/assets/javascripts/admin/components/dashboard-table.js.es6
deleted file mode 100644
index 6db70f9bb89..00000000000
--- a/app/assets/javascripts/admin/components/dashboard-table.js.es6
+++ /dev/null
@@ -1,59 +0,0 @@
-import { ajax } from "discourse/lib/ajax";
-import Report from "admin/models/report";
-import AsyncReport from "admin/mixins/async-report";
-import computed from "ember-addons/ember-computed-decorators";
-import { number } from 'discourse/lib/formatter';
-
-export default Ember.Component.extend(AsyncReport, {
- classNames: ["dashboard-table"],
- classNameBindings : ["isDisabled"],
- help: null,
- helpPage: null,
- isDisabled: Ember.computed.not("siteSettings.log_search_queries"),
- disabledLabel: "admin.dashboard.reports.disabled",
-
- @computed("report")
- values(report) {
- if (!report) return;
- return Ember.makeArray(report.data)
- .map(x => {
- return [ x[0], number(x[1]), x[2] ];
- });
- },
-
- @computed("report")
- labels(report) {
- if (!report) return;
- return Ember.makeArray(report.labels);
- },
-
- loadReport(report_json) {
- this._setPropertiesFromReport(Report.create(report_json));
- },
-
- fetchReport() {
- if (this.get("isDisabled")) return;
-
- this.set("isLoading", true);
-
- let payload = { data: { async: true } };
-
- if (this.get("startDate")) {
- payload.data.start_date = this.get("startDate").format("YYYY-MM-DD[T]HH:mm:ss.SSSZZ");
- }
-
- if (this.get("endDate")) {
- payload.data.end_date = this.get("endDate").format("YYYY-MM-DD[T]HH:mm:ss.SSSZZ");
- }
-
- ajax(this.get("dataSource"), payload)
- .then((response) => {
- this.set('reportKey', response.report.report_key);
- this.loadReport(response.report);
- }).finally(() => {
- if (!Ember.isEmpty(this.get("report.data"))) {
- this.set("isLoading", false);
- };
- });
- }
-});
diff --git a/app/assets/javascripts/admin/mixins/async-report.js.es6 b/app/assets/javascripts/admin/mixins/async-report.js.es6
index c06c01ef141..12b267b059e 100644
--- a/app/assets/javascripts/admin/mixins/async-report.js.es6
+++ b/app/assets/javascripts/admin/mixins/async-report.js.es6
@@ -57,7 +57,11 @@ export default Ember.Mixin.create({
@computed("report")
labels(report) {
if (!report) return;
- return Ember.makeArray(report.data).map(r => r.x);
+ if (report.labels) {
+ return Ember.makeArray(report.labels);
+ } else {
+ return Ember.makeArray(report.data).map(r => r.x);
+ }
},
@computed("report")
diff --git a/app/assets/javascripts/admin/templates/components/dashboard-inline-table.hbs b/app/assets/javascripts/admin/templates/components/dashboard-inline-table.hbs
index 9e97de2f469..ce075761a5d 100644
--- a/app/assets/javascripts/admin/templates/components/dashboard-inline-table.hbs
+++ b/app/assets/javascripts/admin/templates/components/dashboard-inline-table.hbs
@@ -17,15 +17,15 @@
-
- {{#unless hasBlock}}
- {{#each values as |value|}}
+ {{#unless hasBlock}}
+ {{#each values as |value|}}
+
{{number value}} |
- {{/each}}
- {{else}}
- {{yield (hash report=report)}}
- {{/unless}}
-
+
+ {{/each}}
+ {{else}}
+ {{yield (hash report=report)}}
+ {{/unless}}
diff --git a/app/assets/javascripts/admin/templates/components/dashboard-table.hbs b/app/assets/javascripts/admin/templates/components/dashboard-table.hbs
deleted file mode 100644
index 5055d04175d..00000000000
--- a/app/assets/javascripts/admin/templates/components/dashboard-table.hbs
+++ /dev/null
@@ -1,37 +0,0 @@
-{{#if isDisabled}}
- {{{i18n disabledLabel}}}
-{{else}}
- {{#conditional-loading-section isLoading=isLoading title=report.title}}
-
-
-
-
-
-
- {{#each labels as |label|}}
- {{label}} |
- {{/each}}
-
-
-
-
- {{#each values as |value|}}
-
- {{#each value as |v|}}
- {{v}} |
- {{/each}}
-
- {{/each}}
-
-
-
- {{yield}}
-
- {{/conditional-loading-section}}
-{{/if}}
diff --git a/app/assets/javascripts/admin/templates/dashboard_next.hbs b/app/assets/javascripts/admin/templates/dashboard_next.hbs
index d6b0660e55f..d42c25a0417 100644
--- a/app/assets/javascripts/admin/templates/dashboard_next.hbs
+++ b/app/assets/javascripts/admin/templates/dashboard_next.hbs
@@ -87,6 +87,7 @@
{{#dashboard-inline-table dataSourceName="users_by_type" lastRefreshedAt=lastRefreshedAt as |context|}}
+
{{#each context.report.data as |data|}}
@@ -94,9 +95,11 @@
|
{{/each}}
+
{{/dashboard-inline-table}}
{{#dashboard-inline-table dataSourceName="users_by_trust_level" lastRefreshedAt=lastRefreshedAt as |context|}}
+
{{#each context.report.data as |data|}}
@@ -104,6 +107,7 @@
|
{{/each}}
+
{{/dashboard-inline-table}}
{{#conditional-loading-section isLoading=isLoading title=(i18n "admin.dashboard.backups")}}
@@ -148,13 +152,47 @@
- {{#dashboard-table-trending-search
+ {{#dashboard-inline-table
+ dataSourceName="top_referred_topics"
+ lastRefreshedAt=lastRefreshedAt
+ limit=8
+ as |context|}}
+ {{#each context.report.data as |data|}}
+
+
+
+ {{data.topic_title}}
+
+ |
+
+ {{data.num_clicks}}
+ |
+
+ {{/each}}
+ {{/dashboard-inline-table}}
+
+ {{#dashboard-inline-table
+ limit=8
dataSourceName="trending_search"
isEnabled=logSearchQueriesEnabled
disabledLabel="admin.dashboard.reports.trending_search.disabled"
startDate=lastWeek
- endDate=endDate}}
+ endDate=endDate as |context|}}
+ {{#each context.report.data as |data|}}
+
+
+ {{data.term}}
+ |
+
+ {{number data.unique_searches}}
+ |
+
+ {{data.ctr}}
+ |
+
+ {{/each}}
{{{i18n "admin.dashboard.reports.trending_search.more"}}}
- {{/dashboard-table-trending-search}}
-
+ {{/dashboard-inline-table}}
+
+
diff --git a/app/assets/stylesheets/common/admin/dashboard_next.scss b/app/assets/stylesheets/common/admin/dashboard_next.scss
index afe91b2614f..3e9a9fbcf4f 100644
--- a/app/assets/stylesheets/common/admin/dashboard_next.scss
+++ b/app/assets/stylesheets/common/admin/dashboard_next.scss
@@ -120,6 +120,9 @@
border: 1px solid $primary-low;
text-align: center;
}
+ td.left {
+ text-align: left;
+ }
td.value {
i {
diff --git a/app/controllers/admin/reports_controller.rb b/app/controllers/admin/reports_controller.rb
index 2fae3c38d2b..58f3c0454e4 100644
--- a/app/controllers/admin/reports_controller.rb
+++ b/app/controllers/admin/reports_controller.rb
@@ -27,12 +27,18 @@ class Admin::ReportsController < Admin::AdminController
facets = params[:facets].map { |s| s.to_s.to_sym }
end
+ limit = nil
+ if params.has_key?(:limit) && params[:limit].to_i > 0
+ limit = params[:limit].to_i
+ end
+
report = Report.find(report_type,
start_date: start_date,
end_date: end_date,
category_id: category_id,
group_id: group_id,
facets: facets,
+ limit: limit,
async: params[:async])
raise Discourse::NotFound if report.blank?
diff --git a/app/jobs/regular/retrieve_report.rb b/app/jobs/regular/retrieve_report.rb
index 54cac2b8312..2d00ae39838 100644
--- a/app/jobs/regular/retrieve_report.rb
+++ b/app/jobs/regular/retrieve_report.rb
@@ -14,6 +14,7 @@ module Jobs
report.category_id = args['category_id'] if args['category_id']
report.group_id = args['group_id'] if args['group_id']
report.facets = args['facets'].map(&:to_sym) if args['facets']
+ report.limit = args['limit'].to_i if args['limit']
Report.send("report_#{type}", report)
json = report.as_json
diff --git a/app/models/incoming_links_report.rb b/app/models/incoming_links_report.rb
index 5e817e18b28..a0d043acfec 100644
--- a/app/models/incoming_links_report.rb
+++ b/app/models/incoming_links_report.rb
@@ -1,6 +1,6 @@
class IncomingLinksReport
- attr_accessor :type, :data, :y_titles
+ attr_accessor :type, :data, :y_titles, :start_date, :limit
def initialize(type)
@type = type
@@ -14,7 +14,8 @@ class IncomingLinksReport
title: I18n.t("reports.#{self.type}.title"),
xaxis: I18n.t("reports.#{self.type}.xaxis"),
ytitles: self.y_titles,
- data: self.data
+ data: self.data,
+ start_date: start_date
}
end
@@ -24,6 +25,10 @@ class IncomingLinksReport
# Load the report
report = IncomingLinksReport.new(type)
+
+ report.start_date = _opts[:start_date] || 30.days.ago
+ report.limit = _opts[:limit].to_i if _opts[:limit]
+
send(report_method, report)
report
end
@@ -43,19 +48,19 @@ class IncomingLinksReport
report.data = report.data.sort_by { |x| x[:num_clicks] }.reverse[0, 10]
end
- def self.per_user
+ def self.per_user(start_date:)
@per_user_query ||= IncomingLink
- .where('incoming_links.created_at > ? AND incoming_links.user_id IS NOT NULL', 30.days.ago)
+ .where('incoming_links.created_at > ? AND incoming_links.user_id IS NOT NULL', start_date)
.joins(:user)
.group('users.username')
end
- def self.link_count_per_user
- per_user.count
+ def self.link_count_per_user(start_date:)
+ per_user(start_date: start_date).count
end
- def self.topic_count_per_user
- per_user.joins(:post).count("DISTINCT posts.topic_id")
+ def self.topic_count_per_user(start_date:)
+ per_user(start_date: start_date).joins(:post).count("DISTINCT posts.topic_id")
end
# Return top 10 domains that brought traffic to the site within the last 30 days
@@ -64,7 +69,7 @@ class IncomingLinksReport
report.y_titles[:num_topics] = I18n.t("reports.#{report.type}.num_topics")
report.y_titles[:num_users] = I18n.t("reports.#{report.type}.num_users")
- num_clicks = link_count_per_domain
+ num_clicks = link_count_per_domain(start_date: start_date)
num_topics = topic_count_per_domain(num_clicks.keys)
report.data = []
num_clicks.each_key do |domain|
@@ -73,8 +78,8 @@ class IncomingLinksReport
report.data = report.data.sort_by { |x| x[:num_clicks] }.reverse[0, 10]
end
- def self.link_count_per_domain(limit = 10)
- IncomingLink.where('incoming_links.created_at > ?', 30.days.ago)
+ def self.link_count_per_domain(limit: 10, start_date:)
+ IncomingLink.where('incoming_links.created_at > ?', start_date)
.joins(incoming_referer: :incoming_domain)
.group('incoming_domains.name')
.order('count_all DESC')
@@ -95,8 +100,8 @@ class IncomingLinksReport
def self.report_top_referred_topics(report)
report.y_titles[:num_clicks] = I18n.t("reports.#{report.type}.num_clicks")
- num_clicks = link_count_per_topic
- num_clicks = num_clicks.to_a.sort_by { |x| x[1] }.last(10).reverse # take the top 10
+ num_clicks = link_count_per_topic(start_date: report.start_date)
+ num_clicks = num_clicks.to_a.sort_by { |x| x[1] }.last(report.limit || 10).reverse
report.data = []
topics = Topic.select('id, slug, title').where('id in (?)', num_clicks.map { |z| z[0] })
num_clicks.each do |topic_id, num_clicks_element|
@@ -108,9 +113,9 @@ class IncomingLinksReport
report.data
end
- def self.link_count_per_topic
+ def self.link_count_per_topic(start_date:)
IncomingLink.joins(:post)
- .where('incoming_links.created_at > ? AND topic_id IS NOT NULL', 30.days.ago)
+ .where('incoming_links.created_at > ? AND topic_id IS NOT NULL', start_date)
.group('topic_id')
.count
end
diff --git a/app/models/report.rb b/app/models/report.rb
index 7f87778f232..53e1b1bbb10 100644
--- a/app/models/report.rb
+++ b/app/models/report.rb
@@ -4,7 +4,7 @@ class Report
attr_accessor :type, :data, :total, :prev30Days, :start_date,
:end_date, :category_id, :group_id, :labels, :async,
- :prev_period, :facets
+ :prev_period, :facets, :limit
def self.default_days
30
@@ -24,7 +24,8 @@ class Report
report.start_date.to_date.strftime("%Y%m%d"),
report.end_date.to_date.strftime("%Y%m%d"),
report.group_id,
- report.facets
+ report.facets,
+ report.limit
].map(&:to_s).join(':')
end
@@ -55,6 +56,7 @@ class Report
json[:total] = total if total
json[:prev_period] = prev_period if prev_period
json[:prev30Days] = self.prev30Days if self.prev30Days
+ json[:limit] = self.limit if self.limit
if type == 'page_view_crawler_reqs'
json[:related_report] = Report.find('web_crawlers', start_date: start_date, end_date: end_date)&.as_json
@@ -77,6 +79,7 @@ class Report
report.group_id = opts[:group_id] if opts[:group_id]
report.async = opts[:async] || false
report.facets = opts[:facets] || [:total, :prev30Days]
+ report.limit = opts[:limit] if opts[:limit]
report_method = :"report_#{type}"
if respond_to?(report_method)
@@ -405,11 +408,18 @@ class Report
report.data << { key: "silenced", x: label.call("silenced"), y: silenced } if silenced > 0
end
+ def self.report_top_referred_topics(report)
+ report.labels = [I18n.t("reports.top_referred_topics.xaxis"),
+ I18n.t("reports.top_referred_topics.num_clicks")]
+ result = IncomingLinksReport.find(:top_referred_topics, start_date: 7.days.ago, limit: report.limit)
+ report.data = result.data
+ end
+
def self.report_trending_search(report)
report.data = []
select_sql = <<~SQL
- term,
+ lower(term) term,
COUNT(*) AS searches,
SUM(CASE
WHEN search_result_id IS NOT NULL THEN 1
@@ -420,9 +430,9 @@ class Report
trends = SearchLog.select(select_sql)
.where('created_at > ? AND created_at <= ?', report.start_date, report.end_date)
- .group(:term)
+ .group('lower(term)')
.order('unique_searches DESC, click_through ASC, term ASC')
- .limit(20).to_a
+ .limit(report.limit || 20).to_a
report.labels = [:term, :searches, :click_through].map { |key|
I18n.t("reports.trending_search.labels.#{key}")
@@ -436,11 +446,11 @@ class Report
trend.click_through.to_f / trend.searches.to_f
end
- report.data << [
- trend.term,
- trend.unique_searches,
- (ctr * 100).ceil(1).to_s + "%"
- ]
+ report.data << {
+ term: trend.term,
+ unique_searches: trend.unique_searches,
+ ctr: (ctr * 100).ceil(1).to_s + "%"
+ }
end
end
end