// Global JavaScript for MootVision AI // Initialize Feather Icons document.addEventListener('DOMContentLoaded', function() { if (typeof feather !== 'undefined') { feather.replace(); } }); // Theme management class ThemeManager { constructor() { this.currentTheme = 'light'; this.init(); } init() { // Check for saved theme preference or default to light const savedTheme = localStorage.getItem('mootvision-theme'); if (savedTheme) { this.setTheme(savedTheme); } } setTheme(theme) { this.currentTheme = theme; document.documentElement.setAttribute('data-theme', theme); localStorage.setItem('mootvision-theme', theme); } toggleTheme() { const newTheme = this.currentTheme === 'light' ? 'dark' : 'light'; this.setTheme(newTheme); } } // Initialize theme manager const themeManager = new ThemeManager(); // API integration utilities class API { static baseURL = '/api'; static async get(endpoint) { try { const response = await fetch(`${this.baseURL}${endpoint}`); return await response.json(); } catch (error) { console.error('API Error:', error); throw error; } } static async post(endpoint, data) { try { const response = await fetch(`${this.baseURL}${endpoint}`, { method: 'POST', headers: { 'Content-Type': 'application/json', }, body: JSON.stringify(data) }); return await response.json(); } catch (error) { console.error('API Error:', error); throw error; } } } // Job progress tracking class JobTracker { constructor(jobId) { this.jobId = jobId; this.ws = null; this.connect(); } connect() { this.ws = new WebSocket(`ws://localhost/api/ws/jobs/${this.jobId}`); this.ws.onopen = () => { console.log(`WebSocket connected for job ${this.jobId}`); this.updateUI('connected'); }; this.ws.onmessage = (event) => { const data = JSON.parse(event.data); this.handleMessage(data); }; this.ws.onclose = () => { console.log(`WebSocket disconnected for job ${this.jobId}`); setTimeout(() => this.connect(), 5000); // Reconnect after 5 seconds }; } handleMessage(data) { switch (data.type) { case 'progress': this.updateProgress(data.progress); break; case 'log': this.appendLog(data.message); break; case 'completed': this.jobCompleted(data.results); break; case 'error': this.jobError(data.error); break; } } updateProgress(progress) { const progressBar = document.getElementById(`progress-${this.jobId}`); const progressText = document.getElementById(`progress-text-${this.jobId}`); if (progressBar) { progressBar.style.width = `${progress}%`; } if (progressText) { progressText.textContent = `${progress}%`; } } appendLog(message) { const logContainer = document.getElementById(`logs-${this.jobId}`); if (logContainer) { const logEntry = document.createElement('div'); logEntry.className = 'text-sm text-gray-600'; logEntry.textContent = `[${new Date().toLocaleTimeString()}] ${message}`; logContainer.appendChild(logEntry); logContainer.scrollTop = logContainer.scrollHeight; } } jobCompleted(results) { this.updateUI('completed'); if (typeof window.jobCompletedCallback === 'function') { window.jobCompletedCallback(results); } } jobError(error) { this.updateUI('error'); console.error('Job error:', error); } updateUI(status) { // Update UI based on job status const jobElement = document.getElementById(`job-${this.jobId}`); if (jobElement) { jobElement.setAttribute('data-status', status); } } } // Utility functions const Utils = { formatFileSize(bytes) { const sizes = ['Bytes', 'KB', 'MB', 'GB', 'TB']; if (bytes === 0) return '0 Bytes'; const i = parseInt(Math.floor(Math.log(bytes) / Math.log(1024))); return Math.round(bytes / Math.pow(1024, i) * 100) / 100 + ' ' + sizes[i]; }, formatDuration(seconds) { const hours = Math.floor(seconds / 3600); const minutes = Math.floor((seconds % 3600) / 60); const secs = Math.floor(seconds % 60); return `${hours.toString().padStart(2, '0')}:${minutes.toString().padStart(2, '0')}:${secs.toString().padStart(2, '0')}`; }, debounce(func, wait) { let timeout; return function executedFunction(...args) { const later = () => { clearTimeout(timeout); func(...args); }; clearTimeout(timeout); timeout = setTimeout(later, wait); }; }, generateId() { return Date.now().toString(36) + Math.random().toString(36).substr(2); } }; // Export for use in other modules window.API = API; window.JobTracker = JobTracker; window.Utils = Utils; window.themeManager = themeManager;