Spaces:
Running
Running
File size: 3,742 Bytes
ff3c2e9 bf0bce6 ff3c2e9 bf0bce6 ff3c2e9 b17c735 ff3c2e9 b17c735 ff3c2e9 b17c735 ff3c2e9 bf0bce6 ff3c2e9 bf0bce6 ff3c2e9 bf0bce6 | 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 | """Problem Desk endpoints. Contract: outreach-frontend/lib/api/problems.ts."""
from __future__ import annotations
from fastapi import APIRouter, Depends, HTTPException, Query, Response, status
from sqlalchemy.orm import Session
from app.api.deps import get_current_user, get_db
from app.crud import notifications as crud_notify
from app.crud import problems as crud
from app.models import User
from app.schemas.problem import (
CreateCommentInput,
CreateProblemInput,
ProblemCommentOut,
ProblemOut,
UpdateProblemInput,
)
router = APIRouter(tags=["problems"])
def _require(db: Session, problem_id: int):
problem = crud.get_problem(db, problem_id)
if problem is None:
raise HTTPException(status_code=404, detail="Problem not found")
return problem
@router.get("/problems", response_model=list[ProblemOut])
def list_problems(
priority: str = Query("all", max_length=60),
status_filter: str = Query("Open", alias="status", max_length=32),
# Today's embedded Priority Tracker card, personalized per person (2026-10-14) -- see
# crud.list_problems_mentioning()'s own docstring. `priority` is ignored on this path (the Today card
# never offers a priority filter, same as it never offered the full page's status tabs either).
mentioned_me: bool = Query(False),
db: Session = Depends(get_db),
user: User | None = Depends(get_current_user),
):
if mentioned_me:
if user is None:
return []
return [
ProblemOut.from_model(p, count)
for p, count in crud.list_problems_mentioning(db, user.id, status_filter)
]
return [
ProblemOut.from_model(p, count) for p, count in crud.list_problems(db, priority, status_filter)
]
@router.post("/problems", response_model=ProblemOut, status_code=status.HTTP_201_CREATED)
def create_problem(
payload: CreateProblemInput,
db: Session = Depends(get_db),
user: User | None = Depends(get_current_user),
):
problem = crud.create_problem(db, payload, user)
crud_notify.notify_mentions(
db, user, payload.mentions, payload.mention_team,
text=f"{payload.title}. {payload.description}".strip(), problem_id=problem.id,
)
return ProblemOut.from_model(problem, 0)
@router.patch("/problems/{problem_id}", response_model=ProblemOut)
def update_problem(problem_id: int, payload: UpdateProblemInput, db: Session = Depends(get_db)):
problem = _require(db, problem_id)
updated = crud.set_status(db, problem, payload.status)
return ProblemOut.from_model(updated, crud.comment_count(db, problem_id))
@router.delete("/problems/{problem_id}", status_code=status.HTTP_204_NO_CONTENT)
def delete_problem(problem_id: int, db: Session = Depends(get_db)):
crud.delete_problem(db, _require(db, problem_id))
return Response(status_code=status.HTTP_204_NO_CONTENT)
@router.get("/problems/{problem_id}/comments", response_model=list[ProblemCommentOut])
def list_comments(problem_id: int, db: Session = Depends(get_db)):
_require(db, problem_id)
return [ProblemCommentOut.from_model(c) for c in crud.list_comments(db, problem_id)]
@router.post(
"/problems/{problem_id}/comments",
response_model=ProblemCommentOut,
status_code=status.HTTP_201_CREATED,
)
def add_comment(
problem_id: int,
payload: CreateCommentInput,
db: Session = Depends(get_db),
user: User | None = Depends(get_current_user),
):
_require(db, problem_id)
comment = crud.add_comment(db, problem_id, payload, user)
crud_notify.notify_mentions(
db, user, payload.mentions, payload.mention_team, text=payload.comment_text, problem_id=problem_id
)
return ProblemCommentOut.from_model(comment)
|