Shared helpers + frame for the dashboard widgets phoenix_kit_projects
contributes to phoenix_kit_dashboards via phoenix_kit_widgets/0.
Each widget is a Phoenix.LiveComponent the dashboards host renders with
settings / view / size / scope assigns. These helpers centralize the
enablement guard, the lenient project resolver (widgets pick a project by a
free-text "project" setting, since a dashboard widget's settings schema is
static), the shared card frame, and small formatters.
Summary
Functions
True when the projects module is loaded and enabled.
Format a datetime as YYYY-MM-DD, or —.
Pick the effective view: honor the selected view if it's one of valid,
else the first valid view. The user's choice is NEVER overridden by size —
content self-fits via container-query type scaling instead.
A centered, iconed empty-state body (widgets must never look broken-empty).
A scale-aware self-fit font-size style: the type grows with its cq slot but
stays clamped to a consistent px range, so widgets look cohesive at any box
size (no comically large list rows, no unreadable KPI labels). The
--pk-scale var (set by the dashboards fit hook) keeps the clamp
proportional when the board renders scaled down.
A shared widget card frame: header (icon + title + optional link) + body slot.
Format estimated hours compactly (e.g. 12h, 1.5h, —).
Resolve the "project" widget setting (a uuid, exact name, external id, or a
name substring) to a %Project{}. Falls back to the first running project (or
any project) when the setting is blank, so a freshly-added widget shows data.
Projects.list_projects/0 with the widget no-crash guard: a transient DB
error (connection loss, mid-migration missing table) degrades to an empty
list — a widget must never crash the host dashboard.
Projects.project_summary/1 with the widget no-crash guard — nil on a DB
error, which every consuming widget already renders as its empty state.
The current user's uuid out of the host-provided scope assign, or nil.
The 'projects module is off' placeholder body.
Functions
@spec available?() :: boolean()
True when the projects module is loaded and enabled.
@spec date(DateTime.t() | nil) :: String.t()
Format a datetime as YYYY-MM-DD, or —.
Pick the effective view: honor the selected view if it's one of valid,
else the first valid view. The user's choice is NEVER overridden by size —
content self-fits via container-query type scaling instead.
A centered, iconed empty-state body (widgets must never look broken-empty).
Attributes
icon(:string) - Defaults to"hero-clipboard-document-list".message(:string) (required)
A scale-aware self-fit font-size style: the type grows with its cq slot but
stays clamped to a consistent px range, so widgets look cohesive at any box
size (no comically large list rows, no unreadable KPI labels). The
--pk-scale var (set by the dashboards fit hook) keeps the clamp
proportional when the board renders scaled down.
A shared widget card frame: header (icon + title + optional link) + body slot.
Attributes
title(:string) (required)icon(:string) - Defaults to"hero-clipboard-document-list".href(:string) - Defaults tonil.
Slots
inner_block(required)actions
Format estimated hours compactly (e.g. 12h, 1.5h, —).
@spec resolve_project(term()) :: PhoenixKitProjects.Schemas.Project.t() | nil
Resolve the "project" widget setting (a uuid, exact name, external id, or a
name substring) to a %Project{}. Falls back to the first running project (or
any project) when the setting is blank, so a freshly-added widget shows data.
@spec safe_list_projects() :: [PhoenixKitProjects.Schemas.Project.t()]
Projects.list_projects/0 with the widget no-crash guard: a transient DB
error (connection loss, mid-migration missing table) degrades to an empty
list — a widget must never crash the host dashboard.
@spec safe_project_summary(PhoenixKitProjects.Schemas.Project.t()) :: map() | nil
Projects.project_summary/1 with the widget no-crash guard — nil on a DB
error, which every consuming widget already renders as its empty state.
The current user's uuid out of the host-provided scope assign, or nil.