mirror of
https://github.com/discourse/discourse.git
synced 2026-03-04 01:15:08 +08:00
* Reorganise the admin reports listing page — reports are now grouped into logical sections (Engagement, Traffic, Members, Content, Moderation, Security) instead of a flat alphabetical list. Plugin-provided reports are grouped under their plugin name. * Hide legacy/deprecated reports from the listing via a new Report::LEGACY_REPORTS constant, while keeping them accessible by direct URL. Legacy reports show an info banner warning they are deprecated. * Filter out reports from disabled plugins — the reports listing now resolves which plugin each report belongs to (via source file path) and excludes reports whose plugin is disabled. Each report also exposes plugin and plugin_display_name metadata. * Simplify reports page layout — removed the dashboard settings tab from the reports page header, replaced hideTabs logic with showHeader that only renders the DPageHeader on the index route (not on individual report pages). Removed the separate dashboard-reports route/controller/template entirely. Screenshots <img width="1454" height="1494" alt="Screenshot 2026-02-13 at 12 00 05 pm" src="https://github.com/user-attachments/assets/60b62563-1ebe-43f6-a13c-695eb640488c" /> <img width="1459" height="845" alt="Screenshot 2026-02-13 at 12 00 16 pm" src="https://github.com/user-attachments/assets/01ed2d0c-4105-4189-b653-f39074a40a43" /> <img width="1442" height="1086" alt="Screenshot 2026-02-23 at 2 34 16 pm" src="https://github.com/user-attachments/assets/b324c67d-b09c-41b5-8840-f5966486eaa8" />
124 lines
3.4 KiB
Ruby
124 lines
3.4 KiB
Ruby
# frozen_string_literal: true
|
|
|
|
module Reports
|
|
class ListQuery
|
|
class FormattedReport
|
|
attr_reader :type, :name
|
|
|
|
def initialize(name)
|
|
@name = name
|
|
@type = name.to_s.gsub("report_", "")
|
|
end
|
|
|
|
def visible?(admin:)
|
|
return false if Report.hidden?(type, admin:)
|
|
|
|
if SiteSetting.reporting_improvements
|
|
return false if plugin_report? && plugin_disabled?
|
|
return false if Report::LEGACY_REPORTS.include?(type)
|
|
end
|
|
|
|
true
|
|
end
|
|
|
|
def to_h
|
|
result = {
|
|
type:,
|
|
title:,
|
|
description:,
|
|
description_link: I18n.t("reports.#{type}.description_link", default: "").presence,
|
|
}
|
|
|
|
if SiteSetting.reporting_improvements && plugin_report?
|
|
result[:plugin] = plugin_name
|
|
result[:plugin_display_name] = plugin_display_name
|
|
end
|
|
|
|
result
|
|
end
|
|
|
|
private
|
|
|
|
# HACK: We need to show a different label and description for some
|
|
# old reports while people are still relying on them, that lets us
|
|
# point toward the new 'Site traffic' report as well. Not ideal,
|
|
# but apart from duplicating the report there's not a nicer way to do this.
|
|
def title
|
|
return I18n.t("reports.#{type}.title_legacy") if legacy?
|
|
I18n.t("reports.#{type}.title")
|
|
end
|
|
|
|
def description
|
|
return I18n.t("reports.#{type}.description_legacy") if legacy?
|
|
I18n.t("reports.#{type}.description", default: "").presence
|
|
end
|
|
|
|
def legacy?
|
|
SiteSetting.use_legacy_pageviews &&
|
|
type.in?(%w[consolidated_page_views consolidated_page_views_browser_detection])
|
|
end
|
|
|
|
def plugin_name
|
|
return @plugin_name if defined?(@plugin_name)
|
|
|
|
@plugin_name = resolve_plugin_name
|
|
end
|
|
|
|
def resolve_plugin_name
|
|
return unless Report.singleton_class.method_defined?(@name)
|
|
|
|
source_path = Report.method(@name).source_location.first
|
|
return unless source_path&.include?("/plugins/")
|
|
|
|
# Extract plugin name from path like /plugins/discourse-ai/...
|
|
match = source_path.match(%r{/plugins/([^/]+)/})
|
|
match[1] if match
|
|
rescue NameError
|
|
nil
|
|
end
|
|
|
|
def plugin_instance
|
|
return @plugin_instance if defined?(@plugin_instance)
|
|
@plugin_instance = plugin_name && Discourse.plugins_by_name[plugin_name]
|
|
end
|
|
|
|
def plugin_display_name
|
|
plugin_instance&.humanized_name
|
|
end
|
|
|
|
def plugin_report?
|
|
plugin_name.present?
|
|
end
|
|
|
|
def plugin_disabled?
|
|
return true unless plugin_instance
|
|
!plugin_instance.enabled?
|
|
end
|
|
end
|
|
|
|
def self.call(admin:)
|
|
page_view_req_report_methods =
|
|
["page_view_total_reqs"] +
|
|
ApplicationRequest
|
|
.req_types
|
|
.keys
|
|
.select { |r| r =~ /\Apage_view_/ && r !~ /mobile/ }
|
|
.map { |r| r + "_reqs" }
|
|
|
|
if !SiteSetting.use_legacy_pageviews
|
|
page_view_req_report_methods << "page_view_legacy_total_reqs"
|
|
end
|
|
|
|
reports_methods =
|
|
page_view_req_report_methods +
|
|
Report.singleton_methods.grep(/\Areport_(?!about|storage_stats)/)
|
|
|
|
reports_methods
|
|
.filter_map do |report_name|
|
|
report = Reports::ListQuery::FormattedReport.new(report_name)
|
|
report.to_h if report.visible?(admin:)
|
|
end
|
|
.sort_by { |report| report[:title] }
|
|
end
|
|
end
|
|
end
|