Really-amin's picture
Upload 25 files
89ba751 verified
raw
history blame
11.1 kB
/**
* 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');