ipwatch
This commit is contained in:
132
backend/app/routers/architecture.py
Normal file
132
backend/app/routers/architecture.py
Normal file
@@ -0,0 +1,132 @@
|
||||
"""
|
||||
Endpoints API pour l'éditeur d'architecture
|
||||
"""
|
||||
from fastapi import APIRouter, Depends, HTTPException
|
||||
from sqlalchemy.orm import Session
|
||||
from pydantic import BaseModel
|
||||
from typing import List, Optional, Dict, Any
|
||||
from uuid import uuid4
|
||||
from datetime import datetime
|
||||
import json
|
||||
from pathlib import Path
|
||||
|
||||
from backend.app.core.database import get_arch_db
|
||||
from backend.app.models.architecture import ArchitectureNode
|
||||
|
||||
router = APIRouter(prefix="/api/architecture", tags=["Architecture"])
|
||||
DATA_DIR = Path(__file__).resolve().parents[3] / "data"
|
||||
WORLD_FILE = DATA_DIR / "architecture.json"
|
||||
|
||||
|
||||
class ArchitectureNodeCreate(BaseModel):
|
||||
id: Optional[str] = None
|
||||
type: str
|
||||
x: int
|
||||
y: int
|
||||
width: int
|
||||
height: int
|
||||
rotation: int = 0
|
||||
payload: Dict[str, Any]
|
||||
|
||||
|
||||
class ArchitectureNodeResponse(BaseModel):
|
||||
id: str
|
||||
type: str
|
||||
x: int
|
||||
y: int
|
||||
width: int
|
||||
height: int
|
||||
rotation: int
|
||||
payload: Dict[str, Any]
|
||||
created_at: datetime
|
||||
|
||||
class Config:
|
||||
from_attributes = True
|
||||
|
||||
|
||||
class ArchitectureWorldPayload(BaseModel):
|
||||
items: List[Dict[str, Any]]
|
||||
splines: Optional[List[Dict[str, Any]]] = None
|
||||
|
||||
|
||||
@router.get("/nodes", response_model=List[ArchitectureNodeResponse])
|
||||
async def list_nodes(db: Session = Depends(get_arch_db)):
|
||||
"""Liste tous les noeuds d'architecture"""
|
||||
nodes = db.query(ArchitectureNode).order_by(ArchitectureNode.created_at.asc()).all()
|
||||
results = []
|
||||
for node in nodes:
|
||||
try:
|
||||
payload = json.loads(node.payload or "{}")
|
||||
except json.JSONDecodeError:
|
||||
payload = {}
|
||||
results.append(ArchitectureNodeResponse(
|
||||
id=node.id,
|
||||
type=node.type,
|
||||
x=node.x,
|
||||
y=node.y,
|
||||
width=node.width,
|
||||
height=node.height,
|
||||
rotation=node.rotation,
|
||||
payload=payload,
|
||||
created_at=node.created_at
|
||||
))
|
||||
return results
|
||||
|
||||
|
||||
@router.post("/nodes", response_model=ArchitectureNodeResponse)
|
||||
async def create_node(payload: ArchitectureNodeCreate, db: Session = Depends(get_arch_db)):
|
||||
"""Créer un noeud d'architecture"""
|
||||
node_id = payload.id or str(uuid4())
|
||||
node = ArchitectureNode(
|
||||
id=node_id,
|
||||
type=payload.type,
|
||||
x=payload.x,
|
||||
y=payload.y,
|
||||
width=payload.width,
|
||||
height=payload.height,
|
||||
rotation=payload.rotation,
|
||||
payload=json.dumps(payload.payload)
|
||||
)
|
||||
db.add(node)
|
||||
db.commit()
|
||||
db.refresh(node)
|
||||
return ArchitectureNodeResponse(
|
||||
id=node.id,
|
||||
type=node.type,
|
||||
x=node.x,
|
||||
y=node.y,
|
||||
width=node.width,
|
||||
height=node.height,
|
||||
rotation=node.rotation,
|
||||
payload=payload.payload,
|
||||
created_at=node.created_at
|
||||
)
|
||||
|
||||
|
||||
def ensure_world_file() -> None:
|
||||
DATA_DIR.mkdir(parents=True, exist_ok=True)
|
||||
if not WORLD_FILE.exists():
|
||||
WORLD_FILE.write_text(json.dumps({"items": [], "splines": []}, indent=2), encoding="utf-8")
|
||||
|
||||
|
||||
@router.get("/world")
|
||||
async def get_world():
|
||||
"""Charge le fichier architecture.json, le crée si absent."""
|
||||
ensure_world_file()
|
||||
try:
|
||||
data = json.loads(WORLD_FILE.read_text(encoding="utf-8"))
|
||||
except json.JSONDecodeError:
|
||||
data = {"items": [], "splines": []}
|
||||
return data
|
||||
|
||||
|
||||
@router.post("/world")
|
||||
async def save_world(payload: ArchitectureWorldPayload):
|
||||
"""Sauvegarde les éléments du world dans architecture.json."""
|
||||
ensure_world_file()
|
||||
splines = payload.splines or []
|
||||
WORLD_FILE.write_text(
|
||||
json.dumps({"items": payload.items, "splines": splines}, indent=2),
|
||||
encoding="utf-8"
|
||||
)
|
||||
return {"status": "ok", "count": len(payload.items), "splines": len(splines)}
|
||||
Reference in New Issue
Block a user