From fc6e30aebb1d4e917e1114b5f06e4907800ba9c7 Mon Sep 17 00:00:00 2001 From: bruno Date: Sat, 11 Jul 2026 13:49:12 -0400 Subject: [PATCH] =?UTF-8?q?feat:=20ic=C3=B4nes=20par=20type=20de=20fichier?= =?UTF-8?q?=20+=20filtre=20par=20type=20+=20fix=20preview=20PDF?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 1. IcΓ΄nes de fichier contextuelles: - _fileIcon() JS et _file_icon() Python: mappe l'extension vers emoji - πŸ“• PDF, πŸ–ΌοΈ images, 🐍 Python, πŸ“œ JS/TS, 🌐 HTML, 🎨 CSS, πŸ“‹ JSON, πŸ—ƒοΈ SQL, πŸ’» Shell, ⚑ PS1, πŸ“ MD, πŸ“¦ archives... - AppliquΓ© dans sidebar (board.py) + page workspace (x-for + renderChildren) 2. Preview PDF: ne fetch plus le contenu binaire (caractΓ¨res bizarres), affiche πŸ“• 'PDF Document' dans le popup hover 3. Filtre par type: - Chips πŸ“ Pages | πŸ“• PDF | πŸ–ΌοΈ Img | πŸ“œ Code | πŸ“„ Text - _filterTree() accepte un paramΓ¨tre fileType - DΓ©sΓ©lection par second clic sur le mΓͺme chip --- app/routers/board.py | 37 ++++++++++++--- app/templates/local_workspace.html | 73 ++++++++++++++++++++++++++---- 2 files changed, 96 insertions(+), 14 deletions(-) diff --git a/app/routers/board.py b/app/routers/board.py index 96a5980..ccfe352 100644 --- a/app/routers/board.py +++ b/app/routers/board.py @@ -140,6 +140,27 @@ def _build_page_tree(conn, parent_id: int | None, ws_key: str, depth: int = 0, m return items +def _file_icon(name: str) -> str: + """Map file extension to emoji icon.""" + import re + 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 'πŸ“„' + + def _load_workspace_pages(ws_cookie: str) -> list: """Load top-level pages with children for the active workspace.""" if not ws_cookie: @@ -153,11 +174,13 @@ def _load_workspace_pages(ws_cookie: str) -> list: ).fetchall() items = [] for r in rows: + is_folder = r["parent_section"] == "Workspace" + title = r["title"] or "Untitled" items.append({ - "db_id": r["id"], "name": r["title"] or "Untitled", + "db_id": r["id"], "name": title, "id": f"page/{r['id']}", - "icon": "πŸ“" if r["parent_section"] == "Workspace" else "πŸ“„", - "is_folder": r["parent_section"] == "Workspace", + "icon": "πŸ“" if is_folder else _file_icon(title), + "is_folder": is_folder, "children": _load_children(r["id"]), }) return items @@ -174,11 +197,13 @@ def _load_children(parent_id: int) -> list: ).fetchall() children = [] for r in rows: + is_folder = r["parent_section"] == "Workspace" + title = r["title"] or "Untitled" children.append({ - "db_id": r["id"], "name": r["title"] or "Untitled", + "db_id": r["id"], "name": title, "id": f"page/{r['id']}", - "icon": "πŸ“" if r["parent_section"] == "Workspace" else "πŸ“„", - "is_folder": r["parent_section"] == "Workspace", + "icon": "πŸ“" if is_folder else _file_icon(title), + "is_folder": is_folder, "children": _load_children(r["id"]), }) return children diff --git a/app/templates/local_workspace.html b/app/templates/local_workspace.html index 128e24e..628c07a 100644 --- a/app/templates/local_workspace.html +++ b/app/templates/local_workspace.html @@ -107,6 +107,12 @@ .search-clear{background:none;border:none;color:var(--text-tertiary);cursor:pointer;font-size:16px;padding:2px 4px;border-radius:3px;} .search-clear:hover{color:var(--text);background:var(--bg-hover);} +/* Filter chips */ +.filter-chips{display:flex;gap:6px;margin-bottom:10px;flex-wrap:wrap;} +.filter-chip{padding:4px 10px;background:var(--bg-tertiary);border:1px solid var(--border);border-radius:6px;font-size:12px;color:var(--text-secondary);cursor:pointer;transition:all 150ms;} +.filter-chip:hover{background:var(--bg-hover);color:var(--text);} +.filter-chip.active{background:var(--accent);color:#fff;border-color:var(--accent);} + /* File preview tooltip */ .file-preview{position:fixed;z-index:300;background:#1a1a1a;background:var(--bg,#1a1a1a);border:1px solid var(--border-strong,#333);border-radius:10px;box-shadow:0 8px 30px rgba(0,0,0,.5);max-width:400px;min-width:200px;pointer-events:auto;} .file-preview-header{padding:8px 12px;font-size:12px;font-weight:600;color:var(--text-secondary,#888);border-bottom:1px solid var(--border,#333);} @@ -174,6 +180,15 @@ + +
+ + + + + +
+