Candidates: inline rename (fix a name typo without reject + re-add)

A staged candidate could only be renamed by rejecting and re-adding it, which
churns the queue and discards the preview just to fix a typo. Add an inline
Rename on each candidate: a "Rename" pill swaps the name for an input
(Enter saves · Esc cancels), POST /api/admin/candidates/{id}/rename →
sources.rename_candidate(). Empty clears the name (promote then derives one
from the feed host). Preview is preserved; the fixed name carries into promotion.

Tests: test_candidate_rename (rename in place keeps preview, promotes with the
new name, gated + 404). 225 pytest + 11 vitest green.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
jay
2026-06-11 21:39:13 -04:00
parent 3afc1ed37e
commit 070b40584e
4 changed files with 68 additions and 3 deletions
+14
View File
@@ -444,6 +444,10 @@ class CandidatePromoteBody(BaseModel):
poll_interval_minutes: int = 180
class CandidateRenameBody(BaseModel):
name: str = ""
class DigestBody(BaseModel):
enabled: bool = True
@@ -1197,6 +1201,16 @@ def create_app() -> FastAPI:
row = sources.save_candidate(conn, url, preview=preview)
return _candidate_dict(row)
@app.post("/api/admin/candidates/{cid}/rename")
def admin_candidate_rename(cid: int, body: CandidateRenameBody, request: Request) -> dict:
with get_conn() as conn:
_require_admin(conn, request)
try:
row = sources.rename_candidate(conn, cid, (body.name or "").strip() or None)
except ValueError:
raise HTTPException(status_code=404, detail="candidate not found")
return _candidate_dict(row)
@app.post("/api/admin/candidates/{cid}/promote")
def admin_candidate_promote(cid: int, body: CandidatePromoteBody, request: Request) -> dict:
with get_conn() as conn: