mirror of
https://gh.wpcy.net/https://github.com/discourse/discourse.git
synced 2026-05-26 23:09:13 +08:00
Behind the `dashboard_improvements` setting, the Highlights row is hardcoded This commit updates `/admin/dashboard.json` to swap out to a `sections.highlights`. The endpoint takes optional `start_date` / `end_date` so the redesigned page passes its picker range. Legacy dashboard / `AdminDashboard.fetch()` callers get the same response without the new stuff. Core ships three KPIs (`new_signups`, `dau_mau`, `new_contributors`). Plugins register more via a new `register_admin_dashboard_highlight_kpi(type:, report:, enabled:)` (discourse-solved for now). Each plugin owns their own KPI stuff. Caching uses the existing per-report layer (`Report.find_cached`) rather than wrapping the service in its own cache. Toggling a plugin's `enabled:` takes effect immediately, the cache is shared with the Reports tab when an admin drills into a tile, and the cache key isn't fragmented per admin since the data is admin-agnostic. The server returns `report_type` + `report_query` instead of a full URL so routes are stable. Without solved: https://github.com/user-attachments/assets/28612829-b425-4664-bfb9-02e8783f5b93 With solved: https://github.com/user-attachments/assets/3c6b6d6f-44b7-4c61-9b23-0aaaa3f21ddc
110 lines
3.3 KiB
Ruby
Vendored
110 lines
3.3 KiB
Ruby
Vendored
# frozen_string_literal: true
|
|
|
|
describe AdminDashboardHighlights do
|
|
before do
|
|
freeze_time(Time.zone.local(2026, 4, 28, 12, 0, 0))
|
|
Discourse.cache.clear
|
|
end
|
|
|
|
context "when solved is enabled" do
|
|
before { SiteSetting.solved_enabled = true }
|
|
|
|
it "omits the KPI when no category enables accepted answers" do
|
|
Fabricate(:category)
|
|
|
|
result = AdminDashboardHighlights.build(start_date: "2026-04-01", end_date: "2026-04-28")
|
|
expect(result[:kpis].map { |k| k[:type] }).not_to include(:accepted_solutions)
|
|
end
|
|
|
|
it "includes the KPI when at least one category supports accepted answers" do
|
|
category = Fabricate(:category)
|
|
category.custom_fields[DiscourseSolved::ENABLE_ACCEPTED_ANSWERS_CUSTOM_FIELD] = "true"
|
|
category.save!
|
|
|
|
result = AdminDashboardHighlights.build(start_date: "2026-04-01", end_date: "2026-04-28")
|
|
kpi = result[:kpis].find { |k| k[:type] == :accepted_solutions }
|
|
|
|
expect(kpi).to be_present
|
|
expect(kpi[:report_type]).to eq("accepted_solutions")
|
|
end
|
|
end
|
|
|
|
context "when solved is disabled" do
|
|
before { SiteSetting.solved_enabled = false }
|
|
|
|
it "omits the KPI even if a category enables accepted answers" do
|
|
category = Fabricate(:category)
|
|
category.custom_fields[DiscourseSolved::ENABLE_ACCEPTED_ANSWERS_CUSTOM_FIELD] = "true"
|
|
category.save!
|
|
|
|
result = AdminDashboardHighlights.build(start_date: "2026-04-01", end_date: "2026-04-28")
|
|
expect(result[:kpis].map { |k| k[:type] }).not_to include(:accepted_solutions)
|
|
end
|
|
end
|
|
|
|
describe "accepted_solutions report prev_period facet" do
|
|
fab!(:user)
|
|
fab!(:topic)
|
|
fab!(:post) { Fabricate(:post, topic: topic) }
|
|
|
|
it "populates prev_period when the facet is requested" do
|
|
DiscourseSolved::SolvedTopic.create!(
|
|
topic: topic,
|
|
answer_post: post,
|
|
accepter: user,
|
|
created_at: Time.zone.local(2026, 3, 15),
|
|
)
|
|
|
|
report =
|
|
Report.find(
|
|
"accepted_solutions",
|
|
start_date: Time.zone.local(2026, 4, 1),
|
|
end_date: Time.zone.local(2026, 4, 28),
|
|
facets: %i[prev_period],
|
|
)
|
|
|
|
expect(report.prev_period).to be >= 1
|
|
end
|
|
|
|
it "excludes deleted topics from prev_period" do
|
|
DiscourseSolved::SolvedTopic.create!(
|
|
topic: topic,
|
|
answer_post: post,
|
|
accepter: user,
|
|
created_at: Time.zone.local(2026, 3, 15),
|
|
)
|
|
topic.trash!
|
|
|
|
report =
|
|
Report.find(
|
|
"accepted_solutions",
|
|
start_date: Time.zone.local(2026, 4, 1),
|
|
end_date: Time.zone.local(2026, 4, 28),
|
|
facets: %i[prev_period],
|
|
)
|
|
|
|
expect(report.prev_period.to_i).to eq(0)
|
|
end
|
|
|
|
it "excludes private message topics from prev_period" do
|
|
pm = Fabricate(:private_message_topic)
|
|
pm_post = Fabricate(:post, topic: pm)
|
|
DiscourseSolved::SolvedTopic.create!(
|
|
topic: pm,
|
|
answer_post: pm_post,
|
|
accepter: user,
|
|
created_at: Time.zone.local(2026, 3, 15),
|
|
)
|
|
|
|
report =
|
|
Report.find(
|
|
"accepted_solutions",
|
|
start_date: Time.zone.local(2026, 4, 1),
|
|
end_date: Time.zone.local(2026, 4, 28),
|
|
facets: %i[prev_period],
|
|
)
|
|
|
|
expect(report.prev_period.to_i).to eq(0)
|
|
end
|
|
end
|
|
end
|