Global labels: remove project_id, endpoints at /labels
Some checks failed
Deploy Tracker / deploy (push) Failing after 3s
Some checks failed
Deploy Tracker / deploy (push) Failing after 3s
Labels are now app-wide, not project-scoped.
GET/POST /labels, PATCH/DELETE /labels/{id}
This commit is contained in:
parent
1f57f869ba
commit
009789ad8b
@ -1,4 +1,4 @@
|
|||||||
"""Labels API — CRUD for project-scoped labels."""
|
"""Labels API — CRUD for global labels."""
|
||||||
|
|
||||||
import uuid
|
import uuid
|
||||||
|
|
||||||
@ -26,31 +26,27 @@ class LabelUpdate(BaseModel):
|
|||||||
|
|
||||||
class LabelOut(BaseModel):
|
class LabelOut(BaseModel):
|
||||||
id: str
|
id: str
|
||||||
project_id: str
|
|
||||||
name: str
|
name: str
|
||||||
color: str
|
color: str
|
||||||
|
|
||||||
|
|
||||||
@router.get("/projects/{project_id}/labels", response_model=list[LabelOut])
|
@router.get("/labels", response_model=list[LabelOut])
|
||||||
async def list_labels(project_id: str, db: AsyncSession = Depends(get_db)):
|
async def list_labels(db: AsyncSession = Depends(get_db)):
|
||||||
result = await db.execute(
|
result = await db.execute(select(Label).order_by(Label.name))
|
||||||
select(Label).where(Label.project_id == uuid.UUID(project_id)).order_by(Label.name)
|
return [LabelOut(id=str(l.id), name=l.name, color=l.color) for l in result.scalars()]
|
||||||
)
|
|
||||||
return [LabelOut(id=str(l.id), project_id=str(l.project_id), name=l.name, color=l.color) for l in result.scalars()]
|
|
||||||
|
|
||||||
|
|
||||||
@router.post("/projects/{project_id}/labels", response_model=LabelOut)
|
@router.post("/labels", response_model=LabelOut)
|
||||||
async def create_label(
|
async def create_label(
|
||||||
project_id: str,
|
|
||||||
req: LabelCreate,
|
req: LabelCreate,
|
||||||
current_member: Member = Depends(get_current_member),
|
current_member: Member = Depends(get_current_member),
|
||||||
db: AsyncSession = Depends(get_db),
|
db: AsyncSession = Depends(get_db),
|
||||||
):
|
):
|
||||||
label = Label(project_id=uuid.UUID(project_id), name=req.name, color=req.color)
|
label = Label(name=req.name, color=req.color)
|
||||||
db.add(label)
|
db.add(label)
|
||||||
await db.commit()
|
await db.commit()
|
||||||
await db.refresh(label)
|
await db.refresh(label)
|
||||||
return LabelOut(id=str(label.id), project_id=str(label.project_id), name=label.name, color=label.color)
|
return LabelOut(id=str(label.id), name=label.name, color=label.color)
|
||||||
|
|
||||||
|
|
||||||
@router.patch("/labels/{label_id}", response_model=LabelOut)
|
@router.patch("/labels/{label_id}", response_model=LabelOut)
|
||||||
@ -70,7 +66,7 @@ async def update_label(
|
|||||||
label.color = req.color
|
label.color = req.color
|
||||||
await db.commit()
|
await db.commit()
|
||||||
await db.refresh(label)
|
await db.refresh(label)
|
||||||
return LabelOut(id=str(label.id), project_id=str(label.project_id), name=label.name, color=label.color)
|
return LabelOut(id=str(label.id), name=label.name, color=label.color)
|
||||||
|
|
||||||
|
|
||||||
@router.delete("/labels/{label_id}")
|
@router.delete("/labels/{label_id}")
|
||||||
@ -83,8 +79,6 @@ async def delete_label(
|
|||||||
label = result.scalar_one_or_none()
|
label = result.scalar_one_or_none()
|
||||||
if not label:
|
if not label:
|
||||||
raise HTTPException(404, "Label not found")
|
raise HTTPException(404, "Label not found")
|
||||||
# Remove task associations
|
|
||||||
await db.execute(select(TaskLabel).where(TaskLabel.label_id == label.id))
|
|
||||||
await db.delete(label)
|
await db.delete(label)
|
||||||
await db.commit()
|
await db.commit()
|
||||||
return {"ok": True}
|
return {"ok": True}
|
||||||
|
|||||||
@ -54,15 +54,12 @@ class Step(Base):
|
|||||||
|
|
||||||
|
|
||||||
class Label(Base):
|
class Label(Base):
|
||||||
"""Project-scoped labels (like Jira)."""
|
"""Global labels (app-wide)."""
|
||||||
__tablename__ = "labels"
|
__tablename__ = "labels"
|
||||||
|
|
||||||
project_id: Mapped[uuid.UUID] = mapped_column(UUID(as_uuid=True), ForeignKey("projects.id"), nullable=False)
|
name: Mapped[str] = mapped_column(String(100), unique=True, nullable=False)
|
||||||
name: Mapped[str] = mapped_column(String(100), nullable=False)
|
|
||||||
color: Mapped[str] = mapped_column(String(7), default="#6366f1") # hex color
|
color: Mapped[str] = mapped_column(String(7), default="#6366f1") # hex color
|
||||||
|
|
||||||
project: Mapped["Project"] = relationship()
|
|
||||||
|
|
||||||
|
|
||||||
class TaskLabel(Base):
|
class TaskLabel(Base):
|
||||||
"""Many-to-many: tasks ↔ labels."""
|
"""Many-to-many: tasks ↔ labels."""
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user