Spaces:
Paused
Paused
/** | |
* Legal Dashboard Core Module | |
* ========================== | |
* | |
* Shared core functionality for cross-page communication and data synchronization. | |
* This module provides event-driven updates and shared state management across all pages. | |
*/ | |
class DashboardCore { | |
constructor() { | |
this.eventBus = new EventTarget(); | |
this.cache = new Map(); | |
this.apiClient = null; | |
this.isInitialized = false; | |
// Initialize when DOM is ready | |
if (document.readyState === 'loading') { | |
document.addEventListener('DOMContentLoaded', () => this.initialize()); | |
} else { | |
this.initialize(); | |
} | |
} | |
/** | |
* Initialize the core module | |
*/ | |
initialize() { | |
if (this.isInitialized) return; | |
console.log('🚀 Initializing Dashboard Core...'); | |
// Initialize API client | |
this.apiClient = new LegalDashboardAPI(); | |
// Set up localStorage synchronization | |
this.setupLocalStorageSync(); | |
// Set up periodic health checks | |
this.setupHealthChecks(); | |
// Set up cross-page event listeners | |
this.setupEventListeners(); | |
this.isInitialized = true; | |
console.log('✅ Dashboard Core initialized'); | |
// Broadcast initialization event | |
this.broadcast('coreInitialized', { timestamp: Date.now() }); | |
} | |
/** | |
* Broadcast events across pages | |
*/ | |
broadcast(eventName, data = {}) { | |
const event = new CustomEvent(eventName, { | |
detail: { | |
...data, | |
timestamp: Date.now(), | |
source: window.location.pathname | |
} | |
}); | |
this.eventBus.dispatchEvent(event); | |
// Also store in localStorage for cross-tab communication | |
this.storeEvent(eventName, data); | |
console.log(`📡 Broadcast: ${eventName}`, data); | |
} | |
/** | |
* Listen for cross-page events | |
*/ | |
listen(eventName, callback) { | |
const wrappedCallback = (event) => { | |
callback(event.detail); | |
}; | |
this.eventBus.addEventListener(eventName, wrappedCallback); | |
// Return unsubscribe function | |
return () => { | |
this.eventBus.removeEventListener(eventName, wrappedCallback); | |
}; | |
} | |
/** | |
* Store event in localStorage for cross-tab communication | |
*/ | |
storeEvent(eventName, data) { | |
try { | |
const events = JSON.parse(localStorage.getItem('dashboard_events') || '[]'); | |
events.push({ | |
name: eventName, | |
data: data, | |
timestamp: Date.now(), | |
source: window.location.pathname | |
}); | |
// Keep only last 50 events | |
if (events.length > 50) { | |
events.splice(0, events.length - 50); | |
} | |
localStorage.setItem('dashboard_events', JSON.stringify(events)); | |
} catch (error) { | |
console.warn('Failed to store event in localStorage:', error); | |
} | |
} | |
/** | |
* Setup localStorage synchronization | |
*/ | |
setupLocalStorageSync() { | |
// Listen for storage changes (cross-tab communication) | |
window.addEventListener('storage', (event) => { | |
if (event.key === 'dashboard_events') { | |
try { | |
const events = JSON.parse(event.newValue || '[]'); | |
const latestEvent = events[events.length - 1]; | |
if (latestEvent && latestEvent.source !== window.location.pathname) { | |
// Re-broadcast event from other tab | |
this.eventBus.dispatchEvent(new CustomEvent(latestEvent.name, { | |
detail: latestEvent.data | |
})); | |
} | |
} catch (error) { | |
console.warn('Failed to process storage event:', error); | |
} | |
} | |
}); | |
} | |
/** | |
* Setup periodic health checks | |
*/ | |
setupHealthChecks() { | |
// Check API health every 30 seconds | |
setInterval(async () => { | |
try { | |
const health = await this.apiClient.healthCheck(); | |
this.broadcast('healthUpdate', health); | |
} catch (error) { | |
this.broadcast('healthUpdate', { status: 'unhealthy', error: error.message }); | |
} | |
}, 30000); | |
} | |
/** | |
* Setup common event listeners | |
*/ | |
setupEventListeners() { | |
// Listen for document uploads | |
this.listen('documentUploaded', (data) => { | |
this.handleDocumentUpload(data); | |
}); | |
// Listen for document updates | |
this.listen('documentUpdated', (data) => { | |
this.handleDocumentUpdate(data); | |
}); | |
// Listen for document deletions | |
this.listen('documentDeleted', (data) => { | |
this.handleDocumentDelete(data); | |
}); | |
// Listen for scraping updates | |
this.listen('scrapingUpdate', (data) => { | |
this.handleScrapingUpdate(data); | |
}); | |
// Listen for system health updates | |
this.listen('healthUpdate', (data) => { | |
this.handleHealthUpdate(data); | |
}); | |
} | |
/** | |
* Handle document upload events | |
*/ | |
handleDocumentUpload(data) { | |
console.log('📄 Document uploaded:', data); | |
// Update cache | |
this.cache.set(`document_${data.fileId}`, data); | |
// Refresh document lists on relevant pages | |
if (window.location.pathname.includes('documents.html') || | |
window.location.pathname.includes('improved_legal_dashboard.html')) { | |
this.refreshDocumentList(); | |
} | |
// Update dashboard stats | |
this.updateDashboardStats(); | |
// Show notification | |
showToast(`فایل "${data.fileName}" با موفقیت آپلود شد`, 'success'); | |
} | |
/** | |
* Handle document update events | |
*/ | |
handleDocumentUpdate(data) { | |
console.log('📝 Document updated:', data); | |
// Update cache | |
this.cache.set(`document_${data.documentId}`, data); | |
// Refresh document lists | |
this.refreshDocumentList(); | |
// Show notification | |
showToast('سند با موفقیت بهروزرسانی شد', 'success'); | |
} | |
/** | |
* Handle document delete events | |
*/ | |
handleDocumentDelete(data) { | |
console.log('🗑️ Document deleted:', data); | |
// Remove from cache | |
this.cache.delete(`document_${data.documentId}`); | |
// Refresh document lists | |
this.refreshDocumentList(); | |
// Update dashboard stats | |
this.updateDashboardStats(); | |
// Show notification | |
showToast('سند با موفقیت حذف شد', 'info'); | |
} | |
/** | |
* Handle scraping update events | |
*/ | |
handleScrapingUpdate(data) { | |
console.log('🕷️ Scraping update:', data); | |
// Update scraping dashboard if on that page | |
if (window.location.pathname.includes('scraping_dashboard.html')) { | |
this.refreshScrapingDashboard(); | |
} | |
// Show notification | |
showToast(`وضعیت scraping: ${data.status}`, 'info'); | |
} | |
/** | |
* Handle health update events | |
*/ | |
handleHealthUpdate(data) { | |
console.log('💓 Health update:', data); | |
// Update health indicators on all pages | |
this.updateHealthIndicators(data); | |
} | |
/** | |
* Refresh document list (if function exists) | |
*/ | |
refreshDocumentList() { | |
if (typeof loadDocuments === 'function') { | |
loadDocuments(); | |
} | |
if (typeof refreshDocumentTable === 'function') { | |
refreshDocumentTable(); | |
} | |
} | |
/** | |
* Update dashboard statistics | |
*/ | |
async updateDashboardStats() { | |
try { | |
const summary = await this.apiClient.getDashboardSummary(); | |
this.broadcast('dashboardStatsUpdated', summary); | |
// Update dashboard if on dashboard page | |
if (window.location.pathname.includes('improved_legal_dashboard.html')) { | |
if (typeof updateDashboardStats === 'function') { | |
updateDashboardStats(summary); | |
} | |
} | |
} catch (error) { | |
console.error('Failed to update dashboard stats:', error); | |
} | |
} | |
/** | |
* Refresh scraping dashboard | |
*/ | |
refreshScrapingDashboard() { | |
if (typeof loadScrapingData === 'function') { | |
loadScrapingData(); | |
} | |
if (typeof updateScrapingStatus === 'function') { | |
updateScrapingStatus(); | |
} | |
} | |
/** | |
* Update health indicators | |
*/ | |
updateHealthIndicators(healthData) { | |
const healthElements = document.querySelectorAll('.health-indicator'); | |
healthElements.forEach(element => { | |
const status = healthData.status || 'unknown'; | |
element.className = `health-indicator ${status}`; | |
element.textContent = status === 'healthy' ? '🟢' : '🔴'; | |
}); | |
} | |
/** | |
* Get cached data | |
*/ | |
getCachedData(key) { | |
return this.cache.get(key); | |
} | |
/** | |
* Set cached data | |
*/ | |
setCachedData(key, data) { | |
this.cache.set(key, data); | |
} | |
/** | |
* Clear cache | |
*/ | |
clearCache() { | |
this.cache.clear(); | |
} | |
/** | |
* Get API client | |
*/ | |
getApiClient() { | |
return this.apiClient; | |
} | |
/** | |
* Force refresh all data | |
*/ | |
async forceRefresh() { | |
console.log('🔄 Force refreshing all data...'); | |
try { | |
// Clear cache | |
this.clearCache(); | |
// Refresh document list | |
this.refreshDocumentList(); | |
// Update dashboard stats | |
await this.updateDashboardStats(); | |
// Refresh scraping data | |
this.refreshScrapingDashboard(); | |
this.broadcast('dataRefreshed', { timestamp: Date.now() }); | |
showToast('دادهها با موفقیت بهروزرسانی شدند', 'success'); | |
} catch (error) { | |
console.error('Failed to force refresh:', error); | |
showToast('خطا در بهروزرسانی دادهها', 'error'); | |
} | |
} | |
} | |
// Global instance | |
const dashboardCore = new DashboardCore(); | |
// Export for use in other modules | |
if (typeof module !== 'undefined' && module.exports) { | |
module.exports = DashboardCore; | |
} | |
// Make available globally | |
window.dashboardCore = dashboardCore; | |
console.log('📦 Dashboard Core module loaded'); |