- 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)
78 KiB
Changelog - FlowDeck
v5.5.0 (2026-09-08) — Partage : réorganisation & indicateurs
Vue complète du partage : sidebar « Shared » scindée en « Par moi » / « Avec moi », onglet Shared de la bibliothèque filtrable, fenêtre Share rechargée à l'ouverture (bug de refresh), et emoji 👥 sur les fichiers partagés du workspace local.
- Correctif fenêtre Share — ouverture de la boîte de dialogue
(
toggleShareOpen) au lieu de laisser la liste vide après un refresh ; les partages sont rechargés (loadShares) à chaque ouverture. - Sidebar Shared — la section affiche deux sous-groupes : « Par moi » (partages nominatifs créés + pages en « lien ») et « Avec moi » (partages reçus), chacun avec son propre état vide (les pages déjà dans « Par moi » sont exclues de « Avec moi » pour éviter les doublons).
- Bibliothèque — onglet Shared doté d'un filtre « Tous / Par moi /
Avec moi » ; l'endpoint
GET /api/library/sharedacceptedir=made|received|allet renseigneshare_dirsur chaque élément. - Indicateur de partage — la barre du document affiche « 👥 Shared » au lieu de « 🔒 Share » dès que la page est partagée (membre, lien ou publiée) ; état recalculé à la volée après chaque action de partage.
- Workspace local — les fichiers partagés affichent l'emoji 👥 juste
avant leur nom dans l'arborescence (
is_sharedexposé par/api/local-workspace/tree). - Tests (tests/test_sharing.py +6) : direction made/received/all de la
bibliothèque, fallback dir invalide, et rendu
pageIsSharedsur la page. Suite complète 325 verte (+3 PDF pré-existants).
v5.4.1 (2026-09-08) — Partage de page : correctif permissions + autocomplete membres
Le partage à un membre existant échouait avec « Invalid permission. Use view, comment, or edit. » — le client envoyait
editor/commenter/vieweralors que l'API n'accepte queview/comment/edit. Corrigé, et enrichi.
- Correctif permissions — défaut du champ d'invitation passé à
edit; valeurs, libellés et surbrillance du menu de permission des participants alignés sur le contrat API (view/comment/edit). - Mise à jour de permission persistée — nouvel endpoint
PUT /api/pages/{page_id}/share/{share_id}; le menu de permission d'un participant enregistre désormais le changement (avant : visuel uniquement). - Autocomplete des membres existants — en tapant dans le champ d'invitation,
recherche dans
/api/notifications/users/search?q=(debounce 150 ms) avec liste de suggestions (avatar couleur, login, nom complet), navigation clavier ↑/↓/Entrée/Échap ; soi-même et membres déjà partagés exclus. - Partage lié au compte — la sélection d'un membre dans les suggestions
envoie
user_id, le partage est donc lié au compte (pas seulement à un email) ; un email peut toujours être saisi librement. - Upsert anti-doublon — partager un membre déjà présent met à jour sa permission au lieu de créer une ligne dupliquée ; trim de l'email côté serveur.
- Tests (tests/test_sharing.py) : partage par user_id/email, permission invalide rejetée, upsert, PUT permission, suppression avec unset is_shared, erreurs d'auth. Suite complète 319 verte (+3 PDF pré-existants).
v5.4.0 (2026-09-08) — Interactions de bloc
Manipulation riche des blocs façon Notion : undo/redo, duplication, menu de bloc ⋮ (turn into, couleurs, lien vers le bloc, déplacer, supprimer), glisser-déposer multi-sélection et en-têtes de tableau configurables.
- Undo/Redo : pile d'historique (100 entrées) alimentée à chaque mutation
(frappe Entrée, retour arrière, slash, tableau, toggle, colonnes…), rappel
Ctrl+Z/Ctrl+Shift+ZouCtrl+Y, restauration avec re-focus du bloc. - Duplication de bloc :
Ctrl+D, menu bloc ou commande slash « Duplicate » ; copie profonde (enfants columns/toggle inclus) insérée juste en dessous ; en multi-sélection, le groupe entier est dupliqué. - Menu de bloc ⋮ sur la poignée (clic ou clic droit) : « Turn into »
(sous-menu conservant le contenu), Duplicate, Copy link to block
(
#fdblk-<id>, scrolls/focus au chargement), Move to… (dialogue de recherche des pages de l'arbre, déplacement du bloc via l'API), Delete, couleur de texte et de fond appliquées à un bloc ou à la sélection. - Glisser-déposer multi-sélection :
Shift+clicsur la poignée ajoute un bloc à la sélection ; déplacer un bloc sélectionné déplace tout le groupe (reconstruction de l'ordre depuis le DOM viadata-id). - Commandes slash étendues : groupe « Actions » avec Duplicate, Turn into…, Copy link to block et Delete block.
- En-têtes de tableau : toggles « Header row » / « First col » dans la
barre du tableau ;
has_header(toujours actif par défaut) et nouveauxfirst_col_headerpersistés et pris en compte dans les exports Markdown/HTML (app/services/export.py) ainsi que que dansblocksToMarkdownclient. - Intégration realtime : méthode
syncNow/forceEmitsurwindow.__fdRTappelée après chaque mutation programmatique pour pousser immédiatement les ops (undo, duplicate, drag, turn into, couleurs, déplacement, toggles). - Tests (tests/test_block_interactions.py) : persistance des blocs avec
has_header/first_col_header/style, exports table Markdown/HTML, endpoint « Move to » (get page + POST blocks sur la cible).
v5.3.0 (2026-09-08) — Realtime : édition collaborative en direct
- Deux utilisateurs peuvent maintenant éditer une même page en même temps
- les blocs, le titre, les curseurs et la présence se synchronisent via une connexion WebSocket, avec fusion last-write-wins et repli sur polling.
- Passerelle WebSocket
WS /ws/pages/{page_id}(app/services/realtime_server.py- app/routers/realtime.py) : salons en mémoire par page, authentifiés via le cookie de session (refus 4401), page introuvable/supprimée → 4404.
- Protocole de synchronisation :
hello/sync/op/ack/title/sel/ping/peer_join/peer_leave; chaque page porte une version incrémentée à chaque opération appliquée ; un client périmé reçoit unsynccomplet. - Merge last-write-wins par bloc : insert, update (remplacement de bloc), delete, move — appliqués dans l'ordre d'arrivée ; une frappe en cours dans un bloc focalisé n'est jamais écrasée par une mise à jour distante.
- Client éditeur (app/templates/_page_editor_realtime.html) : diff local → ops (update/delete/move/insert), envoi dès que l'utilisateur tape (debounce), application des ops distantes avec re-render discret + re-focus du bloc actif.
- Présence & curseurs : avatars colorés dans la barre du haut et curseurs de chaque pair positionnés dans le document (calque dédié, mise à jour à l'édition/au scroll).
- Titre synchronisé : diffusion du titre (debounce) sans écraser un titre en cours d'édition.
- Fallback polling : si le WebSocket est indisponible, rafraîchissement toutes les 10 s de l'état serveur (adopté uniquement si pas de brouillon local) avec reconnexion automatique.
- Persistance : écriture debounce (~1 s) de
content+titleen base, flush immédiat à la déconnexion du dernier client. - Sécurité :
connect-srcCSP étendu àws:; aucune donnée sensible transmise (les peers n'exposent que id/login/full_name/couleur). - Tests (tests/test_realtime.py) : auth, page absente, hello→sync, merge
LWW à deux clients + persistance, présence join/leave, curseurs, titre,
resync des clients périmés,
apply_op/merge_opsunitaires.
v5.2.0 (2026-09-07) - Automations : un moteur de règles (if-this-then-that)
Nouveau moteur de règles : brancher des actions sur des événements de pages (création, mise à jour, suppression, déplacement), sur un planning cron ou sur un bouton cliquable directement dans l'éditeur.
- Moteur de règles : trigger (événement / cron / bouton), conditions combinables (eq, neq, contains, is_empty, is_not_empty, changed) et actions (webhook, changer une propriété, créer une page, notification).
- Événements couverts : collection créée/modifiée/supprimée, page créée/modifiée/supprimée/déplacée (API et Canvas).
- Déclencheur cron :
*/N * * * *, minute fixe,@hourly,@daily, avec un planificateur en arrière-plan qui exécute les règles dues chaque minute. - Bouton d'automation : nouveau bloc de type
buttondans l'éditeur (menu slash) qui déclenche une règle au clic. - Interface : panneau Automations dans les paramètres (créer, modifier, activer/désactiver, lancer, supprimer, historique des exécutions).
- Historique des exécutions : chaque déclenchement est tracé (statut, détail, page/collection concernée).
v5.1.11 (2026-09-07) — Éditeur : collage intelligent (découpe en blocs)
Coller un texte dans un bloc le plaçait en entier dans ce bloc, même s'il contenait plusieurs paragraphes, des listes, des titres markdown, du code ou un tableau.
- Découpe automatique au collage : le contenu collé est analysé
(
paste2b) et réparti en plusieurs blocs selon son format (markdown ou texte simple). - Pris en charge : titres
#→####, listes à puces (-,*,+), listes numérotées, cases à cocher- [ ]/- [x](y compris[X]), citations>, séparateurs---/***, blocs de code (fences ```), tableaux markdown et paragraphes. - Texte simple : les lignes courtes (≤ 55 caractères) deviennent chacune un bloc ; les blocs de texte longs (paragraphes) restent groupés ; une ligne vide crée une nouvelle section.
- Comportement au curseur : le texte avant le curseur reste dans le bloc courant (qui est réutilisé comme premier bloc si vide), puis les blocs analysés sont insérés, et le texte après le curseur conserve sa propre place (refocus sur le dernier bloc inséré).
- Les blocs non textuels (code, tableau, image, formules…) reçoivent toujours le collage en texte brut, sans découpe.
v5.1.10 (2026-09-07) — Espace local : boîte de renommage à la taille du nom
Renommer un fichier en cliquant sur son nom ouvrait une boîte d'édition qui s'étendait sur toute la largeur de la ligne, et le bouton « Open » restait collé à droite du panneau.
- La boîte de renommage inline (
inline-rename-input) est maintenant large comme le nom du fichier : la largeur est mesurée à l'ouverture (_fitNameWidth) avec un minimum de 60 px et est bornée à l'espace disponible pour les très longs noms (le texte défile alors dans la boîte). - Le bouton Open est placé juste à droite de la boîte d'édition (marge
6 px) au lieu du bord droit : il est déplacé à l'intérieur de la cellule
.name.file, devenueinline-flex(avecoverflow:hidden+max-width), pour que le bouton ne passe jamais à la ligne même en colonne étroite. - S'applique aux deux rendus de l'arbre : la vue principale (x-for) et
renderChildren(dossiers imbriqués / arbre statique).
v5.1.9 (2026-09-07) — Validation robuste des modèles Nvidia + logo Agent noir & blanc
La liste Nvidia « diminuée » de la v5.1.8 contenait encore des modèles en erreur 404/410. Deux causes réelles : (1) le payload de validation ne correspondait pas à celui utilisé au runtime et un
payloadpartagé entre les requêtes concurrentes envoyait des noms de modèles croisés (race) ; (2) rien ne protégeait l'usage si un modèle devenait indisponible après validation.
Validation des modèles (fournisseur bruité)
_validate_chat_models()utilise désormais le payload de production (messages+temperature: 0.2, sansmax_tokens) : un modèle qui répond 200 à la validation répond aussi 200 à l'usage réel.- Race fixée : le payload est reconstruit pour chaque modèle (plus de nom de modèle croisé entre requêtes concurrentes) — c'est pourquoi la v5.1.8 retombait par intermittence sur la liste brute non validée.
- Un seul payload partagé retiré ; retente une fois sur timeout/5xx (les modèles lents mais fonctionnels survivent) ; rejette définitivement les 4xx (404 modèle inconnu, 410 retiré/déprécié) ; garde les 429 (routés donc utilisables).
Repli automatique au runtime (model not found / gone)
LLMClient._http_complete: si le modèle choisi répond 404/410, retente une fois avec le modèle par défaut du provider et ajoute unnoticeexpliquant le basculement — visible dans le panneau Agent (nouvel événement SSE « notice », bandeau.fd-ap-notice, réinitialisé à chaque conversation).- Le modèle réellement utilisé est persisté dans l'historique de conversation.
Panneau Agent — logo noir & blanc thémé
- Le rond bleu en bas à droite (FAB) et le logo du header du panneau (à gauche
de « How can I help you today? ») passent de l'accent bleu + émoji 🤖 à un
rond noir/blanc qui suit le thème clair/sombre, avec une étincelle ✨
monochrome (SVG
currentColor: rond--text-primary, étincelle--bg-primary).
v5.1.8 (2026-09-07) — Multi-lignes réellement conservées + modèles IA validés (Nvidia)
Deux correctifs : le bug multi-lignes (v5.1.7 corrigeait le symptôme au re-rendu, mais la vraie cause était la lecture en
textContentqui élimine les<br>) et, côté Agent, seuls les modèles réellement utilisables du fournisseur Nvidia sont désormais proposés dans la configuration IA.
Éditeur — multilignes conservées (vraie cause)
sync()lisaitel.textContent, qui supprime les<br>: les sauts de ligne étaient perdus dès la sauvegarde du bloc. Ajout degt()(basé surinnerText, qui rend bien les<br>en\n) utilisé parsync(), les tableaux (toggle/columns) et le calcul de position du curseur.- La scission sur Entrée (et la limite bas/haut de bloc) utilisait désormais
splitCaret(): un marqueur temporaire est inséré au curseur puisgt()/innerTextdécoupe le contenu en « avant » / « après », exactement comme un vrai clavier. Fini le décalagebeforequi perdait la fin d'un bloc multi-lignes. _resultText(composer IA) lit pargt()pour préserver les\n.
Agent — validation des modèles (fournisseur bruité)
GET {base}/modelsde Nvidia liste tout le catalogue, mais la plupart des modèles (embeddings, rerank, génération d'images…) répondent 404 sur/v1/chat/completions— l'erreur observée dans la config IA.fetch_provider_models()filtre désormais pournvidia: suppression des modèles manifestement non-chat (nom), puis « probe » réelle de chaque candidat (POST /chat/completions, payload minimal, pipeline limité à 6 en parallèle, 6 s par appel) — seuls les modèles qui répondent sont listés. Un 429 (limite de débit) est conservé (le modèle est routé, donc utilisable).- Filet de sécurité : si toutes les validations échouent, on garde la liste filtrée par nom plutôt que de vider le sélecteur.
- Tests :
tests/test_llm_config.py(5 cas) — catalogue mock, 404 chat, retour sans validation pour les autres providers, chute de sécurité, offline.
v5.1.7 (2026-09-07) — Retours à la ligne conservés quand on change de bloc (Entrée)
Un bloc multi-lignes (Shift+Entrée) perdait ses retours à la ligne dès qu'on appuyait sur Entrée pour créer un nouveau bloc.
Cause
- Shift+Entrée insère des
<br>;sync()litel.textContent, qui contient alors des\n.mdEsc()(render des blocs) échappait le texte mais ne convertissait pas les\n, et le HTML les replie en espace → les lignes disparaissaient au re-rendu après la scission Entrée.
Correctif
mdEsc()convertit désormais les\nrestants en<br>(après les remplacements markdown inline) : les retours à la ligne sont conservés dans tous les types de bloc (paragraphe, listes, to-do, toggle, callout, code…).
Conforme au comportement Notion : le titre affiche « New Page » quand il est vide ; les aides de blocs (« Press 'space' for AI… », « Heading 1 »…) ne s'affichent que lorsque le bloc a le curseur.
Titre « New Page » (document vide)
- Le placeholder du titre utilisait
:emptyavec le texte figé « New page » et la couleur très sombre--text-dim.:emptycasse dès qu'un<br>est injecté dans le contenteditable. - Ajout de
data-placeholder="New Page"et d'une bascule de classe.empty(même mécanisme que les blocs) : le placeholder s'affiche en gris pâle (--text-secondary, opacité .75) dès que le titre est vide, y compris après effacement. save()stocke désormais un titre vide (au lieu de forcer « New page ») : le placeholder persiste après autosave ; la sidebar garde son fallback d'affichage.duplicatePage()retombe sur « New Page » si le titre est vide.
Aides de blocs affichées seulement au focus
- Les placeholders des blocs (« Press 'space' for AI or '/' for commands », « Heading 1 », « List »…) s'affichaient en permanence quand le bloc était vide.
- Les règles passent sous
:focus-within: l'aide n'apparaît que lorsque le bloc est focalisé (curseur dans le bloc) et disparaît dès qu'on le quitte. - Même comportement pour l'aide « Type code... » du bloc code.
Les textes d'aide « Press 'space' for AI or '/' for commands », « Heading 1 », « List », etc. restaient affichés pendant l'édition.
Cause
- La classe
.empty(qui pilote les placeholders) n'était basculée qu'aurender(). Pendant la frappe, l'événementinputmettait à jourdirtyetautoSavemais jamais.empty: le texte d'aide persistait sur un bloc qui avait pourtant du contenu.
Correctif
- Le listener
inputdes blocs (rendurender()) bascule désormais.emptyen direct selon le contenu : dès qu'un caractère est saisi,.emptyest retiré et le placeholder disparaît ; quand le bloc est vidé,.emptyrevient et le placeholder réapparaît (mécanisme identique pour les titres « Heading 1… », listes, callout, etc.).
Résout les derniers retours UI de l'éditeur v5.1.2/5.1.3.
Placeholder « Press 'space' for AI » — jamais affiché
- Cause réelle : la classe
.emptyest basculée sur l'élément interne[data-bid](sélecteur[data-placeholder]au render), mais la règle CSS ciblait l'élément externe.block-content— deux éléments différents, donc le::befored'aide ne se rendait jamais. - La règle cible désormais
.block-content [data-bid].empty::before(l'élément qui porte réellementdata-placeholder+.empty).
Flèches ↑/↓ du menu /
- La navigation dépendait de l'endroit où se trouvait le focus (
_invs bloc vs ailleurs) :onKdn'est lié qu'à#_blocksCt, l'input vit dans#_slashMenu(un voisin), d'où un comportement fragile/incohérent. - Ajout d'un écouteur
keydownau niveau document (actif quand le menu est ouvert) : ↑/↓/Entrée/Échap fonctionnent quel que soit le focus, plus de double déclenchement. - La sélection
.selectedpasse en!importantpour toujours gagner sur.slash-item:hover, et l'élément sélectionné est auto-défilé (scrollIntoView).
Item « vocabulaire / vocabulaire » du menu / mal positionné
- Les icônes texte
'lightbulb'(Callout) et'image'(Image) étaient injectées en clair dans la pastille d'icône, provoquant un texte décalé/débordant. - Remplacées par les emojis
💡(Callout) et🖼️(Image).
Composer « Edit with AI » — largeur
- Le composer AI utilisait une largeur fixe
420px; il s'aligne désormais sur la largeur du bloc ciblé (min 280px, max 1200px).
Résout les régressions du composer AI et de l'éditeur Notion-style v5.1.2.
AI inline — erreur 400 DeepSeek (espace → AI)
fdAgent.generatepassait par l'engine à outils (/conversations/{id}/run) qui envoie un schématools/tool_choiceque DeepSeek rejette en 400 Bad Request.- Bascule de
generatesur l'endpoint/api/agent/generate(sans outils, prompt propre + contexte) : le composer AI, « Ask AI », la note de réunion et la synthèse renvoient désormais un simple texte Markdown. Le bloc « 400 » disparaît.
Bloc vide (placeholder)
- Le hint « Press 'space' for AI or '/' for commands » était rendu trop discret
(
--text-dim). Il passe à--text-secondaryavec opacité, plus lisible. (Le texte n'apparaît que sur un paragraphe réellement vide — comportement Notion.)
Slash menu — flèches ↑/↓
- La sélection n'était pas visible au démarrage (rien de surligné) → les flèches
semblaient inactives.
_rs()est désormais appelé à l'ouverture et après filtrage, et l'item sélectionné reçoit un fond accentué + liseré gauche clair. Testé en jsdom : ↓/↑ déplacent la sélection, Entrée applique l'élément.
Contour du bloc sélectionné
- Suppression des anneaux de focus (
outline/box-shadow) sur tous les blocs éditables ([data-bid],.block-content, titre de page) quand sélectionné.
Poignée de déplacement (⠿)
- La poignée 6 points restait invisible (seule
.block-column-wrapper:hoverla montrait). Ajout de.block-wrapper:hover/:focus-within .block-handle { opacity:1 }pour les blocs normaux.
Tests / validation
- 271 tests pytest verts ; rendu édition 200 (hint/AIC/trigger présents) ;
route
/api/agent/generateenregistrée ; JS validé (node --check+ jsdom).
Adapte le visuel des blocs à l'expérience Notion AI : hint sur bloc vide, menu
/compact avec raccourcis + aperçu au survol, et composer AI inline (« Edit with AI » → « Brewing… » → résultat encadré → « Insert below »).
Bloc vide & commandes (Images 1 & 3)
- Hint de bloc vide : sur un paragraphe vide, le placeholder devient « Press 'space' for AI or '/' for commands ».
- Menu slash refait : compact (icône + nom + raccourci
#/##/###… à droite), groupes renommés (« Basic blocks », « Media », « Data »), footer « Close menu (esc) », champ « Type to search » en bas, et aperçu au survol d'un item (carte « Our Values » / exemple de rendu de bloc), positionnée à côté du menu.
Composer AI inline (Images 2, 4, 5, 6)
- Espace sur un bloc vide ouvre le composer AI inline (pill « Edit with AI »).
- Entrée → l'agent génère : indicateur « Brewing… » animé (bouton ■ pour stopper), puis résultat encadré (markdown rendu : titres, listes, gras…) avec barre d'actions (👍/👎) et bouton « Insert below ».
- Insert below insère le contenu comme vrais blocs (via
applyAIBlocks→md2b).
Tests / validation
- 271 tests pytest verts (aucune régression) ; éditeur rendu 200 (hint, menu, AIC présents) ;
JS validé (
node --check).
L'agent FlowDeck et l'insertion dans les pages affichent désormais le markdown rendu (titre, gras, tableaux, code…) au lieu des caractères bruts
##,**…
Éditeur de page (blocs)
- Insertion agent → vrais blocs :
applyAIBlocks()(et le mode replace defdApplyDocument) convertit la réponse markdown en blocs réels viamd2b():## titre→ blocheading_2, tableaux GFM → bloctable,```→ bloccode, listes-/1., to-do, citations, séparateurs. Plus de##affiché littéralement. - Rendu inline : les blocs de texte affichent désormais le markdown inline
(gras
**, italique*, code`, lien[t](url), barré~~) sans les caractères, viamdEsc()dansrenderBlock(paragraphes, titres, listes, to-do, toggle, citation, callout, code). - Les raccourcis clavier markdown existants (
#+ espace → H1…) restent inchangés.
Panneau FlowDeck Agent
renderMarkdown()(agent_panel.html) : les réponses de l'agent s'affichent en HTML rendu — titres H1–H4, tableaux (GFM), blocs de code, listes à puces/numérotées (+ cases), citations, séparateurs, gras/italique/code/lien/barré. HTML échappé avant rendu (sécurité face au contenu LLM). CSS dédié (.fd-md-*,pre, tableaux).- Le bouton « Insérer dans la page ouverte » continue d'utiliser
fdApplyDocument(maintenant → blocs réels).
Tests / validation
- 271 tests pytest verts (aucune régression). Rendu markdown vérifié fonctionnellement en Node (titres, tableau, code, listes) ; éditeur et panneau rendus 200 avec les nouveaux composants présents.
Livre la v5.3.0 du roadmap : databases inline dans les pages (slash
/database), galerie de templates prédéfinis (CRM, Project tracker, …) et validation des propriétés (required / unique / min / max) côté serveur + UI.
Added — Inline databases (slash /database)
- Commande slash
/database(groupe DATA) dans l'éditeur : ouvre un sélecteur de templates, crée une database inline liée à la page et insère un blocembed_type:'collection'rendu parFlowDeckDB.renderInto. - Le bouton « Database » de la barre Get Started ouvre désormais le même sélecteur (au lieu de créer une database vide directement).
Added — Templates de database prédéfinis
- 6 templates intégrés seedés (migration v4) : Project tracker, CRM / Contacts, Task list, Content calendar, Meeting notes, Reading list — avec icône, description et schéma de propriétés.
app/services/db_templates.py:materialize_properties()(schéma →collection_properties) etcreate_from_template()(collection + propriétés + vue par défaut).POST /db/apietPOST /db/inline/apiacceptent"template": "<nom>"et matérialisent les propriétés (titre exclu — c'est le titre de ligne). Colonneiconajoutée àdatabase_templates(migration v4).apply_db_template(/workspace/templates/database/{id}/apply) matérialise les propriétés.
Added — Validation des propriétés (required / unique / min / max)
- Nouvelle colonne
collection_properties.validation_json(migration v4) ; le type/format et les règles de validation sont portés parvalidate_property_rule()dansproperty_types.py(required, unique, min, max, min_length, max_length). - Serveur :
create_page_apietupdate_page_api(/db/{c}/pages/api,/db/pages/{id}/api) valident les valeurs avant écriture → 400 + message clair. La règleuniqueexclut la page en cours d'édition. Les valeurs sont résolues par id ou par nom. - API propriétés :
POST/PUT /db/{c}/properties/apiacceptentvalidation(persisté). - UI (
_database_table_scripts.html) : la modale « Add property » expose Required, Unique, Min, Max ; en cas de 400 à l'édition d'une cellule, la cellule est marquée en rouge et un toast affiche le message (valeur restaurée).
Tests
- 271 tests (+9 dans
tests/test_db_advanced.py) : templates seedés, création de collection/inline depuis template (propriétés matérialisées), apply template, validation required/unique/min-max (create + update, exclusion de la ligne courante), persistance de la config de validation, payload collection.
Livre deux chantiers du roadmap v5 : la migration au système de schéma versionné (v5.2.0, priorité n°1 — débloque tout le reste) et la Command Palette + recherche full-text (v5.0.0).
Added — Command palette (v5.0.0)
- Palette de commandes
Ctrl+K/Ctrl+Pdansbase.html: modale centrée autofocusée, navigation clavier (↑/↓/Enter/Esc), surlignage fuzzy des correspondances, recherche universelle et quick actions (Nouvelle page, Library, My Tasks, Trash, Settings, Help). Le bouton Search de la sidebar etopenQuickFind()ouvrent désormais la palette (fini le toast « Quick Find — Ctrl+K »). - Endpoint
GET /api/search?q=(app/routers/search.py) + serviceapp/services/search.py: recherche unifiée des pages (titre + contenu) et des databases (nom + description), scopée aux workspaces accessibles de l'utilisateur. - Index full-text FTS5 (
pages_fts, migration v3) avec triggers de synchronisation (insert/update/delete) sur la tablepages; repli automatique surLIKEsi FTS5 absent. Exclusions automatiques des pages supprimées (corbeille).
Added — Migrations versionnées (v5.2.0)
- Runner léger
app/migrations.py(alternative à Alembic pour ce projet SQLite) : tableschema_versionenregistrant la version appliquée ; le schéma de base existant (init_db) devient la baseline v1, et chaque changement futur est une étape versionnée appliquée une seule fois, dans l'ordre. - Migration v2 — indexes manquants :
users(email),user_oauth_tokens(user_id, provider),collections(workspace_id),pages(workspace_id),pages(deleted_at). - Migration v3 — FTS5 :
pages_fts+ triggerspages_fts_ai/ad/au+ backfill. init_db()termine désormais parapply_migrations(conn): nouveau schéma et bases existantes convergent sans rejouer les migrations déjà appliquées.
Tests
- 267 tests (8 nouveaux dans
tests/test_search_migrations.py) : suivi de la versionschema_version, indexes créés, table/triggers FTS5, synchronisation de l'index, recherche pages+collections, exclusions de la corbeille, requête vide et sans résultat.
Corrections
- Test de connexion multi-provider : le modèle configuré globalement (ex.
deepseek-v4-flash) n'est plus envoyé lorsqu'on teste un autre provider (ex. nvidia) — c'était la cause d'un HTTP 404 « model not found ». Chaque provider utilise désormais son modèle par défaut tant que le modèle global ne le concerne pas. - Presets NVIDIA actualisés : les anciens modèles (
nvidia/llama-3.1-70b-instruct,nvidia/nemotron-4-340b-instruct) étaient retirés de la plateforme ou soumis à abonnement ; liste remplacée par des modèles disponibles (nvidia/nemotron-3-super-120b-a12b,meta/llama-3.1-70b-instruct,deepseek-ai/deepseek-v4-pro,z-ai/glm-5.2, …).
Note : un 404 persistant après cette correction vient de NVIDIA lui-même (code « Function … : Not found for account ») — cause fréquente : le droit « Public API Endpoints » pas activé sur le compte/clé pour le modèle choisi.
v4.15.4 (2026-09-06) — Correctifs listes agent (@ et /)
Corrections
- Menus « @ » vides : le template Alpine du menu de mentions avait deux racines (Alpine n'en accepte qu'une) — seuls les titres de sections s'affichaient, sans éléments. Les éléments sont maintenant bien rendus sous chaque section.
- Sélection clavier visible dans le menu « / » : le changement de focus (↑/↓) n'était pas
visible faute de style
.focus; ajout d'un surlignage (fond + barre d'accent à gauche).
v4.15.3 (2026-09-06) — Agent : mentions @ par espace courant + skills composés en arrière-plan
La commande « @ » propose en priorité les fichiers de l'espace de travail ouvert, puis les autres contextes (collections, pages de collections, autres documents). La navigation clavier (↑/↓) positionne maintenant visuellement la sélection dans la fenêtre (défilement), et les fichiers identiques ne sont plus affichés plusieurs fois (déduplication par titre).
Améliorations
- Mentions @ contextuelles : nouvelle API
/api/agent/mentionspar sections : Fichiers de l'espace courant («workspace_idtransmis par le frontend »), Collections / bases, Pages de collections, Autres documents. - Navigation clavier corrigée : ↑/↓ font défiler la liste ouverte pour garder la sélection
visible à l'écran (aussi appliqué au menu
/). Entrée/Tab sélectionne toujours l'élément focalisé. - Déduplication : deux fichiers du même type et même titre (ex. « Sans titre », « Aussi Vide ») n'apparaissent qu'une seule fois dans les propositions.
- Skills composés en arrière-plan : sélectionner un skill n'injecte plus son texte dans la boîte
d'édition. À l'envoi la requête est assemblée :
contexte1 + contexte2 + skill-1 + skill-2 + texte. Les skills intégrés (templace) et enregistrés (skill_ids) sont tous deux pris en compte ; les contextes @ continuent d'être résolus en contenu côté serveur.
v4.15.2 (2026-09-06) — Agent : skills multi-épinglés en bulles + chips de contexte cliquables
Les skills s'épinglent désormais au contexte comme les mentions @ (bulles « / » purples dans l'éditeur du chat), on peut en associer plusieurs à un même post, et chaque bulle de contexte référencée s'ouvre d'un clic comme document courant.
Améliorations
- Skills en bulles : sélectionner un skill (menu
/, intégré ou enregistré) ajoute une vraie bulle dans le composer, comportement identique aux mentions@. La bulle d'un skill intégré greffe son modèle de demande dans le texte ; plusieurs skills peuvent coexister. - Plusieurs skills par post : l'API
/runaccepteskill_ids(tableau) et l'engine injecte tous leurs prompts dans les instructions système (skill_idreste supporté pour la rétro-compatibilité). - Chips de contexte cliquables : cliquer sur une bulle de contexte (
@ document / page / base) ouvre l'élément comme document courant —document:<id>/page:<id>→/pages/<id>,collection:<id>→/db/<id>. Le bouton « ✕ » retire toujours la bulle (sans ouvrir). - Envoi possible avec uniquement des skills (sans texte) : « Applique le(s) skill(s) sélectionné(s)… ».
Correctifs
- L'écriture du chat (
send) renvoie désormais tous lesskill_idépinglés viaskill_ids.
v4.15.1 (2026-09-06) — Agent : réparation des conversations réelles (protocole tool_calls)
Le chatbot ne « répondait » plus : avec un fournisseur réel, dès qu'un outil était appelé la passe suivante était refusée par l'API (message assistant sans ses
tool_calls) et l'agent retombait silencieusement sur le mock hors-ligne, qui se contentait de répéter la question.
Correctifs
- Protocole tool-calling conforme (
agent_engine.py) : le message assistant qui annonce un appel d'outil transporte désormais sestool_calls(avecid), et chaque résultat d'outil répond avec letool_call_idcorrespondant (y compris en cas de refus/permission). Le run se poursuit alors correctement et se termine par une vraie réponse du modèle. - Plus de repli silencieux (
llm_client.py) : quand un fournisseur réel configuré échoue, l'erreur remonte (événement SSEerror) au lieu de produire silencieusement un écho hors-ligne. Le mock n'est utilisé que si le fournisseur est réellement non configuré (offline/ pas de clé). - Les
tool_callsanalysés conservent leuridet les arguments bruts (arguments_raw). - Test de régression
test_engine_tool_protocol_messages.
v4.15.0 (2026-09-06) — Agent : actions sous chaque réponse, mentions @ & skills /
Le panneau FlowDeck Agent gagne l'expérience « type Notion AI » : chaque réponse de l'agent expose des actions rapides (copier, insérer dans la page, feedback 👍/👎), on peut épingler au contexte plusieurs documents / pages / bases via la commande @ (ou le bouton +), et la commande / propose des skills de travail réutilisables en plus des commandes admin existantes.
Sous chaque réponse de l'agent
- ⧉ / ➕ / 👍 / 👎 : boutons à icônes seules (infobulle au survol) — copier la réponse, insérer dans la page ouverte, feedback 👍/👎 enregistré en base.
- Le bandeau statique « Contexte : … » du haut du panneau est supprimé.
Contexte épinglé — commande « @ » / bouton « + » (style Notion AI)
- Le composeur est maintenant un éditeur contenteditable : les références sélectionnées s'insèrent inline comme des pastilles cliquables (icône + nom) directement dans le message.
- Au-dessus du composeur, une barre de contexte groupée rassemble les fichiers épinglés (rangée documents, icônes 📄) et les skills (rangée séparée, icône ✨), chacun retirable.
- @ ouvre le sélecteur (icône + titre + chemin) listant documents, pages et bases ; l'élément choisi devient un jeton inline et une puce de contexte. + épingle un élément au contexte sans l'insérer inline. Les puces persistent jusqu'au retrait (et sont vidées en nouveau chat).
- Contexte d'ouverture : ouvrir l'agent sur un document (
/pages/:id) ou une base (/db/:id) ajoute automatiquement ce contexte comme mention (puce épinglée) — plus de bandeau statique. - À l'envoi, chaque référence est transmise comme mention ; le backend résout son contenu réel.
Skills — commande « / »
- Le menu / liste les skills intégrés (research, resume, brainstorm, plan, meeting-note,
livrable…), les skills enregistrés (table
agent_skills) et les commandes admin classiques. - Un skill intégré pré-remplit le composeur d'un modèle à compléter ; un skill en base s'épingle en
chip et est appliqué via
skill_idà chaque envoi. - Navigation clavier (↑/↓/Entrée/Échap) dans les menus ; aucun envoi parasite pour « / » seul.
Infra & API
- Nouvelle table
agent_feedback(rating, conversation/message, extrait, commentaire). GET /api/agent/mentions?q=: recherche des éléments mentionnables du workspace.POST /api/agent/feedback: enregistre un retour 👍/👎.VERSION→ 4.15.0 ;app/main.pyversion → 4.15.0.
v4.14.0 (2026-09-06) — Agent : création de documents dans un espace + nouveaux outils & titre auto
L'agent sait enfin créer, lire, modifier et supprimer des documents (pages éditeur) dans un espace de travail — la demande « crée un document « Projet » dans le workspace « TEST WS 1 » » ne se termine plus par un simple
search_workspacevide. Il liste aussi les espaces, et renomme automatiquement les conversations avec un titre descriptif au lieu de « Nouvelle conversation ».
Outils (nouveaux / corrigés)
create_document: crée une page éditeur (pages) dans un espace (parworkspace_idouworkspace_name), avec contenu Markdown optionnel — snapshot d'undo.read_document: lit un document (titre + contenu + métadonnées).read_workspaces: liste les espaces accessibles (rôle, nb de documents/collections).delete_document: suppression → corbeille (deleted_at), annulable (softdelete).write_blocksétendu : renommage de titre et/ou écriture des blocs ; undo restaure titre + contenu.search_workspaceétendu : recherche désormais aussi les documents et les espaces de travail.
Contexte & planification
- Contexte de l'agent enrichi : sections « Documents » et « Espaces de travail » (avec ids) pour que le LLM cible le bon espace. Guide mis à jour. Mock hors-ligne : détection « créer un document dans un espace » / « lister les espaces ».
Conversations
- Auto-titre : après la première exécution d'une conversation encore nommée « Nouvelle conversation », l'agent génère un titre descriptif (déterministe, hors-ligne sûr) ; l'historique devient navigable.
UX
- Indication claire dans le composeur du panneau : Entrée ↵ = envoyer · Maj+Entrée = nouvelle ligne (le comportement existait déjà, il est maintenant visible + placeholder mis à jour).
Infra
VERSION→ 4.14.0 ;app/main.pyversion → 4.14.0.
v4.13.2 (2026-09-06) — Saisie libre « écrire un texte » → proposition à appliquer au document
Quand un document est ouvert et qu'on tape directement une demande de rédaction/contenu dans le chat (« Écrire un texte sur… », « Rédige… », « Résume… », « Traduis… »), la requête est maintenant routée vers la génération de texte (sans outils) et affichée comme proposition à appliquer ou rejeter — au lieu d'un
search_workspacepuis d'un simple « Objectif traité ». « Traduire » remplace le contenu de la page ; les autres demandes l'insèrent en fin de page.
Fix
- Envoi libre avec contexte document : détection d'intention de contenu (écrire/rédiger/générer/
résumer/traduire/améliorer/note de réunion/texte sur/série…) →
POST /api/agent/generate+ aperçu « ✓ Appliquer au document / ✕ Rejeter ». - Mock : « écrire » (infinitif) reconnu comme verbe de rédaction.
Infra
VERSION→ 4.13.2 ;app/main.pyversion → 4.13.2.
v4.13.1 (2026-09-06) — Corrections actions contenu Agent & aperçu à approuver
Corrige les actions de contenu sur document (« Résumer », « Traduire cette page », « Proposer des améliorations », « Créer une note de réunion ») qui partaient en recherche (
search_workspace) sans retour utile, et ajoute un flux aperçu des changements → Appliquer / Rejeter.
Fix
- Le contenu du document n'est plus interprété comme des intentions d'outil : le planificateur
(mock) n'analyse que l'objectif de l'utilisateur, jamais le texte injecté dans
# Contexte. Un document contenant « recherche », « collection », etc. ne déclenche plussearch_workspace/create_collectionintempestifs. - Ask AI n'emprunte plus le canal outil : il utilise la génération de texte directe.
Added
- Endpoint
POST /api/agent/generate: génération de texte sans outils (l'IA répond à partir du contexte du document fourni, sans chercher/créer dans le workspace). - Aperçu & approbation : les actions de contenu sur document affichent la proposition de
l'agent dans le panneau avec boutons « ✓ Appliquer au document » / « ✕ Rejeter ». Appliquer
insère la proposition (mode
insert) ou remplace le contenu de la page (modereplacepour « Traduire cette page ») viawindow.fdApplyDocument(); rejeter la conserve sans modification. En mode hors-ligne, l'action explique que la modification nécessite un modèle connecté (pas d'application accidentelle).
Infra
VERSION→ 4.13.1 ;app/main.pyversion → 4.13.1.
v4.13.0 (2026-09-06) — Agent : panneau « Notion AI », ouverture fiable (Ctrl+J) & contexte universel
Refonte complète du panneau Agent (style Notion AI) : ouverture/fermeture fiable (API
window.fdAgent.open/close/toggle, bouton flottant + sidebar « Agents » + raccourciCtrl/Cmd+J), contexte détecté et épinglé à l'ouverture (document en cours, bibliothèque, My Tasks, espaces, base de données, board, corbeille…) et sélecteur fournisseur + modèle intégré à la zone de saisie.
Added
- Ouverture robuste :
window.fdAgent.open()/close()/toggle()appliquent l'état directement (classe.open+ attribut) ; FAB, entrée « Agents » du sidebar, icône Chat etfdAgent.askouvrent explicitement le panneau (fini le toggle silencieux). RaccourciCtrl/Cmd+Jglobal. - Contexte universel
window.FlowDeckCtx: détection par priorité — (1) marqueur d'écran (window.fdViewContext/data-fd-context), (2) document ouvert (éditeur : titre + contenu des blocs), (3) route de l'application (Accueil, Bibliothèque, Corbeille, My Tasks, Espaces, Espace local/Gitea, Base/db, Board, Notes, Paramètres…). Le contexte est épinglé à l'ouverture du panneau, affiché en chip (« Contexte : … ») et rafraîchi automatiquement si l'utilisateur ouvre un autre document avant d'envoyer. - Fournisseur & modèle affichés : sous-titre du panneau
Provider · Modèle(ex.OpenAI · gpt-4o) dès qu'un modèle réel fonctionnel est sélectionné ; « hors-ligne (mock) » n'apparaît que lorsqu'aucun fournisseur actif n'existe. Sélecteurs provider → modèle regroupés dans une pastille « Auto · » au-dessus de la zone de saisie. - Actions rapides contextuelles (état vide) en français selon la section : Résumer / Traduire / Améliorer un document, Créer une note de réunion, Analyser une base, Mes tâches / planifier, ou guides « Comment utiliser FlowDeck ? » et création de collection/board.
Changed
- Panneau redessiné façon Notion AI : largeur 470 px, en-tête « How can I help you today? »,
icône avatar, ligne de contexte, historique, grande
textareaarrondie auto-redimensionnable (jusqu'à ~220 px) avec toolbar (+-équivalent, contexte, modèle, flèche d'envoi) et sélection de modèle en popover.
Infra
VERSION→ 4.13.0 ;app/main.pyversion → 4.13.0.
v4.12.1 (2026-09-05) — Corrections configuration Agent & IA + AI Meeting Note
Correctifs UI sur la section Settings → Agent & IA et remplacement de l'ancien bouton « AI meeting note » (qui insérait du texte) par une vraie boîte de réunion interactive.
Fix
- Champs « Clé API » : le
x-textembarquait le SVG de l'icône œil dans l'attribut HTML, ce qui cassait l'attribut et laissait du texte résiduel (sk-…': '👁'" style="top:50%;">). Les boutons d'affichage/masquage utilisent désormais deux<span x-show>avec l'icône en contenu. - Champs « URL API » : pré-remplis avec l'URL réellement utilisée par l'application (base par
défaut du fournisseur, ex.
https://api.openai.com/v1) quand aucune URL personnalisée n'est stockée — exposée viabase_urldans/api/agent/providers(fournisseur par défaut + au changement de provider).
Changed
- AI Meeting Note : le bouton « Get started » ne génère plus du texte via l'agent. Il crée un
bloc
meetinginteractif dans la page (page renommée « Meeting @date » si vide) :- Étape 1 — consentement (moi-même / message audio auto) + « Start transcribing » ;
- Étape 2 — transcription live via Web Speech API (fr-FR, horodatée), boutons Pause / Stop, fallback « sans audio » (transcript à saisir/coller) si le navigateur ne supporte pas ;
- Étape 3 — onglets Notes / Transcript / Summary, bouton « Générer le résumé » (helper headless
window.fdAgent.generatesur le FlowDeck Agent) produisant Résumé / Décisions / Action items, copie presse-papiers et « Nouvelle transcription ». - Persistance du bloc et de son état dans la page (champ
meetingajouté aux blocs sauvegardés).
Infra
VERSION→ 4.12.1 ;app/main.pyversion → 4.12.1.
v4.12.0 (2026-09-05) — Agent & IA : refonte des réglages, fournisseurs activés/fonctionnels dans le panneau, contexte document & guide
Refonte de la section Settings → Agent & IA pour la rendre plus claire, et aligne le panneau Agent sur la réalité de la configuration : seuls les fournisseurs configurés ET dont le test de connexion a réussi sont proposés (avant, tous les fournisseurs connus apparaissaient, même non configurés). Le panneau sait aussi sur quel document l'utilisateur travaille et peut guider sur l'utilisation de l'application quand aucun document n'est ouvert.
Added
- Vérification des fournisseurs : colonnes
verified/verified_at/last_errorsuruser_llm_keysetllm_config(migration automatique au démarrage). Un fournisseur est « fonctionnel » après un test de connexion réussi ou un chargement de modèles réussi. - Endpoint non-admin
POST /api/agent/keys/{provider}/test: teste la clé enregistrée de l'utilisateur (sans mock) et met à jour l'étatverified; l'endpoint admin/providers/testmarque le fournisseur par défaut de l'espace. /api/agent/providersenrichi : chaque provider exposeconfigured,verified,functional,last_erroretsource(user/global/open) ;default_provider+default_verifieden tête de réponse.- Panneau Agent : les listes fournisseur/modèle ne contiennent plus que les providers activés et fonctionnels (+ mode hors-ligne). Bandeau « Aucun fournisseur activé » avec lien vers les réglages et rappel des clés « à tester » le cas échéant.
- Contexte document : le panneau joint automatiquement la page ouverte (titre + contenu des blocs) à chaque requête — l'agent peut interagir avec le document courant.
- Guide d'utilisation : le prompt système intègre un guide FlowDeck concis pour répondre aux questions « comment faire… ? » (pages, collections/vues, Gitea, corbeille, réglages…) lorsqu'aucun document n'est fourni.
Changed
- Settings → Agent & IA refondu : carte de statut (prêt / N fournisseurs actifs / mode hors-ligne), cartes de fournisseurs avec badges d'état, erreur du dernier test, boutons « Enregistrer & tester », « Tester », « Modèles », « Supprimer » et encart d'aide.
- Le bouton Save configuration admin gagne un rappel « Tester la connexion » pour activer le fournisseur pour tous ; changer de clé réinitialise la vérification.
Fix
- Saisie clé : une clé vide conserve désormais l'existante aussi pour la config globale (au lieu de
l'effacer), et un changement de clé invalide l'ancien statut
verified.
Infra
VERSION→ 4.12.0 ;app/main.pyversion → 4.12.0.
v4.11.1 (2026-09-05) — Correction & intégration des points d'entrée IA
Aligne les entrées AI de l'interface sur le FlowDeck Agent (alignement Guide Notion AI) et corrige les trois boutons qui ne fonctionnaient pas : Ask AI, AI meeting note (toolbar « Get started » de l'éditeur de page) et le bouton rond flottant FlowDeck Agent (coin bas-droit).
Fix
- Bouton flottant Agent 🤖 (coin bas-droit) : le chat restait inerte tant qu'aucune conversation
n'existait (
send()retournait silencieusement sanscurrentConv). Ajout d'une création de conversation lazy (ensureConversation()) effectuée avant chaque envoi — la 1ère saisie crée la conversation puis l'exécute (mode offline ou LLM réel). - Mode hors-ligne plus utile : le mock LLM (
_draft_reply) génère désormais un vrai contenu structuré pour les demandes de rédaction de page (« Ask AI », titre détecté via « intitulée ») et les AI meeting notes (squelette Résumé / Décisions / Action items), au lieu de se contenter de renvoyer le prompt tel quel — les boutons produisent donc du contenu même sans clé API. - « Ask AI » & « AI meeting note » : ne faisaient qu'insérer du texte placeholder
(« Ask AI to write... » / « AI Meeting Note ») sans aucun appel IA. Ils déclenchent désormais une
génération inline réelle via le FlowDeck Agent :
- méthodes
askAI()/meetingNote()/aiRun()/applyAIBlocks()sur l'éditeur de page ; - un prompt contextuel est envoyé au panneau agent (exposition d'
window.fdAgent.ask) ; - la réponse (
event finaldu flux SSE) est insérée automatiquement dans la page sous forme de blocs édités (hookwindow.__fdInsertAI).
- méthodes
- Un état
aiBusyévite les doubles envois pendant la génération.
Infra
VERSION→ 4.11.1.
v4.11.0 (2026-09-05) — Agent IA : clés API par utilisateur & chargement dynamique des modèles
Suite de v4.10.1 : migre la config LLM d'un global admin vers des credentials par utilisateur. Chacun peut enregistrer plusieurs provider + clé API dans son profil, les modèles disponibles sont chargés automatiquement depuis le fournisseur, et le provider/modèle actif d'une conversation se pilote directement dans le chat via des commandes slash.
Added
- Clés par utilisateur : table
user_llm_keys(UNIQUE(user_id, provider)) + serviceapp/services/llm_config.py:get_user_llm_key,list_user_llm_keys(masqué),upsert_user_llm_key,delete_user_llm_key. Une clé vide conserve l'existante. - Chargement dynamique des modèles :
fetch_provider_models()(httpx) — GET{base}/modelspour OpenAI-compatible (Bearer), headersx-api-key/anthropic-version(Anthropic),x-goog-api-key(Gemini) ; stockés dansmodels_jsonet fusionnés dansGET /providers. - Endpoints API (tout utilisateur authentifié) :
GET /api/agent/keys,PUT/DELETE /api/agent/keys/{provider},POST /api/agent/keys/{provider}/models(fallback sur la clé stockée, pas de fuite de clé),PATCH /api/agent/conversations/{id}(title / provider / model — commande slash).
POST /run: utilise la clé API de l'utilisateur pour le provider de la conversation (sinon config globale /.env/ offline mock).- UI Settings → Agent & IA (visible pour tous, plus seulement admin) : carte par provider (clé API masquée, URL API, « Charger les modèles » en live, modèle par défaut, Enregistrer / Supprimer). La config globale reste admin sous « Configuration globale ».
- Commandes slash dans le panel agent :
/help,/providers,/keys,/provider <nom>,/model <nom>— menu de suggestions live, appliquées viaPATCHet sans appel LLM.
Infra
VERSION→ 4.11.0 ; migration idempotente (création tableuser_llm_keys+ index).
Tests
- 239 tests verts (+7 : CRUD clés + masquage des secrets, isolation par utilisateur,
provider invalide, fetch modèles (clé stockée / body gagnant / erreur), PATCH conversation,
/runutilise la clé de l'utilisateur).
Comble le trou UX de v4.10.0 : l'utilisateur pouvait discuter avec l'agent mais ne pouvait configurer ni provider ni modèle. Ajout d'un sélecteur provider/modèle dans le panneau, d'une config runtime persistée en base (table
llm_config) et d'un écran admin avec test de connexion.
Added
- Sélecteur provider/modèle dans le panneau agent (
agent_panel.html) : deux<select>(provider + modèles connus par provider) dans l'en-tête du chat, branchés surPOST /runet persistés par conversation (colonnesprovider/modelsuragent_conversations, migrées automatiquement). Bouton ⚙️ pointant vers la config admin. - Endpoints API :
GET /api/agent/providersenrichi : liste complète des providers avec modèles connus,requires_key,api_baseethas_api_key.PATCH /api/agent/providers(admin) : persiste provider/modèle/clé/base en runtime.POST /api/agent/providers/test(admin) : test de connexion sans fallback mock (méthodeLLMClient.ping()) ; le providerofflinerépond sans réseau.
- Table
llm_config(1 ligne, id=1) + serviceapp/services/llm_config.py: précédence base (runtime) >.env, créée seulement au premier enregistrement. - Écran admin : nouvelle section Agent & IA dans Settings (onglet Admin) : provider, modèle, clé API (masquée / réaffichable), URL API optionnelle, boutons Save configuration et Test connection avec retour d'état inline.
Fixed
LLMClient.__init__: le modèle par défaut suit maintenant la config runtime (DB >.env) au lieu d'être toujoursgpt-4o;PROVIDER_MODELSdocumente les modèles connus par provider.
Infra
VERSION→ 4.10.1 ; migration idempotente des colonnesagent_conversations.provider/model.
Tests
- 232 tests verts (+6 : providers enrichi, PATCH config (admin + 403 non-admin), test connexion offline, test connexion clé manquante, persistance provider/modèle par conversation).
v4.10.0 (2026-09-05) — FlowDeck Agent : agent IA natif conversationnel
Implémentation complète du pilier « Agent IA » : un agent ReAct intégré qui agit sur le workspace (pas seulement répond) — panneau de chat, boucle raisonnement→action, streaming SSE, 18 outils avec snapshots rollback, permissions par rôle, contexte automatique, custom agents, déclencheurs planifiés, skills réutilisables et multi-LLM (offline mock + 8 providers).
Added
- Interface conversationnelle : panneau agent dans le sidebar (🤖 Agents) piloté par Alpine.js + streaming SSE ; FAB ouvrant le chat ; historique de conversations.
- Boucle ReAct (
app/services/agent_engine.py) : raisonnement → action → observation, max 12 itérations, budget de tokens, timeout, journal d'audit + fonctionundo_action()(rollback). - Streaming SSE : endpoint
/api/agent/conversations/{id}/runqui émetreasoning,actionetfinalen temps réel. - 18 outils (
app/services/tool_registry.py) :search_workspace,read_collection,read_page,create_collection,create_view,add_property,create_page,update_page,write_blocks,add_relation,create_sub_item,add_dependency,apply_template,delete_page,delete_collection,read_gitea_issues,sync_gitea,create_gitea_issue— chacun avecToolResult+ snapshot d'undo réversible. - Permissions (
app/services/permission_manager.py) : même ACL que l'utilisateur par rôle workspace (viewer/editor/admin/owner) + gating des outils. - Contexte automatique (
app/services/context_builder.py) : snapshot du workspace actif, collections, pages, mentions@, fichiers uploadés injectés dans le prompt système. - Multi-LLM (
app/services/llm_client.py) : OpenAI, Anthropic, Google, Ollama, DeepSeek, QwenCloud, NVIDIA, OpenRouter + offline mock (planner déterministe, aucune clé requise). - Custom agents, skills, déclencheurs : CRUD agents + conversations,
agent_*tables (agents,agent_conversations,agent_messages,agent_actions,agent_skills,agent_triggers), skills (/api/agent/skills, apply), scheduler de fond pour triggers planifiés.
Infra
VERSION→ 4.10.0 ; config LLM (LLM_PROVIDER/MODEL/API_KEY/API_BASE,AGENT_MAX_*) ; exclusions CSRF/api/agent; routeur agent + tâche scheduler dans le lifespan deapp/main.py.
Tests
- 226 tests verts (+18 v4.10.0 : schéma DB, mock LLM, permissions, outils+undo, engine ReAct + audit + rollback, CRUD agents/conversations, streaming SSE, skills, tools, providers).
v4.9.0 (2026-09-04) — Collaboration : commentaires inline, mentions @, notifications
Implémentation complète du pilier « Collaboration » — basée sur la revue des docs Notion (
docs/Guide_Complet_Notion_sharing_collaborartion.md) : commentaires avec ancres inline, mentions@avec autocomplétion, centre de notifications in-app et emails SMTP.
Added
- Commentaires inline sur les pages : sélection d'un texte dans l'éditeur → bouton flottant
« 💬 Comment » → commentaire ancré (
block_id+ offsets). Tablecommentsétendue (target_type,target_id,anchor_block_id,anchor_start,anchor_end) et migrée de son FKcollection_pagesvers un schéma générique (aucune perte de données, idempotente). - Panneau de commentaires dans l'éditeur : liste, résolution (✔/↪), suppression, compteur dans la topbar.
- Mentions
@: autocomplétion en temps réel (recherche d'utilisateurs), insertion de@logindans un bloc ou un commentaire → notification ciblée à l'utilisateur mentionné. - Centre de notifications in-app : cloche dans la topbar (badge non-lus, polling 30s),
panneau déroulant, « mark as read » / « mark all read ». Table
notifications. - Emails de notification : service SMTP (
app/services/mailer.py) + templates HTML ; préférences email par utilisateur (comments/mentions) réglables dans Settings → Notifications. Sans SMTP configuré, seules les notifications in-app sont émises (aucune erreur). - API :
GET/POST /api/notifications,/api/notifications/read|read-all|prefs,/api/notifications/users/search,GET/POST /api/pages/{id}/comments,PUT/DELETE /api/comments/{id},POST /api/pages/{id}/mentions. - Config SMTP (
SMTP_HOST/PORT/USER/PASSWORD/FROM/USE_TLS,APP_BASE_URL) dans.env.example.
Infra
VERSION→ 4.9.0 ;app/main.py(log +version=) ; routernotifications+collaborationenregistrés ; exclusions CSRF (/api/notifications,/api/comments) ; leRateLimitMiddlewarerespecte désormaissettings.rate_limit_enabled.
Tests
- 208 tests verts (+9 v4.9.0 : table notifications, commentaires inline + mentions, centre de notifications, préférences, recherche utilisateurs, résolution/suppression, mentions de page).
Fixed
- Bouton « + Row » (bas du tableau) inopérant — le code passait la nouvelle ligne en argument
deleteCountdeArray.spliceau lieu d'utilisersplice(index, 0, ligne): aucune ligne n'était jamais insérée. Corrigé ; les insertions de lignes (menu contextuel aussi) fonctionnent. - Coloration/handles alignés sur l'en-tête.
Added
- Bouton « + » à droite du tableau (sur toute la hauteur) → ajoute une colonne à la droite (équivalent d'un « Add column » comme « Add Row »).
- Redimensionnement des colonnes à la souris : au survol d'une bordure de colonne (en-tête) le curseur devient
col-resize; glisser ajuste la largeur. Les largeurs sont persistées dans le bloc (colsW) → conservées au rechargement, à l'ajout/suppression et dans l'auto-save.
Infra
VERSION→ 4.8.1 ; cache CSSapp.css?v=4.8.1.
v4.8.0 (2026-09-03) — Bloc Tableau simple (mode édition Notion)
Insertion via
/table, cellules éditables au clic, ajout/suppression/modification de lignes et colonnes comme dans Notion.
Added
- Bloc
tabledans l'éditeur de page. Nouvelles commandes slash/table(menu « BASIC ») → tableau 3×3 avec en-tête ; première ligne stylée en en-tête, cellulescontenteditableéditées au clic, auto-sauvegarde (format de bloc conservé :{type:'table', rows:[...]}). - Gestion des colonnes : bouton de poignée (⋮⋮) au-dessus de chaque colonne → menu contextuel Insert left / Insert right / Duplicate / Clear contents / Delete column / Delete table.
- Gestion des lignes : bouton « + Row » sous le tableau (clic = ajouter une ligne) + menu contextuel (clic droit sur une cellule de corps) → Insert above / Insert below / Duplicate / Clear row / Delete row / Delete table.
- Import Markdown (GFM) :
md2bdétecte les tableaux pipe (| a | b |+ ligne de séparateurs) et produit un bloctableéditable au lieu de paragraphes aplatis (pages.md/markdown). - Roundtrip Markdown :
blocksToMarkdown(JS) et l'export Python reconstruisent un tableau pipe valide depuis les blocs. - Export : les pages contenant un bloc
tablesortent correctement en Markdown / HTML / PDF (géré côté serveur). - UX : cliquer sous un tableau en fin de page ajoute un paragraphe pour continuer la rédaction.
Infra
VERSION→ 4.8.0 ;app/main.py(log +version=) ; cache CSSapp.css?v=4.8.0; ROADMAP renuméroté (v4.8.0 Bloc Tableau, Collaboration → v4.9.0, Agent → v4.10.0).
Tests
- Suite pytest verte (199) ; vérification syntaxe JS du template via
node --check.
v4.7.3 (2026-09-03) — Fix export PDF/HTML : tableaux + émojis
Fixed
- Tableaux Markdown rendus comme du texte brut dans les exports HTML/PDF (les lignes
| a | b |ressortaient en paragraphes). Ajout d'un parseur GFM de tableaux (_md_to_blocks→ bloctable) et d'un rendu en vrai<table>(en-tête<th>, corps<td>, alignement gauche/centre/droite, bordures fines via.ftable). Le format Markdown reconstruit un tableau pipe valide. - Émojis en « carrés noirs » dans le PDF. Cause : le moteur
xhtml2pdf(reportlab) n'embarque que des polices de base sans glyphes Unicode/émojis. Le moteur PDF passe à WeasyPrint (vraies tables CSS + émojis couleur via Pango +fonts-noto-color-emoji, installés dans l'image Docker). Repli automatique surxhtml2pdfsi WeasyPrint n'a pas ses libs natives (ex. poste de dev Windows) — le contenu s'exporte quand même.
Infra
Dockerfile: ajout des libs WeasyPrint (pango/harfbuzz/gdk-pixbuf/shared-mime-info) + policesfonts-dejavu-coreetfonts-noto-color-emoji.requirements.txt: +weasyprint==69.0(xhtml2pdf conservé en repli).
Tests
- 199 tests (4 nouveaux) : parse table →
<table>HTML réel + alignements ; standalone HTML embarque.ftable; roundtrip table → markdown pipe ; PDF d'une page avec table = PDF valide. - Vérifié en réel sur
README.md: PDF avec tableau structuré + émojis en couleur (pixels colorés confirmés), HTML avec tableau bordé.
v4.7.2 (2026-09-03) — Fix export : le contenu des documents était absent
Fixed
- Export Markdown / HTML / PDF : seuls le nom de page et le titre étaient inclus, jamais le contenu. Cause : le service d'export ne lisait que les pages en
content_format='blocks'. Or les documents peuvent être stockés autrement :content_format='file'(fichiers.md/code uploadés) : lecontentde la page n'est que des métadonnées JSON — le vrai texte est un fichier sur disque (/data/uploads/workspace_*). L'export n'allait jamais le lire → uniquement le titre.content_format='markdown': le HTML/PDF se contentait d'envelopper chaque ligne en<p>(titres et listes aplatis).
- Le service résout désormais la vraie source pour les 3 formats : lit le fichier sur disque pour les pages
file, rend les pagesmarkdown/fichiers.mden blocs (headings, listes, code…), et traite les fichiers texte non-markdown comme bloc de code. Les fichiers binaires (PDF/images) sont laissés de côté (rien d'exploitable). - Chemin des uploads rendu configurable pour les tests via
FLOWDECK_DATA_DIR(défaut/data, identique àdashboard.py).
Tests
- 195 tests au total (5 nouveaux v4.7.2) : page markdown → corps exporté ; page markdown → HTML avec headings/listes ; fichier
.mduploadé → contenu réel dans Markdown/HTML/PDF ; fichier code → exporté ; fichier binaire → non déversé. - Vérifié en réel sur
/data(pageREADME.mdet arborescence « Base de Connaissances » → fichiers.md) : le corps complet est maintenant présent dans les 3 formats.
v4.7.1 (2026-09-03) — Fix UI éditeur : menus Share / More invisibles
Fixed
- Boutons « Share » et « ⋯ » (More) sans réaction visible dans l'éditeur de page — les popovers (share-dialog, more-menu, activity-popover, move-dialog), enfants de
.page-editor-wrapper(conteneur àoverflow-y:auto), étaient ancrés enabsolute; top:100%→ rendus SOUS le viewport, donc invisibles. Repositionnés enposition:fixedsous la topbar (scoped.page-editor-wrapper > …pour ne pas casser les.more-menudes pages library/local_workspace) + variantes mobile dans le media query < 768px. - Sous-menu Export se refermait — l'itém « ↗ Export » faisait
moreOpen=falseavant d'ouvrirexportOpen: les 4 formats restaient inaccessibles au clic. Devient un toggle (exportOpen = !exportOpen), le menu More reste ouvert. - Cache CSS — version du query string
app.cssbumpée (v=3.0.0→v=4.7.1) pour invalider le cache navigateur.
Vérifié
- Playwright headless (desktop 1280×800) : Share, More, sous-menu Export, popover Activity et menu More après scroll = tous visibles dans le viewport ; téléchargement Markdown + toast « Exported as Markdown » OK ; zéro pageerror.
- 190/190 tests pytest passent.
v4.7.0 (2026-09-03) — Export
Added
- Export Markdown — conversion serveur complète de tous les blocs (headings, listes, to-do, quote, code, math, toggle, colonnes, callout, image), images incluses
- Export Markdown récursif — les sous-pages sont incluses automatiquement
- Export PDF — via
xhtml2pdf(pur Python, aucun lib système), rendu print-friendly - Export HTML — document autonome self-contained (styles inline)
- Export Site — site statique multi-pages en
.zip(index.html + une page HTML par sous-page) - 4 endpoints serveur :
/api/export/markdown|html|pdf|site/{page_id} - UI : menu « More › Export » dans l'éditeur (Markdown, HTML, PDF, Site .zip)
Améliorations
- Nouveau service
app/services/export.py(conversion blocs → Markdown / HTML / PDF réutilisable) - Nouveau routeur
app/routers/export.py - Téléchargements via
Content-Disposition(avec nom de fichier encodé UTF-8)
Tests
- 190 tests au total (6 nouveaux tests v4.7.0) : Markdown, sous-pages, HTML, PDF, Site zip, 404
v4.6.0 (2026-09-02) — Content Blocks Enrichis
Added
- Callout blocks — boîtes colorées avec sélecteur d'emoji/icône cliquable
- Table of contents — bloc auto-généré depuis les headings, avec ancres de navigation
- Math equations — bloc LaTeX/KaTeX avec aperçu en temps réel (édition inline)
table_of_contentsetmath— nouveaux types dans le slash menu (éditeur)- Multi-colonnes — bloc
columnsavec layout flexible, bouton "+ Add column" / retrait - Toggle lists enrichis — contenu expandable/collapsible avec blocs enfants imbriqués
Améliorations
- Intégration KaTeX 0.16.11 self-hosté (
/static/js/katex.min.js,/static/css/katex.min.css,/static/fonts/) — aucun CDN externe - Rendu des nouveaux blocs dans les pages publiques (
/p/<slug>): TOC ancré, KaTeX, colonnes flex, toggle<details> - Export Markdown étendu aux nouveaux types de blocs
- Correction d'un bug pré-existant :
public_page.htmln'importait pas la macrofd_icon→ erreur de rendu des pages publiées
Tests
- 183 tests au total (5 nouveaux tests v4.6.0) couvrant le rendu public TOC/math/colonnes/toggle et la persistance
children
v2.7.1 (2026-07-13) — Private Pages Gitea
Added
- Table
gitea_private_pages: pages FlowDeck locales liées à un projet Gitea (user_id, owner, repo) - API CRUD: GET/POST/PUT/DELETE
/api/gitea/projects/{owner}/{repo}/private-pages - UI: liste des pages privées + éditeur titre/contenu dans le workspace Gitea
- Sidebar: lien "Private Pages" dans l'arborescence du workspace
- Persistance: les pages survivent au changement de workspace / session
Fixed
get_user_repos(limit=100)—bruno/flowdeckétait tronqué à la page 2 (30 repos par défaut)
v2.7.0 (2026-07-13) — Intégration Gitea Phase 1
Added
- OAuth2 Provider: Gitea comme fournisseur OAuth2 pour FlowDeck (Client ID/Secret dans
.env) - Redirect URI dynamique: basé sur le header
Host— fonctionne depuislocalhostet192.168.x.x - Workspace listing: 2 sections — My Workspaces + Gitea Projects (groupés par organisation)
- Tabs par org: All | user | org1 | org2 avec compteurs de projets
- Barre de recherche: filtrage live par nom/description dans Gitea Projects
- Lazy tree: arborescence chargée un dossier à la fois (API Gitea
GET /repos/{o}/{r}/contents) - File viewer: lecture fichiers Gitea avec décodage base64
- Éditeur + commit: modifier un fichier et commiter dans Gitea avec message personnalisé
- Delete fichier: suppression avec confirmation + commit
- Arborescence dans le sidebar: comme un workspace local, avec lazy-load des sous-dossiers
- Settings › Integrations: connecter/déconnecter Gitea (
GET /api/gitea/status,DELETE /api/gitea/disconnect) - Fallback token admin: opérations GET utilisent le token serveur si pas de token OAuth utilisateur
- Write ops protégées: commit et delete exigent un token OAuth utilisateur
- Routes API:
/api/gitea/orgs,/api/gitea/projects,/api/gitea/projects/{o}/{r}/tree,/api/gitea/projects/{o}/{r}/file,/api/gitea/projects/{o}/{r}/labels
Fixed
- Bouton "Register with Gitea" ne crée plus de session admin fantôme (fallback retiré)
_sidebar_datagère le cookiegitea:owner:repopour l'arborescence
v2.6.0 (2026-07-13) — My Account & Auth Locale
Added
- Section My Account: modifier username, full name, email, mot de passe
- Toggle mot de passe: bouton voir/cacher dans les formulaires login/register
- Label "Email or username": login accepte les deux formats
- Refresh cookie session: après modification du compte, le cookie est mis à jour
- Register avec Gitea: boutons dynamiques "Login/Register with Gitea" selon l'onglet actif
Fixed
- Session cookie non rafraîchi après
PUT /api/settings/account(création nouvelle session) - Input login
type="email"→type="text"(accepte usernames non-email)
v2.5.0 (2026-07-13) — Administration Avancée
Added
- Premier compte = admin automatique:
is_admin=1pour le premier utilisateur créé - Panneau Admin dans Settings: visible uniquement pour les admins
- Users & Roles: créer/modifier/supprimer utilisateurs, changer rôles
- Table
login_history: audit des connexions (IP, user_agent, timestamp) - Statistiques par utilisateur: workspaces, pages, dernière connexion
- API
/api/admin/*: users, stats, audit — protégées paradmin_required - CSRF fix: token CSRF dans toutes les requêtes admin (
adminFetch)
v2.4.0 (2026-07-13) — Tags Personnalisés par Utilisateur
Added
- Tags isolés par
user_id: chaque utilisateur voit uniquement ses propres tags UNIQUE(name, user_id): remplaceUNIQUE(name)dans la tabletags- Migration: tags existants assignés au premier utilisateur
- Filtrage transparent: l'API retourne les tags filtrés par
user_id(session cookie)
Fixed
- Affichage des tags dans le menu contextuel workspace (sync Alpine.js)
- Création de tag avec couleur persistée
- Fermeture auto du menu contextuel après ajout de tag
- Filtrage par tags:
toggleTagFilter()appelledoFilter() - Pastilles tags: fond = couleur du tag, sans rond séparé
v2.3.0 (2026-07-12) — Multi-Vues Workspace & Preview Panel
Added
- Sélecteur de vue: Tree, List, Details, Title, Content — 5 modes d'affichage
- Vue List: liste compacte avec Name, Type, Size, Modified
- Vue Details: table complète avec Path, Author, Tags
- Vue Title: grille de cartes avec icônes et métadonnées
- Vue Content: liste avec aperçu inline (taille ou nombre d'items)
- Preview Panel: panneau latéral droit avec contenu du fichier sélectionné
- Header avec icône + titre + bouton fermer
- Métadonnées (type, taille, date)
- Tags affichés en chips
- Corps avec rendu du contenu (blocks JSON → HTML, texte brut)
- Actions: Open, Rename, Delete
- Animation slide-in/out
- Tri par date: options Oldest/Newest dans le selecteur de tri
v2.2.0 (2026-07-12) — Tags & Recherche Avancée
Added
- Tags: système complet de tags avec tables
tags+page_tags, CRUD API - API Tags:
GET/POST/DELETE /api/local-workspace/items/{id}/tags,GET /api/local-workspace/tags - Vue Table enrichie: colonnes Name, Path, Size, Modified, Type, Author, Tags
- Filtrage par tags: barre de chips avec compteurs, clic pour filtrer
- Ajout/retrait tags inline: bouton + dans la table, chips avec × pour retirer
- Tree endpoint enrichi: chaque nœud retourne
size,size_display,created_at,updated_at,author,tags - Filtre "Dossiers": nouveau chip Folders dans la barre de filtres
- Auto-switch table: quand recherche/filtre actif, passe en vue table automatiquement
v2.1.1 (2026-07-12) — Fix Arborescence Workspace
Fixed
- Arborescence: création fichier/dossier dans un sous-dossier met à jour l'arbre sans rechargement
- parentFolder: corrigé le bug où
parentFolderétait nullifié avant l'insertion dans l'arbre JS - displayTree: nouvelle référence array après chaque mutation pour forcer le re-render Alpine.js
- doSort/doFilter: gèrent maintenant le cas où un filtre/tri est actif après création
v2.1.0 (2026-07-10) — Intégrations Avancées
Added
- API publique:
/api/v1(collections, pages, my-tasks) avec token auth - Token generation:
POST /api/v1/token - Webhooks sortants:
GET/POST/DELETE /workspace/webhooks+ dispatcher - PWA:
GET /manifest.json - CSRF:
/api/v1exempté
Tests
- 73/73 passent (+6 tests v2.1)
v2.0.0 (2026-07-10) — Multi-User Workspaces & Editor Complete
Added
- Workspaces: tables
workspaces+workspace_members, CRUD API, roles admin/editor/commenter/viewer - Comments: table
commentsavec thread (parent_id), resolved - Page History: table
page_history, snapshot JSON - Favorites: table
favorites, add/remove/list - Templates:
database_templates+page_templates, apply API - CSV Import/Export:
POST .../import/csv,GET .../export/csv - Public Sharing:
GET /workspace/public/{id}(read-only, no auth)
Tests
- 67/67 passent (+7 tests v2.0)
v1.9.0 (2026-07-10) — My Tasks Dashboard
Added
- My Tasks:
GET /my-tasks(HTML),GET /my-tasks/api(JSON) - Agrégation cross-collection, vues All/Today/Overdue/Next 7 days
v1.8.0 (2026-07-10) — Sub-items & Dependencies
Added
- Sub-items: parent_id auto-référence, GET/POST sub-items
- Status aggregate:
GET .../status-aggregate - Dependencies:
POST .../dependencies,POST .../check-deps
v1.7.0 (2026-07-10) — Vues Améliorées
Added
- View config:
PUT /db/views/{id}/config(group_by, card_size, cover, visible) - Save view as:
POST /db/{id}/views/save-as - List views:
GET /db/{id}/views/api
v1.6.0 (2026-07-10) — Vues Manquantes
Added
- Calendar: grid mensuel, navigation mois
- Gallery: cartes visuelles, card_size configurable
- List: vue compacte avec preview
- Timeline: barres horizontales Gantt
- Table: rendu SSR avec colonnes properties
- View tabs: navigation Table/Board/Calendar/Gallery/List/Timeline
v1.5.0 (2026-07-10) — Relations & Rollups
Added
- FormulaEngine: 19 fonctions (prop, if, concat, round, now, today, dateAdd, replace, ...)
- RollupEngine: 12 agrégations (count, sum, avg, min, max, range, unique, percent_checked)
- Relation: lien bidirectionnel, API create/link
v1.4.0 (2026-07-10) — Propriétés Avancées
Added
- Table
collection_properties: 21 types Notion - Service
property_types.py: validation, formatage, auto-values
v1.3.0 (2026-07-10) — Database Concept
Added
- Tables:
collections,collection_pages,collection_views - Router
/db: CRUD collections + pages (16 endpoints) - GiteaBoardCompat: adaptateur boards legacy → Collections
v1.0.0 (2026-07-08) — Production
Added
- FastAPI lifespan, 28 tests, CI/CD Gitea Actions, CSS 31KB, 10 templates
- 5 vues: Kanban, Table, Status Overview, Team Load, Detailed Board
- Filtres cumulables AND, tri multi-critères
- Card detail modal, checklists, commentaires Gitea
- Propriétés custom, AI keywords, sync API