92 lines
2.7 KiB
Python
92 lines
2.7 KiB
Python
from __future__ import annotations
|
|
|
|
import json
|
|
import shutil
|
|
from datetime import datetime, timezone
|
|
|
|
from fastapi import APIRouter, Request
|
|
from fastapi.responses import JSONResponse
|
|
|
|
from card_store import (
|
|
list_templates,
|
|
normalize_template_key,
|
|
read_template_meta,
|
|
sync_templates_context_file,
|
|
template_dir,
|
|
template_html_path,
|
|
template_meta_path,
|
|
)
|
|
from route_helpers import read_json_request
|
|
|
|
router = APIRouter()
|
|
|
|
|
|
@router.get("/templates")
|
|
async def get_templates() -> JSONResponse:
|
|
return JSONResponse(list_templates())
|
|
|
|
|
|
@router.post("/templates")
|
|
async def save_template(request: Request) -> JSONResponse:
|
|
try:
|
|
payload = await read_json_request(request)
|
|
except ValueError as exc:
|
|
return JSONResponse({"error": str(exc)}, status_code=400)
|
|
|
|
key = normalize_template_key(str(payload.get("key", "")))
|
|
title = str(payload.get("title", "")).strip()
|
|
content = str(payload.get("content", "")).strip()
|
|
notes = str(payload.get("notes", "")).strip()
|
|
example_state = payload.get("example_state", {})
|
|
if not isinstance(example_state, dict):
|
|
example_state = {}
|
|
|
|
if not key:
|
|
return JSONResponse({"error": "template key is required"}, status_code=400)
|
|
if not content:
|
|
return JSONResponse({"error": "template content is required"}, status_code=400)
|
|
|
|
current_template_dir = template_dir(key)
|
|
current_template_dir.mkdir(parents=True, exist_ok=True)
|
|
now = datetime.now(timezone.utc).isoformat()
|
|
existing_meta = read_template_meta(key)
|
|
created_at = str(existing_meta.get("created_at") or now)
|
|
|
|
template_html_path(key).write_text(content, encoding="utf-8")
|
|
template_meta_path(key).write_text(
|
|
json.dumps(
|
|
{
|
|
"key": key,
|
|
"title": title,
|
|
"notes": notes,
|
|
"example_state": example_state,
|
|
"created_at": created_at,
|
|
"updated_at": now,
|
|
},
|
|
indent=2,
|
|
ensure_ascii=False,
|
|
)
|
|
+ "\n",
|
|
encoding="utf-8",
|
|
)
|
|
|
|
sync_templates_context_file()
|
|
return JSONResponse(
|
|
{
|
|
"status": "ok",
|
|
"id": key,
|
|
"key": key,
|
|
"example_state": example_state,
|
|
"file_url": f"/card-templates/{key}/template.html",
|
|
}
|
|
)
|
|
|
|
|
|
@router.delete("/templates/{template_key}")
|
|
async def delete_template(template_key: str) -> JSONResponse:
|
|
key = normalize_template_key(template_key)
|
|
if not key:
|
|
return JSONResponse({"error": "invalid template key"}, status_code=400)
|
|
shutil.rmtree(template_dir(key), ignore_errors=True)
|
|
sync_templates_context_file()
|
|
return JSONResponse({"status": "ok", "key": key})
|