fix: Library page — hover effects, workspace filter, tree, rename
FlowDeck CI / test (push) Failing after 5s
FlowDeck CI / docker (push) Has been skipped

1. Hover effects fixed: converted table to div-based flexbox layout
   (tr/td don't support display:flex). .lib-row now properly shows
   drag handle, checkbox, and OPEN button on hover.

2. Recents filter by workspace: /api/library/recents now accepts
   workspace_id parameter. Template passes active_workspace_id from
   sidebar context to API calls.

3. Tree hierarchy: API now enriches items with has_children via
   _enrich_children() batch query — shows expand chevrons for
   pages with sub-pages.

4. Rename on click: single click on title starts inline rename
   (was opening page). OPEN button still opens side peek.

5. Code cleanup: extracted _enrich_children() helper to eliminate
   duplicate code across 6 endpoints.
This commit is contained in:
2026-07-18 11:10:55 -04:00
parent 28a41a30da
commit 6a2d56a7bd
3 changed files with 93 additions and 54 deletions
+1
View File
@@ -220,6 +220,7 @@ async def library_page(request: Request, owner: str = Query(default=""), repo: s
sidebar["nav_workspace_id"] = ws["id"] if ws else 0
template = env.get_template("library.html")
sidebar["active_workspace_id"] = sidebar.get("nav_workspace_id", 0)
return template.render(**sidebar)
+32
View File
@@ -100,6 +100,25 @@ def _rows_to_items(rows, uid: int = 1) -> list:
return [_build_item(dict(r), uid) for r in rows]
def _enrich_children(items: list) -> list:
"""Add has_children info to items in a single batch query."""
if not items:
return items
ids = [it["id"] for it in items]
placeholders = ",".join(["?" for _ in ids])
with get_conn() as conn:
child_rows = conn.execute(
f"SELECT parent_id, COUNT(*) as cnt FROM pages "
f"WHERE parent_id IN ({placeholders}) AND deleted_at IS NULL "
f"GROUP BY parent_id",
ids,
).fetchall()
child_counts = {r["parent_id"]: r["cnt"] for r in child_rows}
for it in items:
it["has_children"] = bool(child_counts.get(it["id"], 0))
return items
# ═══════════ Tab endpoints ═══════════
BASE_SELECT = (
@@ -113,6 +132,7 @@ async def library_recents(
request: Request,
source_type: str = Query(default="all"),
tree: int = Query(default=0),
workspace_id: int = Query(default=0),
):
if source_type not in SOURCE_TYPES:
source_type = "all"
@@ -120,6 +140,12 @@ async def library_recents(
uid = _get_user_id(request)
query = f"{BASE_SELECT} FROM pages p WHERE p.parent_section != 'Trash' AND p.deleted_at IS NULL"
params: list = []
# Filter by active workspace
if workspace_id:
query += " AND p.workspace_id = ?"
params.append(workspace_id)
query, params = _apply_source_filter(query, params, source_type)
query += " ORDER BY p.updated_at DESC LIMIT 50"
@@ -127,6 +153,7 @@ async def library_recents(
rows = conn.execute(query, params).fetchall()
items = _rows_to_items(rows, uid)
_enrich_children(items)
return {"items": items}
@@ -154,6 +181,7 @@ async def library_favorites(
rows = conn.execute(query, params).fetchall()
items = _rows_to_items(rows, uid)
_enrich_children(items)
return {"items": items}
@@ -176,6 +204,7 @@ async def library_shared(
rows = conn.execute(query, params).fetchall()
items = _rows_to_items(rows, uid)
_enrich_children(items)
return {"items": items}
@@ -198,6 +227,7 @@ async def library_published(
rows = conn.execute(query, params).fetchall()
items = _rows_to_items(rows, uid)
_enrich_children(items)
return {"items": items}
@@ -220,6 +250,7 @@ async def library_private(
rows = conn.execute(query, params).fetchall()
items = _rows_to_items(rows, uid)
_enrich_children(items)
return {"items": items}
@@ -242,4 +273,5 @@ async def library_workspace(
rows = conn.execute(query, params).fetchall()
items = _rows_to_items(rows, uid)
_enrich_children(items)
return {"items": items}