fix: Library preserves sidebar tree and categorizes by parent_section
FlowDeck CI / test (push) Failing after 8s
FlowDeck CI / docker (push) Has been skipped

- Sidebar data (board._sidebar_data()) no longer overwritten by library content
- New variables: lib_recent, lib_favorites, lib_shared, lib_private
- Pages categorized by parent_section column: Private/Favorites/Shared
- Recents tab shows all non-trashed pages ordered by updated_at
- library.html updated to use lib_* variables instead of sidebar data
- Favorites/Shared tabs hidden when empty (lib_has_favorites/lib_has_shared)
This commit is contained in:
2026-07-10 09:31:18 -04:00
parent a251ccfe2d
commit fbf0335c3a
2 changed files with 51 additions and 34 deletions
+38 -28
View File
@@ -71,42 +71,52 @@ async def trash_page(request: Request, owner: str = Query(default=""), repo: str
@router.get("/library", response_class=HTMLResponse)
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."""
"""Library page avec onglets Recents, Favorites, Shared, Private — scopé au workspace.
La sidebar garde exactement la même arborescence que dans le workspace.
Seul le contenu principal change pour afficher les pages triées par catégorie.
"""
from jinja2 import Environment, FileSystemLoader
from app.routers.board import _sidebar_data as board_sidebar
env = Environment(loader=FileSystemLoader("app/templates"))
sidebar = board_sidebar(request, owner, repo)
# Load all pages for the workspace from DB
sidebar = board_sidebar(request, owner, repo) # Sidebar intacte, inchangée
ws_key = f"{owner}/{repo}" if owner and repo else ""
with get_conn() as conn:
base_query = (
"SELECT id, title, workspace, parent_section, updated_at FROM pages "
"WHERE parent_section != 'Trash'"
)
params = []
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",
base_query += " AND workspace=?"
params.append(ws_key)
base_query += " ORDER BY updated_at DESC"
rows = conn.execute(base_query, params).fetchall()
def to_page(r):
r = dict(r)
return {
"id": f"page/{r['id']}",
"name": r["title"] or "Untitled",
"icon": "📄",
"url": f"/pages/{page['id']}",
"url": f"/pages/{r['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"] = []
"source": r.get("workspace") or "🔒 Private",
"last_edited": r.get("updated_at", "now"),
"last_visited": r.get("updated_at", "now"),
}
all_pages = [to_page(r) for r in rows]
# Catégoriser par parent_section — sidebar data intacte
sidebar["lib_recent"] = all_pages
sidebar["lib_favorites"] = [p for p, r in zip(all_pages, rows) if (r["parent_section"] or "") == "Favorites"]
sidebar["lib_shared"] = [p for p, r in zip(all_pages, rows) if (r["parent_section"] or "") == "Shared"]
sidebar["lib_private"] = [p for p, r in zip(all_pages, rows) if (r["parent_section"] or "Private") == "Private"]
sidebar["lib_has_favorites"] = len(sidebar["lib_favorites"]) > 0
sidebar["lib_has_shared"] = len(sidebar["lib_shared"]) > 0
template = env.get_template("library.html")
return template.render(**sidebar)
+13 -6
View File
@@ -15,12 +15,16 @@
<button class="view-tab" :class="{ active: tab === 'recents' }" @click="tab = 'recents'">
<span class="tab-icon">🕒</span> Recents
</button>
{% if lib_has_favorites %}
<button class="view-tab" :class="{ active: tab === 'favorites' }" @click="tab = 'favorites'">
<span class="tab-icon">⭐</span> Favorites
</button>
{% endif %}
{% if lib_has_shared %}
<button class="view-tab" :class="{ active: tab === 'shared' }" @click="tab = 'shared'">
<span class="tab-icon">👥</span> Shared
</button>
{% endif %}
<button class="view-tab" :class="{ active: tab === 'private' }" @click="tab = 'private'">
<span class="tab-icon">🔒</span> Private
</button>
@@ -61,8 +65,8 @@
<!-- Recents -->
<div x-show="tab === 'recents'">
{% for page in recent_pages %}{{ page_row(page) }}{% endfor %}
{% if not recent_pages %}
{% for page in lib_recent %}{{ page_row(page) }}{% endfor %}
{% if not lib_recent %}
<div class="lib-empty">
<div style="font-size:48px;margin-bottom:16px;">🕒</div>
<h3>No recent pages</h3>
@@ -72,8 +76,8 @@
<!-- Favorites -->
<div x-show="tab === 'favorites'">
{% for page in favorite_pages %}{{ page_row(page) }}{% endfor %}
{% if not favorite_pages %}
{% for page in lib_favorites %}{{ page_row(page) }}{% endfor %}
{% if not lib_favorites %}
<div class="lib-empty">
<div style="font-size:48px;margin-bottom:16px;">⭐</div>
<h3>No favorites</h3>
@@ -84,17 +88,20 @@
<!-- Shared -->
<div x-show="tab === 'shared'">
{% for page in lib_shared %}{{ page_row(page) }}{% endfor %}
{% if not lib_shared %}
<div class="lib-empty">
<div style="font-size:48px;margin-bottom:16px;">👥</div>
<h3>No shared pages</h3>
<p>Shared pages from your team will appear here.</p>
</div>
{% endif %}
</div>
<!-- Private -->
<div x-show="tab === 'private'">
{% for page in private_pages %}{{ page_row(page) }}{% endfor %}
{% if not private_pages %}
{% for page in lib_private %}{{ page_row(page) }}{% endfor %}
{% if not lib_private %}
<div class="lib-empty">
<div style="font-size:48px;margin-bottom:16px;">🔒</div>
<h3>No private pages</h3>