Commit Graph
167 Commits
Author SHA1 Message Date
bruno 0218d8f5e5 fix: /local-workspace — chemin du header + clic sur un dossier du sidebar (v7.69.9)
FlowDeck CI / lint (push) Successful in 1m37s
FlowDeck CI / test (push) Failing after 24m19s
FlowDeck CI / docker (push) Skipped
Corrige deux régressions de /local-workspace :

- le chemin du header restait bloqué sur « Home / <workspace> » quel que
  soit le dossier affiché : la route rend désormais breadcrumb_items
  (Home / <workspace> / <dossier> / <sous-dossier>, niveaux cliquables,
  collapse « … » au-delà de 4) et la navigation sans rechargement recalcule
  le chemin via l'event flowdeck:breadcrumb-changed ;
- le clic sur un dossier du sidebar affichait TOUS les composants à la
  fois : Alpine.data('wsInitData') retournait le même objet singleton, le
  2e montage (navigation partielle) levait « Cannot redefine property:
  \ » et initTree abandonnait, laissant tout le contenu au state
  brut. La factory retourne désormais une enveloppe fraîche par montage
  qui délègue à l'état réactif partagé. #lw-config est aussi relu à chaque
  exécution (le 2e montage gardait le folder_id du 1er chargement).

Inclus également le travail en cours de l'arbre : Library (colonnes Last
visited/Source, ordre d'en-tête, favoris à icônes Workspace), Meeting
Notes (bloc, CSS, routes, docs), coloration de code hljs, badges
favori/publié dans l'arbre local-workspace, docs (DATA_MODEL,
architectures) et tests associés.
2026-10-09 16:58:04 -04:00
bruno 6d7af3fb64 feat: éditeur visuel d'automations (pipeline steps) + fix CSP multi-instructions (v7.45.0)
FlowDeck CI / docker (push) Successful in 1m51s
FlowDeck CI / lint (push) Successful in 1m56s
FlowDeck CI / test (push) Successful in 15m9s
Added — Settings → Automations, pipeline visuel (API steps v7.0) :
- Cartes ordinees (trigger/condition/delay/action) : resume + edition
  TYPÉE par kind/type (datalist evenements, 7 ops, 8 types d'action avec
  leurs champs reels), ajout/edition/suppression/haut-bas via
  POST/PUT/DELETE /workspace/automations[/steps]/...
- ✨ Convertir le JSON en pipeline (legacy → steps ordonnes) ; textareas
  JSON masques des qu'un step existe.
- Gate E2E « editeur visuel de steps » : creation → edition → ajout →
  carte « Action · webhook » sous CSP reel.

Fixed (trouve par le gate) — 51 expressions Alpine MULTI-INSTRUCTIONS
(`a=1; b()`) = interdites par le parseur CSP (une seule expression par
directive ; ';' = token inattendu) — INVISIBLE pour le scan par tokens :
- Conversion en methodes dans 11 fichiers : nav settings x8 (navTo),
  menu section base x7 (closeAndSetCount/Move/...), parts+editeur x13
  (setSharePerm, more*, markAndSave...), breadcrumb x5 (hover*/goClose),
  library/local x6 (menus popup), board x3 (pickStatus/...), ctx-menu x2
  (addTagAndClear), agent/card/gitea/workspaces x6.
- Scanner dedie scan_semi (inventaire ';' hors chaines) ajoute au lot.

Verifs : 39 templates Jinja parse OK · scan expressions = 0 incompatible
(4 faux positifs en chaines) · **E2E 8/8** · suite **1094/1094** ·
ruff OK · docs a jour
2026-10-02 16:56:29 -04:00
bruno 3cab76fed5 feat: A20 phase 3 LOT 2 — settings + local workspace verts en CSP preview (v7.39.0)
FlowDeck CI / lint (push) Canceled after 0s
FlowDeck CI / test (push) Canceled after 0s
FlowDeck CI / docker (push) Canceled after 0s
Ajout :
- 2 gates csp_preview de plus : settings (composant lie, overlay visible)
  et local workspace (recherche focalisee via Alpine.nextTick, chips
  filtre en SVG via bindSvg, 0 erreur) → 3 surfaces vertes sous build
  CSP : library, settings, local workspace.

Changed :
- settings : window.history.back()/new Date(...) → methodes
  historyBack/fmtLastLogin/fmtAuditDate ; ?. → ternaires.
- local workspace : x-data="_wsInitData" → registre wsInitData() ;
  14 x-html → x-init + Alpine.effect (bindSvg/bindFileIcon/bindNodeIcon/
  bindChildren/bindPreview) ; $nextTick+$refs arrow → toggleSearch() ;
  window.FlowDeck.* → createPageAt/createFolderAt ; ?. → ternaires ;
  @contextmenu="_wsInitData.*" → appel de methode.

Piesges resolus (CHANGELOG en details) :
- snapshot ji du build CSP = valeurs globalThis au boot → l'objet mis sur
  window avant Alpine est banni (« Accessing global variables ») → objet
  porte par une CONST LEXICALE (non propriete globalThis) + factory
  Alpine.data → MEME objet partage, reactivite intacte.
- bloc preview hors div racine (structure pre-existante, masquee par le
  fallback window standard) → composant wsPreview DELEGUANT vers
  _wsInitData via Alpine.reactive (wrapper unique : les magics $nextTick
  ne sont redefinissables qu'une fois).
- .env local : RATE_LIMIT_REQUESTS=600 (rafales E2E vs 60/min par IP ;
  defaut produit inchange).

suite **1093/1093** · ruff OK · eslint 0/0 · E2E **5/5** (3 csp_preview + 2
smoke) · CSP preview ET standard = 0 erreur sur /local-workspace · docs
a jour
2026-10-02 13:24:46 -04:00
bruno 45917c194d fix: A27 phase 2b — +3 801 L extraits (recette config JSON) (v7.23.0)
FlowDeck CI / lint (push) Successful in 1m55s
FlowDeck CI / docker (push) Canceled after 0s
FlowDeck CI / test (push) Canceled after 37m14s
4 blocs interpolés extraits avec la recette de la 2a (config JSON inline +
JS statique, substitutions sur le CORPS du bloc) :
- local_workspace.html → local_workspace.js (2 031 L, lw-config :
  current_folder_id, workspace_id)
- settings.html → settings.js (1 093 L, st-config : avatar, user
  full_name/login/email, is_admin (bool), auth_method — 2 routes rendent ce
  template, expressions « or "" » préservées pour les valeurs Undefined)
- _page_editor_realtime.html → page_editor_realtime.js (531 L, rt-config :
  SELF id/login/full_name/color)
- board.html → board.js (146 L, bd-config : owner/repo/initial_view)

BONUS sécurité : les valeurs passent par |tojson (échappement JSON explicite)
au lieu d'être interpolées dans des strings JS. Tags : config JSON (nonce
conservé) + <script src> ?v={{ asset_version }} ; loaders JSON.parse en tête
(try/catch → {}). Correctif sur le loader (accolade try en trop, caught par
node --check avant tout commit).

Cumul A27 : 10 560 L extraites (13 904 → 3 344 restantes, -76 %).
Reste structurel : base 1 338 ({% block %}/{% for %}) + database_table 1 323
(if/else) + 279 warnings eslint (12 fichiers, 0 erreur).

suite **1089/1089** · ruff OK · node --check ×4 vert · docs à jour
2026-10-01 20:37:07 -04:00
bruno c718fe06de fix: A20 (partiel) — CSP nonce par requête, unsafe-inline sort de script-src (v7.7.0)
FlowDeck CI / lint (push) Canceled after 0s
FlowDeck CI / test (push) Canceled after 0s
FlowDeck CI / docker (push) Canceled after 0s
- ContentSecurityPolicyMiddleware : nonce aléatoire par requête dans la
  ContextVar `CSP_NONCE` (posée avant `call_next` → visible des templates),
  `script-src 'self' 'unsafe-eval' 'nonce-…'` — plus aucun script inline
  sans nonce ne tourne (fin des XSS injectés en JS)
- 38 tags `<script>` des templates : `nonce="{{ csp_nonce() }}"` (passage
  scripté, vérifié : 0 restant) ; `LOCAL_LOGIN_HTML` (constante de module) :
  helper `_with_nonce()` au rendu ; collections.py : 3 scripts Python
  (chart/form/map) noncés
- `<meta name="htmx-config" content='{"inlineScriptNonce": …}'>` dans base.html
  : htmx ré-injecte les <script> des réponses boostées avec le bon nonce
- `script-src-attr 'unsafe-inline'` : les 74 handlers `onclick=` inline
  restent couverts (le nonce les aurait désactivés aussi)
- chart.js (cdn.jsdelivr.net) et leaflet (unpkg) ajoutés à script-src/style-src
  : vues chart/map déjà BLOQUÉES par la CSP depuis toujours
  (commentaire ponytail: upgrade = vendoriser puis retirer les hôtes)
- reste d'A20 : unsafe-eval (Alpine x-data → @alpinejs/csp), externalisation
  JS (A27), resserrer img-src/connect-src

test : test_csp_nonce_per_request (page base.html + page hors template,
nonce unique par requête)

suite **1037/1037** · `ruff check app tests` OK · docs à jour
2026-10-01 10:41:39 -04:00
bruno 1f705ce512 fix: A19 terminé — plus aucun préfixe cookie-auth exempt du CSRF (v7.3.6)
FlowDeck CI / test (push) Successful in 20m10s
FlowDeck CI / lint (push) Successful in 1m51s
FlowDeck CI / docker (push) Canceled after 0s
- 46 appels non-GET équipés de `X-CSRF-Token` (expression cookie en ligne,
  portée indifférente) : agent_panel (9), settings (12), local_workspace (15),
  gitea_workspace (4), workspace (2), workspaces (5), library (2), welcome (2 en v7.3.5)
- 5 derniers préfixes sortis d'`EXCLUDED_PATHS` : /api/workspace (+/api/workspaces),
  /api/local-workspace, /api/settings, /api/gitea, /api/agent
- il ne reste exempté que : Bearer (/api/webhook, /api/v1, /api/v2, /scim/v2),
  callbacks /auth/*, pages publiques (/s/, /f/), /api/csrf-token et /api/frontend-error
- vérif : `node --check` des <script> des 39 templates → 0 échec (avant et après)
- tests : `anon_csrf()` sur les 5 tests d'anonymat devenus CSRF-first
- suite **1026/1026** · `ruff check app tests` OK
2026-10-01 07:41:23 -04:00
bruno d125eb399e fix: A3–A8 — bloc « fallback admin » de l'audit sécurité (401 sans session, ACL, CSRF)
FlowDeck CI / lint (push) Successful in 1m49s
FlowDeck CI / test (push) Successful in 21m47s
FlowDeck CI / docker (push) Successful in 1m45s
- A3 : helper `_require_user_id()` (401 sans session) sur profile/password/token/forge ; `PUT /api/user/password` exige `current_password` vérifié ; `/api/user` sorti de la liste CSRF exemptée
- A4 : `POST /api/v1/token` → 401 sans session, chemin legacy `user_id=0` supprimé
- A5 : CRUD membres d'espace (POST/PUT/DELETE) : session + rôle admin de l'espace (ou admin global), placeholder user créé en `is_admin=0`, GET membres sans session → 401
- A6 : `_require_view` → 404 et `_require_edit` → 401 quand il n'y a pas de session (fin du legacy single-user sur les collections)
- A7 : création ET lecture de page → 401 sans session (PermissionManager conservé) ; `/board/api/pages` sorti de `EXCLUDED_PATHS` ; header CSRF manquant ajouté sur setItemIcon (local_workspace)
- A8 : seed admin sans mot de passe codé en dur — aléatoire au premier boot loggé une fois, ou `FLOWDECK_ADMIN_PASSWORD` ; re-seed seulement si absent
- tests : client connecté par défaut via `_TestSessionAuth` (session + CSRF injectés à la volée, jamais dans le cookie jar → plus de CookieConflict), helper `anon()` sur les 40 tests d'anonymat ; 1016/1016 verts, `ruff check app tests` OK
2026-09-30 22:04:13 -04:00
bruno b5207216f1 feat: v6.0.0 PWA offline support
- manifest + icones, service worker (precache, network-first, Background Sync)

- module client FlowOffline (IndexedDB, queue, delta, flush) + hook editeur

- endpoints /api/v2/sync/{delta,batch,status} + moteur de sync (conflits LWW/orpheline/copie offline)

- migrations offline_sync_queue + sync_version (triggers)

- UI offline (banner, badge sync, toasts, icone dirty) + doc /help

- tests pytest (sync, migrations, SW, offline) + E2E Playwright; bump 6.0.0
2026-09-18 13:05:40 -04:00
bruno 0d475c3d2d fix(workspace): compteurs de tags dynamiques + counts scoped par workspace
FlowDeck CI / lint (push) Successful in 53s
FlowDeck CI / test (push) Successful in 5m47s
FlowDeck CI / docker (push) Successful in 48s
2026-09-14 20:26:27 -04:00
bruno 7096707b3e fix(workspace): tags count update dynamique via /api/local-workspace/tags
FlowDeck CI / lint (push) Successful in 53s
FlowDeck CI / test (push) Successful in 5m46s
FlowDeck CI / docker (push) Successful in 49s
2026-09-14 19:33:54 -04:00
bruno 9ab47d8113 fix(workspace): menu contextuel après navigation partielle + sync sidebar/header au rename
FlowDeck CI / lint (push) Successful in 52s
FlowDeck CI / test (push) Failing after 3h14m19s
FlowDeck CI / docker (push) Skipped
2026-09-14 18:20:43 -04:00
bruno 41c1d315d3 feat(workspace,editor): creation dans le dossier courant + sync live du titre (sidebar/header)
FlowDeck CI / lint (push) Successful in 54s
FlowDeck CI / test (push) Successful in 5m50s
FlowDeck CI / docker (push) Successful in 47s
- creation fichier/dossier a la racine du dossier courant ou d'un dossier cible (context-menu, boutons de survol) via createPage/showCreateFolderModal(parentId)
- instances de modeles en tant qu'enfant d'un dossier (parent_id) ; nom vide -> 'Untitled'
- sidebar de la librairie rafraichi apres delete/move/duplicate/rename (_syncSidebar)
- editeur: le titre se synchronise en direct dans le sidebar, le breadcrumb et l'onglet (pages et fichiers) et persiste via PUT /board/api/pages/{id}
2026-09-14 17:05:03 -04:00
bruno 3b3e95e23a fix(cloudflare): proteger les scripts inline des pages du Rocket Loader
FlowDeck CI / lint (push) Successful in 48s
FlowDeck CI / test (push) Successful in 5m2s
FlowDeck CI / docker (push) Successful in 42s
Rocket Loader (Cloudflare) reecrit les balises script inline en type=...-text/javascript et les execute de facon differee, ce qui casse l'enregistrement des composants Alpine et l'init des pages lors d'un acces direct via le tunnel (ex. /settings ne se chargeait pas au complet). Ajout de data-cfasync=false sur les scripts inline des pages completes et des partiels du shell (settings, accounts, trash, workspace, board, gitea_workspace, welcome, import, page_editor_collection/embed, _database_table_scripts, _notification_bell, public_page, local_workspace). Les fragments charges via HTMX restent inchanges.
2026-09-13 12:35:28 -04:00
bruno df78badd0c feat(sidebar): Notion-style floating peek card, pin toggle & drag-resize
FlowDeck CI / lint (push) Successful in 46s
FlowDeck CI / test (push) Successful in 4m24s
FlowDeck CI / docker (push) Successful in 44s
2026-09-12 23:46:17 -04:00
bruno e707becbf8 feat(nav): partial HTMX navigation — swap main content without full reload
FlowDeck CI / lint (push) Successful in 45s
FlowDeck CI / test (push) Successful in 4m17s
FlowDeck CI / docker (push) Successful in 41s
Intercept internal links and load only .main-wrapper via htmx.ajax, keeping the sidebar/header shell in place. Adds history pushState/popstate handling, sidebar active-state resync and document title update. Moves page script blocks inside #main-content so they run on swap, and makes editor/board scripts idempotent. Routes navigateTo/breadcrumb/library/local-workspace through window.fdNavigate and fixes the duplicated navigateTo definition.
2026-09-12 21:26:56 -04:00
bruno da3e09c215 feat(icon): Notion-style icon picker + custom workspace emojis; fix side peek file content & ctx menu overflow
FlowDeck CI / lint (push) Successful in 45s
FlowDeck CI / test (push) Failing after 3h6m55s
FlowDeck CI / docker (push) Skipped
2026-09-12 20:05:53 -04:00
bruno 7a6c66a609 feat: add download + copy file content to context menus and editor
FlowDeck CI / lint (push) Successful in 45s
FlowDeck CI / test (push) Successful in 4m8s
FlowDeck CI / docker (push) Successful in 38s
- Add /api/pages/{id}/download and /api/pages/{id}/file-content endpoints
- Add Download + Copy content to shared context menu (_ctx_menu.html)
- Wire handlers in local-workspace and library context menus
- Add Download + Copy content to editor '...' menu for file pages
- Multi-block selection copy/cut/paste with Ctrl+C/X/V shortcuts
- Align page title with blocks start (CSS pseudo-element offset)
2026-09-12 12:53:17 -04:00
bruno d1d8c6fd2a fix(local-workspace): move tag filter bar above the tree; use SVG chevron for 'Show less'
FlowDeck CI / lint (push) Successful in 43s
FlowDeck CI / test (push) Successful in 4m0s
FlowDeck CI / lint (pull_request) Successful in 43s
FlowDeck CI / test (pull_request) Successful in 4m4s
FlowDeck CI / docker (push) Successful in 37s
FlowDeck CI / docker (pull_request) Successful in 36s
Reposition the workspace tag filter bar above the tree view and replace the emoji toggle with a monochrome SVG chevron for visual consistency.
2026-09-12 08:54:33 -04:00
bruno 881c3e3e0a feat(library): tags + tag filtering, monochrome icons; fix live tag updates
- library: expose page tags (batch), render tag chips per row and add a tag
  filter bar; register tag create/associate/remove in the shared context menu
  exactly like local-workspace
- library: restore monochrome SVG icons (folder/edit/image/file) matching
  local-workspace, with optional custom page_icon
- workspace: refresh tag chips/filter live on tag add/remove (reassign arrays
  + tagsVersion) instead of requiring a page reload
- ctxmenu: measure the rendered menu and clamp it to the viewport on open
2026-09-11 22:33:37 -04:00
bruno c36082be6a fix(ctxmenu): repair library rendering and complete unified row menu
- library.html: remove leftover syntax error + orphan </template></div> that
  broke libraryPage() (page showed 'undefined' and no files), call the correct
  fdCtx.openMenu and use self instead of a throwaway libraryPage() instance
- _ctx_menu.html: full conventional menu with shortcuts, tags + colour picker,
  edit-icon picker; closes on outside click and Escape
- local_workspace.html: migrate onContextMenu to the shared fdCtx store with
  complete handlers; drop legacy window._ctxMenuData DOM hacks
- dashboard.py: expose page_icon + favorited in the workspace tree
2026-09-11 22:00:54 -04:00
bruno fbc8d657e7 feat(ctxmenu): unify row context menu via shared partial (_ctx_menu.html) for library+workspace; keep data-cfasync=false on page_editor_scripts 2026-09-11 21:24:01 -04:00
bruno cef01dffaf fix(cloudflare): prevent Rocket Loader from deferring Alpine's inline alpine:init listeners (data-cfasync=false on all Alpine-critical script blocks) — fixes partial page load on mobile behind Cloudflare 2026-09-11 17:32:31 -04:00
bruno da1fccb38f feat(workspace): Notion-style multi-select, select/unselect all, Library-style bulk action bar with move-to modal 2026-09-11 16:42:46 -04:00
bruno 3b27c57230 feat: badge emoji partagé (noir & blanc) dans l'arborescence + sidebar «Par moi» inclut is_shared
FlowDeck CI / test (push) Failing after 18s
FlowDeck CI / docker (push) Skipped
- board/dashboard: helper _load_shared_sidebar_pages intégrant les pages marquées is_shared directement
- _workspace_tree_macro: badge 👥 N&B sur les fichiers partagés du tree du sidebar
- local_workspace: badge 👥 en noir & blanc
- static/css/app.css: style .page-shared-badge
2026-09-08 13:57:35 -04:00
bruno 0112a5b5d8 v5.5.0 Partage v2 : fenêtre Share rechargée, sidebar « Par moi »/« Avec moi », Library dir=made/received, badge 👥 + indicateurs
FlowDeck CI / test (push) Failing after 18s
FlowDeck CI / docker (push) Skipped
- Correctif : la fenêtre Share rechargait ses partages à chaque ouverture (before: liste vide après refresh)
- Sidebar « Shared » scindée en sous-groupes « Par moi » (partages nominatifs + liens) et « Avec moi » (partages reçus), sans doublons
- Bibliothèque : filtre « Tous / Par moi / Avec moi » sur l'onglet Shared ; /api/library/shared?dir=made|received|all + share_dir par élément
- Document : bouton barre affiche « 👥 Shared ▾ » quand la page est partagée (membre, lien ou publiée), recalculé à la volée
- Workspace local : emoji 👥 juste avant le nom des fichiers partagés (is_shared exposé par /api/local-workspace/tree)
- Tests +6 (tests/test_sharing.py) : direction made/received/all, fallback dir invalide, rendu pageIsShared ; suite 325 verte (+3 PDF pré-existants)
2026-09-08 11:52:29 -04:00
bruno 52d7a0d006 fix(local-workspace): boite de renommage a la taille du nom + bouton Open a cote
FlowDeck CI / test (push) Failing after 15s
FlowDeck CI / docker (push) Skipped
- La boite d'edition inline est desormais large comme le nom du fichier
  (largeur mesuree a l'ouverture via _fitNameWidth, min 60px, bornee a
  l'espace disponible pour les tres longs noms — le texte defile dedans).
- Le bouton Open est place juste a droite de la boite (marge 6px) au lieu du
  bord du panneau : deplace dans la cellule .name.file, passee en inline-flex
  (overflow hidden + max-width) pour ne jamais passer a la ligne.
- Applique aux deux rendus de l'arbre (vue principale x-for + renderChildren).
- Verifie en Chrome headless : input = largeur du nom (38%/12% de la ligne au
  lieu de 100%), bouton Open a 6px de la boite, pas de passage a la ligne.
- Tests : 278 passent.
2026-09-07 18:11:05 -04:00
bruno f7d87e6555 fix resize: use pointer capture to handle drag over iframe
FlowDeck CI / test (push) Failing after 5s
FlowDeck CI / docker (push) Has been skipped
When dragging the resize handle rightward to narrow the panel, the
mouse cursor moved over the iframe which captured mouse events.
document-level mousemove stopped firing, making narrowing impossible.

Fix: replace mouse events with pointer events + setPointerCapture.
The handle element captures ALL pointer events during drag regardless
of where the cursor moves (over iframe, outside window, etc).
Applied to both local_workspace.html and library.html.
2026-07-22 11:18:25 -04:00
bruno afe670bdd3 peek panels: reusable editor module — shared _page_editor_content.html + embed template
FlowDeck CI / test (push) Failing after 4s
FlowDeck CI / docker (push) Has been skipped
Architecture for zero code duplication:
- Extract page editor HTML into _page_editor_content.html (shared include)
- page_editor.html includes it (same behavior as before)
- page_editor_embed.html includes it with empty topbar (no header in peek)
- board.py: ?embed=1 renders page_editor_embed.html

Peek panels now load /pages/{id}?embed=1 in iframe:
- Editor renders without sidebar or header breadcrumb/actions
- Full editing capability (blocks, markdown, slash commands, save)
- Same code — one change to _page_editor_content.html updates everywhere
2026-07-22 10:50:02 -04:00
bruno e32abfbfa6 revert iframe approach, restore vanilla JS peek + re-add resize handles
FlowDeck CI / test (push) Failing after 6s
FlowDeck CI / docker (push) Has been skipped
Reverted the iframe-based peek panels (d13f137, 99fee56) which caused:
- Sidebar/header still visible inside iframe despite embed CSS
- Resize handle broken by iframe layout

Restored:
- Vanilla JS content loading via API (_loadPreviewContentVanilla)
- Peek-body div instead of iframe
- Resize handles on both library and local-workspace panels
  (click=close, drag=resize, width persisted in localStorage)
2026-07-22 10:34:50 -04:00
bruno 514b1da9a7 Revert "peek panels: load full page editor in iframe + resize handles"
This reverts commit d13f13785b.
2026-07-22 10:32:33 -04:00
bruno d13f13785b peek panels: load full page editor in iframe + resize handles
FlowDeck CI / test (push) Failing after 5s
FlowDeck CI / docker (push) Has been skipped
- Add ?embed=1 to /pages/{id} route, passes embed_mode to template
- base.html: embed-mode class hides sidebar/topbar, removes margins
- Replace peek-body content with iframe loading /pages/{id}?embed=1
  in both library.html and local_workspace.html
- Remove async content loading (now editor handles rendering)
- Add resize handle on left edge of peek panels (both library + local-ws)
  - Click without drag: closes panel
  - Click + drag horizontal: resizes panel width (300px to 90vw)
  - Width persisted in localStorage (fd_peek_width)
- 100% code reuse: editor runs same /pages/{id} with embed flag
2026-07-22 10:10:21 -04:00
bruno 348793ba13 local-workspace: fix peek-header icons vertical stacking — add missing flex CSS
FlowDeck CI / test (push) Failing after 4s
FlowDeck CI / docker (push) Has been skipped
The .peek-header class from library.html CSS was not available on the
local-workspace page, causing header buttons to stack vertically.
Added inline display:flex;align-items:center;gap:4px on the header div.
2026-07-22 09:43:51 -04:00
bruno cbba7c506a local-workspace: match preview panel design to Library peek-overlay
FlowDeck CI / test (push) Failing after 4s
FlowDeck CI / docker (push) Has been skipped
- Same 560px width, same header layout (close | icon+title | open | fav | copy | more)
- Header uses peek-header class from library CSS for identical styling
- Meta info (type, size, date) moved inline into body as subtle header
- Tags moved inline into body below meta
- More menu with Open, Favorite, Copy link, Close actions
- Copy link button uses navigator.clipboard API with toast feedback
- Bottom action buttons removed (now in header + more menu)
- Empty state matches library (file icon + 'Select a file to preview')
2026-07-22 09:37:29 -04:00
bruno 38a188e6e2 local-workspace: fix preview content rendering for all document types
FlowDeck CI / test (push) Failing after 5s
FlowDeck CI / docker (push) Has been skipped
Root cause: blocks format content is a direct array [{id,type,content}],
not wrapped in {blocks:[...]}. Old code checked blocks.blocks which was
always undefined, so internal pages showed nothing.

Fixes:
- Handle blocks as raw array or {blocks:[...]} wrapper (both formats)
- Add heading styling (h3-h6 based on heading_1/2/3), code blocks (pre)
- Add proper markdown format handler (renders as pre-wrapped text)
- Add format=file handler showing file metadata + Open file link
- Add unknown format fallback as pre-wrapped text with char limit
- Clean up escaped quotes — no more double-escaped \" in strings
- Better empty state messages (Empty document, No content)
2026-07-22 09:27:15 -04:00
bruno 50aed9e357 local-workspace: make preview panel a fixed overlay like Library side peek
FlowDeck CI / test (push) Failing after 4s
FlowDeck CI / docker (push) Has been skipped
- Replace flex-based panel with position:fixed overlay (right side, 480px wide)
- Slide-in animation: translateX(100%) -> translateX(0) via CSS transition
- Slide-out on close: translateX(100%) then hide after 200ms
- Uses requestAnimationFrame for smooth slide-in trigger
- Matches Library peek-overlay behavior exactly
2026-07-22 09:15:07 -04:00
bruno 31db48a40d local-workspace: replace Alpine preview panel with vanilla JS DOM manipulation
FlowDeck CI / test (push) Failing after 4s
FlowDeck CI / docker (push) Has been skipped
Alpine 3.14.9 x-if and x-show are fundamentally broken for reactive
visibility toggling of the preview panel. Complete rewrite:

- Replace all Alpine directives in preview panel with static HTML + IDs
- selectForPreview(): vanilla JS to populate fields and show panel
- closePreviewPanel(): vanilla JS to hide panel
- _loadPreviewContentVanilla(): async content loader using innerHTML
- Open button wired via onclick to navigate to /pages/{id}
- No Alpine reactivity dependencies - panel just works
2026-07-22 09:09:17 -04:00
bruno 45eefa0c11 local-workspace: fix preview panel null errors, wrap inner content in x-if
FlowDeck CI / test (push) Failing after 4s
FlowDeck CI / docker (push) Has been skipped
- Keep outer x-show on preview-panel div for transition animation
- Wrap all inner content referencing previewItem in <template x-if=previewItem>
  to prevent Alpine from evaluating expressions when previewItem is null
- Clean up debug console.logs from earlier debugging
- This combines x-show (reliable visibility toggle) with x-if (null guard)
2026-07-22 08:59:24 -04:00
bruno c4ff0a41e0 local-workspace: replace x-if/x-show with x-show only for preview panel
FlowDeck CI / test (push) Failing after 4s
FlowDeck CI / docker (push) Has been skipped
Root cause: Alpine 3.14.9 x-if on template element doesn't reliably re-render
when a reactive property changes. previewItem was being set (confirmed by logs)
but x-if never re-evaluated.

Fix: replace <template x-if> wrapper with direct x-show on the preview-panel div.
x-show with x-transition is the reliable pattern for this Alpine version.
2026-07-22 08:54:40 -04:00
bruno b76aaad5ee local-workspace: add debug logs + fix x-show/x-if conflict on preview panel
FlowDeck CI / test (push) Failing after 4s
FlowDeck CI / docker (push) Has been skipped
- Add console.log in selectForPreview and openSidePeek to trace button clicks
- Add console.log in Alpine OPEN button click handler
- Remove redundant x-show from preview-panel (was conflicting with x-if transition)
- This should fix the preview panel not appearing when Open button is clicked
2026-07-22 08:49:10 -04:00
bruno c4d654676c local-workspace: add debug console.log to selectForPreview and openSidePeek
FlowDeck CI / test (push) Failing after 5s
FlowDeck CI / docker (push) Has been skipped
2026-07-22 08:45:58 -04:00
bruno fbd191c85b local-workspace: reposition Open button to right of title, fix hover visibility
FlowDeck CI / test (push) Failing after 4s
FlowDeck CI / docker (push) Has been skipped
- Add CSS rule .ws-tree-item:hover .hover-only for tree item hover visibility
- Move OPEN button OUT of .actions div, place it right after title span with
  margin-left:auto and .hover-only class (matches Library layout exactly)
- Fix renderChildren() static HTML: button now between name span and .actions
- Remove duplicate button from inside .actions div
- Button calls selectForPreview(node) or openSidePeek(id) for side preview panel
2026-07-22 08:36:45 -04:00
bruno 288f99d81e local-workspace: add Open button on file hover like Library, opens in side preview panel
FlowDeck CI / test (push) Failing after 5s
FlowDeck CI / docker (push) Has been skipped
- Add openSidePeek(id) helper method to find node by id and open in side preview
- Update renderChildren() static HTML OPEN button: replace full page nav with selectForPreview
- Add OPEN button in Alpine x-for tree template actions div for file items
- Uses existing preview-panel (right side panel) instead of navigating away
2026-07-22 08:25:39 -04:00
bruno 3fcfa8fdbb style: bouton New page → icône document+plus (même que sidebar)
FlowDeck CI / test (push) Failing after 4s
FlowDeck CI / docker (push) Has been skipped
2026-07-21 21:30:55 -04:00
bruno ce2bae1f1b feat: fichier filter dropdown + fonctionnel sur toutes les vues
FlowDeck CI / test (push) Failing after 12s
FlowDeck CI / docker (push) Has been skipped
- 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
2026-07-21 20:47:32 -04:00
bruno 85b4d624b8 refactor: local-workspace UI → Library-style
FlowDeck CI / test (push) Failing after 4s
FlowDeck CI / docker (push) Has been skipped
CSS:
- Ajouté: ws-container, ws-tabs-row, ws-tab, ws-icon-btn, ws-btn-primary
- Ajouté: ws-dropdown, ws-search-bar, ws-select-bar, ws-row
- Ajouté: row-name, row-icon, row-title, hover-only, ws-checkbox
- Ajouté: tree-chevron, btn-open, more-menu (Library-style)
- Conservé: ws-tree, ws-tree-item, ws-act, breadcrumb-row pour compatibilité

Navbar:
- Breadcrumb + toolbar fusionnés en une seule row propre
- Dropdowns style Library (View, Sort)
- Search toggle avec barre coulissante
- Bulk bar → ws-select-bar avec icônes SVG

Context menu:
- .ctx-menu → .more-menu (style Library)
- Toutes les refs JS mises à jour

143 tests passent
2026-07-21 15:53:36 -04:00
bruno 3079d53cab fix: sidebar root external-link → href static (pas Alpine :href)
FlowDeck CI / test (push) Failing after 4s
FlowDeck CI / docker (push) Has been skipped
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
2026-07-21 11:59:05 -04:00
bruno d3bada54f0 feat: sidebar tree — add external-link icon to /local-workspace
FlowDeck CI / test (push) Failing after 4s
FlowDeck CI / docker (push) Has been skipped
- local_workspace.html: hover actions (folder) → + external-link → /local-workspace
- Ajouté dans JS renderChildren ET template x-for
- 143 tests passent
2026-07-21 11:54:12 -04:00
bruno 3fcc12ad8c feat: sweep complet — tous les émojis → outline SVG icons
Templates modifiés (22 fichiers):
- _icons.html: +14 new icons (paperclip, external-link, sparkles, lightbulb, tag,
  file-text, save, upload, trending-up, zap, alert-triangle, user, eye-off)
- base.html: +8 JS icons, 🦎🐙🔑🔗👁📋🔲📑❓⚠️→SVG
- page_editor.html: 43→0 émojis (📎📄🔒🔗⭐📋📁✨📝🗄📑📊📅🗓🖼📥🌐✏💬💡 etc)
- settings.html: 30→0 (⚙️📋🏷🧩👥💾🙈👁🔒🌙☀️🌳📊📝⚠🦎✅🐙🔗✏🗑)
- local_workspace.html: 25→0 (📄📁✏🗑⚠📋➕)
- gitea_workspace.html: 25→0 (🔗📄📤🔄⚙📁📄🔒✏🗑💾)
- board.html: 13→0 (📁📊📋☰📈👥✕✓🗑⚡🔍)
- workspace.html: 11→0 (🏠🔑⚙📁🔗📂🐙)
- landing.html: 8→0 (📚🚀📝📊🦎🌐🔒⚡)
- trash.html, table_view, dashboard, accounts, card_detail, public_page,
  workspaces, team_load, notes, _header, detailed_board, card, board_fragment
- Ajouté import _icons.html aux fragments standalone
- 143 tests passent
2026-07-21 08:27:10 -04:00
bruno b88a972531 fix: 4 colored JS icons in /local-workspace hover → outline SVG
- 📄 New file → getSvgIcon('file',14)
- 📁 New folder → getSvgIcon('folder',14)
- ✏️ Rename → getSvgIcon('edit',14)
- 🗑 Delete → getSvgIcon('trash',14)
- 143 tests passent
2026-07-21 08:10:30 -04:00
bruno aa434e9fe9 fix: derniers émojis — workspaces 🏠, hover actions, sidebar context menu
FlowDeck CI / test (push) Failing after 5s
FlowDeck CI / docker (push) Has been skipped
- workspaces.html: 🏠→home SVG (page_icon, header)
- local_workspace.html: ✏️🗑 ✕→SVG (rename, delete, clear buttons, rename modal)
- base.html: ✏️🗑️📁📄→SVG (context menus Rename/Delete/New File/Folder)
  + pageIcon default '📁'→'folder', modal title '📁 New Folder'→SVG
- 143 tests passent
2026-07-20 23:13:01 -04:00