File size: 5,804 Bytes
77f281e b07f5e4 77f281e b07f5e4 77f281e b07f5e4 77f281e b07f5e4 77f281e b07f5e4 77f281e b07f5e4 77f281e b07f5e4 77f281e b07f5e4 77f281e b07f5e4 ed7ee89 b07f5e4 | 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 | from fastapi import APIRouter, Depends, HTTPException, status, Response, BackgroundTasks
from sqlalchemy.orm import Session
from typing import List, Optional
import logging
from datetime import datetime
from core.database import get_db, SessionLocal
from models import db_models
from models.schemas import CanvasCreateRequest, CanvasEditRequest, CanvasResponse
from services.canvas_service import canvas_service
from api.auth import get_current_user
from api.websocket_routes import manager
router = APIRouter(prefix="/api/canvas", tags=["Canvas - Collaborative Editing"])
logger = logging.getLogger(__name__)
async def run_canvas_generation(canvas_id: int, request: CanvasCreateRequest, user_id: int):
"""Background task for canvas summary generation"""
db = SessionLocal()
connection_id = f"user_{user_id}"
try:
db_canvas = db.query(db_models.Canvas).filter(db_models.Canvas.id == canvas_id).first()
if not db_canvas: return
# Call AI service
content = await canvas_service.generate_canvas_summary(
file_key=request.file_key,
text_input=request.text_input
)
if not content:
raise Exception("AI failed to generate canvas content")
db_canvas.text = content
db_canvas.status = "completed"
db.commit()
# Notify via WebSocket
await manager.send_result(connection_id, {
"type": "canvas",
"id": db_canvas.id,
"status": "completed",
"title": db_canvas.title
})
except Exception as e:
logger.error(f"Background canvas generation failed: {e}")
db_canvas = db.query(db_models.Canvas).filter(db_models.Canvas.id == canvas_id).first()
if db_canvas:
db_canvas.status = "failed"
db_canvas.error_message = str(e)
db.commit()
await manager.send_error(connection_id, f"Canvas generation failed: {str(e)}")
finally:
db.close()
@router.post("/create", response_model=CanvasResponse)
async def create_canvas(
request: CanvasCreateRequest,
background_tasks: BackgroundTasks,
current_user: db_models.User = Depends(get_current_user),
db: Session = Depends(get_db)
):
"""
Initiates Canvas creation in the background.
"""
source_id = None
if request.file_key:
source = db.query(db_models.Source).filter(
db_models.Source.s3_key == request.file_key,
db_models.Source.user_id == current_user.id
).first()
if not source:
raise HTTPException(status_code=403, detail="Not authorized to access this file")
source_id = source.id
# Create initial record
file_base = request.file_key.split('/')[-1].rsplit('.', 1)[0] if request.file_key else None
# Priority: 1. File-based name, 2. User Title (if not default 'string'), 3. Default timestamp
if file_base:
title = f"Canvas-{file_base}"
elif request.title and request.title != "string":
title = request.title
else:
title = f"Canvas {datetime.now().strftime('%Y-%m-%d %H:%M')}"
db_canvas = db_models.Canvas(
title=title,
user_id=current_user.id,
source_id=source_id,
status="processing"
)
db.add(db_canvas)
db.commit()
db.refresh(db_canvas)
# Offload to background task
background_tasks.add_task(run_canvas_generation, db_canvas.id, request, current_user.id)
return db_canvas
@router.get("/", response_model=List[CanvasResponse])
async def list_canvases(
current_user: db_models.User = Depends(get_current_user),
db: Session = Depends(get_db)
):
"""List all canvases for the current user."""
return db.query(db_models.Canvas).filter(db_models.Canvas.user_id == current_user.id).all()
@router.get("/{canvas_id}", response_model=CanvasResponse)
async def get_canvas(
canvas_id: int,
current_user: db_models.User = Depends(get_current_user),
db: Session = Depends(get_db)
):
"""Get a specific canvas by ID."""
canvas = db.query(db_models.Canvas).filter(
db_models.Canvas.id == canvas_id,
db_models.Canvas.user_id == current_user.id
).first()
if not canvas:
raise HTTPException(status_code=404, detail="Canvas not found")
return canvas
@router.put("/{canvas_id}", response_model=CanvasResponse)
async def update_canvas_text(
canvas_id: int,
request: CanvasEditRequest,
current_user: db_models.User = Depends(get_current_user),
db: Session = Depends(get_db)
):
"""
Manually update the text of an existing canvas.
"""
db_canvas = db.query(db_models.Canvas).filter(
db_models.Canvas.id == canvas_id,
db_models.Canvas.user_id == current_user.id
).first()
if not db_canvas:
raise HTTPException(status_code=404, detail="Canvas not found")
try:
db_canvas.text = request.text
db_canvas.status = "completed"
db.commit()
db.refresh(db_canvas)
return db_canvas
except Exception as e:
logger.error(f"Error updating canvas: {e}")
raise HTTPException(status_code=500, detail=str(e))
@router.delete("/{canvas_id}")
async def delete_canvas(
canvas_id: int,
current_user: db_models.User = Depends(get_current_user),
db: Session = Depends(get_db)
):
"""Delete a canvas."""
db_canvas = db.query(db_models.Canvas).filter(
db_models.Canvas.id == canvas_id,
db_models.Canvas.user_id == current_user.id
).first()
if not db_canvas:
raise HTTPException(status_code=404, detail="Canvas not found")
db.delete(db_canvas)
db.commit()
return {"message": "Canvas deleted successfully"}
|