Features: - Complete dashboard redesign with improved UI components and layout - Implement custom section builder for personalized book organization - Add new events tracking system for user interactions - Enhance search functionality with better static search.js - Update TypeScript type definitions for API responses Backend: - Update Go dependencies in go.mod - Add new frontend routes in router Templates: - Update admin and dashboard templates with new components Frontend: - Refactor analytics, collections, conflicts, and queue modules - Add new documentation features in docs.ts - Implement linking between books and collections - Add toast notifications for user feedback - Include placeholder book SVG asset This commit consolidates multiple feature additions and improvements across the entire stack including backend, templates, and frontend.
87 lines
2.9 KiB
TypeScript
87 lines
2.9 KiB
TypeScript
function toggleSidebar(): void {
|
|
const sidebar = document.getElementById('docs-sidebar');
|
|
const overlay = document.getElementById('docs-overlay');
|
|
|
|
if (sidebar && overlay) {
|
|
sidebar.classList.toggle('translate-x-0');
|
|
sidebar.classList.toggle('-translate-x-full');
|
|
overlay.classList.toggle('hidden');
|
|
}
|
|
}
|
|
|
|
function initializeDocsSearch(): void {
|
|
const searchInput = document.getElementById('docs-search') as HTMLInputElement;
|
|
const searchResults = document.getElementById('docs-search-results');
|
|
|
|
if (!searchInput || !searchResults) return;
|
|
|
|
let docsSearchTimeout: ReturnType<typeof setTimeout> | null = null;
|
|
|
|
searchInput.addEventListener('input', () => {
|
|
const query = searchInput.value.trim();
|
|
|
|
if (docsSearchTimeout) {
|
|
clearTimeout(docsSearchTimeout);
|
|
}
|
|
|
|
if (query.length < 2) {
|
|
searchResults.innerHTML = '';
|
|
searchResults.classList.add('hidden');
|
|
return;
|
|
}
|
|
|
|
docsSearchTimeout = setTimeout(() => {
|
|
performDocsSearch(query);
|
|
}, 300);
|
|
});
|
|
}
|
|
|
|
function performDocsSearch(query: string): void {
|
|
const searchResults = document.getElementById('docs-search-results');
|
|
if (!searchResults) return;
|
|
|
|
if (!(window as any).lunr) {
|
|
console.warn('Lunr.js not loaded');
|
|
return;
|
|
}
|
|
|
|
try {
|
|
const idx = (window as any).lunrIndex;
|
|
if (!idx) {
|
|
searchResults.innerHTML = '<p class="p-2 text-sm" style="color: var(--text-secondary)">Search index not loaded</p>';
|
|
searchResults.classList.remove('hidden');
|
|
return;
|
|
}
|
|
|
|
const results = idx.search(query);
|
|
|
|
if (results.length === 0) {
|
|
searchResults.innerHTML = '<p class="p-2 text-sm" style="color: var(--text-secondary)">No results found</p>';
|
|
} else {
|
|
searchResults.innerHTML = results.slice(0, 10).map((result: { ref: string }) => {
|
|
const doc = (window as any).docsData?.[result.ref];
|
|
if (!doc) return '';
|
|
|
|
return `
|
|
<a href="${result.ref}" class="block p-2 hover:bg-opacity-50 transition-colors" style="background-color: var(--bg-secondary)">
|
|
<p class="font-medium text-sm" style="color: var(--text-primary)">${doc.title || result.ref}</p>
|
|
${doc.section ? `<p class="text-xs" style="color: var(--text-secondary)">${doc.section}</p>` : ''}
|
|
</a>
|
|
`;
|
|
}).join('');
|
|
}
|
|
|
|
searchResults.classList.remove('hidden');
|
|
} catch (error) {
|
|
console.error('Search error:', error);
|
|
searchResults.innerHTML = '<p class="p-2 text-sm" style="color: var(--text-secondary)">Search error</p>';
|
|
searchResults.classList.remove('hidden');
|
|
}
|
|
}
|
|
|
|
document.addEventListener('DOMContentLoaded', () => {
|
|
initializeDocsSearch();
|
|
});
|
|
|
|
(window as any).toggleSidebar = toggleSidebar;
|