feat(monitors): Monitors absorbs the Status page; Status is removed (#5270)
CI / lint (push) Successful in 4s
CI / integration (push) Successful in 1m10s
CI / unit (push) Successful in 1m36s
CI / publish (push) Successful in 1m28s

Status repeated the Monitors page's counts, check strip and uptime. Monitors
now has one header row and every column Status had: the last 30 checks,
latest response with its trend, uptime over 24h / 7d / 30d (the range picker
goes) and TLS days on every row. /status and /status/rows and the nav link
are removed outright; the dashboard Overview (/status/widget) stays and its
Details link goes to Monitors.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
2026-10-07 15:36:38 -04:00
co-authored by Claude Opus 5.5
parent eaf9f1bcb8
commit 434127b3e1
16 changed files with 72 additions and 256 deletions
+4 -14
View File
@@ -16,7 +16,6 @@ from steward.core.audit import audit_request
from steward.models.users import UserRole
from steward.models.monitors import Monitor, MonitorType, MONITOR_TYPE_VALUES
from steward.core.status import _heartbeat_title, streak_start
from steward.core.time_range import DEFAULT_RANGE
from steward.models.hosts import Host
from steward.monitors import service as monitor_svc
@@ -47,23 +46,15 @@ def _form_opts(form, mtype: str) -> dict:
@require_role(UserRole.viewer)
async def index():
poll_interval = current_app.config.get("MONITORS_POLL_INTERVAL", 60)
return await render_template(
"monitors/index.html",
poll_interval=poll_interval,
current_range=request.args.get("range", DEFAULT_RANGE),
)
return await render_template("monitors/index.html", poll_interval=poll_interval)
@monitors_bp.get("/rows")
@require_role(UserRole.viewer)
async def rows():
async with current_app.db_sessionmaker() as db:
data, counts, range_key = await monitor_svc.monitor_rows(
db, request.args.get("range", DEFAULT_RANGE), current_app.config.get("THRESHOLDS", {}))
return await render_template(
"monitors/rows.html",
monitor_data=data, counts=counts, range_key=range_key,
)
data, counts = await monitor_svc.monitor_rows(db, current_app.config.get("THRESHOLDS", {}))
return await render_template("monitors/rows.html", monitor_data=data, counts=counts)
@monitors_bp.post("/add")
@@ -219,8 +210,7 @@ async def widget():
widget_id = request.args.get("wid", "0")
async with current_app.db_sessionmaker() as db:
data, counts, _ = await monitor_svc.monitor_rows(
db, DEFAULT_RANGE, current_app.config.get("THRESHOLDS", {}))
data, counts = await monitor_svc.monitor_rows(db, current_app.config.get("THRESHOLDS", {}))
if type_filter in MONITOR_TYPE_VALUES:
data = [d for d in data if d["monitor"].type == type_filter]
# Counted after the type filter, so the verdict speaks for what is listed.