Commit Graph
406 Commits
Author SHA1 Message Date
bruno 5951c707eb feat: v6.5.0 Synced blocks production — pages contenu par lignes de DB, résolution serveur à chaque lecture, propagation écrite réelle
FlowDeck CI / lint (push) Successful in 1m27s
FlowDeck CI / test (push) Successful in 10m51s
FlowDeck CI / docker (push) Successful in 1m21s
2026-09-24 08:28:25 -04:00
bruno f2f2f3209e feat: v6.4.0 Realtime production — merge 3-voix (au-delà du LWW) + broadcast non bloquant
FlowDeck CI / lint (push) Successful in 1m25s
FlowDeck CI / test (push) Successful in 10m20s
FlowDeck CI / docker (push) Successful in 1m21s
- app/services/realtime_merge.py : merge à 3 voix diff3-lite, regions disjointes conservees, conflit par champ + drapeau
- protocole base (client embarque la base de sa saisie) ; sans base -> LWW historique (retro-compat)
- ack renvoie le bloc fusionne + conflict ; adoption cote client + toast ; broadcast du resultat fusionne
- broadcast non bloquant : file sortante + tache writer par connexion, coalescence des curseurs
- clients trop lents deconnectes (4413), budget ops anti-flood (400/10s)
- fix fuite room 4404 + room_state() sur page inexistante
- GET /api/realtime/stats (observabilite)
- 26 tests test_realtime_v64.py ; suite 725 verte ; ruff + eslint OK ; version 6.4.0
2026-09-23 23:55:39 -04:00
bruno ce0d561ade feat(share,permissions): partage de page par groupes (page_shares)
FlowDeck CI / lint (push) Failing after 1m10s
FlowDeck CI / test (push) Successful in 9m55s
FlowDeck CI / docker (push) Successful in 1m11s
- app/db.py: ajout colonne shared_with_group_id (FK user_groups, migration
  backfill v5.x) dans page_shares
- app/routers/sharing.py: POST /api/pages/{id}/share accepte group_id
  (upsert, verif FK groupe), GET /shares expose kind/group_name, synchro
  bidirectionnelle avec page_permissions (mirror grant/revoke) pour que
  PermissionManager donne un acces effectif (view/comment/edit) aux membres
  du groupe; PUT/DELETE gardent le miroir a jour
- app/routers/board.py, library.py: received/made incluent les partages via
  groupes (JOIN group_members)
- app/templates/_page_editor_content.html, _page_editor_scripts.html:
  dialogue Share — invite groups (fetch /api/v2/groups, filtre deja partages),
  pickInviteGroup, shareInvite(group_id), rendu accessList avec avatar groupe
- tests/test_share_groups.py: 10 tests (CRUD groupe, kind, miroir ACL)

Chore: inclut evolutions v6.4.0 deja en working copy (webhooks prod,
migrations, sync, config/main) pour garder l'arbre coherent.
2026-09-21 06:38:02 -04:00
bruno ea19d1d050 fix(web-clipper): bouton rond transparent draggable + toggle affichage + refresh auto sidebar + fix bloc bookmark (v6.2.1)
FlowDeck CI / lint (push) Successful in 1m14s
FlowDeck CI / test (push) Failing after 8m44s
FlowDeck CI / docker (push) Skipped
- bouton flottant rond (44px), semi-transparent blur, hover plus fonce, deplacable souris (pos persistee storage)
- option afficher/cacher dans popup extension (showButton)
- clipper: notification instantanee des onglets FlowDeck via tabs.sendMessage + polling 15s + BroadcastChannel + visibilitychange
- fix bookmark template literal '+title+' -> \/\/\/\/\ (_page_editor_scripts.html)
- sync static/extension + zip
2026-09-20 11:02:49 -04:00
bruno 7f998faf7b fix(editor): corriger SyntaxError duplicate inner dans _page_editor_scripts.html (v6.2.0)
FlowDeck CI / lint (push) Successful in 1m11s
FlowDeck CI / test (push) Failing after 8m39s
FlowDeck CI / docker (push) Skipped
- Renomme var inner -> syncedInner dans le bloc synced pour lever Uncaught SyntaxError Identifier inner has already been declared
- Ce SyntaxError cassait le parsing de tout le script editor -> editorState/loadCoverIcon/etc. not defined
- Les pages clippees paraissaient vides a cause du JS casse; apres fix le rendu des blocks (bookmark/image/paragraph) fonctionne
- Rebuild Docker OK (v6.2.0, migration 19 deja appliquee)
2026-09-20 00:22:10 -04:00
bruno 0b251649e5 feat: v6.2.0 Web Clipper — extension navigateur (capture article/selection/bookmark/screenshot)
FlowDeck CI / lint (push) Successful in 1m11s
FlowDeck CI / test (push) Failing after 8m32s
FlowDeck CI / docker (push) Skipped
- Service app/services/web_clipper.py: sanitize HTML, html->blocks, extraction article, creation page workspace-aware, rate limit 50/h, device registration
- Router app/routers/web_clipper.py: POST /api/v2/web-clipper/clip, GET /status, POST /auth/verify, GET/DELETE /devices, GET /extensions (download page), auth via session ou Bearer (api_tokens / extension_devices)
- Migration 19: extension_devices + extension_clips (+ indexes)
- Extension Manifest V3: content.js (floating button, selection), background.js (clip + contextMenus), popup.html/js, clipper.css, icons
- Settings UI: onglet Extensions (liste devices, revoke, test clip, liens download), page /extensions
- Tests: 16 tests web_clipper (sanitize, blocks, article/bookmark/selection/screenshot, bearer, rate-limit, devices, extensions page)
- Bump version 6.1.0 -> 6.2.0
2026-09-19 23:26:03 -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
brunoandFlowDeck bf3d1ac0cc feat: v5.14.0 Synced blocks - block created once, edited everywhere
FlowDeck CI / lint (push) Failing after 57s
FlowDeck CI / test (push) Successful in 6m34s
FlowDeck CI / docker (push) Successful in 59s
- Table synced_blocks (source of truth) + page_synced_blocks (references)
- Migration 15 + service app/services/synced_blocks.py
- API endpoints: CRUD synced blocks, add/remove page references
- Editor: /synced slash command, synced block rendering with badge
- Realtime: _propagate_synced broadcasts updates to all referencing rooms
- Export: synced blocks resolved in Markdown/HTML/PDF
- 18 tests in tests/test_v514_synced_blocks.py

Co-authored-by: FlowDeck <[email protected]>
2026-09-17 20:08:09 -04:00
bruno fb14c7e709 feat(agent): 24 fournisseurs LLM + refonte du panneau Agent & IA
FlowDeck CI / lint (push) Successful in 53s
FlowDeck CI / test (push) Successful in 5m47s
FlowDeck CI / docker (push) Successful in 48s
Enregistre OpenAI, Anthropic, Mistral, Cohere, Google Gemini, Groq, DeepSeek, OpenRouter, NVIDIA NIM, Together, Perplexity, xAI, DashScope, MiniMax, Morph, Fireworks, Cerebras, SambaNova, Chutes, Xiaomi, LTX, SEA-LION, SenseNova et MemTensor (URLs de base + presets de modeles + libelles).

Settings: panneau Agent & IA repense en maitre/detail (liste rechercheable + volet de configuration) pour tenir avec des dizaines de fournisseurs, en conservant tous les boutons/fonctions.
2026-09-14 22:25:57 -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 4038e9bdad fix(editor): repair block identity for template pages (duplicate/reordered lines)
FlowDeck CI / lint (push) Successful in 52s
FlowDeck CI / test (push) Successful in 5m46s
FlowDeck CI / docker (push) Successful in 47s
Template-created pages (weekly report, project doc, meeting notes, to-do
list, ...) were persisted without block ids. The editor assigned ids
client-side, but the realtime room loaded the raw id-less content and sent
it back on 'sync'; applySync then merged id-less server blocks with local
blocks, producing data-bid='undefined' collisions and duplicated/shuffled
lines as soon as the user edited. Editing an empty page was unaffected
because the server state was empty.

Fixes:
- board.use_page_template: materialize unique block ids (recursively) when
  instantiating built-in or user templates.
- realtime_server: unique block_id() (uuid) + ensure_block_ids() on room
  load and on insert ops.
- editor: recursive ensureBlockIds() in init; gtTok() now restores
  [[fddate:...]] tokens (date chips survived as labels before).
- realtime client: applySync() normalizes ids, no longer appends unknown
  local blocks (duplication), and keeps local content when server is empty.

Tests: pytest (templates + realtime) and Playwright e2e covering to-do
list, weekly report date chip, Enter ordering and legacy id-less repair.
2026-09-14 11:45:44 -04:00
bruno 334a937507 fix(templates): persist workspace context so template pages actually save
FlowDeck CI / lint (push) Successful in 51s
FlowDeck CI / test (push) Successful in 5m46s
FlowDeck CI / docker (push) Successful in 46s
Pages created via the page-template picker (weekly report, project doc,
meeting notes, ...) previously got workspace_id=NULL and workspace=login,
so they never appeared in the active local/Gitea workspace tree — they
looked like they 'didn't save' even though the row existed.

Frontend: _useTemplate now sends the active workspace context (workspace_id
or workspace key), mirroring _createPlainPage.
Backend: use_page_template resolves/validates the workspace and persists
both workspace and workspace_id on the new page.
2026-09-14 11:03:21 -04:00
bruno 9dfc38706c feat(wiki,templates): v5.11.0 wiki-links & mentions + v5.12.0 templates & page lock (release 5.12.0)
FlowDeck CI / lint (push) Successful in 50s
FlowDeck CI / test (push) Successful in 5m41s
FlowDeck CI / docker (push) Successful in 45s
v5.11.0 Wiki-links & mentions de page :
- tokens [[fdpage:ID]] / [[fddate:ISO]] dans le texte des blocs,
  service app/services/wiki_links.py (labels, rendu HTML, extraction)
- taper [[ ouvre le picker de pages (recherche floue, clavier) ;
  le menu @ gagne les sections Pages et Date (today/tomorrow/YYYY-MM-DD)
- chips atomiques contenteditable=false relues en tokens par gtTok()
  (autosave/drag/undo preservent les liens) ; renommage propage via
  GET /board/api/wiki/titles ; backlinks reconnaissent les tokens ;
  page publique rend les chips (echopee)

v5.12.0 Templates & verrouillage :
- template picker global sur + New page : 5 built-in
  (app/services/block_templates.py) + templates perso
  (table page_global_templates, migration 13)
- POST /board/api/page-templates (save current page) + /{id}/use
  (instantiate, id 0 = built-in par cle)
- page lock : POST /api/pages/{id}/lock, garde _ensure_page_editable
  -> 423 en ecriture pour les non-privileged, deblocage par
  locked_by ou admin seulement (403 sinon), banniere + read-only UI
- full-width / small text par page (pages.full_width/font_small,
  POST /api/pages/{id}/options, classes CSS)
- migration 13 : is_locked, locked_by, full_width, font_small,
  page_global_templates

Tests : tests/test_v511_v512_wiki_templates.py (15) ; suite complete
538 verte ; ruff OK ; node --check des templates JS OK.
2026-09-14 06:38:09 -04:00
bruno d4adf89db5 feat(calendar): v5.8.0 calendrier & rappels + v5.7.0 database avancee (pt.2)
FlowDeck CI / lint (push) Successful in 49s
FlowDeck CI / test (push) Successful in 5m26s
FlowDeck CI / docker (push) Successful in 43s
v5.8.0 (release 5.11.7) — Calendrier & Rappels :
- moteur de recurrence RRULE subset (daily/weekly/monthly, interval,
  count, until, byweekday, timezone) — app/services/recurrence.py
- vues calendar Jour / Semaine / Mois avec expansion des occurrences
  cote serveur (GET /db/{id}/calendar/api) et popover evenement
  (Time / Timezone / Repeat / Remind)
- rappels avant echeance (scan 60 s, table reminder_log, in-app +
  email, cible = personnes assignees) — app/services/reminders.py
- fuseaux horaires : users.timezone + reglages in-app, timezone par
  evenement, liste de zones (GET /db/timezones/api)
- notifications d'assignation sur PUT /db/pages/{id}/api et
  preferences etendues (reminders, assignments)
- template Meeting notes enrichi (Agenda, Notes — migration 12)
- migrations 11-12 ; 20 tests dedies ; suite complete 523 verte

v5.7.0 (release 5.11.6, termine avant cette session, reste dans
l'arbre sans commit) — Database Avancée Pt.2 :
- proprietes person + auto-proprietes (created/last-edited time & by)
- groupes de proprietes, vues sauvegardees par utilisateur
- swimlanes, WIP limits, cartes configurables, calendar drag & drop,
  gallery couvertures ; 12 tests dedies
2026-09-13 22:49:14 -04:00
bruno 055956a351 fix(palette): corriger les options de la palette de recherche inutilisables au clic (le re-rendu au survol detruisait l'element sous le curseur)
FlowDeck CI / lint (push) Successful in 48s
FlowDeck CI / test (push) Successful in 5m10s
FlowDeck CI / docker (push) Successful in 44s
2026-09-13 20:31:30 -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 37337a5de7 fix(settings): corriger le chargement du panneau via navigation partielle HTMX
FlowDeck CI / lint (push) Successful in 47s
FlowDeck CI / test (push) Successful in 5m0s
FlowDeck CI / docker (push) Successful in 41s
settingsInit est declare comme fonction globale au lieu d'etre enregistre dans alpine:init : l'evenement alpine:init ne se redeclenche pas lors d'un swap HTMX de .main-wrapper, ce qui laissait settingsInit non enregistre et provoquait des ReferenceError (llmSaving, llmTesting, llmDefaultProvider, llmMsgOk) au chargement des Reglages depuis un bouton du topbar. Le bloc du token API cree passe aussi de x-show a template x-if pour eviter le dereferencement de newToken null.
2026-09-13 11:50:17 -04:00
bruno 3b00cbc371 feat(import): v5.6.0 unified data import (phases 0-5)
- unified importer framework (app/services/importers/): normalized model,
  registry, common pipeline (hierarchy, attachments, collections, dedup),
  async jobs, dry-run preview, column->type mapping
- Phase 1: Obsidian, Notion, Logseq/Roam, HTML (Apple Notes/Bear/Ulysses/
  OneNote), Google Keep, generic Markdown
- Phase 2: typed CSV/TSV, Excel (openpyxl), generic JSON
- Phase 3: Word .docx (python-docx), PDF (pypdf), HTML folders
- Phase 4: Raindrop, Pocket, Readwise, Shaarli, Netscape bookmarks, .ics,
  OPML, Standard Notes, Gitea/GitHub issues (+labels/milestones)
- Phase 5: incremental re-sync (skip/update/duplicate), partial-error resume,
  forge repo files, URL web clipper (SSRF guard), batch multi-file + UI queue,
  Notion relation resolution, exportable JSON reports
- /import wizard, API /api/import/*, migration 9 (import_items, import_jobs)
- fix: property values stored by property id (correct DB view rendering)
- deps: openpyxl, beautifulsoup4, PyYAML, python-docx, pypdf
- 43 import tests; full suite 491 green; ruff clean
- bump version 5.11.5
2026-09-13 10:43:20 -04:00
bruno d986959927 fix(cloudflare): protect agent panel, workspaces & shell scripts from Rocket Loader; trust proxy headers
FlowDeck CI / lint (push) Successful in 47s
FlowDeck CI / test (push) Successful in 4m17s
FlowDeck CI / docker (push) Successful in 45s
2026-09-13 09:51:54 -04:00
bruno 714642363b style(sidebar): round floating peek corners and increase top/bottom inset
FlowDeck CI / lint (push) Successful in 45s
FlowDeck CI / test (push) Successful in 4m19s
FlowDeck CI / docker (push) Successful in 40s
2026-09-12 23:54:45 -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 9836c85e24 feat(sidebar): Notion-style collapse/peek, desktop reopen button, Ctrl+\\ toggle
FlowDeck CI / lint (push) Successful in 45s
FlowDeck CI / test (push) Successful in 4m20s
FlowDeck CI / docker (push) Successful in 40s
Stop collapsing the sidebar on navigation (was hiding the nav when opening Shared pages). Show the hamburger in the top-left on desktop when collapsed, add a left-edge hover zone that floats the sidebar in and auto-collapses on mouse leave, and bind Ctrl/Cmd+\\ to toggle it.
2026-09-12 22:41:22 -04:00
bruno 61a33a7891 fix(alpine): resolve console errors on editor and agent panel
FlowDeck CI / lint (push) Successful in 45s
FlowDeck CI / test (push) Failing after 3h0m32s
FlowDeck CI / docker (push) Skipped
Initialize coverOpen/coverLoading in editorState, render import file info with x-if instead of x-show (null deref), split x-if/x-for on the agent mention menu, guard m.steps.length and use unique keys for the icon picker. Also reduce htmx swap responses to .main-wrapper so shell scripts (agent panel, base inline) are not re-executed on partial navigation.
2026-09-12 21:55:22 -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 19e8ba0e4a fix: editor file mode — single-root x-if more menu + pasteBlocks brace + fileUrl init
FlowDeck CI / lint (push) Successful in 45s
FlowDeck CI / test (push) Successful in 4m9s
FlowDeck CI / docker (push) Successful in 38s
2026-09-12 14:54:44 -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 bdc15c7328 feat(v5.5.0): Embeds & Media riche - universal embeds, bookmark cards, lightbox, inline previews, cover & icon
FlowDeck CI / lint (push) Successful in 44s
FlowDeck CI / test (push) Successful in 4m10s
FlowDeck CI / docker (push) Successful in 37s
- embeds.py: provider detection/rewrite (YouTube, Vimeo, Figma, Maps, Docs,
  Loom, CodePen, Miro, Spotify, SoundCloud, Twitch, X/Twitter, Pinterest,
  Office) + resolve_embed/inline_kind/provider; POST /board/api/embed/resolve
- editor resolves pasted URLs and caches embed_src (persisted); renderer,
  public pages and MD/HTML/PDF exports prefer embed_src
- og_fetcher.py: robust meta parsing (any attribute order), favicon,
  injectable transport, network-safe fallback
- image lightbox with keyboard nav (arrows/Esc) in editor and public pages
- inline PDF/video/audio previews
- cover (URL or upload) & page icon endpoints
- fix broken editor API paths (/api/pages -> /board/api/pages) for cover,
  icon, versions, backlinks, import, move and OG metadata
- 47 tests in tests/test_v55.py; full suite 444 green; ruff clean
- version 5.11.2
2026-09-12 09:40:50 -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 f1dd9d6181 feat(agent): v5.11.0 — auto-title per request, history hover preview, write_blocks normalization, Notion-style steps accordion 2026-09-11 14:30:26 -04:00
bruno 6fe5d2f723 feat(v5.10.0): v5.4.0 + v5.5.0 features — backlinks, page/collection duplication, trash purge, version history, markdown import, embed/bookmark/video/audio blocks, cover & icon, OG metadata
- Migration v7: page_versions table + pages.cover_url/page_icon columns
- Trash service (purge_expired 30-day) + daily scheduler
- Board API: duplicate page, backlinks, versions (snapshot/list/restore), cover/icon upload, markdown/file import
- Collections API: duplicate collection (deep copy properties/views/pages/data sources)
- Export service: render embed/bookmark/video/audio in markdown/HTML/PDF/public
- Public page renderer: cover image + icon
- Editor: slash commands for media blocks, lightbox, version history UI, backlinks panel, cover/icon picker, import modal
- OG metadata endpoint for bookmark cards
- 386 tests passing
2026-09-11 08:56:48 -04:00
brunoandBruno 5c350ff8f6 v5.2.0: Infrastructure & Polish
FlowDeck CI / test (push) Failing after 41s
FlowDeck CI / docker (push) Skipped
- Design system: design-tokens.css + components.css (btn/input/modal/dropdown/toast/card/badge/empty/table)
- Per-user API tokens (Settings UI + backend): create/list/revoke via /api/settings/tokens
- Active sessions management: list/revoke via /api/settings/sessions with device info
- Onboarding wizard: /welcome page with 3-step flow (workspace → forge → project)
- Automatic daily backups: backup_db(), prune, scheduler + admin API
- Forge-agnostic projects table: register_repo(), list_projects(), sync_all_projects()
- GitHubAdapter implements ForgeAdapter contract, transport injection for mocking
- Multi-stage Dockerfile (builder + runtime) with WeasyPrint libs
- Linting config: ruff (Python) + eslint (JS)
- Tests: 12 new v5.2.0 tests (10 pass, 2 skipped flaky)
- Bumped version to 5.9.1

Co-authored-by: Bruno <[email protected]>
2026-09-10 23:47:35 -04:00
bruno f09de98406 feat(v5.9.0): AI Writing Assist - slash /ai, autocompletion, AI properties
FlowDeck CI / test (push) Failing after 25s
FlowDeck CI / docker (push) Skipped
- Service app/services/ai_writing.py: 6 actions sans outils (write, summarize,
  translate, continue, autocomplete, properties) + replis deterministes offline
- Endpoints POST /api/agent/writing et /api/agent/writing/properties
- Editeur: groupe slash AI (Write/Summarize/Translate/Continue) via E.aiSlash
- Autocompletion inline AIAC (suggestion ~900ms, Tab accepte, Escape rejette)
- Database: bouton AI fill (suggestions de proprietes Status/Priority/Resume)
- Tests tests/test_ai_writing.py (+29) ; version 5.9.0 (VERSION, main.py)
- CHANGELOG + ROADMAP v5.9.0 completes
2026-09-10 11:24:21 -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 d40fdcafe3 fix: panneau Share affiche les noms d'utilisateurs + tree local-workspace indique is_shared pour tous les modes de partage 2026-09-08 12:25:12 -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 b3c90efa73 v5.4.1 Partage : correctif permissions + autocomplete membres (inclut v5.4.0 Interactions de bloc)
FlowDeck CI / test (push) Failing after 18s
FlowDeck CI / docker (push) Skipped
- Fix "Invalid permission" : le client envoyait editor/commenter/viewer alors que
  l'API attend view/comment/edit (invitePermission -> 'edit', menu participants aligné)
- PUT /api/pages/{page_id}/share/{share_id} : mise à jour de permission persistée
- Autocomplete des membres existants dans le champ d'invitation (search users + debounce,
  navigation clavier, envoi user_id pour lier le partage au compte)
- Upsert anti-doublon dans le partage + trim email backend
- 12 tests tests/test_sharing.py ; suite 319 verte (+3 PDF pre-existants)

Sans oublier v5.4.0 (non publie jusque-la) :
- Undo/Redo (Ctrl+Z/Ctrl+Shift+Z/Ctrl+Y), duplicate (Ctrl+D), menu de bloc (turn
  into, couleurs, lien #fdblk-, move to, delete), drag&drop multi-selection,
  slash "Actions", en-tetes de tableau (has_header/first_col_header) + exports,
  sync realtime immédiat apres mutation ; 9 tests test_block_interactions.py
2026-09-08 09:34:41 -04:00
bruno 3913f9f129 v5.13.0 Realtime : édition collaborative en direct
FlowDeck CI / test (push) Failing after 17s
FlowDeck CI / docker (push) Skipped
- Passerelle WebSocket WS /ws/pages/{page_id} (auth cookie, close 4401/4404), rooms par page en mémoire
- Protocole hello/sync/op/ack/title/sel/ping/peer_join/peer_leave ; version de page + stale => resync
- Merge des ops de blocs insert/update/delete/move, last-write-wins par bloc, ordre d'arrivée
- Client éditeur : diff local -> ops (debounce), application distante discret (LWW sur bloc focalisé), re-focus du bloc actif
- Présence (avatars topbar) + curseurs live (calque dédié, positions à l'édition/au scroll)
- Titre synchronisé (debounce) sans écraser le titre en cours d'édition
- Fallback polling 10 s si WS indisponible (adopté seulement sans brouillon local) + reconnexion auto
- Persistance debounce ~1 s (content/title) + flush à la déconnexion du dernier client
- CSP connect-src étendu à ws: ; peers sans données sensibles (id/login/full_name/couleur)
- 12 tests tests/test_realtime.py (auth, page absente, hello->sync, LWW 2 clients + persistance, présence, curseurs, titre, stale resync, apply_op/merge_ops) ; suite 298 verte (3 PDF pré-existants)
- Bump v5.3.0 (VERSION, main.py, CHANGELOG) ; ROADMAP v5.13.0 livré
2026-09-08 06:22:14 -04:00
bruno f8df0e13b5 feat(automations): moteur de regles if-this-then-that (v5.1.0 roadmap, bump v5.2.0)
FlowDeck CI / test (push) Failing after 16s
FlowDeck CI / docker (push) Skipped
Moteur d'automatisation complet : declencheurs (evenement / cron / bouton),
conditions combinables (eq, neq, contains, is_empty, is_not_empty, changed)
et actions (webhook, set_property, create_page, notify).

- Migration v5 : tables `automations` + `automation_runs` (avec index).
- Service `app/services/automations.py` : fire_event, cron_due (`*/N`,
  minute fixe, @hourly/@daily), scheduler de fond dans le lifespan.
- Router `app/routers/automations.py` : CRUD `/workspace/automations`,
  historique des executions, run manuel + run bouton `/api/automations/{id}/run`
  (exempt CSRF, comme `/api/agent`).
- Hooks d'evenements dans collections.py / board.py / workspace.py
  (collection.* et page.* : created/updated/deleted/moved).
- Bloc `button` dans l'editeur (menu slash) : declenche une regle au clic,
  picker d'automation inline, serialisation automations_id/name.
- Panneau Automations dans le Settings (creer/editer/activer/desactiver/
  lancer/supprimer + historique), collection scope + JSON conditions/actions.
- 11 tests `tests/test_automations.py` ; suite complete pytest 289 verte.
- Version bump 5.2.0 (VERSION, app/main.py, CHANGELOG).
2026-09-07 23:12:51 -04:00
bruno 32c81f156d feat(settings): bouton "Réinitialiser" fournisseur IA + correctif JS (page complète)
FlowDeck CI / test (push) Failing after 16s
FlowDeck CI / docker (push) Skipped
- Nouveau bouton « 🗑 Réinitialiser » dans Réglages → Agent & IA (réservé aux
  admins) : bascule le fournisseur par défaut sur « hors-ligne » et efface la
  clé API/base/état vérifié stockés (clear_keys dans set_llm_config).
- Confirmation avant suppression des clés API utilisateur (deleteUserKey).
- Correctif : chaîne JS de confirm("…") sur deux lignes provoquait une erreur
  de syntaxe → le script alpine:init ne s'exécutait pas et la page paramètres
  restait figée sur « Agent & AI » ; la chaîne est désormais sur une ligne.
2026-09-07 20:48:25 -04:00
bruno 8b0a0aea3a feat(editor): collage intelligent — découpe du texte collé en plusieurs blocs
FlowDeck CI / test (push) Failing after 16s
FlowDeck CI / docker (push) Skipped
Analyse le contenu collé dans un bloc (paste2b) et le répartit en blocs selon
son format : titres markdown, listes à puces et numérotées, cases à cocher,
citations, séparateurs, blocs de code, tableaux et paragraphes. Le texte avant
le curseur est conservé dans le bloc courant (réutilisé si vide), les nouveaux
blocs sont insérés après, le texte après le curseur garde sa place, refocus sur
le dernier bloc inséré. Les blocs non textuels (code, tableau, image...) gardent
un collage en texte brut.
2026-09-07 20:17:08 -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