feat: sous-pages — parent_id, sidebar hiérarchique, bouton +New sub-page
- DB: parent_id dans table pages (ALTER TABLE migration auto) - Sidebar: pages parent_id IS NULL affichées, sous-pages indentées en dessous - API: create_page accepte parent_id (0 = racine) - JS: newSubPage extrait page ID et passe parent_id - page_editor: liste les sous-pages + bouton '+ New sub-page'
This commit is contained in:
+17
-6
@@ -139,7 +139,7 @@ def _sidebar_data(request: Request, owner: str = "", repo: str = "") -> dict:
|
||||
# Load pages for this project workspace
|
||||
with get_conn() as conn:
|
||||
pages = conn.execute(
|
||||
"SELECT id, title, updated_at FROM pages WHERE workspace=? ORDER BY updated_at DESC LIMIT 10",
|
||||
"SELECT id, title, parent_id, updated_at FROM pages WHERE workspace=? AND parent_id IS NULL ORDER BY updated_at DESC LIMIT 10",
|
||||
(ws_key,),
|
||||
).fetchall()
|
||||
for p in pages:
|
||||
@@ -147,6 +147,16 @@ def _sidebar_data(request: Request, owner: str = "", repo: str = "") -> dict:
|
||||
"id": f"page/{p['id']}", "name": p["title"], "icon": "📄",
|
||||
"url": f"/pages/{p['id']}", "active": False, "indent": 0,
|
||||
})
|
||||
# Load sub-pages
|
||||
subs = conn.execute(
|
||||
"SELECT id, title FROM pages WHERE parent_id=? ORDER BY updated_at DESC",
|
||||
(p["id"],),
|
||||
).fetchall()
|
||||
for sp in subs:
|
||||
recent.append({
|
||||
"id": f"page/{sp['id']}", "name": sp["title"], "icon": "·",
|
||||
"url": f"/pages/{sp['id']}", "active": False, "indent": 1,
|
||||
})
|
||||
return {"workspace_name": ws_name, "workspace_initial": ws_name[0].upper() if ws_name else "B",
|
||||
"current_page": repo or "Dashboard", "last_edited": "now",
|
||||
"recent_pages": recent, "private_pages": [r for r in recent if r.get("active") or r["id"].startswith("page/")],
|
||||
@@ -439,18 +449,19 @@ async def extract_ai_keywords(owner: str, repo: str):
|
||||
@router.post("/api/pages")
|
||||
async def create_page(request: Request, title: str = Query(default="New page"),
|
||||
section: str = Query(default="Private"),
|
||||
project: str = Query(default="")):
|
||||
"""Create a new Markdown page in the given project workspace."""
|
||||
project: str = Query(default=""),
|
||||
parent_id: int = Query(default=0)):
|
||||
"""Create a new Markdown page, optionally as a sub-page."""
|
||||
user = SessionManager.decode_session(request.cookies.get("flowdeck_session", ""))
|
||||
ws_key = project if project else (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_key, title, section),
|
||||
"INSERT INTO pages (workspace, title, parent_section, parent_id) VALUES (?,?,?,?)",
|
||||
(ws_key, title, section, parent_id if parent_id > 0 else None),
|
||||
)
|
||||
conn.commit()
|
||||
page_id = cur.lastrowid
|
||||
return {"status": "ok", "id": page_id, "title": title, "workspace": ws_key}
|
||||
return {"status": "ok", "id": page_id, "title": title, "workspace": ws_key, "parent_id": parent_id}
|
||||
|
||||
|
||||
@router.get("/api/pages/{page_id}")
|
||||
|
||||
@@ -71,7 +71,13 @@ async def view_page_root(request: Request, page_id: int):
|
||||
parts = ws.split("/") if "/" in ws else ["", ""]
|
||||
owner, repo = parts[0], parts[1] if len(parts) > 1 else ""
|
||||
sidebar = board_sidebar(request, owner, repo)
|
||||
ctx = {**sidebar, "page": page}
|
||||
# Load sub-pages
|
||||
with get_conn() as conn:
|
||||
subs = conn.execute(
|
||||
"SELECT id, title FROM pages WHERE parent_id=? ORDER BY updated_at DESC",
|
||||
(page_id,),
|
||||
).fetchall()
|
||||
ctx = {**sidebar, "page": page, "sub_pages": [dict(s) for s in subs]}
|
||||
template = env.get_template("page_editor.html")
|
||||
return template.render(**ctx)
|
||||
|
||||
|
||||
Reference in New Issue
Block a user