feat(ui): alerts, monitors, hosts, schedules and maintenance lists put problems first, with since-times (#5210)
#5210 "Problems first, with since-time, across every list" (milestone 477), first batch. - Alerts: the Active list reads firing, no data, acknowledged, pending, the longest-running first, and re-polls itself. An acknowledged alert says how long it has been breaching (from the alert's events; acknowledging moves last_transition_at) and, apart from that, who acknowledged it and when. Rules show what each is doing now; disabled rules sort last. The current value reads the latest-value table (#5208) instead of plugin_metrics. - Monitors: a down monitor says "Down 12m · connection refused" in the list. - Hosts: sorted down, agent gone quiet, pending, healthy. The agent column shows "—" for a missing reading (was 0%) and a Stale badge with its age. agent_metrics_by_host is gone; the list reads agent_overview_by_host. - Schedules: failing first (failed or interrupted run, or a firing that could not start one), then running, then the rest, paused last; status badge from the shared states. - Maintenance windows: active (ending soonest), then upcoming (starting soonest), with expired folded away; each says when it ends/starts/ended. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
@@ -443,6 +443,7 @@ async def schedules():
|
||||
})
|
||||
if editing_id and s.id == editing_id:
|
||||
editing = s
|
||||
rows.sort(key=_schedule_order)
|
||||
|
||||
# Default the source dropdown to the first source (or the edited schedule's
|
||||
# source), and pre-render that source's playbooks so the playbook dropdown
|
||||
@@ -472,6 +473,23 @@ async def schedules():
|
||||
)
|
||||
|
||||
|
||||
def _schedule_order(row: dict) -> tuple:
|
||||
"""Schedules list order: failing first (its last run failed or was cut
|
||||
short, or its last firing could not start one), then running, then the
|
||||
rest, paused last; by name within each."""
|
||||
s, run = row["s"], row["last_run"]
|
||||
status = run.status.value if run else None
|
||||
if not s.enabled:
|
||||
rank = 3
|
||||
elif status in ("failed", "interrupted") or (s.last_error and run is None):
|
||||
rank = 0
|
||||
elif status in ("queued", "running"):
|
||||
rank = 1
|
||||
else:
|
||||
rank = 2
|
||||
return rank, s.name.lower()
|
||||
|
||||
|
||||
def _schedule_form_fields(form) -> tuple[dict | None, str | None]:
|
||||
"""Validate + extract schedule fields from a form. Returns (fields, error)."""
|
||||
name = (form.get("name", "") or "").strip()
|
||||
|
||||
Reference in New Issue
Block a user