Dashboard Registration
Experimental
Dashboards are experimental: the DSL and behavior may change in a future release.
register_dashboard
AdminPortal::Engine.routes.draw do
register_dashboard AdminPortal::HomeDashboard, at: "/" # the portal root
register_dashboard AdminPortal::SalesDashboard, at: "sales" # /admin/dashboards/sales
register_dashboard Reports::WeeklyDashboard, at: "reports/weekly", as: "weekly"
end| Argument | Meaning |
|---|---|
at: | Path under the portal's dashboards/ segment. "/" or "" mounts at the engine root |
prefix: | Leading path segment, "dashboards" by default. nil draws the mount at the bare at: path (/admin/sales); a string swaps the segment (prefix: "reports" → /admin/reports/sales). Does not affect helper names |
as: | Route helper prefix. Defaults to at: with slashes replaced, or the class slug for a root mount |
Routes drawn
GET /dashboards/sales → DashboardsController#show sales_dashboard_path
GET /dashboards/sales/cards/:card → DashboardsController#card sales_dashboard_card_pathEvery path is drawn under dashboards/, so a dashboard never shadows a register_resource route of the same name (at: "sales" next to a Sale resource). The route helpers carry no prefix.
With prefix: nil nothing reserves the path, so keep at: clear of your resource routes yourself.
A root mount draws root for the page and /dashboards/<as>/cards/:card for the cards (/<as>/cards/:card with prefix: nil). Replace the portal's generated root to: "dashboard#index" line with the registration; two root routes clash. The generated DashboardController and its view are then unrouted and can be deleted. The guide walks through it.
On a :path entity-scoped portal the routes sit inside the scope segment and the helpers are prefixed (organization_scoped_sales_dashboard_path). URLs built by the framework thread the current tenant through; when building your own use dashboard_path_for(SalesDashboard), available in controllers, views and components.
The controller
register_dashboard synthesizes <Portal>::DashboardsController < <Portal>::PlutoniumController including Plutonium::Dashboard::Controller and the portal's Concerns::Controller, so it carries the portal's authentication, entity scoping and layout. On the main app it synthesizes a bare ::DashboardsController < ApplicationController.
Define the class yourself to take over; the synthesized one is only created when the constant is missing.
module AdminPortal
class DashboardsController < PlutoniumController
include Plutonium::Dashboard::Controller
before_action { set_page_title("Reports") }
end
endThe concern provides show and card, current_dashboard, current_dashboard_class, authorize_dashboard! and dashboard_card_path(card).
The card endpoint
GET <mount>/cards/:card runs authorize?, looks the key up among the dashboard's cards, checks its condition:, and renders the card inside <turbo-frame id="pu-dashboard-card-<key>">. Unknown or hidden cards respond 404 (Plutonium::Dashboard::UnknownCardError); a denied authorize? responds 403. A request without a Turbo-Frame header renders the card inside the full layout.
Sidebar
registered_dashboards (a controller helper, also available in components) lists the dashboards mounted on the current engine, and dashboard_path_for(klass) builds each page path. The gem's _resource_sidebar.html.erb groups them under a Dashboards item (plutonium.resource.nav.dashboards) after the Home link (plutonium.resource.nav.home), skipping the one mounted at the root, which the Home link already opens.
Generator
rails g pu:dashboard Sales --dest=admin_portal # /admin/dashboards/sales
rails g pu:dashboard Home --dest=admin_portal --at=/ # portal root
rails g pu:dashboard Reporting --dest=main_app --at=reportsWrites app/dashboards/<portal>/<name>_dashboard.rb in the package (or app/dashboards/ for main_app) and adds the register_dashboard line to the routes. Idempotent.
Assets
Chart cards load plutonium-charts.js (Chart.js and Chartkick) on demand; the file ships with the gem beside plutonium.js and is precompiled with it. Plutonium.configuration.assets.charts_script names the asset ("plutonium-charts.min.js" by default). When PLUTONIUM_DEV is set the file comes from the src/build manifest like the main bundle.
