240 lines
7.0 KiB
JavaScript
240 lines
7.0 KiB
JavaScript
// Admin Dashboard JavaScript - Documentation Style
|
|
|
|
document.addEventListener('DOMContentLoaded', function() {
|
|
// Highlight active navigation links
|
|
highlightActiveLinks();
|
|
|
|
// Setup UI toggles
|
|
setupUIToggles();
|
|
|
|
// Setup search functionality
|
|
setupSearch();
|
|
});
|
|
|
|
// Highlight the current active navigation links
|
|
function highlightActiveLinks() {
|
|
const currentPath = window.location.pathname;
|
|
|
|
// Handle top navigation links
|
|
const navLinks = document.querySelectorAll('.nav-link');
|
|
navLinks.forEach(link => {
|
|
link.classList.remove('active');
|
|
const href = link.getAttribute('href');
|
|
|
|
// Check if current path starts with the nav link path
|
|
// This allows section links to be highlighted when on sub-pages
|
|
if (currentPath === href ||
|
|
(href !== '/admin' && currentPath.startsWith(href))) {
|
|
link.classList.add('active');
|
|
}
|
|
});
|
|
|
|
// Handle sidebar links
|
|
const sidebarLinks = document.querySelectorAll('.doc-link');
|
|
sidebarLinks.forEach(link => {
|
|
link.classList.remove('active');
|
|
if (link.getAttribute('href') === currentPath) {
|
|
link.classList.add('active');
|
|
|
|
// Also highlight parent section if needed
|
|
const parentSection = link.closest('.sidebar-section');
|
|
if (parentSection) {
|
|
parentSection.classList.add('active-section');
|
|
}
|
|
}
|
|
});
|
|
}
|
|
|
|
// Setup UI toggle functionality
|
|
function setupUIToggles() {
|
|
// Toggle sidebar on mobile
|
|
const menuToggle = document.querySelector('.menu-toggle');
|
|
const sidebar = document.querySelector('.sidebar');
|
|
|
|
if (menuToggle && sidebar) {
|
|
menuToggle.addEventListener('click', function() {
|
|
sidebar.classList.toggle('open');
|
|
});
|
|
}
|
|
|
|
// Toggle log panel
|
|
const logToggle = document.querySelector('.log-toggle');
|
|
const logPanel = document.querySelector('.log-panel');
|
|
|
|
if (logToggle && logPanel) {
|
|
logToggle.addEventListener('click', function() {
|
|
logPanel.classList.toggle('open');
|
|
});
|
|
}
|
|
|
|
// Setup Docusaurus-style collapsible menu
|
|
setupTreeviewMenu();
|
|
}
|
|
|
|
// Setup sidebar navigation
|
|
function setupTreeviewMenu() {
|
|
// Set active sidebar links based on current URL
|
|
setActiveSidebarLinks();
|
|
|
|
// Setup collapsible sections
|
|
setupCollapsibleSections();
|
|
}
|
|
|
|
// Set active sidebar links based on current URL
|
|
function setActiveSidebarLinks() {
|
|
const currentPath = window.location.pathname;
|
|
|
|
// Find all sidebar links
|
|
const sidebarLinks = document.querySelectorAll('.sidebar-link');
|
|
|
|
// Remove any existing active classes
|
|
sidebarLinks.forEach(link => {
|
|
link.classList.remove('active');
|
|
});
|
|
|
|
// Find and mark active links
|
|
let activeFound = false;
|
|
sidebarLinks.forEach(link => {
|
|
const linkPath = link.getAttribute('href');
|
|
|
|
// Check if the current path matches or starts with the link path
|
|
// For exact matches or if it's a parent path
|
|
if (currentPath === linkPath ||
|
|
(linkPath !== '/admin' && currentPath.startsWith(linkPath))) {
|
|
// Mark this link as active
|
|
link.classList.add('active');
|
|
activeFound = true;
|
|
|
|
// Expand the parent section if this link is inside a collapsible section
|
|
const parentSection = link.closest('.sidebar-content-section')?.parentElement;
|
|
if (parentSection && parentSection.classList.contains('collapsible')) {
|
|
parentSection.classList.remove('collapsed');
|
|
}
|
|
}
|
|
});
|
|
}
|
|
|
|
// Setup collapsible sections
|
|
function setupCollapsibleSections() {
|
|
// Find all toggle headings
|
|
const toggleHeadings = document.querySelectorAll('.sidebar-heading.toggle');
|
|
|
|
// Set all sections as collapsed by default
|
|
document.querySelectorAll('.sidebar-section.collapsible').forEach(section => {
|
|
section.classList.add('collapsed');
|
|
});
|
|
|
|
toggleHeadings.forEach(heading => {
|
|
// Add click event to toggle section
|
|
heading.addEventListener('click', function() {
|
|
const section = this.parentElement;
|
|
section.classList.toggle('collapsed');
|
|
});
|
|
});
|
|
|
|
// Open the section that contains the active link
|
|
const activeLink = document.querySelector('.sidebar-link.active');
|
|
if (activeLink) {
|
|
const parentSection = activeLink.closest('.sidebar-section.collapsible');
|
|
if (parentSection) {
|
|
parentSection.classList.remove('collapsed');
|
|
}
|
|
}
|
|
}
|
|
|
|
// Refresh processes data without page reload
|
|
function refreshProcesses() {
|
|
// Show loading indicator
|
|
const loadingIndicator = document.getElementById('refresh-loading');
|
|
if (loadingIndicator) {
|
|
loadingIndicator.style.display = 'inline';
|
|
}
|
|
|
|
// Get the processes content element
|
|
const tableContent = document.querySelector('.processes-table-content');
|
|
|
|
// Use Unpoly to refresh the content
|
|
if (tableContent && window.up) {
|
|
// Use Unpoly's API to reload the fragment
|
|
up.reload('.processes-table-content', {
|
|
url: '/admin/system/processes-data',
|
|
headers: {
|
|
'X-Requested-With': 'XMLHttpRequest'
|
|
}
|
|
}).then(() => {
|
|
console.log('Process data refreshed successfully via Unpoly');
|
|
}).catch(error => {
|
|
console.error('Error refreshing processes data:', error);
|
|
}).finally(() => {
|
|
// Hide loading indicator
|
|
if (loadingIndicator) {
|
|
loadingIndicator.style.display = 'none';
|
|
}
|
|
});
|
|
} else {
|
|
// Fallback to fetch if Unpoly is not available
|
|
fetch('/admin/system/processes-data', {
|
|
method: 'GET',
|
|
headers: {
|
|
'Accept': 'text/html',
|
|
'X-Requested-With': 'XMLHttpRequest'
|
|
},
|
|
cache: 'no-store'
|
|
})
|
|
.then(response => {
|
|
if (!response.ok) {
|
|
throw new Error('Network response was not ok: ' + response.status);
|
|
}
|
|
return response.text();
|
|
})
|
|
.then(html => {
|
|
// Update the processes table content
|
|
if (tableContent) {
|
|
// Replace the table content with the new HTML
|
|
tableContent.innerHTML = html;
|
|
console.log('Process data refreshed successfully via fetch');
|
|
} else {
|
|
console.error('Could not find processes table content element');
|
|
}
|
|
})
|
|
.catch(error => {
|
|
console.error('Error refreshing processes data:', error);
|
|
})
|
|
.finally(() => {
|
|
// Hide loading indicator
|
|
if (loadingIndicator) {
|
|
loadingIndicator.style.display = 'none';
|
|
}
|
|
});
|
|
}
|
|
}
|
|
|
|
// Note: Logging functionality has been moved to Unpoly-based implementation
|
|
|
|
// Setup search functionality
|
|
function setupSearch() {
|
|
const searchInput = document.querySelector('.search-box input');
|
|
if (searchInput) {
|
|
searchInput.addEventListener('keyup', function(e) {
|
|
if (e.key === 'Enter') {
|
|
performSearch(this.value);
|
|
}
|
|
});
|
|
}
|
|
}
|
|
|
|
// Perform search
|
|
function performSearch(query) {
|
|
if (!query.trim()) return;
|
|
|
|
// Log the search query
|
|
window.adminLog(`Searching for: ${query}`, 'info');
|
|
|
|
// In a real application, this would send an AJAX request to search the docs
|
|
// For now, just simulate a search by redirecting to a search results page
|
|
// window.location.href = `/admin/search?q=${encodeURIComponent(query)}`;
|
|
|
|
// For demo purposes, show a message in the console
|
|
console.log(`Search query: ${query}`);
|
|
}
|