feat(dashboard): a curated default layout, merged duplicate widgets, a labelled Overview (#5213)
- New installs start from widgets.RECOMMENDED, packed row by row for the enabled plugins; the edit drawer can reset a dashboard to it. - Host Agent — Resources folds into Hosts — Overview (which gains load 1m), UniFi — Devices into UniFi — Overview; migration 0032 moves existing dashboards onto the survivors. - The Overview labels what it counts (hosts, monitors up/down/pending, alerts firing) and lists firing alerts and down monitors with since-times. - Uptime polls every 5 minutes (poll_seconds) instead of every cycle. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
+49
-36
@@ -9,6 +9,9 @@
|
||||
# type - "select" (only type currently supported)
|
||||
# default - default value (int or str determines how it's parsed from the form)
|
||||
# options - list of {value, label} dicts
|
||||
#
|
||||
# "poll" refreshes the cell every monitor poll interval; "poll_seconds"
|
||||
# overrides that cadence for a widget whose data moves slowly.
|
||||
from __future__ import annotations
|
||||
|
||||
WIDGET_REGISTRY: dict[str, dict] = {
|
||||
@@ -60,7 +63,7 @@ WIDGET_REGISTRY: dict[str, dict] = {
|
||||
"status_overview": {
|
||||
"key": "status_overview",
|
||||
"label": "Overview",
|
||||
"description": "At-a-glance summary — host count, monitor up/down/pending, and alerts",
|
||||
"description": "What needs attention across Steward: hosts, monitors and firing alerts, problems listed with since-times",
|
||||
"hx_url": "/status/widget",
|
||||
"detail_url": "/status/",
|
||||
"plugin": None,
|
||||
@@ -70,7 +73,7 @@ WIDGET_REGISTRY: dict[str, dict] = {
|
||||
"hosts_overview": {
|
||||
"key": "hosts_overview",
|
||||
"label": "Hosts — Overview",
|
||||
"description": "One row per host: monitor status + uptime and agent CPU/memory/disk, linking to the host hub",
|
||||
"description": "One row per host: monitor status, uptime, and agent CPU, memory, disk and load, linking to the host page",
|
||||
"hx_url": "/hosts/overview/widget",
|
||||
"detail_url": "/hosts/",
|
||||
"plugin": None,
|
||||
@@ -84,7 +87,9 @@ WIDGET_REGISTRY: dict[str, dict] = {
|
||||
"hx_url": "/hosts/uptime/widget",
|
||||
"detail_url": "/hosts/uptime",
|
||||
"plugin": None,
|
||||
"poll": False,
|
||||
"poll": True,
|
||||
# Uptime moves slowly and reads 30 days of checks: every 5 minutes, not every poll.
|
||||
"poll_seconds": 300,
|
||||
"params": [],
|
||||
},
|
||||
"traefik_routers": {
|
||||
@@ -184,29 +189,6 @@ WIDGET_REGISTRY: dict[str, dict] = {
|
||||
},
|
||||
],
|
||||
},
|
||||
"unifi_devices": {
|
||||
"key": "unifi_devices",
|
||||
"label": "UniFi — Devices",
|
||||
"description": "Network infrastructure devices with online/offline state",
|
||||
"hx_url": "/plugins/unifi/widget/devices",
|
||||
"detail_url": "/plugins/unifi/",
|
||||
"plugin": "unifi",
|
||||
"poll": True,
|
||||
"params": [
|
||||
{
|
||||
"key": "type_filter",
|
||||
"label": "Device type",
|
||||
"type": "select",
|
||||
"default": "all",
|
||||
"options": [
|
||||
{"value": "all", "label": "All devices"},
|
||||
{"value": "wireless", "label": "Wireless APs"},
|
||||
{"value": "wired", "label": "Wired only"},
|
||||
{"value": "offline", "label": "Offline devices"},
|
||||
],
|
||||
},
|
||||
],
|
||||
},
|
||||
"docker_containers": {
|
||||
"key": "docker_containers",
|
||||
"label": "Docker — Services & failures",
|
||||
@@ -260,16 +242,6 @@ WIDGET_REGISTRY: dict[str, dict] = {
|
||||
"poll": True,
|
||||
"params": [],
|
||||
},
|
||||
"host_resources": {
|
||||
"key": "host_resources",
|
||||
"label": "Host Agent — Resources",
|
||||
"description": "Fleet view: CPU, memory, disk, and load per host — each with a trend sparkline",
|
||||
"hx_url": "/plugins/host_agent/widget",
|
||||
"detail_url": "/hosts/",
|
||||
"plugin": "host_agent",
|
||||
"poll": True,
|
||||
"params": [],
|
||||
},
|
||||
"host_resource_history": {
|
||||
"key": "host_resource_history",
|
||||
"label": "Host Agent — History Graph",
|
||||
@@ -301,6 +273,47 @@ WIDGET_REGISTRY: dict[str, dict] = {
|
||||
},
|
||||
}
|
||||
|
||||
# Widgets that were merged into another (#5213): migration 0032 moved every
|
||||
# placement of the old key onto the new one, so nothing here renders them.
|
||||
RETIRED = {
|
||||
"host_resources": "hosts_overview", # Hosts — Overview carries cpu/mem/disk/load per host
|
||||
"unifi_devices": "unifi_overview", # UniFi — Overview lists the offline devices
|
||||
}
|
||||
|
||||
# The recommended dashboard (#5213): what needs attention first, then the
|
||||
# fleet, then each integration. (key, width, height, config) on the 12-column
|
||||
# grid, one cell 70px tall; a widget whose plugin is off is skipped and the
|
||||
# rest close up. Seeded into the first dashboard and offered by
|
||||
# "Reset to the recommended layout" in edit mode.
|
||||
RECOMMENDED: list[tuple[str, int, int, dict]] = [
|
||||
("status_overview", 12, 3, {}),
|
||||
("hosts_overview", 6, 7, {}),
|
||||
("monitors", 6, 7, {"show_down_only": "no", "limit": 10}),
|
||||
("docker_containers", 6, 6, {}),
|
||||
("docker_resources", 6, 6, {"limit": 10}),
|
||||
("uptime_summary", 6, 5, {}),
|
||||
("traefik_routers", 6, 5, {}),
|
||||
("unifi_overview", 6, 4, {}),
|
||||
("snmp_devices", 6, 4, {}),
|
||||
("traefik_request_chart", 12, 4, {}),
|
||||
]
|
||||
|
||||
|
||||
def recommended_layout(plugins_cfg: dict) -> list[dict]:
|
||||
"""RECOMMENDED placed on the grid for what is enabled: left to right,
|
||||
a new row when the next one does not fit, each row as tall as its
|
||||
tallest widget. [{key, x, y, w, h, config}]."""
|
||||
available = {w["key"] for w in get_available_widgets(plugins_cfg)}
|
||||
out, x, y, row_h = [], 0, 0, 0
|
||||
for key, w, h, config in RECOMMENDED:
|
||||
if key not in available:
|
||||
continue
|
||||
if x + w > 12:
|
||||
x, y, row_h = 0, y + row_h, 0
|
||||
out.append({"key": key, "x": x, "y": y, "w": w, "h": h, "config": config})
|
||||
x, row_h = x + w, max(row_h, h)
|
||||
return out
|
||||
|
||||
|
||||
# Group each widget for the picker (Core monitors / Monitoring capabilities /
|
||||
# Integrations), mirroring the Settings → Plugins taxonomy. Capability plugins
|
||||
|
||||
Reference in New Issue
Block a user