"""FlowDeck — Board : wiki. Découpe A28 de l'ancien app/routers/board.py (2 101 lignes, 53 routes) — un module par concern, contrat inchangé. """ from __future__ import annotations import logging from fastapi import APIRouter, Query, Request from app.db import get_conn logger = logging.getLogger(__name__) router = APIRouter(tags=["board"], prefix="/board") @router.get("/api/wiki/pages") def wiki_page_search(request: Request, q: str = Query(default="")): """v5.11.0: page picker for [[ wiki-links. Fuzzy-ish title search across every non-deleted page the current user can see (single source: pages).""" q = (q or "").strip().lower() with get_conn() as conn: rows = conn.execute( """SELECT id, title, page_icon, workspace FROM pages WHERE deleted_at IS NULL ORDER BY updated_at DESC LIMIT 500""" ).fetchall() results = [] for r in rows: title = r["title"] or "Untitled" if q: # subsequence match ("mtg" → "Meeting notes") or plain substring. hay = title.lower() it = iter(hay) subseq = all(ch in it for ch in q) if q not in hay and not subseq: continue results.append({ "id": r["id"], "title": title, "icon": r["page_icon"] or "", "workspace": r["workspace"] or "", }) if len(results) >= 20: break return {"pages": results} @router.get("/api/wiki/titles") def wiki_titles(request: Request, ids: str = Query(default="")): """v5.11.0: resolve page-id lists to current labels (rename propagation).""" parsed: list[int] = [] for part in (ids or "").split(","): part = part.strip() if part.isdigit(): parsed.append(int(part)) parsed = parsed[:200] out: dict[str, str] = {} if parsed: placeholders = ",".join("?" * len(parsed)) with get_conn() as conn: rows = conn.execute( f"SELECT id, title, page_icon, deleted_at FROM pages WHERE id IN ({placeholders})", parsed, ).fetchall() for r in rows: if r["deleted_at"]: out[str(r["id"])] = "Deleted page" else: icon = (r["page_icon"] or "") out[str(r["id"])] = (icon + " " if icon else "") + (r["title"] or "Untitled") return {"titles": out}