mirror of
https://gh.wpcy.net/https://github.com/discourse/discourse.git
synced 2026-06-19 01:44:11 +08:00
The "Daily engaged" KPI on the admin dashboard could show an upward trend while engagement was actually falling, because the current period was summed while the previous period it compared against was a daily average. This commit drives the average-versus-sum choice off each report's `average` flag instead of a hardcoded check, so average reports like `daily_engaged_users` average both periods while cumulative reports keep summing both.
65 lines
2 KiB
Ruby
Vendored
65 lines
2 KiB
Ruby
Vendored
# frozen_string_literal: true
|
|
|
|
# Including classes must expose `start_date` and `end_date`.
|
|
module AdminDashboardKpis
|
|
private
|
|
|
|
def build_kpi(type, report_name)
|
|
args = { start_date: start_date, end_date: end_date, facets: %i[prev_period] }
|
|
|
|
report = Report.find_cached(report_name, args)
|
|
if report.nil?
|
|
report = Report.find(report_name, args)
|
|
Report.cache(report) if report && report.error.blank?
|
|
end
|
|
|
|
return nil if report.nil? || report_error?(report) || report_data(report).nil?
|
|
|
|
current = period_value(report_data(report), average: report_average?(report))
|
|
previous = report_prev_period(report)
|
|
|
|
{
|
|
type: type,
|
|
value: current,
|
|
previous_value: previous,
|
|
percent_change: compute_percent_change(current, previous),
|
|
report_type: report_name,
|
|
report_query: {
|
|
start_date: start_date.to_date.iso8601,
|
|
end_date: end_date.to_date.iso8601,
|
|
},
|
|
}
|
|
end
|
|
|
|
# Report.find returns a Report object; Report.find_cached returns the as_json
|
|
# hash (symbol-keyed). The accessors below cope with either.
|
|
def report_error?(report_or_hash)
|
|
report_or_hash.is_a?(Hash) ? report_or_hash[:error].present? : report_or_hash.error.present?
|
|
end
|
|
|
|
def report_data(report_or_hash)
|
|
report_or_hash.is_a?(Hash) ? report_or_hash[:data] : report_or_hash.data
|
|
end
|
|
|
|
def report_prev_period(report_or_hash)
|
|
report_or_hash.is_a?(Hash) ? report_or_hash[:prev_period] : report_or_hash.prev_period
|
|
end
|
|
|
|
def report_average?(report_or_hash)
|
|
report_or_hash.is_a?(Hash) ? report_or_hash[:average] : report_or_hash.average
|
|
end
|
|
|
|
def period_value(data, average:)
|
|
return nil if data.empty?
|
|
|
|
ys = data.map { |point| point[:y] }
|
|
return (ys.sum(&:to_f) / ys.size).round(1) if average
|
|
|
|
ys.sum(&:to_i)
|
|
end
|
|
|
|
def compute_percent_change(current, previous)
|
|
return nil if previous.blank? || previous.zero? || current.blank?
|
|
((current.to_f - previous) / previous * 100).round(2)
|
|
end
|
|
end
|