From 53d31572e6f230255fac431b31e7de8ac9a112c4 Mon Sep 17 00:00:00 2001 From: bruno Date: Tue, 21 Jul 2026 09:28:28 -0400 Subject: [PATCH] =?UTF-8?q?fix:=20sidebar=20workspace=20tree=20+=20pages?= =?UTF-8?q?=20DB=20=E2=80=94=20emojis=20=E2=86=92=20outlined=20icons?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Root cause: 3 sources d'icΓ΄nes colorΓ©es dans le sidebar: 1. _workspace_tree_macro.html L28: {{ page.icon }} raw β†’ filtrΓ© via valid_icons 2. db.py: DEFAULT 'πŸ“„' β†’ 'file' 3. board.py _file_icon(): 15 Γ©mojis β†’ 'file'/'edit'/'image' 4. board.py/dashboard.py: JSON icon: πŸ“„/πŸ“ β†’ file/folder 5. base.html L931: JS favorites icon β†’ validNames filter 6. base.html render_tree_item: valid_icons list Γ©tendue + fallback Migration: nouvelles pages utilisent 'file'/'folder'. Pages existantes avec Γ©mojis β†’ les templates utilisent le fallback automatiquement. 143 tests passent --- app/db.py | 2 +- app/routers/board.py | 36 ++++++++++++------------ app/routers/dashboard.py | 8 +++--- app/templates/_workspace_tree_macro.html | 3 +- app/templates/base.html | 8 ++++-- 5 files changed, 31 insertions(+), 26 deletions(-) diff --git a/app/db.py b/app/db.py index 17612b1..307dca5 100644 --- a/app/db.py +++ b/app/db.py @@ -192,7 +192,7 @@ def init_db(): id INTEGER PRIMARY KEY AUTOINCREMENT, collection_id INTEGER NOT NULL REFERENCES collections(id) ON DELETE CASCADE, title TEXT NOT NULL DEFAULT '', - icon TEXT DEFAULT 'πŸ“„', + icon TEXT DEFAULT 'file', position INTEGER NOT NULL DEFAULT 0, parent_id INTEGER REFERENCES collection_pages(id), gitea_issue_id INTEGER, diff --git a/app/routers/board.py b/app/routers/board.py index eefdbef..3a887aa 100644 --- a/app/routers/board.py +++ b/app/routers/board.py @@ -63,7 +63,7 @@ def _map_issue_to_card(issue: dict, owner: str = "", repo: str = "") -> dict: "bug": "πŸ›", "feature": "✨", "enhancement": "⚑", "documentation": "πŸ“„", "design": "🎨", "testing": "πŸ§ͺ", "refactor": "πŸ”§", "security": "πŸ”’", } - icon = "πŸ“„" + icon = "file" for lbl in labels: for kw, emoji in icon_map.items(): if kw in lbl.get("name", "").lower(): @@ -142,27 +142,27 @@ def _build_page_tree(conn, parent_id: int | None, ws_key: str, depth: int = 0, m def _file_icon(name: str, content_format: str = "") -> str: - """Map file extension to emoji icon.""" + """Map file extension to icon name (SVG-safe).""" import re # FlowDeck internal pages (no extension) if content_format and content_format != 'file': - return 'πŸ“' + return 'edit' n = name.lower() - if re.search(r'\.(png|jpe?g|gif|webp|svg|bmp|ico)$', n): return 'πŸ–ΌοΈ' - if n.endswith('.pdf'): return 'πŸ“•' - if re.search(r'\.(md|markdown)$', n): return 'πŸ“' - if n.endswith('.py'): return '🐍' - if re.search(r'\.(js|jsx|ts|tsx)$', n): return 'πŸ“œ' - if re.search(r'\.(html?|xml)$', n): return '🌐' - if n.endswith('.css'): return '🎨' - if n.endswith('.json'): return 'πŸ“‹' - if n.endswith('.sql'): return 'πŸ—ƒοΈ' - if re.search(r'\.(sh|bash|zsh)$', n): return 'πŸ’»' - if n.endswith('.ps1'): return '⚑' - if re.search(r'\.(rs|go|java|rb|php|c|cpp|h|swift|kt|scala|r)$', n): return 'πŸ“œ' - if re.search(r'\.(txt|log)$', n): return 'πŸ“„' - if re.search(r'\.(zip|tar|gz|rar|7z)$', n): return 'πŸ“¦' - return 'πŸ“„' + if re.search(r'\.(png|jpe?g|gif|webp|svg|bmp|ico)$', n): return 'image' + if n.endswith('.pdf'): return 'file' + if re.search(r'\.(md|markdown)$', n): return 'edit' + if n.endswith('.py'): return 'file' + if re.search(r'\.(js|jsx|ts|tsx)$', n): return 'file' + if re.search(r'\.(html?|xml)$', n): return 'file' + if n.endswith('.css'): return 'file' + if n.endswith('.json'): return 'file' + if n.endswith('.sql'): return 'file' + if re.search(r'\.(sh|bash|zsh)$', n): return 'file' + if n.endswith('.ps1'): return 'file' + if re.search(r'\.(rs|go|java|rb|php|c|cpp|h|swift|kt|scala|r)$', n): return 'file' + if re.search(r'\.(txt|log)$', n): return 'file' + if re.search(r'\.(zip|tar|gz|rar|7z)$', n): return 'file' + return 'file' def _load_workspace_pages(ws_cookie: str) -> list: diff --git a/app/routers/dashboard.py b/app/routers/dashboard.py index 48e45ec..d76c884 100644 --- a/app/routers/dashboard.py +++ b/app/routers/dashboard.py @@ -96,7 +96,7 @@ def _sidebar_data(request: Request, repos: list[dict], include_workspace: bool = recent_pages.append({ "id": full_name, "name": repo.get("name", full_name), - "icon": "πŸ“", + "icon": "folder", "url": f"/board/{full_name}", "active": False, "indent": 0, @@ -430,7 +430,7 @@ async def help_page(request: Request):
-

πŸ“Workspaces

+

{{ fd_icon("folder",16) }}Workspaces

Organize your work into separate workspaces. Each has its own pages and files.