| """
|
| Projects API Routes - Workspace management
|
| """
|
| from fastapi import APIRouter, Depends, HTTPException |
| from pydantic import BaseModel |
| from typing import Optional, List |
| from datetime import datetime |
| from sqlalchemy.orm import Session |
|
|
| from app.api.deps import get_scoped_db |
| from app.models import Project, Entity, Relationship |
|
|
|
|
| router = APIRouter(prefix="/projects", tags=["Projects"])
|
|
|
|
|
| class ProjectCreate(BaseModel):
|
| name: str
|
| description: Optional[str] = None
|
| color: str = "#00d4ff"
|
| icon: str = "folder"
|
|
|
|
|
| class ProjectResponse(BaseModel):
|
| id: str
|
| name: str
|
| description: Optional[str]
|
| color: str
|
| icon: str
|
| entity_count: int = 0
|
| created_at: datetime
|
|
|
| class Config:
|
| from_attributes = True
|
|
|
|
|
| @router.get("", response_model=List[ProjectResponse]) |
| def list_projects(db: Session = Depends(get_scoped_db)): |
| """List all projects""" |
| projects = db.query(Project).order_by(Project.created_at.desc()).all() |
|
|
| result = []
|
| for p in projects:
|
| entity_count = db.query(Entity).filter(Entity.project_id == p.id).count()
|
| result.append(ProjectResponse(
|
| id=p.id,
|
| name=p.name,
|
| description=p.description,
|
| color=p.color,
|
| icon=p.icon,
|
| entity_count=entity_count,
|
| created_at=p.created_at
|
| ))
|
|
|
| return result
|
|
|
|
|
| @router.post("", response_model=ProjectResponse) |
| def create_project(project: ProjectCreate, db: Session = Depends(get_scoped_db)): |
| """Create a new project""" |
| new_project = Project( |
| name=project.name, |
| description=project.description, |
| color=project.color,
|
| icon=project.icon
|
| )
|
| db.add(new_project)
|
| db.commit()
|
| db.refresh(new_project)
|
|
|
| return ProjectResponse(
|
| id=new_project.id,
|
| name=new_project.name,
|
| description=new_project.description,
|
| color=new_project.color,
|
| icon=new_project.icon,
|
| entity_count=0,
|
| created_at=new_project.created_at
|
| )
|
|
|
|
|
| @router.get("/{project_id}", response_model=ProjectResponse) |
| def get_project(project_id: str, db: Session = Depends(get_scoped_db)): |
| """Get project by ID""" |
| project = db.query(Project).filter(Project.id == project_id).first() |
|
|
| if not project:
|
| raise HTTPException(status_code=404, detail="Project not found")
|
|
|
| entity_count = db.query(Entity).filter(Entity.project_id == project_id).count()
|
|
|
| return ProjectResponse(
|
| id=project.id,
|
| name=project.name,
|
| description=project.description,
|
| color=project.color,
|
| icon=project.icon,
|
| entity_count=entity_count,
|
| created_at=project.created_at
|
| )
|
|
|
|
|
| @router.delete("/{project_id}") |
| def delete_project(project_id: str, db: Session = Depends(get_scoped_db)): |
| """Delete project and optionally its entities""" |
| project = db.query(Project).filter(Project.id == project_id).first() |
|
|
| if not project:
|
| raise HTTPException(status_code=404, detail="Project not found")
|
|
|
|
|
| db.query(Entity).filter(Entity.project_id == project_id).update({"project_id": None})
|
| db.query(Relationship).filter(Relationship.project_id == project_id).update({"project_id": None})
|
|
|
| db.delete(project)
|
| db.commit()
|
|
|
| return {"message": f"Project '{project.name}' deleted"}
|
|
|
|
|
| @router.put("/{project_id}") |
| def update_project(project_id: str, project: ProjectCreate, db: Session = Depends(get_scoped_db)): |
| """Update project""" |
| existing = db.query(Project).filter(Project.id == project_id).first() |
|
|
| if not existing:
|
| raise HTTPException(status_code=404, detail="Project not found")
|
|
|
| existing.name = project.name
|
| existing.description = project.description
|
| existing.color = project.color
|
| existing.icon = project.icon
|
| db.commit()
|
|
|
| return {"message": "Project updated"}
|
|
|