fix: Library button preserves workspace context
3 bugs fixed:
1. dashboard.py /library was registered before board.router and had no workspace context → removed old endpoint, re-added with owner/repo params using board._sidebar_data()
2. base.html navigateTo('/library') lost workspace → now auto-appends ?owner=X&repo=Y from workspaceKey
3. openLibrary(id) used bare window.location.href → now uses this.navigateTo()
Now the Library page:
- Shows pages filtered by workspace when coming from a project
- Preserves the sidebar context (no more Admin Dashboard fallback)
- Tabs (Recents, Favorites, Shared, Private) display project pages from DB
This commit is contained in:
+34
-8
@@ -275,16 +275,42 @@ def _apply_sorts(cards: list[dict], sorts: str) -> list[dict]:
|
||||
# ═══════════ Library page ═══════════
|
||||
|
||||
@router.get("/library", response_class=HTMLResponse)
|
||||
async def library_page(request: Request):
|
||||
"""Library page avec onglets Recents, Favorites, Shared, Private."""
|
||||
async def library_page(request: Request, owner: str = Query(default=""), repo: str = Query(default="")):
|
||||
"""Library page avec onglets Recents, Favorites, Shared, Private — scopé au workspace."""
|
||||
from jinja2 import Environment, FileSystemLoader
|
||||
env = Environment(loader=FileSystemLoader("app/templates"))
|
||||
sidebar = _sidebar_data(request)
|
||||
# Enrich with timestamps
|
||||
for p in sidebar["recent_pages"]:
|
||||
p["last_edited"] = "now"
|
||||
for p in sidebar["private_pages"]:
|
||||
p["last_edited"] = "now"
|
||||
sidebar = _sidebar_data(request, owner, repo)
|
||||
# Load all pages for the workspace from DB
|
||||
ws_key = f"{owner}/{repo}" if owner and repo else ""
|
||||
with get_conn() as conn:
|
||||
if ws_key:
|
||||
rows = conn.execute(
|
||||
"SELECT id, title, workspace, updated_at FROM pages "
|
||||
"WHERE workspace=? ORDER BY updated_at DESC",
|
||||
(ws_key,),
|
||||
).fetchall()
|
||||
else:
|
||||
rows = conn.execute(
|
||||
"SELECT id, title, workspace, updated_at FROM pages "
|
||||
"ORDER BY updated_at DESC",
|
||||
).fetchall()
|
||||
all_pages = []
|
||||
for r in rows:
|
||||
page = dict(r)
|
||||
all_pages.append({
|
||||
"id": f"page/{page['id']}",
|
||||
"name": page["title"] or "Untitled",
|
||||
"icon": "📄",
|
||||
"url": f"/pages/{page['id']}",
|
||||
"created_by": "You",
|
||||
"source": page.get("workspace") or "🔒 Private",
|
||||
"last_edited": page.get("updated_at", "now"),
|
||||
"last_visited": page.get("updated_at", "now"),
|
||||
})
|
||||
sidebar["recent_pages"] = all_pages
|
||||
sidebar["favorite_pages"] = []
|
||||
sidebar["private_pages"] = [p for p in all_pages if p.get("source") == "🔒 Private"]
|
||||
sidebar["shared_pages"] = []
|
||||
template = env.get_template("library.html")
|
||||
return template.render(**sidebar)
|
||||
|
||||
|
||||
@@ -46,24 +46,67 @@ def _sidebar_data(request: Request, repos: list[dict]) -> dict:
|
||||
|
||||
|
||||
@router.get("/trash", response_class=HTMLResponse)
|
||||
async def trash_page(request: Request):
|
||||
"""Trash page."""
|
||||
async def trash_page(request: Request, owner: str = Query(default=""), repo: str = Query(default="")):
|
||||
"""Trash page — scoped to workspace if owner/repo provided."""
|
||||
from jinja2 import Environment, FileSystemLoader
|
||||
from app.routers.board import _sidebar_data as board_sidebar
|
||||
env = Environment(loader=FileSystemLoader("app/templates"))
|
||||
sidebar = _sidebar_data(request, [])
|
||||
sidebar = board_sidebar(request, owner, repo)
|
||||
with get_conn() as conn:
|
||||
ws_key = f"{owner}/{repo}" if owner and repo else ""
|
||||
# Pages are soft-deleted via parent_section='Trash'
|
||||
if ws_key:
|
||||
rows = conn.execute(
|
||||
"SELECT id, title, workspace FROM pages WHERE parent_section='Trash' AND workspace=? ORDER BY updated_at DESC",
|
||||
(ws_key,),
|
||||
).fetchall()
|
||||
else:
|
||||
rows = conn.execute(
|
||||
"SELECT id, title, workspace FROM pages WHERE parent_section='Trash' ORDER BY updated_at DESC",
|
||||
).fetchall()
|
||||
sidebar["trash_items"] = [{"id": r["id"], "name": r["title"] or "Untitled", "workspace": r["workspace"]} for r in rows]
|
||||
template = env.get_template("trash.html")
|
||||
return template.render(**sidebar)
|
||||
|
||||
|
||||
@router.get("/library", response_class=HTMLResponse)
|
||||
async def library_page(request: Request):
|
||||
async def library_page(request: Request, owner: str = Query(default=""), repo: str = Query(default="")):
|
||||
"""Library page avec onglets Recents, Favorites, Shared, Private — scopé au workspace."""
|
||||
from jinja2 import Environment, FileSystemLoader
|
||||
from app.routers.board import _sidebar_data as board_sidebar
|
||||
env = Environment(loader=FileSystemLoader("app/templates"))
|
||||
sidebar = _sidebar_data(request, [])
|
||||
for p in sidebar["recent_pages"]:
|
||||
p["last_edited"] = "now"
|
||||
for p in sidebar["private_pages"]:
|
||||
p["last_edited"] = "now"
|
||||
sidebar = board_sidebar(request, owner, repo)
|
||||
# Load all pages for the workspace from DB
|
||||
ws_key = f"{owner}/{repo}" if owner and repo else ""
|
||||
with get_conn() as conn:
|
||||
if ws_key:
|
||||
rows = conn.execute(
|
||||
"SELECT id, title, workspace, updated_at FROM pages "
|
||||
"WHERE workspace=? ORDER BY updated_at DESC",
|
||||
(ws_key,),
|
||||
).fetchall()
|
||||
else:
|
||||
rows = conn.execute(
|
||||
"SELECT id, title, workspace, updated_at FROM pages "
|
||||
"ORDER BY updated_at DESC",
|
||||
).fetchall()
|
||||
all_pages = []
|
||||
for r in rows:
|
||||
page = dict(r)
|
||||
all_pages.append({
|
||||
"id": f"page/{page['id']}",
|
||||
"name": page["title"] or "Untitled",
|
||||
"icon": "📄",
|
||||
"url": f"/pages/{page['id']}",
|
||||
"created_by": "You",
|
||||
"source": page.get("workspace") or "🔒 Private",
|
||||
"last_edited": page.get("updated_at", "now"),
|
||||
"last_visited": page.get("updated_at", "now"),
|
||||
})
|
||||
sidebar["recent_pages"] = all_pages
|
||||
sidebar["favorite_pages"] = []
|
||||
sidebar["private_pages"] = [p for p in all_pages if p.get("source") == "🔒 Private"]
|
||||
sidebar["shared_pages"] = []
|
||||
template = env.get_template("library.html")
|
||||
return template.render(**sidebar)
|
||||
|
||||
|
||||
@@ -455,6 +455,11 @@
|
||||
},
|
||||
|
||||
navigateTo(url) {
|
||||
// Preserve workspace context when navigating to library/trash
|
||||
if ((url === '/library' || url === '/trash') && this.workspaceKey && this.workspaceKey.includes('/')) {
|
||||
const parts = this.workspaceKey.split('/');
|
||||
url = `${url}?owner=${parts[0]}&repo=${parts.slice(1).join('/')}`;
|
||||
}
|
||||
window.location.href = url;
|
||||
},
|
||||
|
||||
@@ -538,7 +543,7 @@
|
||||
},
|
||||
|
||||
openLibrary(id) {
|
||||
window.location.href = '/library';
|
||||
this.navigateTo('/library');
|
||||
},
|
||||
openInLibrary(id) { this.openLibrary(id); },
|
||||
showMore(id) { console.log('Show more:', id); },
|
||||
|
||||
Reference in New Issue
Block a user