- Dropdown Filter dans la toolbar (icône filtre, à côté de Sort)
- Menu avec Folders, Pages, PDF, Images, Code, Text + Clear filter
- doFilter() applique maintenant filterType au tree view via _filterTree()
- Filter chips visibles dans toutes les vues comme indicateur
- L'enhanced table prend le relais quand un filtre est actif dans les vues non-tree
143 tests passent
- dashboard.py: quote(filename) dans file_url (espaces/caractères spéciaux)
- page_editor.html: iframe PDF → onerror fallback avec lien Open in new tab
- 143 tests passent
Maintenant au bon endroit: base.html sidebar-section-actions (L229-233)
Pas dans local_workspace.html tree (où il n'était pas visible).
143 tests passent
Alpine ne résolvait pas wsId dans le scope x-for.
Maintenant: href='/local-workspace' (route qui utilise le cookie ws actif).
+ hard refresh nécessaire (Ctrl+Shift+R) pour vider cache ancien JS.
143 tests passent
_header.html L54: {{ page_icon }} affichait le mot 'home'/'file'/'paperclip'
au lieu de l'icône SVG. Maintenant détecte les noms connus → fd_icon().
Fallback pour les valeurs non-reconnues: affiche tel quel.
143 tests passent
page_editor.html L5: le bouton star utilisait x-text avec fd_icon('star',14)
contenant des guillemets doubles SVG → Expression Error.
→ x-html + getSvgIcon('star',14) (JS, pas de guillemets dans l'expression)
→ share/lock/link: utilisent déjà la concaténation ~ (safe)
143 tests passent
- List (compact): rangée '..' avec icône folder avant les données
- Details (enhanced): rangée '..' avec toutes les colonnes
- Cards (title grid): carte '..' dans la grille
- Content (content list): élément '..' avec preview 'Parent folder'
- x-show='currentFolder > 0' pour n'afficher que dans un sous-dossier
- 143 tests passent
- Workspaces: bouton bleu '+' maintenant centré, 48px, min-height 140px (plus coupé)
- Library no-workspace: 'Open a Workspace...' avec lien Go to Workspaces au lieu de Loading
- Library: boutons '+ Add new' et 'New page' cachés quand pas de workspace
- Settings: espacement bouton Upload photo (margin-bottom, margin-top augmentés)
- 143 tests passent
- Section 'Notion apps' retirée
- Liens statiques en bas du sidebar (toujours visibles): Library, My Tasks, Trash, Help
- Nouvelle route /help avec page d'aide (raccourcis, guide rapide)
- Trash visible pour tous (plus de condition sur auth_method)
- 143 tests passent
- Meetings '+' button → gardé avec has_active_workspace
- Sidebar footer 'New page' → gardé avec has_active_workspace
- Context menu New File/New Folder → déjà gardé car l'arbre est caché sans workspace
- Workspace section déjà gardée (commit précédent)
- 143 tests passent
- Ajout flag has_active_workspace dans _sidebar_data (dashboard.py + board.py)
- Template base.html: quand has_active_workspace=False:
- Titre section → '📁 No workspace open'
- Boutons New File/New Folder cachés
- Message 'Open a workspace to see your files'
- Guard JS newPageInWorkspace()/newFolderInWorkspace(): toast + redirect si pas de workspace
- 143 tests passent
- createPage() now detects active workspace context (library, local-workspace page, sidebar)
- In a local/Gitea workspace: creates workspace item via /api/local-workspace/items with prompt
- No workspace: creates general Notion page via /board/api/pages (no prompt)
- Added hidden #fd-local-ws-id in local_workspace.html to expose workspace_id
- _confirmCreateFolder() passes workspace_id for Gitea workspaces
- Added _getContext() helper that checks multiple context sources in priority order
- Added _toast() helper for cross-component notifications
- Add global window.FlowDeck namespace with createPage() and showCreateFolderModal()
- createPage() creates a Notion-style page via /board/api/pages (same as sidebar bottom-right button)
- showCreateFolderModal() opens a global themed modal (dark/light) instead of browser prompt()
- All New Page buttons now call window.FlowDeck.createPage()
- All New Folder buttons now call window.FlowDeck.showCreateFolderModal()
- Global New Folder modal uses existing .flowdeck-modal CSS classes for theme consistency
- Updated Ctrl+N keyboard shortcut to use unified createPage()
Le x-show sur #lib-table dépendait de flatItems.length,
qu'Alpine 3.14.9 ne détecte pas. Maintenant _renderTable()
contrôle l'affichage/masquage directement via style.display.
Abandon complet d'Alpine pour le rendu du tableau :
- _renderTable() fait innerHTML directement sur #lib-table-body
- Plus de x-for, plus de x-html, plus de getters
- SortableJS supprimé (causait removeEventListener sur null)
- Fix startRename/commitRenameById pour utiliser les IDs DOM
Le x-for d'Alpine 3.14.9 ne détecte pas les changements d'array.
Remplacement complet par x-html avec génération HTML manuelle.
Ajout de window._libData pour les onclick handlers globaux.
Fonctions _byId pour toggle/expand/rename/open depuis le HTML.
Alpine 3.14.9 ne détecte pas le changement de référence d'array
(this.flatItems = result). Utilisation de splice() pour muter
l'array en place. Ajout de $nextTick pour forcer le re-render.
Ajoute des logs dans init(), loadTab() et _recomputeFlatItems()
pour identifier pourquoi flatItems reste vide malgré le chargement API.
CSP: ajout fonts.googleapis.com/gstatic.com pour débloquer Google Fonts.
Remplacé visibility:hidden par opacity:0.4 pour les hover-only.
Cela garantit que les éléments sont RENDUS et visibles en permanence,
avec accentuation au hover (opacity 1).
Les pages du workspace local ont workspace='' mais workspace_id=27.
Le filtre workspace != '' les excluait, retournant 0 items.
Ajout de OR workspace_id IS NOT NULL pour inclure les pages locales.
Simplification du frontend: le workspace tab appelle l'API standard avec workspace_id.