feat: v1.1.3 — dashboard alerts panel, sparkline charts, log sanitisation, CSS vars

This commit is contained in:
markmorado
2026-03-10 14:10:00 +01:00
parent a0a502f82a
commit 3947dae7b9
16 changed files with 638 additions and 267 deletions

View File

@@ -1,13 +1,14 @@
from fastapi import APIRouter, Depends, Request
from fastapi.responses import HTMLResponse, RedirectResponse
from fastapi.responses import HTMLResponse, JSONResponse, RedirectResponse
from fastapi.templating import Jinja2Templates
from sqlalchemy.orm import Session
from sqlalchemy import func, distinct
from datetime import datetime, timedelta
from ..db import get_db
from ..models import ProxmoxServer, AuditLog
from ..models import ProxmoxServer, AuditLog, User
from ..template_helpers import add_i18n_context
from ..rbac.decorators import PermissionChecker
router = APIRouter()
templates = Jinja2Templates(directory="app/templates")
@@ -72,6 +73,37 @@ def dashboard(request: Request, db: Session = Depends(get_db)):
return templates.TemplateResponse("dashboard.html", context)
@router.get("/api/dashboard/alerts")
def get_dashboard_alerts(
db: Session = Depends(get_db),
current_user: User = Depends(PermissionChecker("logs.view"))
):
"""Вернуть события error/critical за последние 24 ч для дашборда"""
since_24h = datetime.utcnow() - timedelta(hours=24)
alerts = db.query(AuditLog).filter(
AuditLog.level.in_(['error', 'critical']),
AuditLog.created_at >= since_24h
).order_by(AuditLog.created_at.desc()).limit(50).all()
return JSONResponse(content={
"alerts": [
{
"id": a.id,
"level": a.level,
"category": a.category,
"action": a.action,
"message": a.message,
"username": a.username,
"resource_name": a.resource_name,
"server_name": a.server_name,
"created_at": a.created_at.isoformat() if a.created_at else None,
}
for a in alerts
],
"total": len(alerts)
})
@router.get("/containers", response_class=HTMLResponse, include_in_schema=False)
def containers(request: Request):
lang = request.cookies.get("language", "en")