/** * Custom JavaScript for the monitoring dashboard */ // Auto-dismiss alerts after 5 seconds document.addEventListener('DOMContentLoaded', function() { const alerts = document.querySelectorAll('.alert-dismissible'); alerts.forEach(alert => { setTimeout(() => { const bsAlert = new bootstrap.Alert(alert); bsAlert.close(); }, 5000); }); }); // Copy to clipboard functionality function copyToClipboard(text) { navigator.clipboard.writeText(text).then(() => { showToast('Copied to clipboard!', 'success'); }).catch(err => { console.error('Failed to copy:', err); showToast('Failed to copy', 'danger'); }); } // Show toast notification function showToast(message, type = 'info') { const toastContainer = document.getElementById('toastContainer'); if (!toastContainer) { const container = document.createElement('div'); container.id = 'toastContainer'; container.className = 'position-fixed bottom-0 end-0 p-3'; container.style.zIndex = '9999'; document.body.appendChild(container); } const toast = document.createElement('div'); toast.className = `toast align-items-center text-white bg-${type} border-0`; toast.setAttribute('role', 'alert'); toast.setAttribute('aria-live', 'assertive'); toast.setAttribute('aria-atomic', 'true'); toast.innerHTML = `
${message}
`; document.getElementById('toastContainer').appendChild(toast); const bsToast = new bootstrap.Toast(toast); bsToast.show(); toast.addEventListener('hidden.bs.toast', () => { toast.remove(); }); } // Refresh data without page reload function refreshStats() { const refreshBtn = document.getElementById('refreshBtn'); if (refreshBtn) { refreshBtn.classList.add('disabled'); refreshBtn.innerHTML = ' Refreshing...'; setTimeout(() => { location.reload(); }, 1000); } } // Format timestamps to relative time function formatRelativeTime() { const timeElements = document.querySelectorAll('[data-timestamp]'); timeElements.forEach(element => { const timestamp = parseInt(element.getAttribute('data-timestamp')); const date = new Date(timestamp * 1000); element.textContent = getRelativeTime(date); }); } function getRelativeTime(date) { const now = new Date(); const diff = now - date; const seconds = Math.floor(diff / 1000); const minutes = Math.floor(seconds / 60); const hours = Math.floor(minutes / 60); const days = Math.floor(hours / 24); if (seconds < 60) return 'just now'; if (minutes < 60) return `${minutes} minute${minutes > 1 ? 's' : ''} ago`; if (hours < 24) return `${hours} hour${hours > 1 ? 's' : ''} ago`; if (days < 30) return `${days} day${days > 1 ? 's' : ''} ago`; return date.toLocaleDateString(); } // Auto-refresh dashboard every 5 minutes let autoRefreshInterval; function startAutoRefresh(interval = 300000) { // 5 minutes default if (autoRefreshInterval) { clearInterval(autoRefreshInterval); } autoRefreshInterval = setInterval(() => { console.log('Auto-refreshing dashboard...'); location.reload(); }, interval); } // Stop auto-refresh function stopAutoRefresh() { if (autoRefreshInterval) { clearInterval(autoRefreshInterval); autoRefreshInterval = null; } } // Keyboard shortcuts document.addEventListener('keydown', function(e) { // Ctrl/Cmd + K to focus search (if exists) if ((e.ctrlKey || e.metaKey) && e.key === 'k') { e.preventDefault(); const searchInput = document.querySelector('[type="search"]'); if (searchInput) searchInput.focus(); } // Ctrl/Cmd + N to create new site if ((e.ctrlKey || e.metaKey) && e.key === 'n') { e.preventDefault(); const createBtn = document.querySelector('[href*="sites/create"]'); if (createBtn) window.location.href = createBtn.href; } }); // Initialize tooltips document.addEventListener('DOMContentLoaded', function() { const tooltipTriggerList = [].slice.call(document.querySelectorAll('[data-bs-toggle="tooltip"]')); tooltipTriggerList.map(function (tooltipTriggerEl) { return new bootstrap.Tooltip(tooltipTriggerEl); }); }); // Initialize popovers document.addEventListener('DOMContentLoaded', function() { const popoverTriggerList = [].slice.call(document.querySelectorAll('[data-bs-toggle="popover"]')); popoverTriggerList.map(function (popoverTriggerEl) { return new bootstrap.Popover(popoverTriggerEl); }); }); // Chart.js default configuration if (typeof Chart !== 'undefined') { Chart.defaults.font.family = "'Inter', sans-serif"; Chart.defaults.color = getComputedStyle(document.documentElement).getPropertyValue('--text-secondary'); } // Handle dark mode chart updates document.addEventListener('DOMContentLoaded', function() { const darkModeObserver = new MutationObserver(function(mutations) { mutations.forEach(function(mutation) { if (mutation.attributeName === 'class') { const isDark = document.documentElement.classList.contains('dark'); updateChartsForTheme(isDark); } }); }); darkModeObserver.observe(document.documentElement, { attributes: true, attributeFilter: ['class'] }); }); function updateChartsForTheme(isDark) { if (typeof Chart !== 'undefined' && Chart.instances.length > 0) { const textColor = isDark ? '#9ca3af' : '#6b7280'; Chart.defaults.color = textColor; // Update all chart instances Chart.instances.forEach(chart => { chart.options.scales.x.ticks.color = textColor; chart.options.scales.y.ticks.color = textColor; chart.options.scales.x.grid.color = isDark ? 'rgba(255, 255, 255, 0.1)' : 'rgba(0, 0, 0, 0.1)'; chart.options.scales.y.grid.color = isDark ? 'rgba(255, 255, 255, 0.1)' : 'rgba(0, 0, 0, 0.1)'; chart.update(); }); } } // Status badge updater function updateStatusBadge(element, status) { element.className = 'badge'; if (status >= 200 && status < 400) { element.classList.add('bg-success'); element.innerHTML = ' Online'; } else if (status) { element.classList.add('bg-danger'); element.innerHTML = ' Down'; } else { element.classList.add('bg-secondary'); element.textContent = 'Not Checked'; } } // Export data as CSV function exportToCSV(data, filename = 'export.csv') { const csv = data.map(row => row.join(',')).join('\n'); const blob = new Blob([csv], { type: 'text/csv' }); const url = window.URL.createObjectURL(blob); const a = document.createElement('a'); a.href = url; a.download = filename; a.click(); window.URL.revokeObjectURL(url); } // Print functionality function printReport() { window.print(); } // Console welcome message console.log( '%cSite Monitor Dashboard', 'font-size: 20px; font-weight: bold; color: #4f46e5;' ); console.log( '%cBuilt with Laravel + Bootstrap + Alpine.js', 'font-size: 12px; color: #6b7280;' );