103 lines
3.3 KiB
Python
103 lines
3.3 KiB
Python
import json
|
|
|
|
from fastapi import APIRouter, Depends, HTTPException
|
|
from sqlalchemy.orm import Session
|
|
|
|
from ..auth import verify_token
|
|
from ..database import get_db
|
|
from ..models import GraphLayout
|
|
from ..schemas import (
|
|
GraphLayoutCreate,
|
|
GraphLayoutDetailResponse,
|
|
GraphLayoutResponse,
|
|
GraphLayoutUpdate,
|
|
)
|
|
|
|
router = APIRouter(prefix="/api/layouts", tags=["layouts"], dependencies=[Depends(verify_token)])
|
|
|
|
|
|
def _to_response(layout: GraphLayout) -> GraphLayoutResponse:
|
|
return GraphLayoutResponse.model_validate(layout)
|
|
|
|
|
|
def _to_detail_response(layout: GraphLayout) -> GraphLayoutDetailResponse:
|
|
base = GraphLayoutResponse.model_validate(layout)
|
|
return GraphLayoutDetailResponse(
|
|
**base.model_dump(),
|
|
node_positions=json.loads(layout.node_positions),
|
|
viewport=json.loads(layout.viewport),
|
|
)
|
|
|
|
|
|
@router.get("", response_model=list[GraphLayoutResponse])
|
|
def list_layouts(project_id: int | None = None, db: Session = Depends(get_db)):
|
|
query = db.query(GraphLayout)
|
|
if project_id is not None:
|
|
query = query.filter(GraphLayout.project_id == project_id)
|
|
return [_to_response(l) for l in query.order_by(GraphLayout.updated_at.desc()).all()]
|
|
|
|
|
|
@router.get("/{layout_id}", response_model=GraphLayoutDetailResponse)
|
|
def get_layout(layout_id: int, db: Session = Depends(get_db)):
|
|
layout = db.get(GraphLayout, layout_id)
|
|
if not layout:
|
|
raise HTTPException(404, "Layout not found")
|
|
return _to_detail_response(layout)
|
|
|
|
|
|
@router.post("", response_model=GraphLayoutDetailResponse, status_code=201)
|
|
def create_layout(data: GraphLayoutCreate, db: Session = Depends(get_db)):
|
|
if data.is_default:
|
|
db.query(GraphLayout).filter(
|
|
GraphLayout.project_id == data.project_id
|
|
).update({"is_default": False})
|
|
|
|
layout = GraphLayout(
|
|
name=data.name,
|
|
description=data.description,
|
|
project_id=data.project_id,
|
|
node_positions=json.dumps(data.node_positions),
|
|
viewport=json.dumps(data.viewport),
|
|
is_default=data.is_default,
|
|
)
|
|
db.add(layout)
|
|
db.commit()
|
|
db.refresh(layout)
|
|
return _to_detail_response(layout)
|
|
|
|
|
|
@router.put("/{layout_id}", response_model=GraphLayoutDetailResponse)
|
|
def update_layout(layout_id: int, data: GraphLayoutUpdate, db: Session = Depends(get_db)):
|
|
layout = db.get(GraphLayout, layout_id)
|
|
if not layout:
|
|
raise HTTPException(404, "Layout not found")
|
|
|
|
update_data = data.model_dump(exclude_unset=True)
|
|
|
|
if update_data.get("is_default"):
|
|
db.query(GraphLayout).filter(
|
|
GraphLayout.project_id == layout.project_id,
|
|
GraphLayout.id != layout_id,
|
|
).update({"is_default": False})
|
|
|
|
if "node_positions" in update_data:
|
|
update_data["node_positions"] = json.dumps(update_data["node_positions"])
|
|
if "viewport" in update_data:
|
|
update_data["viewport"] = json.dumps(update_data["viewport"])
|
|
|
|
for key, value in update_data.items():
|
|
setattr(layout, key, value)
|
|
|
|
db.commit()
|
|
db.refresh(layout)
|
|
return _to_detail_response(layout)
|
|
|
|
|
|
@router.delete("/{layout_id}", status_code=204)
|
|
def delete_layout(layout_id: int, db: Session = Depends(get_db)):
|
|
layout = db.get(GraphLayout, layout_id)
|
|
if not layout:
|
|
raise HTTPException(404, "Layout not found")
|
|
db.delete(layout)
|
|
db.commit()
|