feat: Notion sidebar complete — 7 sections, nav icons, auto-update title
FlowDeck CI / test (push) Failing after 4s
FlowDeck CI / docker (push) Has been skipped

- Sidebar: 7 collapsible sections (Meetings, Recents, Favorites, Agents, Shared, Private, Notion apps)
- Nav icon row: Home with text + icon, Chat/Inbox/Search icon-only, collapse on right
- Notion apps: Library, My Tasks, Trash, Help
- Footer: New chat Ctrl+O + New page buttons
- Auto-update: sidebar items reflect title changes immediately on save
- CSS: nav-icon-btn, home-btn, collapse-btn, empty-hint, outline none
This commit is contained in:
2026-07-09 16:39:22 -04:00
parent c02e00726e
commit 780cccf79f
3 changed files with 126 additions and 55 deletions
+4 -1
View File
@@ -234,7 +234,10 @@ function editor(pid,title,fmt,raw){
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'].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();}).catch(()=>{this.saving=false;});
.then(r=>r.json()).then(()=>{this.saving=false;this.dirty=false;this.lastSaved=new Date().toLocaleTimeString();
// Update sidebar items with new title
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';});
}).catch(()=>{this.saving=false;});
},
md2b(md){const bl=[];let cb=null;for(const line of md.split('\n')){if(cb){if(line.trim()==='```'){bl.push(cb);cb=null;}else cb.content+=(cb.content?'\n':'')+line;continue;}const t=line.trim();if(!t)continue;if(t.startsWith('```')){cb=this.mkB('code','',{language:t.substring(3).trim()||'Plain Text'});continue;}if(t.startsWith('# ')&&!t.startsWith('## '))bl.push(this.mkB('heading_1',t.substring(2)));else if(t.startsWith('## ')&&!t.startsWith('### '))bl.push(this.mkB('heading_2',t.substring(3)));else if(t.startsWith('### ')&&!t.startsWith('#### '))bl.push(this.mkB('heading_3',t.substring(4)));else if(t.startsWith('#### '))bl.push(this.mkB('heading_4',t.substring(5)));else if(t==='---'||t==='***')bl.push(this.mkB('divider',''));else if(/^[-*+] /.test(t))bl.push(this.mkB('bulleted_list',t.substring(2)));else if(/^\d+\. /.test(t))bl.push(this.mkB('numbered_list',t.replace(/^\d+\. /,'')));else if(t.startsWith('- [ ] ')||t.startsWith('* [ ] '))bl.push(this.mkB('to_do',t.substring(6)));else if(t.startsWith('- [x] ')||t.startsWith('* [x] '))bl.push(this.mkB('to_do',t.substring(6),{checked:true}));else if(t.startsWith('> '))bl.push(this.mkB('quote',t.substring(2)));else bl.push(this.mkB('paragraph',t));}if(cb)bl.push(cb);return bl;},