feat: add /admin/templates/preview endpoint; add preview button to template editor

This commit is contained in:
auto-bot
2025-12-24 10:58:43 +08:00
parent 74b8b8e8ed
commit 0def77dc30
2 changed files with 64 additions and 1 deletions
+27 -1
View File
@@ -1,4 +1,4 @@
from fastapi import APIRouter, Request, Form, Depends, HTTPException
from fastapi import APIRouter, Request, Form, Depends, HTTPException, Body
from fastapi.responses import HTMLResponse, RedirectResponse, JSONResponse
from fastapi.templating import Jinja2Templates
from sqlalchemy.orm import Session, joinedload, aliased
@@ -7,6 +7,7 @@ import json
from app.db import SessionLocal, Target, NotificationChannel, MessageTemplate, WebhookEndpoint, RequestLog, DeliveryLog, ProcessingRule, RuleAction
from app.services.stats import stats_service
from app.services.engine import engine
from app.templates import safe_render
router = APIRouter(prefix="/admin", tags=["admin"])
templates = Jinja2Templates(directory="templates")
@@ -424,6 +425,31 @@ async def delete_template(id: int = Form(...), db: Session = Depends(get_db)):
db.commit()
return RedirectResponse(url="/admin/templates", status_code=303)
@router.post("/templates/preview")
async def preview_template(data: dict = Body(...), db: Session = Depends(get_db)):
"""
Preview a template with an optional sample payload.
Request JSON: { "template_content": "...", "sample_payload": {...}, "vars": {...} }
"""
template_content = data.get("template_content")
if not template_content:
return JSONResponse({"error": "template_content is required"}, status_code=400)
sample_payload = data.get("sample_payload") or {}
# Build render context using engine's flatten helper if available
try:
render_context = engine._flatten_payload(sample_payload) if hasattr(engine, "_flatten_payload") else dict(sample_payload)
# Merge any provided template vars
extra_vars = data.get("vars") or {}
if isinstance(extra_vars, dict):
render_context.update(extra_vars)
rendered = safe_render(template_content, render_context)
return JSONResponse({"rendered": rendered})
except Exception as e:
return JSONResponse({"error": str(e)}, status_code=400)
# --- Logs ---
@router.get("/logs", response_class=HTMLResponse)
async def list_logs(request: Request, db: Session = Depends(get_db)):