feat: sidebar tree dynamically refreshes after CRUD in local-workspace
FlowDeck CI / test (push) Failing after 4s
FlowDeck CI / docker (push) Has been skipped

- New endpoint GET /api/sidebar/workspace-tree returns sidebar tree HTML fragment
- refreshSidebarTree() in appState() fetches and replaces #sidebar-workspace-items
- Custom event 'flowdeck:sidebar-refresh' dispatched after doCreate/doRename/doDelete
- newFolderInWorkspace, deleteWorkspacePage, wsCtxAction('rename') now use
  refreshSidebarTree() instead of window.location.reload()
- Sidebar stays in sync without full page refresh
This commit is contained in:
2026-07-16 08:53:44 -04:00
parent 72636a77ea
commit 6f40c8953a
3 changed files with 95 additions and 3 deletions
+31 -3
View File
@@ -636,11 +636,17 @@
case 'rename':
var newName = prompt('Rename:', name);
if (newName && newName.trim()) {
var self = this;
fetch('/api/local-workspace/items/' + id, {
method: 'PUT',
headers: { 'Content-Type': 'application/json', 'X-CSRF-Token': this.getCsrfToken() },
body: JSON.stringify({ name: newName.trim() })
}).then(function(r) { if (r.ok) window.location.reload(); });
}).then(function(r) {
if (r.ok) {
self.refreshSidebarTree();
document.dispatchEvent(new CustomEvent('flowdeck:sidebar-refresh'));
}
});
}
break;
case 'delete':
@@ -970,7 +976,7 @@
body: JSON.stringify({ name: name.trim(), type: 'folder' })
})
.then(r => { if (!r.ok) throw new Error('Failed'); return r.json(); })
.then(() => { window.location.reload(); })
.then(() => { this.refreshSidebarTree(); })
.catch(err => { this.toast('Failed: ' + err.message, 'error'); });
},
deleteWorkspacePage(pageId) {
@@ -980,10 +986,25 @@
headers: { 'X-CSRF-Token': this.getCsrfToken() }
})
.then(r => { if (!r.ok) throw new Error('Failed'); return r.json(); })
.then(() => { window.location.reload(); })
.then(() => { this.refreshSidebarTree(); document.dispatchEvent(new CustomEvent('flowdeck:sidebar-refresh')); })
.catch(err => { this.toast('Failed: ' + err.message, 'error'); });
},
refreshSidebarTree() {
// Reload the sidebar workspace tree after CRUD in the main content area
fetch('/api/sidebar/workspace-tree')
.then(r => r.text())
.then(html => {
const ul = document.getElementById('sidebar-workspace-items');
if (!ul) return;
// Preserve the "Manage Workspaces" link (last <li>)
const manageLink = ul.querySelector('li:last-child');
ul.innerHTML = html;
if (manageLink) ul.appendChild(manageLink);
})
.catch(e => console.error('Sidebar refresh failed:', e));
},
// ── Drag & Drop ──
dragOverId: null,
dragStart(ev, id) {
@@ -1176,6 +1197,13 @@
}
};
// -- Global sidebar refresh handler (called by local_workspace after CRUD) --
document.addEventListener('flowdeck:sidebar-refresh', function() {
var appEl = document.querySelector('[x-data]');
var data = appEl && appEl.__x ? appEl.__x.$data : null;
if (data && data.refreshSidebarTree) data.refreshSidebarTree();
});
// ═══════════ GLOBAL KEYBOARD SHORTCUTS ═══════════
document.addEventListener('keydown', function(e) {
var tag = (document.activeElement && document.activeElement.tagName) || '';