From 23df10732b6d9e2014fc13bb7b0378c6f6d5de25 Mon Sep 17 00:00:00 2001 From: Bruno Charest Date: Fri, 4 Sep 2026 12:10:22 -0400 Subject: [PATCH] fix(editor): v4.8.1 bloc Tableau - +Row, +Colonne a droite, redim colonnes - + Row (bas) ne fonctionnait pas: splice(index,ligne) -> splice(index,0,ligne) - bouton + a droite du tableau = ajoute une colonne a droite - redimensionnement colonnes a la souris (curseur col-resize) + persistance colsW - VERSION/CHANGELOG/ROADMAP/css?v bump 4.8.1 --- CHANGELOG.md | 13 ++++++++ ROADMAP.md | 7 +++- VERSION | 2 +- app/main.py | 4 +-- app/templates/_page_editor_scripts.html | 43 ++++++++++++++++++++++--- app/templates/base.html | 2 +- static/css/app.css | 23 ++++++++++++- 7 files changed, 84 insertions(+), 10 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 7f0333d..2cbf069 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,18 @@ # Changelog — FlowDeck +## v4.8.1 (2026-09-03) — Fix bloc Tableau : boutons + Ligne / + Colonne, redimensionnement + +### Fixed +- **Bouton « + Row » (bas du tableau) inopérant** — le code passait la nouvelle ligne en argument `deleteCount` de `Array.splice` au lieu d'utiliser `splice(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 CSS `app.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. diff --git a/ROADMAP.md b/ROADMAP.md index 4540665..b06623d 100644 --- a/ROADMAP.md +++ b/ROADMAP.md @@ -307,6 +307,11 @@ Détails livrés : - [x] **Colonnes** — poignée (⋮⋮) au-dessus de chaque colonne → Insérer à gauche/droite, Dupliquer, Effacer le contenu, Supprimer la colonne, Supprimer le tableau. - [x] **Import Markdown (GFM)** — `md2b` transforme les tableaux pipe en bloc `table` au lieu de les aplatir en paragraphes ; roundtrip Markdown (JS + export) et sortie MD/HTML/PDF correcte d'un bloc `table`. +### v4.8.1 — Fix bloc Tableau ✅ (2026-09-03) +- [x] **« + Row » (bas) corrigé** — l'insertion de ligne utilisait `splice(index, ligne)` (mauvaise signature) → aucune ligne ajoutée ; désormais `splice(index, 0, ligne)`. +- [x] **Bouton « + » à droite** — ajoute une colonne à droite (équivalent « Add column »). +- [x] **Redimensionnement des colonnes** — curseur `col-resize` au survol des bordures d'en-tête, drag = largeur ; persisté via `colsW`. + ### v4.9.0 — Collaboration - [ ] **Inline comments** — commentaires sur sélection de texte - [ ] **@mentions** — notifier un utilisateur → page/commentaire @@ -459,4 +464,4 @@ v4.0.2 ✅ v4.1.0 ✅ v4.2.0 ✅ v4.3.0 ✅ v4.4.0 ✅ v4.5.0 ✅ Quality Data Sources Templates + 10 Views Tasks & Sprints & Content Export Bloc Table Collab + Pro + Agent & Tests & Linked DB Dashboards complets Dependencies My Tasks Blocks MD/PDF/HTML simple Agent IA (futur) -*Dernière mise à jour: 2026-09-03 — v4.8.0 Bloc Tableau simple (édition Notion) ✅* +*Dernière mise à jour: 2026-09-03 — v4.8.1 Bloc Tableau : + Row / + Col / redimensionnement ✅* diff --git a/VERSION b/VERSION index 6ca6df1..2871567 100644 --- a/VERSION +++ b/VERSION @@ -1 +1 @@ -4.8.0 \ No newline at end of file +4.8.1 \ No newline at end of file diff --git a/app/main.py b/app/main.py index 3a28738..8197425 100644 --- a/app/main.py +++ b/app/main.py @@ -39,13 +39,13 @@ async def lifespan(_app: FastAPI): (admin_hash,) ) conn.commit() - logger.info("FlowDeck v4.8.0 started on port %d", settings.app_port) + logger.info("FlowDeck v4.8.1 started on port %d", settings.app_port) yield app = FastAPI( title="FlowDeck", - version="4.8.0", + version="4.8.1", docs_url="/docs" if settings.log_level == "DEBUG" else None, redoc_url=None, lifespan=lifespan, diff --git a/app/templates/_page_editor_scripts.html b/app/templates/_page_editor_scripts.html index 47b22ed..7da1aab 100644 --- a/app/templates/_page_editor_scripts.html +++ b/app/templates/_page_editor_scripts.html @@ -27,7 +27,7 @@ function _tblNew(rows,cols){var out=[];for(var i=0;iw)index=w;b.rows.forEach(function(r){r.splice(index,0,'');});} - function _tblAddRow(b,index){_tblClone(b);var w=b.rows.length&&b.rows[0]?b.rows[0].length:1;if(index<0)index=0;if(index>b.rows.length)index=b.rows.length;b.rows.splice(index,_tblNew(1,w)[0]);} + function _tblAddRow(b,index){_tblClone(b);var w=b.rows.length&&b.rows[0]?b.rows[0].length:1;if(index<0)index=0;if(index>b.rows.length)index=b.rows.length;b.rows.splice(index,0,_tblNew(1,w)[0]);} function _tblDupCol(b,index){_tblClone(b);b.rows.forEach(function(r){var v=(indexr.length?r.length:index+1;r.splice(at,0,v);});} function _tblDupRow(b,index){_tblClone(b);if(index<0||index>b.rows.length)return;b.rows.splice(index+1,0,(b.rows[index]||[]).slice());} function _tblClearCol(b,index){_tblClone(b);b.rows.forEach(function(r){if(r&&indexw)w=r.length;});if(w<1)w=2; + var widths=(b&&Array.isArray(b.colsW))?b.colsW:[]; var bid=b.id;var h=''; h+='
'; + h+='
'; h+='
'; for(var c=0;c'+_tblGrip()+'
'; @@ -53,12 +55,18 @@ h+=''; for(var ci=0;ci'+esc(v)+''; + var wpx=(widths[ci]&&widths[ci]>0)?(' style="width:'+widths[ci]+'px"'):''; + h+='<'+tag+' class="ftable-cell'+(isHead?' head':'')+'" contenteditable="true" data-r="'+ri+'" data-c="'+ci+'"'+wpx+' spellcheck="false">'+esc(v); + if(isHead)h+=''; + h+=''; } h+=''; } h+=''; h+='
'; + h+='
'; + h+='
'; + h+='
'; h+='
'; return h; } @@ -108,6 +116,29 @@ e.render();e.dirty=true;e.autoSave(); _tblFocus(bid,focusR,focusC); } + function _tblResizeStart(ev){ + var sp=ev.target&&ev.target.closest?ev.target.closest('.ftable-resize'):null;if(!sp)return; + var th=sp.parentElement;if(!th)return; + var wrap=th.closest('.ftable-editor');if(!wrap)return; + var bid=wrap.getAttribute('data-bid');var col=parseInt(sp.getAttribute('data-col')||'0',10); + var b=_tblBlockById(bid);if(!b)return; + ev.preventDefault();ev.stopPropagation(); + var E=window.E;if(E&&E.sync)E.sync(); + var widths=(b.colsW&&Array.isArray(b.colsW))?b.colsW.slice():[]; + while(widths.length<=col)widths.push(null); + var startX=ev.clientX;var base=widths[col]||th.getBoundingClientRect().width; + document.body.style.cursor='col-resize';document.body.style.userSelect='none'; + function move(me){var dx=me.clientX-startX;var nw=Math.max(48,Math.min(760,base+dx));th.style.width=Math.round(nw)+'px';widths[col]=Math.round(nw);} + function up(me){ + document.removeEventListener('mousemove',move);document.removeEventListener('mouseup',up); + document.body.style.cursor='';document.body.style.userSelect=''; + move(me); + b.colsW=widths; + if(E){E.dirty=true;E.autoSave();} + } + document.addEventListener('mousemove',move); + document.addEventListener('mouseup',up); + } function _tblInitDelegate(){ if(window._tblDelegate)return;window._tblDelegate=true; document.addEventListener('click',function(ev){ @@ -118,6 +149,7 @@ if(act==='colmenu'){_tblMenuOpen(gr?gr.left:ev.clientX,(gr?gr.bottom:ev.clientY)+4,bid,'col',col);ev.preventDefault();} else if(act==='colplus'){var b=_tblBlockById(bid);if(b){window.E.sync();_tblAddCol(b,col+1);window.E.render();window.E.dirty=true;window.E.autoSave();_tblFocus(bid,1,col+1);}} else if(act==='rowadd'){var b2=_tblBlockById(bid);if(b2){window.E.sync();var n=b2.rows.length;_tblAddRow(b2,n);window.E.render();window.E.dirty=true;window.E.autoSave();_tblFocus(bid,n,0);}} + else if(act==='coladdright'){var b4=_tblBlockById(bid);if(b4){window.E.sync();var cw=(b4.rows&&b4.rows[0])?b4.rows[0].length:1;_tblAddCol(b4,cw);window.E.render();window.E.dirty=true;window.E.autoSave();_tblFocus(bid,1,cw);}} return; } if(document.getElementById('_tblMenu')&&!(ev.target.closest&&ev.target.closest('[data-tbl]')))_tblMenuClose(); @@ -131,7 +163,10 @@ if(r===0)_tblMenuOpen(ev.clientX,ev.clientY,bid,'col',c); else _tblMenuOpen(ev.clientX,ev.clientY,bid,'row',r); }); - document.addEventListener('mousedown',function(ev){if(document.getElementById('_tblMenu')&&!ev.target.closest('#_tblMenu'))_tblMenuClose();}); + document.addEventListener('mousedown',function(ev){ + if(ev.target&&ev.target.closest&&ev.target.closest('.ftable-resize')){_tblResizeStart(ev);return;} + if(document.getElementById('_tblMenu')&&!(ev.target.closest&&ev.target.closest('#_tblMenu')))_tblMenuClose(); + }); } const SM={_o:false,_i:-1,_s:0,_q:'',_it:[], @@ -653,7 +688,7 @@ const t=document.getElementById('_titleEl');if(t)this.pageTitle=t.textContent?.trim()||'New page'; this.saving=true; const csrf=document.cookie.match(/csrf_token=([^;]+)/); - fetch(`/board/api/pages/${this.pid}/blocks`,{method:'POST',headers:{'Content-Type':'application/json','X-CSRF-Token':csrf?csrf[1]:''},body:JSON.stringify({title:this.pageTitle,blocks:this.blocks.map(b=>{const c={id:b.id,type:b.type,content:b.content};['checked','expanded','language','icon','src','alt','style','embed_type','collection_id','dbs','file_name','file_size','file_mime','children','rows','align','has_header'].forEach(k=>{if(b[k]!=null)c[k]=b[k];});return c;})})}) + fetch(`/board/api/pages/${this.pid}/blocks`,{method:'POST',headers:{'Content-Type':'application/json','X-CSRF-Token':csrf?csrf[1]:''},body:JSON.stringify({title:this.pageTitle,blocks:this.blocks.map(b=>{const c={id:b.id,type:b.type,content:b.content};['checked','expanded','language','icon','src','alt','style','embed_type','collection_id','dbs','file_name','file_size','file_mime','children','rows','align','has_header','colsW'].forEach(k=>{if(b[k]!=null)c[k]=b[k];});return c;})})}) .then(r=>r.json()).then(()=>{this.saving=false;this.dirty=false;this.lastSaved=new Date().toLocaleTimeString(); document.querySelectorAll(`.sidebar-item[data-page-id="page/${this.pid}"]`).forEach(item=>{const n=item.querySelector('.page-name');if(n)n.textContent=this.pageTitle||'New page';}); if(cb)cb(); diff --git a/app/templates/base.html b/app/templates/base.html index 92ff97f..8d70587 100644 --- a/app/templates/base.html +++ b/app/templates/base.html @@ -5,7 +5,7 @@ FlowDeck — {% block title_prefix %}Home{% endblock %} - +