118 lines
4.6 KiB
Python
118 lines
4.6 KiB
Python
"""Dashboard API: aggregated stats, health distribution, gateway trend,
|
|
kanban overview, cron recent, and global search — all mock data for now."""
|
|
from datetime import datetime, timezone
|
|
|
|
from fastapi import APIRouter, Depends, Query
|
|
|
|
from app.middleware.auth import require_auth
|
|
from app.models.user import User
|
|
|
|
router = APIRouter(tags=["dashboard"])
|
|
|
|
|
|
@router.get("/dashboard/summary")
|
|
async def dashboard_summary(_user: User = Depends(require_auth)):
|
|
# TODO: replace with real data — hermes gateway status + kanban + cron
|
|
return {
|
|
"online_count": 12,
|
|
"offline_count": 46,
|
|
"total_profiles": 58,
|
|
"running_tasks": 3,
|
|
"cron_failures_today": 1,
|
|
"updated_at": datetime.now(timezone.utc).isoformat(timespec="seconds"),
|
|
}
|
|
|
|
|
|
@router.get("/dashboard/health-distribution")
|
|
async def health_distribution(_user: User = Depends(require_auth)):
|
|
# TODO: replace with real health-score calculation (Phase 4)
|
|
return {
|
|
"A": 22,
|
|
"B": 18,
|
|
"C": 10,
|
|
"D": 8,
|
|
"total": 58,
|
|
"d_profiles": ["ops-engineer", "monitor", "visualizer", "hebo", "..."],
|
|
}
|
|
|
|
|
|
@router.get("/dashboard/gateway-trend")
|
|
async def gateway_trend(_user: User = Depends(require_auth)):
|
|
# TODO: replace with real 24h aggregation from event store
|
|
return [
|
|
{"hour": "2026-07-22T08:00", "restarts": 2, "feishu_disconnects": 1, "heartbeat_timeouts": 0},
|
|
{"hour": "2026-07-22T09:00", "restarts": 0, "feishu_disconnects": 0, "heartbeat_timeouts": 1},
|
|
{"hour": "2026-07-22T10:00", "restarts": 1, "feishu_disconnects": 0, "heartbeat_timeouts": 0},
|
|
{"hour": "2026-07-22T11:00", "restarts": 0, "feishu_disconnects": 2, "heartbeat_timeouts": 0},
|
|
{"hour": "2026-07-22T12:00", "restarts": 0, "feishu_disconnects": 0, "heartbeat_timeouts": 0},
|
|
{"hour": "2026-07-22T13:00", "restarts": 3, "feishu_disconnects": 1, "heartbeat_timeouts": 2},
|
|
{"hour": "2026-07-22T14:00", "restarts": 0, "feishu_disconnects": 0, "heartbeat_timeouts": 1},
|
|
{"hour": "2026-07-22T15:00", "restarts": 1, "feishu_disconnects": 0, "heartbeat_timeouts": 0},
|
|
]
|
|
|
|
|
|
@router.get("/dashboard/kanban-summary")
|
|
async def kanban_summary(_user: User = Depends(require_auth)):
|
|
# TODO: replace with real kanban task data
|
|
return [
|
|
{"board": "europe-briefing", "running": "S4", "ready": "S5"},
|
|
{"board": "tech-weekly", "running": "S1", "ready": None},
|
|
{"board": "ops-review", "running": "M2", "ready": "M3"},
|
|
]
|
|
|
|
|
|
@router.get("/dashboard/cron-recent")
|
|
async def cron_recent(_user: User = Depends(require_auth)):
|
|
# TODO: replace with real cron execution history
|
|
return [
|
|
{"job": "taiwan-briefing", "status": "success", "time": "07:15"},
|
|
{"job": "hindsight", "status": "failure", "time": "21:13"},
|
|
{"job": "guangxi-donation", "status": "paused"},
|
|
{"job": "daily-report", "status": "success", "time": "08:00"},
|
|
{"job": "weekly-digest", "status": "success", "time": "09:30"},
|
|
]
|
|
|
|
|
|
@router.get("/search")
|
|
async def global_search(
|
|
q: str = Query("", min_length=1),
|
|
_user: User = Depends(require_auth),
|
|
):
|
|
# TODO: replace with real full-text search across profiles, tasks, cron, events
|
|
keyword = q.lower()
|
|
|
|
profiles = []
|
|
if "gateway" in keyword or "monitor" in keyword:
|
|
profiles.append({"name": "gateway-monitor", "status": "online"})
|
|
if "visual" in keyword:
|
|
profiles.append({"name": "visualizer", "status": "online"})
|
|
if "hebo" in keyword or "ops" in keyword:
|
|
profiles.append({"name": "ops-engineer", "status": "online"})
|
|
|
|
kanban_tasks = []
|
|
if "briefing" in keyword or "europe" in keyword:
|
|
kanban_tasks.append({"title": "Europe Briefing S4", "column": "RUNNING"})
|
|
if "tech" in keyword or "weekly" in keyword:
|
|
kanban_tasks.append({"title": "Tech Weekly S1", "column": "RUNNING"})
|
|
|
|
cron_jobs = []
|
|
if "taiwan" in keyword or "briefing" in keyword:
|
|
cron_jobs.append({"job": "taiwan-briefing", "status": "active"})
|
|
if "hindsight" in keyword:
|
|
cron_jobs.append({"job": "hindsight", "status": "active"})
|
|
if "donation" in keyword or "guangxi" in keyword:
|
|
cron_jobs.append({"job": "guangxi-donation", "status": "paused"})
|
|
|
|
events = []
|
|
if "gateway" in keyword or keyword == "restart":
|
|
events.append({"title": "Gateway restart detected", "status": "active"})
|
|
if "feishu" in keyword or "disconnect" in keyword:
|
|
events.append({"title": "Feishu disconnect alert", "status": "active"})
|
|
|
|
return {
|
|
"profiles": profiles,
|
|
"kanban_tasks": kanban_tasks,
|
|
"cron_jobs": cron_jobs,
|
|
"events": events,
|
|
}
|