PhoenixKitDashboards (PhoenixKitDashboards v0.4.0)

Copy Markdown View Source

Customizable dashboards for PhoenixKit.

Lets users compose dashboard pages from widgets contributed by any PhoenixKit module. A widget is a self-contained Phoenix.LiveComponent; a dashboard is a free-form 2D grid of placed widget instances, each with its own size, position, and settings. Layouts are persisted per user (personal dashboards) and per system/role (shared dashboards).

Architecture

Exposing widgets from another module

Any module can contribute widgets by defining a zero-arity phoenix_kit_widgets/0 returning plain maps — no dependency on this package:

def phoenix_kit_widgets do
  [%{key: "emails.deliverability", name: "Deliverability",
     module_key: "emails", component: PhoenixKitEmails.Widgets.DeliverabilityLive,
     default_size: %{w: 6, h: 2}}]
end

See PhoenixKitDashboards.Widget for the full contract.

Summary

Functions

Project-extension catalog entry for the phoenix_kit_projects hub — duck-typed contract (no dependency on that package, no @impl): a read-only Dashboard tab rendering one linked SHARED dashboard (config["dashboard_uuid"], picked from project_dashboard_options/0).

This module's own widgets, exposed through the same phoenix_kit_widgets/0 contract every other module uses (see the "Exposing widgets" section above), so the Registry discovers them uniformly — the built-ins are a live worked example of the contract, not a special-cased internal path.

Options for the project-extension config picker: every SHARED (scope == "system") dashboard, as %{value:, label:} — the only scope a project-wide tab may render (personal/role dashboards carry per-user visibility). [] when the table is unavailable.

Pins every label this module declares as a gettext msgid.

Functions

phoenix_kit_project_extensions()

@spec phoenix_kit_project_extensions() :: [map()]

Project-extension catalog entry for the phoenix_kit_projects hub — duck-typed contract (no dependency on that package, no @impl): a read-only Dashboard tab rendering one linked SHARED dashboard (config["dashboard_uuid"], picked from project_dashboard_options/0).

phoenix_kit_widgets()

@spec phoenix_kit_widgets() :: [map()]

This module's own widgets, exposed through the same phoenix_kit_widgets/0 contract every other module uses (see the "Exposing widgets" section above), so the Registry discovers them uniformly — the built-ins are a live worked example of the contract, not a special-cased internal path.

project_dashboard_options()

@spec project_dashboard_options() :: [%{value: String.t(), label: String.t()}]

Options for the project-extension config picker: every SHARED (scope == "system") dashboard, as %{value:, label:} — the only scope a project-wide tab may render (personal/role dashboards carry per-user visibility). [] when the table is unavailable.

translatable_labels()

@spec translatable_labels() :: [String.t()]

Pins every label this module declares as a gettext msgid.

permission_metadata/0 and admin_tabs/0 declare their labels as plain string literals, so mix gettext.extract never sees this file — PhoenixKit.Dashboard.Tab.localized_label/1 (and the permissions matrix' PhoenixKit.Users.Permissions.localized_module_label/1) translate them at render time through each declaration's gettext_backend/gettext_domain, but only if the msgid already exists in this module's own catalogue.

Without this anchor, "Dashboards" happens to also appear as a literal gettext("Dashboards") call in Web.DashboardsLive's page title — so it would stay in default.pot today, but only by coincidence (see phoenix_kit_warehouse's translatable_labels/0, which hit exactly this trap). The other three tab labels have no such coincidental anchor at all.

dgettext_noop/2 registers the msgid and returns it unchanged — nothing here runs at request time.