- Replace direct 'New Document' with modal wizard that asks for library first - Separate 'New Document' (📄) and 'New Library' (📁) buttons in header - Update sidebar quick links to show both options with clear icons - Add modal for library creation with name input - Add CSS for form-control and modal-close button styling - Minor improvements to document.js (type=button, event.stopPropagation) - Keyboard shortcut Ctrl+N now opens document creation modal
100 lines
3.6 KiB
JavaScript
100 lines
3.6 KiB
JavaScript
// Sidebar Component
|
|
|
|
export function renderSidebar({ libraries, tags, selectedLibrary, selectedTag, onSelectLibrary, onSelectTag, onHome }) {
|
|
const buildLibraryTree = (libs, parentId = null, depth = 0) => {
|
|
return libs
|
|
.filter(l => l.parentId === parentId)
|
|
.map(lib => {
|
|
const children = libs.filter(l => l.parentId === lib.id);
|
|
const hasChildren = children.length > 0;
|
|
const isSelected = selectedLibrary === lib.id;
|
|
|
|
return `
|
|
<div class="tree-node">
|
|
<div class="tree-item ${isSelected ? 'active' : ''}" data-action="library" data-library-id="${lib.id}">
|
|
<span class="tree-toggle ${hasChildren ? 'expanded' : ''}" style="padding-left:${depth * 12}px">
|
|
${hasChildren ? '▶' : ''}
|
|
</span>
|
|
<span class="icon">📁</span>
|
|
<span class="label">${escapeHtml(lib.name)}</span>
|
|
</div>
|
|
${hasChildren ? `<div class="tree-children">${buildLibraryTree(libraries, lib.id, depth + 1)}</div>` : ''}
|
|
</div>
|
|
`;
|
|
})
|
|
.join('');
|
|
};
|
|
|
|
// Store callbacks in a way that's safe and doesn't rely on inline script execution
|
|
const callbacks = {
|
|
onSelectLibrary,
|
|
onSelectTag,
|
|
onHome
|
|
};
|
|
|
|
return `
|
|
<aside class="sidebar">
|
|
<div class="sidebar-scroll">
|
|
<div class="sidebar-section">
|
|
<h3>📚 Libraries</h3>
|
|
<div class="library-tree">
|
|
<div class="tree-item ${!selectedLibrary ? 'active' : ''}" data-action="home">
|
|
<span class="icon">🏠</span>
|
|
<span class="label">All Documents</span>
|
|
</div>
|
|
${buildLibraryTree(libraries)}
|
|
</div>
|
|
</div>
|
|
<div class="sidebar-section">
|
|
<h3>🏷️ Tags</h3>
|
|
<div class="tag-list">
|
|
${tags.map(tag => `
|
|
<div class="tag-item ${selectedTag === tag.name ? 'active' : ''}" data-action="tag" data-tag="${escapeHtml(tag.name)}">
|
|
<span>#${escapeHtml(tag.name)}</span>
|
|
<span class="tag-count">${tag.count}</span>
|
|
</div>
|
|
`).join('')}
|
|
</div>
|
|
</div>
|
|
<div class="quick-links">
|
|
<a class="quick-link" data-action="home">📋 All Documents</a>
|
|
<a class="quick-link" onclick="window.showNewDocModal()">📄 New Document</a>
|
|
<a class="quick-link" onclick="window.showNewLibraryModal()">📁 New Library</a>
|
|
</div>
|
|
</div>
|
|
</aside>
|
|
<script>
|
|
(function() {
|
|
var callbacks = window.__sidebarCallbacks;
|
|
document.querySelectorAll('[data-action="home"]').forEach(function(el) {
|
|
el.addEventListener('click', function(e) {
|
|
e.stopPropagation();
|
|
if (callbacks && callbacks.onHome) callbacks.onHome();
|
|
});
|
|
});
|
|
document.querySelectorAll('[data-action="library"]').forEach(function(el) {
|
|
el.addEventListener('click', function(e) {
|
|
e.stopPropagation();
|
|
var id = this.getAttribute('data-library-id');
|
|
if (callbacks && callbacks.onSelectLibrary) callbacks.onSelectLibrary(id);
|
|
});
|
|
});
|
|
document.querySelectorAll('[data-action="tag"]').forEach(function(el) {
|
|
el.addEventListener('click', function(e) {
|
|
e.stopPropagation();
|
|
var tag = this.getAttribute('data-tag');
|
|
if (callbacks && callbacks.onSelectTag) callbacks.onSelectTag(tag);
|
|
});
|
|
});
|
|
})();
|
|
</script>
|
|
`;
|
|
}
|
|
|
|
function escapeHtml(str) {
|
|
if (!str) return '';
|
|
const div = document.createElement('div');
|
|
div.textContent = str;
|
|
return div.innerHTML;
|
|
}
|