// Dashboard JavaScript for Calejo Control Adapter // Tab management function showTab(tabName) { // Hide all tabs document.querySelectorAll('.tab-content').forEach(tab => { tab.classList.remove('active'); }); document.querySelectorAll('.tab-button').forEach(button => { button.classList.remove('active'); }); // Show selected tab document.getElementById(tabName + '-tab').classList.add('active'); event.target.classList.add('active'); // Load data for the tab if (tabName === 'status') { loadStatus(); } else if (tabName === 'scada') { loadSCADAStatus(); } else if (tabName === 'signals') { loadSignals(); } else if (tabName === 'logs') { loadLogs(); } else if (tabName === 'protocol-mapping') { loadProtocolMappings(); } } // Alert management function showAlert(message, type) { const alertsDiv = document.getElementById('alerts'); const alertDiv = document.createElement('div'); alertDiv.className = `alert ${type}`; alertDiv.textContent = message; alertsDiv.appendChild(alertDiv); // Auto-remove after 5 seconds setTimeout(() => { alertDiv.remove(); }, 5000); } // Status functions async function loadStatus() { try { const response = await fetch('/api/v1/dashboard/status'); const status = await response.json(); const statusGrid = document.getElementById('status-grid'); statusGrid.innerHTML = ''; for (const [key, value] of Object.entries(status)) { const statusCard = document.createElement('div'); statusCard.className = `status-card ${value}`; statusCard.innerHTML = `
${value.toUpperCase()}
`; statusGrid.appendChild(statusCard); } } catch (error) { console.error('Error loading status:', error); showAlert('Failed to load system status', 'error'); } } function refreshStatus() { loadStatus(); } // Configuration functions async function loadConfiguration() { try { const response = await fetch('/api/v1/dashboard/config'); const config = await response.json(); // Populate form fields document.getElementById('db_host').value = config.database.db_host; document.getElementById('db_port').value = config.database.db_port; document.getElementById('db_name').value = config.database.db_name; document.getElementById('db_user').value = config.database.db_user; document.getElementById('opcua_enabled').checked = config.opcua.enabled; document.getElementById('opcua_port').value = config.opcua.port; document.getElementById('modbus_enabled').checked = config.modbus.enabled; document.getElementById('modbus_port').value = config.modbus.port; document.getElementById('rest_api_host').value = config.rest_api.host; document.getElementById('rest_api_port').value = config.rest_api.port; document.getElementById('rest_api_cors_enabled').checked = config.rest_api.cors_enabled; document.getElementById('health_monitor_port').value = config.monitoring.health_monitor_port; showAlert('Configuration loaded successfully', 'success'); } catch (error) { console.error('Error loading configuration:', error); showAlert('Failed to load configuration', 'error'); } } async function saveConfiguration() { try { const config = { database: { db_host: document.getElementById('db_host').value, db_port: parseInt(document.getElementById('db_port').value), db_name: document.getElementById('db_name').value, db_user: document.getElementById('db_user').value, db_password: document.getElementById('db_password').value }, opcua: { enabled: document.getElementById('opcua_enabled').checked, host: 'localhost', port: parseInt(document.getElementById('opcua_port').value) }, modbus: { enabled: document.getElementById('modbus_enabled').checked, host: 'localhost', port: parseInt(document.getElementById('modbus_port').value), unit_id: 1 }, rest_api: { enabled: true, host: document.getElementById('rest_api_host').value, port: parseInt(document.getElementById('rest_api_port').value), cors_enabled: document.getElementById('rest_api_cors_enabled').checked }, monitoring: { health_monitor_port: parseInt(document.getElementById('health_monitor_port').value), metrics_enabled: true }, security: { jwt_secret_key: '', api_key: '' } }; const response = await fetch('/api/v1/dashboard/config', { method: 'POST', headers: { 'Content-Type': 'application/json' }, body: JSON.stringify(config) }); const result = await response.json(); if (result.valid) { showAlert('Configuration saved successfully', 'success'); if (result.warnings.length > 0) { showAlert('Warnings: ' + result.warnings.join(', '), 'warning'); } } else { showAlert('Configuration validation failed: ' + result.errors.join(', '), 'error'); } } catch (error) { console.error('Error saving configuration:', error); showAlert('Failed to save configuration', 'error'); } } async function validateConfiguration() { try { const config = { database: { db_host: document.getElementById('db_host').value, db_port: parseInt(document.getElementById('db_port').value), db_name: document.getElementById('db_name').value, db_user: document.getElementById('db_user').value, db_password: document.getElementById('db_password').value }, opcua: { enabled: document.getElementById('opcua_enabled').checked, host: 'localhost', port: parseInt(document.getElementById('opcua_port').value) }, modbus: { enabled: document.getElementById('modbus_enabled').checked, host: 'localhost', port: parseInt(document.getElementById('modbus_port').value), unit_id: 1 }, rest_api: { enabled: true, host: document.getElementById('rest_api_host').value, port: parseInt(document.getElementById('rest_api_port').value), cors_enabled: document.getElementById('rest_api_cors_enabled').checked }, monitoring: { health_monitor_port: parseInt(document.getElementById('health_monitor_port').value), metrics_enabled: true }, security: { jwt_secret_key: '', api_key: '' } }; const response = await fetch('/api/v1/dashboard/config', { method: 'POST', headers: { 'Content-Type': 'application/json' }, body: JSON.stringify(config) }); const result = await response.json(); if (result.valid) { showAlert('Configuration is valid', 'success'); if (result.warnings.length > 0) { showAlert('Warnings: ' + result.warnings.join(', '), 'warning'); } } else { showAlert('Configuration validation failed: ' + result.errors.join(', '), 'error'); } } catch (error) { console.error('Error validating configuration:', error); showAlert('Failed to validate configuration', 'error'); } } // Logs functions async function loadLogs() { try { const response = await fetch('/api/v1/dashboard/logs?limit=50'); const data = await response.json(); const logsContainer = document.getElementById('logs-container'); logsContainer.innerHTML = ''; data.logs.forEach(log => { const logEntry = document.createElement('div'); logEntry.className = `log-entry ${log.level.toLowerCase()}`; logEntry.innerHTML = ` ${log.timestamp} ${log.level} ${log.message} `; logsContainer.appendChild(logEntry); }); } catch (error) { console.error('Error loading logs:', error); showAlert('Failed to load logs', 'error'); } } // Action functions async function restartSystem() { if (confirm('Are you sure you want to restart the system? This will temporarily interrupt service.')) { try { const response = await fetch('/api/v1/dashboard/restart', { method: 'POST' }); const result = await response.json(); showAlert(`Restart initiated: ${result.message}`, 'success'); } catch (error) { console.error('Error restarting system:', error); showAlert('Failed to restart system', 'error'); } } } async function createBackup() { try { const response = await fetch('/api/v1/dashboard/backup'); const result = await response.json(); showAlert(`Backup initiated: ${result.message}`, 'success'); } catch (error) { console.error('Error creating backup:', error); showAlert('Failed to create backup', 'error'); } } async function runHealthCheck() { try { const response = await fetch('/health'); const result = await response.json(); showAlert(`Health check: ${result.status}`, 'success'); } catch (error) { console.error('Error running health check:', error); showAlert('Health check failed', 'error'); } } function viewMetrics() { window.open('/metrics', '_blank'); } // SCADA/Hardware functions function showSCADAAlert(message, type) { const alertsDiv = document.getElementById('scada-alerts'); const alertDiv = document.createElement('div'); alertDiv.className = `alert ${type}`; alertDiv.textContent = message; alertsDiv.appendChild(alertDiv); // Auto-remove after 5 seconds setTimeout(() => { alertDiv.remove(); }, 5000); } async function loadSCADAConfig() { try { // Load current SCADA configuration const response = await fetch('/api/v1/dashboard/scada-config'); const config = await response.json(); // Populate SCADA form fields document.getElementById('modbus_enabled_scada').checked = config.modbus.enabled; document.getElementById('modbus_port_scada').value = config.modbus.port; document.getElementById('modbus_slave_id').value = config.modbus.slave_id; document.getElementById('modbus_baud_rate').value = config.modbus.baud_rate; document.getElementById('opcua_enabled_scada').checked = config.opcua.enabled; document.getElementById('opcua_port_scada').value = config.opcua.port; document.getElementById('opcua_security_mode').value = config.opcua.security_mode; document.getElementById('device_mapping').value = config.device_mapping; showSCADAAlert('SCADA configuration loaded successfully', 'success'); } catch (error) { console.error('Error loading SCADA configuration:', error); showSCADAAlert('Failed to load SCADA configuration', 'error'); } } async function saveSCADAConfig() { try { const config = { modbus: { enabled: document.getElementById('modbus_enabled_scada').checked, port: parseInt(document.getElementById('modbus_port_scada').value), slave_id: parseInt(document.getElementById('modbus_slave_id').value), baud_rate: parseInt(document.getElementById('modbus_baud_rate').value) }, opcua: { enabled: document.getElementById('opcua_enabled_scada').checked, port: parseInt(document.getElementById('opcua_port_scada').value), security_mode: document.getElementById('opcua_security_mode').value }, device_mapping: document.getElementById('device_mapping').value }; const response = await fetch('/api/v1/dashboard/scada-config', { method: 'POST', headers: { 'Content-Type': 'application/json' }, body: JSON.stringify(config) }); const result = await response.json(); if (result.success) { showSCADAAlert('SCADA configuration saved successfully', 'success'); } else { showSCADAAlert('Failed to save SCADA configuration: ' + result.error, 'error'); } } catch (error) { console.error('Error saving SCADA configuration:', error); showSCADAAlert('Failed to save SCADA configuration', 'error'); } } async function testSCADAConnection() { try { const response = await fetch('/api/v1/dashboard/test-scada'); const result = await response.json(); if (result.success) { showSCADAAlert('SCADA connection test successful', 'success'); } else { showSCADAAlert('SCADA connection test failed: ' + result.error, 'error'); } } catch (error) { console.error('Error testing SCADA connection:', error); showSCADAAlert('Failed to test SCADA connection', 'error'); } } async function loadSCADAStatus() { try { const response = await fetch('/api/v1/dashboard/scada-status'); const status = await response.json(); const statusGrid = document.getElementById('scada-status-grid'); statusGrid.innerHTML = ''; const scadaStatus = [ { name: 'Modbus Server', status: status.modbus_enabled ? 'running' : 'stopped' }, { name: 'OPC UA Server', status: status.opcua_enabled ? 'running' : 'stopped' }, { name: 'Device Connections', status: status.device_connections > 0 ? 'running' : 'stopped' }, { name: 'Data Acquisition', status: status.data_acquisition ? 'running' : 'stopped' } ]; scadaStatus.forEach(item => { const statusCard = document.createElement('div'); statusCard.className = `status-card ${item.status}`; statusCard.innerHTML = `${item.status.toUpperCase()}
`; statusGrid.appendChild(statusCard); }); // Add connection details const detailsDiv = document.createElement('div'); detailsDiv.style.gridColumn = '1 / -1'; detailsDiv.innerHTML = `Modbus Port: ${status.modbus_port || 'Not configured'}
OPC UA Port: ${status.opcua_port || 'Not configured'}
Connected Devices: ${status.device_connections || 0}
Last Data Update: ${status.last_update || 'Never'}
Active Signals: ${stats.active_signals || 0}
Total Signals: ${stats.total_signals || 0}
Error Rate: ${stats.error_rate || '0%'}
`; statsGrid.appendChild(card); } // Update signals table const signalsBody = document.getElementById('signals-body'); signalsBody.innerHTML = ''; data.signals.forEach(signal => { const row = document.createElement('tr'); row.innerHTML = `