feat: sidebar tree dynamically refreshes after CRUD in local-workspace
- 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:
+31
-3
@@ -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) || '';
|
||||
|
||||
@@ -1111,6 +1111,8 @@ window._wsInitData = (function() {
|
||||
_reloadAfterAction() {
|
||||
this._saveExpandedState();
|
||||
this._loadFolder(this.currentFolder);
|
||||
// Notify sidebar to refresh its tree
|
||||
document.dispatchEvent(new CustomEvent('flowdeck:sidebar-refresh'));
|
||||
},
|
||||
|
||||
// ── Inline Rename ──
|
||||
@@ -1555,6 +1557,8 @@ window._wsInitData = (function() {
|
||||
this.doFilter();
|
||||
}
|
||||
this._saveExpandedState();
|
||||
// Notify sidebar to refresh its tree
|
||||
document.dispatchEvent(new CustomEvent('flowdeck:sidebar-refresh'));
|
||||
}
|
||||
},
|
||||
|
||||
|
||||
Reference in New Issue
Block a user