agentic.email/backend/app/routers/sticky_notes.py
2026-10-03 21:14:44 +05:30

109 lines
3.9 KiB
Python

from bson import ObjectId
from fastapi import APIRouter, Depends, HTTPException, status
from pymongo import ReturnDocument
from app.database import get_mongo_database
from app.models import Account
from app.routers.auth import get_current_account
from app.schemas import StickyNoteCreate, StickyNoteRead, StickyNoteUpdate, utc_now
router = APIRouter(prefix="/sticky-notes", tags=["sticky-notes"])
def serialize_note(document: dict) -> StickyNoteRead:
return StickyNoteRead(
id=str(document["_id"]),
title=document["title"],
body=document.get("body", ""),
tags=document.get("tags", []),
color=document.get("color", "yellow"),
created_at=document["created_at"],
updated_at=document["updated_at"],
)
@router.get("", response_model=list[StickyNoteRead])
async def list_sticky_notes(
database=Depends(get_mongo_database),
account: Account = Depends(get_current_account),
):
cursor = database.sticky_notes.find({"account_id": str(account.id)}).sort(
"updated_at", -1
)
return [serialize_note(document) async for document in cursor]
@router.post("", response_model=StickyNoteRead, status_code=status.HTTP_201_CREATED)
async def create_sticky_note(
payload: StickyNoteCreate,
database=Depends(get_mongo_database),
account: Account = Depends(get_current_account),
):
now = utc_now()
document = {
"account_id": str(account.id),
"title": payload.title.strip(),
"body": payload.body.strip(),
"tags": [tag.strip() for tag in payload.tags if tag.strip()],
"color": payload.color,
"created_at": now,
"updated_at": now,
}
result = await database.sticky_notes.insert_one(document)
document["_id"] = result.inserted_id
return serialize_note(document)
@router.patch("/{note_id}", response_model=StickyNoteRead)
async def update_sticky_note(
note_id: str,
payload: StickyNoteUpdate,
database=Depends(get_mongo_database),
account: Account = Depends(get_current_account),
):
if not ObjectId.is_valid(note_id):
raise HTTPException(
status_code=status.HTTP_422_UNPROCESSABLE_ENTITY,
detail="Invalid note ID.",
)
updates = payload.model_dump(exclude_unset=True)
if "title" in updates:
updates["title"] = updates["title"].strip()
if "body" in updates:
updates["body"] = updates["body"].strip()
if "tags" in updates and updates["tags"] is not None:
updates["tags"] = [tag.strip() for tag in updates["tags"] if tag.strip()]
if not updates:
document = await database.sticky_notes.find_one(
{"_id": ObjectId(note_id), "account_id": str(account.id)}
)
if document is None:
raise HTTPException(status_code=status.HTTP_404_NOT_FOUND, detail="Note not found.")
return serialize_note(document)
updates["updated_at"] = utc_now()
document = await database.sticky_notes.find_one_and_update(
{"_id": ObjectId(note_id), "account_id": str(account.id)},
{"$set": updates},
return_document=ReturnDocument.AFTER,
)
if document is None:
raise HTTPException(status_code=status.HTTP_404_NOT_FOUND, detail="Note not found.")
return serialize_note(document)
@router.delete("/{note_id}", status_code=status.HTTP_204_NO_CONTENT)
async def delete_sticky_note(
note_id: str,
database=Depends(get_mongo_database),
account: Account = Depends(get_current_account),
):
if not ObjectId.is_valid(note_id):
raise HTTPException(
status_code=status.HTTP_422_UNPROCESSABLE_ENTITY,
detail="Invalid note ID.",
)
result = await database.sticky_notes.delete_one(
{"_id": ObjectId(note_id), "account_id": str(account.id)}
)
if result.deleted_count == 0:
raise HTTPException(status_code=status.HTTP_404_NOT_FOUND, detail="Note not found.")