fix: login → /workspaces, workspace tree filtered, sidebar CRUD
- Login redirect (all modes) now goes to /workspaces - Workspace tree API filters by active workspace_id (no leak) - Workspace name in sidebar from cookie (active_ws_name) - Sidebar workspace section: 📄 new page + 📁 new folder buttons - deleteWorkspacePage() in sidebar with confirmation - _load_workspace_pages() helper with workspace_id filter - CSS for sidebar-item-delete button (× on hover)
This commit is contained in:
+29
-2
@@ -88,13 +88,18 @@
|
||||
<span>📁 {{ active_ws_name or 'Workspace' }}</span>
|
||||
</div>
|
||||
<div class="sidebar-section-actions">
|
||||
<button class="section-action-btn" title="New Page" @click.stop="newPageInWorkspace()">+</button>
|
||||
<button class="section-action-btn" title="New Page" @click.stop="newPageInWorkspace()">📄</button>
|
||||
<button class="section-action-btn" title="New Folder" @click.stop="newFolderInWorkspace()">📁</button>
|
||||
</div>
|
||||
</div>
|
||||
<div class="sidebar-section-items" x-show="sectionsOpen.workspace" x-transition>
|
||||
<ul class="sidebar-items" data-section="workspace">
|
||||
{% for page in workspace_pages %}
|
||||
{{ render_tree_item(page) }}
|
||||
<li class="sidebar-item" data-id="{{ page.db_id }}">
|
||||
<span class="page-icon">📄</span>
|
||||
<a href="/pages/{{ page.db_id }}" class="page-name">{{ page.name }}</a>
|
||||
<button class="sidebar-item-delete" onclick="event.preventDefault();app.deleteWorkspacePage({{ page.db_id }})" title="Delete">×</button>
|
||||
</li>
|
||||
{% endfor %}
|
||||
{% if not workspace_pages %}
|
||||
<li class="sidebar-item empty-hint"><span class="page-icon">📄</span><span class="page-name text-dim">No pages yet</span></li>
|
||||
@@ -637,6 +642,28 @@
|
||||
.then(data => { window.location.href = `/pages/${data.id}`; })
|
||||
.catch(err => { alert('Failed: ' + err.message); });
|
||||
},
|
||||
newFolderInWorkspace() {
|
||||
const name = prompt('Folder name:');
|
||||
if (!name || !name.trim()) return;
|
||||
fetch('/api/local-workspace/items', {
|
||||
method: 'POST',
|
||||
headers: { 'Content-Type': 'application/json', 'X-CSRF-Token': this.getCsrfToken() },
|
||||
body: JSON.stringify({ name: name.trim(), type: 'folder' })
|
||||
})
|
||||
.then(r => { if (!r.ok) throw new Error('Failed'); return r.json(); })
|
||||
.then(() => { window.location.reload(); })
|
||||
.catch(err => { alert('Failed: ' + err.message); });
|
||||
},
|
||||
deleteWorkspacePage(pageId) {
|
||||
if (!confirm('Delete this page?')) return;
|
||||
fetch(`/api/local-workspace/items/${pageId}`, {
|
||||
method: 'DELETE',
|
||||
headers: { 'X-CSRF-Token': this.getCsrfToken() }
|
||||
})
|
||||
.then(r => { if (!r.ok) throw new Error('Failed'); return r.json(); })
|
||||
.then(() => { window.location.reload(); })
|
||||
.catch(err => { alert('Failed: ' + err.message); });
|
||||
},
|
||||
|
||||
createEmptyPage() {
|
||||
this.showNewPageMenu = false;
|
||||
|
||||
Reference in New Issue
Block a user