diff --git a/app/db.py b/app/db.py index 4aec95a..484350d 100644 --- a/app/db.py +++ b/app/db.py @@ -130,6 +130,16 @@ def init_db(): created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP, UNIQUE(project_owner, project_name, keyword) ); + + CREATE TABLE IF NOT EXISTS pages ( + id INTEGER PRIMARY KEY AUTOINCREMENT, + workspace TEXT NOT NULL, + title TEXT NOT NULL DEFAULT 'New page', + content TEXT NOT NULL DEFAULT '', + parent_section TEXT DEFAULT 'Private', + created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP, + updated_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP + ); """) conn.commit() diff --git a/app/routers/board.py b/app/routers/board.py index 3240363..5b6d66b 100644 --- a/app/routers/board.py +++ b/app/routers/board.py @@ -115,18 +115,34 @@ def _map_issue_to_card(issue: dict, owner: str = "", repo: str = "") -> dict: } -def _sidebar_data(request: Request, owner: str, repo: str) -> dict: +def _sidebar_data(request: Request, owner: str = "", repo: str = "") -> dict: user = SessionManager.decode_session(request.cookies.get("flowdeck_session", "")) ws = user.get("login", "Bruno") if user else "Bruno" - recent = [{"id": f"{owner}/{repo}", "name": repo, "icon": "๐", - "url": f"/board/{owner}/{repo}", "active": True, "indent": 0}] - for sv in ["Detailed board", "Table view", "Status overview", "Team Load"]: - recent.append({"id": f"{owner}/{repo}/{sv.lower().replace(' ', '-')}", - "name": sv, "icon": "ยท", "url": f"/board/{owner}/{repo}", - "active": False, "indent": 1}) + recent = [] + if owner and repo: + recent = [ + {"id": f"{owner}/{repo}", "name": "Kanban board", "icon": "๐", + "url": f"/board/{owner}/{repo}", "active": True, "indent": 0}, + ] + for sv in ["Detailed board", "Table view", "Status overview", "Team Load"]: + recent.append({"id": f"{owner}/{repo}/{sv.lower().replace(' ', '-')}", + "name": sv, "icon": "ยท", "url": f"/board/{owner}/{repo}", + "active": False, "indent": 1}) + # Load user-created pages from DB + with get_conn() as conn: + pages = conn.execute( + "SELECT id, title, updated_at FROM pages WHERE workspace=? ORDER BY updated_at DESC LIMIT 10", + (ws,), + ).fetchall() + for p in pages: + recent.append({ + "id": f"page/{p['id']}", "name": p["title"], "icon": "๐", + "url": f"/pages/{p['id']}", "active": False, "indent": 0, + }) return {"workspace_name": ws, "workspace_initial": ws[0].upper() if ws else "B", - "current_page": repo, "last_edited": "2m ago", - "recent_pages": recent, "private_pages": recent[:1], "user": user} + "current_page": repo or "Dashboard", "last_edited": "now", + "recent_pages": recent, "private_pages": [r for r in recent if r.get("active")], + "user": user} def _extract_ai_keywords(owner: str, repo: str, labels: list[dict], body: str = ""): @@ -391,7 +407,60 @@ async def extract_ai_keywords(owner: str, repo: str): return {"status": "ok", "issues_scanned": len(issues)} -# โโโโโโโโโโโ v0.9.0: Sync endpoint โโโโโโโโโโโ +# โโโโโโโโโโโ Pages Markdown โโโโโโโโโโโ + +@router.post("/api/pages") +async def create_page(request: Request, title: str = Query(default="New page"), + section: str = Query(default="Private")): + """Create a new Markdown page.""" + user = SessionManager.decode_session(request.cookies.get("flowdeck_session", "")) + ws = user.get("login", "Bruno") if user else "Bruno" + with get_conn() as conn: + cur = conn.execute( + "INSERT INTO pages (workspace, title, parent_section) VALUES (?,?,?)", + (ws, title, section), + ) + conn.commit() + page_id = cur.lastrowid + return {"status": "ok", "id": page_id, "title": title} + + +@router.get("/api/pages/{page_id}") +async def get_page(page_id: int): + """Get a Markdown page.""" + with get_conn() as conn: + row = conn.execute("SELECT * FROM pages WHERE id=?", (page_id,)).fetchone() + if not row: + raise HTTPException(404, "Page not found") + return dict(row) + + +@router.put("/api/pages/{page_id}") +async def update_page(page_id: int, title: str = Query(default=""), + content: str = Query(default="")): + """Update a page's title and/or content.""" + with get_conn() as conn: + if title: + conn.execute("UPDATE pages SET title=?, updated_at=CURRENT_TIMESTAMP WHERE id=?", (title, page_id)) + if content: + conn.execute("UPDATE pages SET content=?, updated_at=CURRENT_TIMESTAMP WHERE id=?", (content, page_id)) + conn.commit() + return {"status": "ok"} + + +@router.get("/pages/{page_id}", response_class=HTMLResponse) +async def view_page(request: Request, page_id: int): + """Render a page as HTML.""" + from jinja2 import Environment, FileSystemLoader + env = Environment(loader=FileSystemLoader("app/templates")) + with get_conn() as conn: + row = conn.execute("SELECT * FROM pages WHERE id=?", (page_id,)).fetchone() + if not row: + return HTMLResponse("