UNPKG

bigbasealpha

Version:

Professional Grade Custom Database System - A sophisticated, dependency-free database with encryption, caching, indexing, and web dashboard

863 lines (757 loc) 34.4 kB
/** * Enhanced Settings Manager for BigBaseAlpha Dashboard * Handles advanced configuration and settings management */ class EnhancedSettingsManager { constructor() { this.settings = {}; this.originalSettings = {}; this.hasUnsavedChanges = false; this.init(); } init() { this.loadCurrentSettings(); this.setupEventListeners(); this.setupSliders(); this.setupAdvancedToggle(); this.setupValidation(); this.startSystemStatusMonitoring(); } loadCurrentSettings() { // Load current settings from API fetch('/api/config/detailed') .then(response => response.json()) .then(data => { this.settings = data; this.originalSettings = JSON.parse(JSON.stringify(data)); this.populateFormFields(); }) .catch(error => { console.error('Error loading settings:', error); // Use default settings if API fails this.settings = { database: { name: "BigBaseAlpha", path: "./bigbase_data", format: "json", autoSync: true }, performance: { cacheSize: 128, maxConnections: 100, queryTimeout: 30, enableIndexing: true, enableCompression: true }, security: { encryption: false, encryptionKey: "", auditLogging: true, sessionTimeout: 30, twoFactorAuth: false }, backup: { autoBackup: true, interval: "daily", retention: 30, location: "./backups" }, monitoring: { enabled: true, alertEmail: "", memoryThreshold: 80, diskThreshold: 85, alerts: { performance: true, security: true, backup: true, errors: false } }, ui: { theme: "dark", language: "tr", animations: true, soundEffects: false, refreshRate: 2 } }; this.originalSettings = JSON.parse(JSON.stringify(this.settings)); this.populateFormFields(); this.showNotification('Failed to load settings from server, using defaults', 'warning'); }); } populateFormFields() { // Database settings this.setFieldValue('db-name', this.settings.database.name); this.setFieldValue('db-path', this.settings.database.path); this.setFieldValue('db-format', this.settings.database.format); this.setCheckboxValue('auto-sync', this.settings.database.autoSync); // Performance settings this.setSliderValue('cache-size', this.settings.performance.cacheSize); this.setSliderValue('max-connections', this.settings.performance.maxConnections); this.setFieldValue('query-timeout', this.settings.performance.queryTimeout); this.setCheckboxValue('enable-indexing', this.settings.performance.enableIndexing); this.setCheckboxValue('enable-compression', this.settings.performance.enableCompression); // Security settings this.setCheckboxValue('enable-encryption', this.settings.security.encryption); this.setFieldValue('encryption-key', this.settings.security.encryptionKey); this.setCheckboxValue('enable-audit', this.settings.security.auditLogging); this.setFieldValue('session-timeout', this.settings.security.sessionTimeout); this.setCheckboxValue('enable-2fa', this.settings.security.twoFactorAuth); // Backup settings this.setCheckboxValue('auto-backup', this.settings.backup.autoBackup); this.setFieldValue('backup-interval', this.settings.backup.interval); this.setFieldValue('backup-retention', this.settings.backup.retention); this.setFieldValue('backup-location', this.settings.backup.location); // Monitoring settings this.setCheckboxValue('enable-monitoring', this.settings.monitoring.enabled); this.setFieldValue('alert-email', this.settings.monitoring.alertEmail); this.setSliderValue('memory-threshold', this.settings.monitoring.memoryThreshold); this.setSliderValue('disk-threshold', this.settings.monitoring.diskThreshold); // Alert types Object.keys(this.settings.monitoring.alerts).forEach(alertType => { this.setCheckboxValue(`alert-${alertType}`, this.settings.monitoring.alerts[alertType]); }); // UI settings this.setFieldValue('theme-select', this.settings.ui.theme); this.setFieldValue('language-select', this.settings.ui.language); this.setCheckboxValue('animations', this.settings.ui.animations); this.setCheckboxValue('sound-effects', this.settings.ui.soundEffects); this.setFieldValue('refresh-rate', this.settings.ui.refreshRate); // Update JSON editor this.updateConfigJson(); } setFieldValue(fieldId, value) { const field = document.getElementById(fieldId); if (field) { field.value = value; } } setCheckboxValue(fieldId, value) { const field = document.getElementById(fieldId); if (field) { field.checked = value; } } setSliderValue(fieldId, value) { const slider = document.getElementById(fieldId); const valueDisplay = slider?.parentElement.querySelector('.slider-value'); if (slider) { slider.value = value; } if (valueDisplay) { if (fieldId.includes('threshold')) { valueDisplay.textContent = `${value}%`; } else if (fieldId === 'cache-size') { valueDisplay.textContent = `${value} MB`; } else { valueDisplay.textContent = value; } } } setupEventListeners() { // Form field change listeners const formFields = document.querySelectorAll('.form-input, .form-select, input[type="checkbox"]'); formFields.forEach(field => { field.addEventListener('change', () => { this.markAsChanged(); this.validateField(field); }); }); // Button listeners this.setupButtonListeners(); // Auto-save functionality this.setupAutoSave(); } setupButtonListeners() { // Generate encryption key const generateKeyBtn = document.getElementById('generate-key'); if (generateKeyBtn) { generateKeyBtn.addEventListener('click', () => { this.generateEncryptionKey(); }); } // Save settings const saveBtn = document.getElementById('save-all-settings'); if (saveBtn) { saveBtn.addEventListener('click', () => { this.saveAllSettings(); }); } // Reset to defaults const resetBtn = document.getElementById('reset-to-defaults'); if (resetBtn) { resetBtn.addEventListener('click', () => { this.resetToDefaults(); }); } // Discard changes const discardBtn = document.getElementById('discard-changes'); if (discardBtn) { discardBtn.addEventListener('click', () => { this.discardChanges(); }); } // Export config const exportBtn = document.getElementById('export-config'); if (exportBtn) { exportBtn.addEventListener('click', () => { this.exportConfiguration(); }); } // Advanced config validation const validateBtn = document.querySelector('.config-actions .btn-warning'); if (validateBtn) { validateBtn.addEventListener('click', () => { this.validateJsonConfig(); }); } // Apply advanced config const applyBtn = document.querySelector('.config-actions .btn-primary'); if (applyBtn) { applyBtn.addEventListener('click', () => { this.applyJsonConfig(); }); } } setupSliders() { const sliders = document.querySelectorAll('.slider'); sliders.forEach(slider => { slider.addEventListener('input', (e) => { const value = e.target.value; const valueDisplay = e.target.parentElement.querySelector('.slider-value'); if (valueDisplay) { if (e.target.id.includes('threshold')) { valueDisplay.textContent = `${value}%`; } else if (e.target.id === 'cache-size') { valueDisplay.textContent = `${value} MB`; } else { valueDisplay.textContent = value; } } this.markAsChanged(); }); }); } setupAdvancedToggle() { const toggleBtn = document.getElementById('toggle-advanced'); const advancedContent = document.getElementById('advanced-content'); if (toggleBtn && advancedContent) { toggleBtn.addEventListener('click', () => { const isVisible = advancedContent.style.display !== 'none'; if (isVisible) { advancedContent.style.display = 'none'; toggleBtn.textContent = 'Show Advanced'; } else { advancedContent.style.display = 'block'; toggleBtn.textContent = 'Hide Advanced'; this.updateConfigJson(); } }); } } setupValidation() { // Real-time validation for specific fields const emailField = document.getElementById('alert-email'); if (emailField) { emailField.addEventListener('blur', () => { this.validateEmail(emailField); }); } const pathFields = ['db-path', 'backup-location']; pathFields.forEach(fieldId => { const field = document.getElementById(fieldId); if (field) { field.addEventListener('blur', () => { this.validatePath(field); }); } }); } setupAutoSave() { // Auto-save every 30 seconds if there are changes setInterval(() => { if (this.hasUnsavedChanges) { this.autoSave(); } }, 30000); } markAsChanged() { this.hasUnsavedChanges = true; this.updateSaveStatus('unsaved', 'You have unsaved changes'); // Enable save button const saveBtn = document.getElementById('save-all-settings'); if (saveBtn) { saveBtn.disabled = false; saveBtn.classList.add('btn-success'); } } validateField(field) { const fieldId = field.id; let isValid = true; let message = ''; switch (fieldId) { case 'alert-email': isValid = this.validateEmail(field); break; case 'db-path': case 'backup-location': isValid = this.validatePath(field); break; case 'query-timeout': isValid = this.validateTimeout(field); break; case 'backup-retention': isValid = this.validateRetention(field); break; } this.showFieldValidation(field, isValid, message); return isValid; } validateEmail(field) { const email = field.value.trim(); if (email && !/^[^\s@]+@[^\s@]+\.[^\s@]+$/.test(email)) { this.showFieldError(field, 'Please enter a valid email address'); return false; } this.clearFieldError(field); return true; } validatePath(field) { const path = field.value.trim(); if (path && !/^[a-zA-Z0-9._\-\/\\:]+$/.test(path)) { this.showFieldError(field, 'Please enter a valid file path'); return false; } this.clearFieldError(field); return true; } validateTimeout(field) { const timeout = parseInt(field.value); if (timeout < 1 || timeout > 300) { this.showFieldError(field, 'Timeout must be between 1 and 300 seconds'); return false; } this.clearFieldError(field); return true; } validateRetention(field) { const retention = parseInt(field.value); if (retention < 1 || retention > 365) { this.showFieldError(field, 'Retention must be between 1 and 365 days'); return false; } this.clearFieldError(field); return true; } showFieldError(field, message) { field.style.borderColor = '#ef4444'; // Remove existing error message const existingError = field.parentElement.querySelector('.field-error'); if (existingError) { existingError.remove(); } // Add error message const errorEl = document.createElement('div'); errorEl.className = 'field-error'; errorEl.textContent = message; errorEl.style.color = '#ef4444'; errorEl.style.fontSize = '0.75rem'; errorEl.style.marginTop = '0.25rem'; field.parentElement.appendChild(errorEl); } clearFieldError(field) { field.style.borderColor = ''; const errorEl = field.parentElement.querySelector('.field-error'); if (errorEl) { errorEl.remove(); } } generateEncryptionKey() { const characters = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789'; let key = ''; for (let i = 0; i < 32; i++) { key += characters.charAt(Math.floor(Math.random() * characters.length)); } const keyField = document.getElementById('encryption-key'); if (keyField) { keyField.value = key; this.markAsChanged(); // Show success animation keyField.style.background = 'rgba(16, 185, 129, 0.1)'; setTimeout(() => { keyField.style.background = ''; }, 1000); } } async saveAllSettings() { try { // Collect all current form values const currentSettings = this.collectFormData(); // Validate all settings if (!this.validateAllSettings(currentSettings)) { this.showNotification('Please fix validation errors before saving', 'error'); return; } // Show saving state this.showSavingState(true); // Save to API const response = await fetch('/api/config', { method: 'PUT', headers: { 'Content-Type': 'application/json' }, body: JSON.stringify(currentSettings) }); if (response.ok) { this.settings = currentSettings; this.originalSettings = JSON.parse(JSON.stringify(currentSettings)); this.hasUnsavedChanges = false; this.updateSaveStatus('saved', 'All settings saved successfully'); this.showNotification('Settings saved successfully!', 'success'); } else { throw new Error('Failed to save settings'); } } catch (error) { console.error('Error saving settings:', error); this.showNotification('Failed to save settings', 'error'); } finally { this.showSavingState(false); } } collectFormData() { return { database: { name: document.getElementById('db-name')?.value || '', path: document.getElementById('db-path')?.value || '', format: document.getElementById('db-format')?.value || 'json', autoSync: document.getElementById('auto-sync')?.checked || false }, performance: { cacheSize: parseInt(document.getElementById('cache-size')?.value || '128'), maxConnections: parseInt(document.getElementById('max-connections')?.value || '100'), queryTimeout: parseInt(document.getElementById('query-timeout')?.value || '30'), enableIndexing: document.getElementById('enable-indexing')?.checked || false, enableCompression: document.getElementById('enable-compression')?.checked || false }, security: { encryption: document.getElementById('enable-encryption')?.checked || false, encryptionKey: document.getElementById('encryption-key')?.value || '', auditLogging: document.getElementById('enable-audit')?.checked || false, sessionTimeout: parseInt(document.getElementById('session-timeout')?.value || '30'), twoFactorAuth: document.getElementById('enable-2fa')?.checked || false }, backup: { autoBackup: document.getElementById('auto-backup')?.checked || false, interval: document.getElementById('backup-interval')?.value || 'daily', retention: parseInt(document.getElementById('backup-retention')?.value || '30'), location: document.getElementById('backup-location')?.value || './backups' }, monitoring: { enabled: document.getElementById('enable-monitoring')?.checked || false, alertEmail: document.getElementById('alert-email')?.value || '', memoryThreshold: parseInt(document.getElementById('memory-threshold')?.value || '80'), diskThreshold: parseInt(document.getElementById('disk-threshold')?.value || '85'), alerts: { performance: document.getElementById('alert-performance')?.checked || false, security: document.getElementById('alert-security')?.checked || false, backup: document.getElementById('alert-backup')?.checked || false, errors: document.getElementById('alert-errors')?.checked || false } }, ui: { theme: document.getElementById('theme-select')?.value || 'dark', language: document.getElementById('language-select')?.value || 'tr', animations: document.getElementById('animations')?.checked || false, soundEffects: document.getElementById('sound-effects')?.checked || false, refreshRate: parseInt(document.getElementById('refresh-rate')?.value || '2') } }; } validateAllSettings(settings) { let isValid = true; // Validate all form fields const allFields = document.querySelectorAll('.form-input, .form-select'); allFields.forEach(field => { if (!this.validateField(field)) { isValid = false; } }); return isValid; } resetToDefaults() { if (confirm('Are you sure you want to reset all settings to defaults? This action cannot be undone.')) { // Reset to default values this.settings = { database: { name: "BigBaseAlpha", path: "./bigbase_data", format: "json", autoSync: true }, performance: { cacheSize: 128, maxConnections: 100, queryTimeout: 30, enableIndexing: true, enableCompression: true }, security: { encryption: false, encryptionKey: "", auditLogging: true, sessionTimeout: 30, twoFactorAuth: false }, backup: { autoBackup: true, interval: "daily", retention: 30, location: "./backups" }, monitoring: { enabled: true, alertEmail: "", memoryThreshold: 80, diskThreshold: 85, alerts: { performance: true, security: true, backup: true, errors: false } }, ui: { theme: "dark", language: "tr", animations: true, soundEffects: false, refreshRate: 2 } }; this.populateFormFields(); this.markAsChanged(); this.showNotification('Settings reset to defaults', 'info'); } } discardChanges() { if (confirm('Are you sure you want to discard all unsaved changes?')) { this.settings = JSON.parse(JSON.stringify(this.originalSettings)); this.populateFormFields(); this.hasUnsavedChanges = false; this.updateSaveStatus('saved', 'Changes discarded'); this.showNotification('Changes discarded', 'info'); } } exportConfiguration() { const config = this.collectFormData(); const dataStr = JSON.stringify(config, null, 2); const dataBlob = new Blob([dataStr], { type: 'application/json' }); const link = document.createElement('a'); link.href = URL.createObjectURL(dataBlob); link.download = `bigbase-config-${new Date().toISOString().split('T')[0]}.json`; link.click(); this.showNotification('Configuration exported successfully', 'success'); } updateConfigJson() { const configTextarea = document.getElementById('config-json'); if (configTextarea) { const currentConfig = this.collectFormData(); configTextarea.value = JSON.stringify(currentConfig, null, 2); } } validateJsonConfig() { const configTextarea = document.getElementById('config-json'); if (!configTextarea) return; try { const config = JSON.parse(configTextarea.value); this.showNotification('JSON configuration is valid', 'success'); configTextarea.style.borderColor = '#10b981'; } catch (error) { this.showNotification('Invalid JSON configuration: ' + error.message, 'error'); configTextarea.style.borderColor = '#ef4444'; } } applyJsonConfig() { const configTextarea = document.getElementById('config-json'); if (!configTextarea) return; try { const config = JSON.parse(configTextarea.value); this.settings = config; this.populateFormFields(); this.markAsChanged(); this.showNotification('Configuration applied from JSON', 'success'); } catch (error) { this.showNotification('Failed to apply JSON configuration: ' + error.message, 'error'); } } autoSave() { // Implement auto-save logic console.log('Auto-saving settings...'); this.updateSaveStatus('auto-saved', 'Auto-saved'); } showSavingState(saving) { const saveBtn = document.getElementById('save-all-settings'); if (saveBtn) { if (saving) { saveBtn.disabled = true; saveBtn.textContent = '💾 Saving...'; } else { saveBtn.disabled = false; saveBtn.textContent = '💾 Save All Settings'; } } } updateSaveStatus(status, message) { const statusIcon = document.querySelector('.status-icon'); const statusText = document.querySelector('.status-text'); const statusTime = document.querySelector('.status-time'); if (statusIcon && statusText && statusTime) { switch (status) { case 'saved': statusIcon.textContent = '✅'; statusText.textContent = message; statusTime.textContent = `Last saved: ${new Date().toLocaleTimeString()}`; break; case 'unsaved': statusIcon.textContent = '⚠️'; statusText.textContent = message; statusTime.textContent = ''; break; case 'auto-saved': statusIcon.textContent = '🔄'; statusText.textContent = message; statusTime.textContent = `Auto-saved: ${new Date().toLocaleTimeString()}`; break; } } } showNotification(message, type = 'info') { // Integration with existing notification system if (window.notifications) { window.notifications.show(message, type); } else { console.log(`[${type.toUpperCase()}] ${message}`); } } startSystemStatusMonitoring() { // Update system status immediately this.updateSystemStatus(); // Update every 3 seconds (faster updates) this.statusInterval = setInterval(() => { this.updateSystemStatus(); }, 3000); } async updateSystemStatus() { try { const response = await fetch('/api/system/status'); if (response.ok) { const status = await response.json(); this.displaySystemStatus(status); } else { throw new Error('Failed to fetch system status'); } } catch (error) { console.error('Error fetching system status:', error); this.displaySystemStatusError(); } } async displaySystemStatus(status) { try { // Update status icon and text const statusIcon = document.getElementById('status-icon'); const statusText = document.getElementById('status-text'); const statusTime = document.getElementById('status-time'); if (statusIcon && statusText && statusTime) { // Update icon to success state statusIcon.innerHTML = ` <path fill-rule="evenodd" d="M10 18a8 8 0 100-16 8 8 0 000 16zm3.707-9.293a1 1 0 00-1.414-1.414L9 10.586 7.707 9.293a1 1 0 00-1.414 1.414l2 2a1 1 0 001.414 0l4-4z" clip-rule="evenodd"/> `; statusIcon.className = 'status-icon online'; statusText.textContent = 'System Online'; statusTime.textContent = `Updated: ${new Date().toLocaleTimeString()}`; } // Update memory usage const memoryFill = document.getElementById('memory-fill'); const memoryValue = document.getElementById('memory-value'); if (memoryFill && memoryValue) { const memoryPercent = parseFloat(status.memory.used) || 0; memoryFill.style.width = `${Math.min(memoryPercent, 100)}%`; memoryValue.textContent = `${memoryPercent.toFixed(1)}%`; // Update color based on usage memoryFill.className = 'metric-fill'; if (memoryPercent > 90) { memoryFill.classList.add('danger'); } else if (memoryPercent > 75) { memoryFill.classList.add('warning'); } } // Update database status const dbStatus = document.getElementById('db-status'); const dbCollections = document.getElementById('db-collections'); if (dbStatus && dbCollections) { const isConnected = status.database && status.database.status === 'connected'; dbStatus.textContent = isConnected ? 'Connected' : 'Disconnected'; dbStatus.className = `status-badge ${isConnected ? 'connected' : 'disconnected'}`; const collectionCount = (status.database && status.database.collections) || 0; dbCollections.textContent = `${collectionCount} collections`; } // Update uptime const uptimeValue = document.getElementById('uptime-value'); if (uptimeValue) { const uptime = (status.uptime && status.uptime.formatted) || '00:00:00'; uptimeValue.textContent = uptime; } // Update performance metrics if available if (status.performance) { // Cache Performance const cacheValue = document.getElementById('cache-performance-value'); if (cacheValue) { cacheValue.textContent = `${status.performance.cacheHitRate}%`; } // Query Latency const latencyValue = document.getElementById('query-latency-value'); if (latencyValue) { latencyValue.textContent = `${status.performance.queryLatency}ms`; } // Throughput const throughputValue = document.getElementById('throughput-value'); if (throughputValue) { throughputValue.textContent = `${status.performance.throughput.toLocaleString()} ops/sec`; } // Active Connections const connectionsValue = document.getElementById('connections-value'); if (connectionsValue) { connectionsValue.textContent = status.performance.connections.toString(); } } // Update CPU usage if available if (status.cpu) { const cpuValue = document.getElementById('cpu-usage-value'); if (cpuValue) { cpuValue.textContent = `${status.cpu.load.toFixed(1)}%`; } } } catch (error) { console.error('Error displaying system status:', error); this.displaySystemStatusError(); } } displaySystemStatusError() { const statusIcon = document.getElementById('status-icon'); const statusText = document.getElementById('status-text'); const statusTime = document.getElementById('status-time'); if (statusIcon && statusText && statusTime) { // Update icon to error state statusIcon.innerHTML = ` <path fill-rule="evenodd" d="M10 18a8 8 0 100-16 8 8 0 000 16zM8.707 7.293a1 1 0 00-1.414 1.414L8.586 10l-1.293 1.293a1 1 0 101.414 1.414L10 11.414l1.293 1.293a1 1 0 001.414-1.414L11.414 10l1.293-1.293a1 1 0 00-1.414-1.414L10 8.586 8.707 7.293z" clip-rule="evenodd"/> `; statusIcon.className = 'status-icon error'; statusText.textContent = 'Connection Error'; statusTime.textContent = `Last attempt: ${new Date().toLocaleTimeString()}`; } // Set default values for metrics const memoryFill = document.getElementById('memory-fill'); const memoryValue = document.getElementById('memory-value'); if (memoryFill && memoryValue) { memoryFill.style.width = '0%'; memoryValue.textContent = 'N/A'; } const dbStatus = document.getElementById('db-status'); const dbCollections = document.getElementById('db-collections'); if (dbStatus && dbCollections) { dbStatus.textContent = 'Disconnected'; dbStatus.className = 'status-badge disconnected'; dbCollections.textContent = '0 collections'; } const uptimeValue = document.getElementById('uptime-value'); if (uptimeValue) { uptimeValue.textContent = '00:00:00'; } } destroy() { // Clean up intervals when settings page is closed if (this.statusInterval) { clearInterval(this.statusInterval); } } } // Initialize Enhanced Settings Manager let enhancedSettingsManager = null; function initEnhancedSettings() { if (!enhancedSettingsManager) { enhancedSettingsManager = new EnhancedSettingsManager(); } } function destroyEnhancedSettings() { if (enhancedSettingsManager) { enhancedSettingsManager.destroy(); enhancedSettingsManager = null; } } // Export for use in main dashboard window.EnhancedSettingsManager = EnhancedSettingsManager; window.initEnhancedSettings = initEnhancedSettings; window.destroyEnhancedSettings = destroyEnhancedSettings;