diff --git a/static/js/clusters-search.js b/static/js/clusters-search.js index 291be7ab28..9dcf05146f 100644 --- a/static/js/clusters-search.js +++ b/static/js/clusters-search.js @@ -23,40 +23,44 @@ } function createSearchInterface() { - // Find the intro section to insert search box after it - const introSection = document.querySelector('.wg-blank'); - if (!introSection) return; - - // Create search container - const searchContainer = document.createElement('div'); - searchContainer.className = 'cluster-search-container'; - searchContainer.innerHTML = ` -
-
-
-
- -
- - -
+ // Create sidebar container + const sidebar = document.createElement('div'); + sidebar.id = 'clusterSearchSidebar'; + sidebar.className = 'cluster-search-sidebar'; + sidebar.innerHTML = ` + +
+
+

Search Clusters

+ +
+
+
+ +
+
-
+ +
`; - // Insert after intro section - introSection.parentNode.insertBefore(searchContainer, introSection.nextSibling); + // Insert at beginning of body + document.body.insertBefore(sidebar, document.body.firstChild); } function setupSearchHandlers() { @@ -64,8 +68,31 @@ const searchBtn = document.getElementById('clusterSearchBtn'); const clearBtn = document.getElementById('clusterClearBtn'); const resultsDiv = document.getElementById('clusterSearchResults'); + const toggleBtn = document.getElementById('clusterSearchToggle'); + const closeBtn = document.getElementById('clusterSearchClose'); + const panel = document.getElementById('clusterSearchPanel'); + + if (!searchInput || !searchBtn || !clearBtn || !toggleBtn || !closeBtn || !panel) return; + + // Toggle sidebar + toggleBtn.addEventListener('click', function() { + panel.classList.toggle('open'); + if (panel.classList.contains('open')) { + searchInput.focus(); + } + }); - if (!searchInput || !searchBtn || !clearBtn) return; + // Close sidebar + closeBtn.addEventListener('click', function() { + panel.classList.remove('open'); + }); + + // Close on escape key + document.addEventListener('keydown', function(e) { + if (e.key === 'Escape' && panel.classList.contains('open')) { + panel.classList.remove('open'); + } + }); // Search on button click searchBtn.addEventListener('click', performSearch); @@ -198,19 +225,19 @@ return; } - let html = `
Found ${results.length} tab(s) containing "${escapeHtml(query)}" (${results.reduce((sum, r) => sum + r.matches, 0)} total matches). Click on a result to view it:
`; - html += '
'; + let html = `
Found ${results.length} tab(s) with ${results.reduce((sum, r) => sum + r.matches, 0)} matches
`; + html += '
'; results.forEach(function(result) { html += ` - -
-
${escapeHtml(result.cluster)} → ${escapeHtml(result.tab)}
- ${result.matches} match${result.matches > 1 ? 'es' : ''} +
+
+ ${escapeHtml(result.tab)} + ${result.matches}
-

${result.snippet}

-
+
${escapeHtml(result.cluster)}
+
${result.snippet}
+
`; }); @@ -218,10 +245,9 @@ resultsDiv.innerHTML = html; // Add click handlers to results - const resultLinks = resultsDiv.querySelectorAll('.cluster-search-result'); - resultLinks.forEach(function(link) { - link.addEventListener('click', function(e) { - e.preventDefault(); + const resultItems = resultsDiv.querySelectorAll('.search-result-item'); + resultItems.forEach(function(item) { + item.addEventListener('click', function() { const tabId = this.getAttribute('data-tab-id'); const result = results.find(r => r.tabId === tabId); if (result) { @@ -229,12 +255,16 @@ highlightMatches(result.tabPane, query); // Scroll to the section result.section.scrollIntoView({ behavior: 'smooth', block: 'start' }); + // Mark as active + resultItems.forEach(r => r.classList.remove('active')); + this.classList.add('active'); } }); }); // Auto-expand first result if (results.length > 0) { + resultItems[0].classList.add('active'); activateTab(results[0]); highlightMatches(results[0].tabPane, query); } @@ -322,31 +352,195 @@ }); } - // Add CSS for highlighting + // Add CSS for sidebar and highlighting const style = document.createElement('style'); style.textContent = ` + /* Highlight styling */ .cluster-highlight { background-color: #ffeb3b; padding: 2px 0; font-weight: bold; } - .cluster-search-container { - position: sticky; - top: 70px; + /* Sidebar toggle button */ + .cluster-search-toggle { + position: fixed; + left: 0; + top: 200px; + background: #007bff; + color: white; + border: none; + border-radius: 0 5px 5px 0; + padding: 12px 15px; + cursor: pointer; + z-index: 1000; + box-shadow: 2px 2px 5px rgba(0,0,0,0.2); + font-size: 14px; + transition: background 0.3s; + } + + .cluster-search-toggle:hover { + background: #0056b3; + } + + .cluster-search-toggle i { + margin-right: 5px; + } + + /* Sidebar panel */ + .cluster-search-panel { + position: fixed; + left: -350px; + top: 0; + width: 350px; + height: 100vh; background: white; - z-index: 100; - padding: 20px 0 10px 0; - box-shadow: 0 2px 4px rgba(0,0,0,0.1); + box-shadow: 2px 0 10px rgba(0,0,0,0.1); + z-index: 1001; + transition: left 0.3s ease; + display: flex; + flex-direction: column; + overflow: hidden; + } + + .cluster-search-panel.open { + left: 0; + } + + /* Sidebar header */ + .cluster-search-header { + display: flex; + justify-content: space-between; + align-items: center; + padding: 15px 20px; + border-bottom: 1px solid #dee2e6; + background: #f8f9fa; + } + + .cluster-search-header h4 { + margin: 0; + font-size: 18px; + color: #333; } - .cluster-search-result:hover { + .cluster-search-close { + background: none; + border: none; + font-size: 20px; + color: #666; cursor: pointer; + padding: 5px; + line-height: 1; + } + + .cluster-search-close:hover { + color: #333; + } + + /* Sidebar body */ + .cluster-search-body { + padding: 20px; + flex: 1; + overflow-y: auto; + } + + /* Search results summary */ + .search-summary { + background: #e7f3ff; + padding: 10px; + border-radius: 5px; + margin-bottom: 15px; + font-size: 0.9rem; + color: #004085; } - .cluster-search-result mark { + /* Search results list */ + .search-results-list { + display: flex; + flex-direction: column; + gap: 10px; + } + + /* Individual search result */ + .search-result-item { + background: #f8f9fa; + border: 1px solid #dee2e6; + border-radius: 5px; + padding: 12px; + cursor: pointer; + transition: all 0.2s; + } + + .search-result-item:hover { + background: #e9ecef; + border-color: #007bff; + box-shadow: 0 2px 5px rgba(0,0,0,0.1); + } + + .search-result-item.active { + background: #e7f3ff; + border-color: #007bff; + box-shadow: inset 0 0 0 1px #007bff; + } + + .search-result-header { + display: flex; + justify-content: space-between; + align-items: center; + margin-bottom: 5px; + } + + .search-result-header strong { + font-size: 0.95rem; + color: #333; + flex: 1; + margin-right: 10px; + } + + .search-result-header .badge { + font-size: 0.75rem; + } + + .search-result-cluster { + font-size: 0.8rem; + color: #666; + margin-bottom: 8px; + } + + .search-result-snippet { + font-size: 0.8rem; + color: #555; + line-height: 1.4; + } + + .search-result-snippet mark { background-color: #ffeb3b; padding: 1px 2px; + font-weight: 600; + } + + /* Mobile responsive */ + @media (max-width: 768px) { + .cluster-search-panel { + width: 100%; + left: -100%; + } + + .cluster-search-panel.open { + left: 0; + } + + .cluster-search-toggle { + top: 150px; + font-size: 12px; + padding: 10px 12px; + } + } + + /* Alert styling in sidebar */ + .cluster-search-body .alert { + font-size: 0.85rem; + padding: 8px 12px; } `; document.head.appendChild(style);