0
0
Fork 0
mirror of https://github.com/discourse/discourse.git synced 2026-08-08 17:53:55 +08:00
discourse/lib/admin_dashboard/reports/section.rb
Osama Sayegh be54920a12
FEATURE: Customisable Reports section on the new admin dashboard (#40264)
Adds the frontend for the Reports section on the redesigned admin
dashboard. Admins can choose which reports appear on their dashboard,
reorder them, and add/remove cards via a "Manage reports" modal. A
plugin API lets plugins ship their own report providers and custom card
renderers — used by Data Explorer to surface DE queries alongside core
reports.

Follow-up to backend PR:
https://github.com/discourse/discourse/pull/40017
2026-05-25 13:55:25 +03:00

63 lines
1.8 KiB
Ruby
Vendored

# frozen_string_literal: true
module AdminDashboard
module Reports
class Section
def self.build(guardian:, search: nil)
new(guardian: guardian, search: search).build
end
def initialize(guardian:, search: nil)
@guardian = guardian
@search = search.presence
end
def build
items = visible_items.map { |_row, resolved| serialize(resolved) }
items = filter_by_search(items) if @search
{ items: items, show_labels: AdminDashboard::Reports::Registry.providers.length > 1 }
end
private
attr_reader :guardian
def visible_items
rows = AdminDashboardReport.order(created_at: :desc).to_a
resolved_by_row_id = resolve_rows(rows)
# When more rows resolve than VISIBLE_CAP allows, the older overflow
# is hidden — clip by created_at recency first, then re-sort the
# survivors by the admin's chosen position.
rows
.filter_map { |row| (obj = resolved_by_row_id[row.id]) && [row, obj] }
.first(AdminDashboardReport::VISIBLE_CAP)
.sort_by { |row, _obj| row.position }
end
def resolve_rows(rows)
per_source =
AdminDashboard::Reports::Registry.dispatch_per_source(rows) do |provider, group|
provider.resolve_many(group.map(&:identifier), guardian: guardian)
end
rows.each_with_object({}) do |row, resolved|
resolved[row.id] = per_source.dig(row.source, row.identifier)
end
end
def serialize(resolved)
resolved.to_h
end
def filter_by_search(items)
query = @search.downcase
items.select do |item|
item[:title].to_s.downcase.include?(query) ||
item[:description].to_s.downcase.include?(query)
end
end
end
end
end