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 ═══════════
|
# ═══════════ Library page ═══════════
|
||||||
|
|
||||||
@router.get("/library", response_class=HTMLResponse)
|
@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."""
|
"""Library page avec onglets Recents, Favorites, Shared, Private — scopé au workspace."""
|
||||||
from jinja2 import Environment, FileSystemLoader
|
from jinja2 import Environment, FileSystemLoader
|
||||||
env = Environment(loader=FileSystemLoader("app/templates"))
|
env = Environment(loader=FileSystemLoader("app/templates"))
|
||||||
sidebar = _sidebar_data(request)
|
sidebar = _sidebar_data(request, owner, repo)
|
||||||
# Enrich with timestamps
|
# Load all pages for the workspace from DB
|
||||||
for p in sidebar["recent_pages"]:
|
ws_key = f"{owner}/{repo}" if owner and repo else ""
|
||||||
p["last_edited"] = "now"
|
with get_conn() as conn:
|
||||||
for p in sidebar["private_pages"]:
|
if ws_key:
|
||||||
p["last_edited"] = "now"
|
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")
|
template = env.get_template("library.html")
|
||||||
return template.render(**sidebar)
|
return template.render(**sidebar)
|
||||||
|
|
||||||
|
|||||||
@@ -46,24 +46,67 @@ def _sidebar_data(request: Request, repos: list[dict]) -> dict:
|
|||||||
|
|
||||||
|
|
||||||
@router.get("/trash", response_class=HTMLResponse)
|
@router.get("/trash", response_class=HTMLResponse)
|
||||||
async def trash_page(request: Request):
|
async def trash_page(request: Request, owner: str = Query(default=""), repo: str = Query(default="")):
|
||||||
"""Trash page."""
|
"""Trash page — scoped to workspace if owner/repo provided."""
|
||||||
from jinja2 import Environment, FileSystemLoader
|
from jinja2 import Environment, FileSystemLoader
|
||||||
|
from app.routers.board import _sidebar_data as board_sidebar
|
||||||
env = Environment(loader=FileSystemLoader("app/templates"))
|
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")
|
template = env.get_template("trash.html")
|
||||||
return template.render(**sidebar)
|
return template.render(**sidebar)
|
||||||
|
|
||||||
|
|
||||||
@router.get("/library", response_class=HTMLResponse)
|
@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 jinja2 import Environment, FileSystemLoader
|
||||||
|
from app.routers.board import _sidebar_data as board_sidebar
|
||||||
env = Environment(loader=FileSystemLoader("app/templates"))
|
env = Environment(loader=FileSystemLoader("app/templates"))
|
||||||
sidebar = _sidebar_data(request, [])
|
sidebar = board_sidebar(request, owner, repo)
|
||||||
for p in sidebar["recent_pages"]:
|
# Load all pages for the workspace from DB
|
||||||
p["last_edited"] = "now"
|
ws_key = f"{owner}/{repo}" if owner and repo else ""
|
||||||
for p in sidebar["private_pages"]:
|
with get_conn() as conn:
|
||||||
p["last_edited"] = "now"
|
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")
|
template = env.get_template("library.html")
|
||||||
return template.render(**sidebar)
|
return template.render(**sidebar)
|
||||||
|
|
||||||
|
|||||||
@@ -455,6 +455,11 @@
|
|||||||
},
|
},
|
||||||
|
|
||||||
navigateTo(url) {
|
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;
|
window.location.href = url;
|
||||||
},
|
},
|
||||||
|
|
||||||
@@ -538,7 +543,7 @@
|
|||||||
},
|
},
|
||||||
|
|
||||||
openLibrary(id) {
|
openLibrary(id) {
|
||||||
window.location.href = '/library';
|
this.navigateTo('/library');
|
||||||
},
|
},
|
||||||
openInLibrary(id) { this.openLibrary(id); },
|
openInLibrary(id) { this.openLibrary(id); },
|
||||||
showMore(id) { console.log('Show more:', id); },
|
showMore(id) { console.log('Show more:', id); },
|
||||||
|
|||||||
Reference in New Issue
Block a user