diff --git a/db-status.js b/db-status.js
index 6cfd89b..d072f01 100644
--- a/db-status.js
+++ b/db-status.js
@@ -7,24 +7,192 @@ class DatabaseStatusMonitor {
connection: document.getElementById('dbConnection'),
latency: document.getElementById('dbLatency'),
write: document.getElementById('dbWrite'),
- timestamp: document.getElementById('dbTimestamp')
+ timestamp: document.getElementById('dbTimestamp'),
+ retryBtn: document.getElementById('dbRetryBtn'),
+ statusBar: document.getElementById('dbStatusBar'),
+ detailsPanel: document.getElementById('dbStatusDetails'),
+ errorBanner: document.getElementById('sqlErrorBanner'),
+ errorMessage: document.getElementById('sqlErrorMessage'),
+ errorDetails: document.getElementById('sqlErrorDetails')
};
+ this.logs = [];
+ this.maxLogs = 50;
+
+ // Make status bar clickable to show details
+ if (this.elements.statusBar) {
+ this.elements.statusBar.style.cursor = 'pointer';
+ this.elements.statusBar.addEventListener('click', (e) => {
+ // Don't toggle if clicking the retry button
+ if (!e.target.closest('.db-retry-btn')) {
+ this.toggleDetails();
+ }
+ });
+ }
+ }
+
+ addLog(message, type = 'info') {
+ const timestamp = new Date().toLocaleTimeString('en-US', {
+ hour12: false,
+ hour: '2-digit',
+ minute: '2-digit',
+ second: '2-digit'
+ });
+
+ const logEntry = {
+ timestamp,
+ message,
+ type // 'info', 'success', 'error', 'warning'
+ };
+
+ this.logs.unshift(logEntry);
+ if (this.logs.length > this.maxLogs) {
+ this.logs.pop();
+ }
+
+ // Console logging with emoji
+ const emoji = {
+ 'info': 'ℹ️',
+ 'success': '✅',
+ 'error': '❌',
+ 'warning': '⚠️'
+ };
+
+ console.log(`${emoji[type]} [DB-STATUS ${timestamp}] ${message}`);
+
+ // Update logs display
+ this.updateLogsDisplay();
+ }
+
+ updateLogsDisplay() {
+ const logsContainer = document.getElementById('detailLogs');
+ if (!logsContainer) return;
+
+ logsContainer.innerHTML = '
Recent Logs:
';
+ this.logs.slice(0, 20).forEach(log => {
+ const logDiv = document.createElement('div');
+ logDiv.className = `db-log-entry db-log-${log.type}`;
+ logDiv.textContent = `[${log.timestamp}] ${log.message}`;
+ logsContainer.appendChild(logDiv);
+ });
+ }
+
+ toggleDetails() {
+ if (this.elements.detailsPanel) {
+ const isHidden = this.elements.detailsPanel.style.display === 'none';
+ this.elements.detailsPanel.style.display = isHidden ? 'block' : 'none';
+ if (isHidden) {
+ this.addLog('Details panel opened', 'info');
+ }
+ }
}
async checkStatus() {
+ this.addLog('Checking database status...', 'info');
+
try {
const response = await fetch('/api/db-status');
const data = await response.json();
+ this.addLog(`Response received: ${data.connected ? 'Connected' : 'Disconnected'}`,
+ data.connected ? 'success' : 'error');
+
+ if (data.error) {
+ this.addLog(`Error: ${data.error}`, 'error');
+ }
+
+ if (data.poolStats) {
+ this.addLog(`Pool: ${data.poolStats.freeConnections}/${data.poolStats.totalConnections} free, ${data.poolStats.queuedRequests} queued`, 'info');
+ }
+
this.updateUI(data);
+ this.updateDetails(data);
+ this.updateErrorBanner(data);
} catch (error) {
+ this.addLog(`Failed to fetch status: ${error.message}`, 'error');
console.error('Failed to fetch database status:', error);
- this.updateUI({
+ const errorData = {
connected: false,
latency: 0,
writeCapable: false,
error: 'Failed to connect to server'
- });
+ };
+ this.updateUI(errorData);
+ this.updateErrorBanner(errorData);
+ }
+ }
+
+ updateErrorBanner(status) {
+ if (!this.elements.errorBanner) return;
+
+ if (!status.connected || status.error) {
+ // Show error banner
+ this.elements.errorBanner.style.display = 'block';
+
+ // Update error message
+ if (this.elements.errorMessage) {
+ this.elements.errorMessage.textContent = status.error || 'Connection failed';
+ }
+
+ // Update error details
+ if (this.elements.errorDetails) {
+ const details = [];
+
+ if (status.host) {
+ details.push(`🖥️ Host: ${status.host}`);
+ }
+ if (status.database) {
+ details.push(`🗄️ Database: ${status.database}`);
+ }
+ if (status.user) {
+ details.push(`👤 User: ${status.user}`);
+ }
+ if (status.latency !== undefined) {
+ details.push(`⏱️ Latency: ${status.latency}ms`);
+ }
+ if (status.poolStats) {
+ details.push(`🔗 Pool: ${status.poolStats.freeConnections}/${status.poolStats.totalConnections} free`);
+ }
+
+ details.push(`🕐 Last Check: ${new Date().toLocaleTimeString()}`);
+
+ this.elements.errorDetails.innerHTML = details.map(d =>
+ `${d}
`
+ ).join('');
+ }
+ } else {
+ // Hide error banner when connected
+ this.elements.errorBanner.style.display = 'none';
+ }
+ }
+
+ updateDetails(status) {
+ // Update detail panel
+ const detailStatus = document.getElementById('detailStatus');
+ const detailHost = document.getElementById('detailHost');
+ const detailDatabase = document.getElementById('detailDatabase');
+ const detailError = document.getElementById('detailError');
+
+ if (detailStatus) {
+ detailStatus.textContent = status.connected ? '✅ Connected' : '❌ Disconnected';
+ detailStatus.style.color = status.connected ? '#10b981' : '#ef4444';
+ }
+
+ if (detailHost) {
+ detailHost.textContent = status.host || 'unknown';
+ }
+
+ if (detailDatabase) {
+ detailDatabase.textContent = status.database || 'unknown';
+ }
+
+ if (detailError) {
+ if (status.error) {
+ detailError.textContent = status.error;
+ detailError.style.color = '#ef4444';
+ } else {
+ detailError.textContent = 'None';
+ detailError.style.color = '#10b981';
+ }
}
}
@@ -94,8 +262,36 @@ class DatabaseStatusMonitor {
this.elements.timestamp.textContent = timeString;
}
+ async retryConnection() {
+ this.addLog('🔄 Manual retry triggered', 'info');
+
+ // Visual feedback on button
+ if (this.elements.retryBtn) {
+ this.elements.retryBtn.disabled = true;
+ this.elements.retryBtn.classList.add('retrying');
+ const originalText = this.elements.retryBtn.innerHTML;
+ this.elements.retryBtn.innerHTML = `
+
+ Retrying...
+ `;
+
+ await this.checkStatus();
+
+ setTimeout(() => {
+ this.elements.retryBtn.disabled = false;
+ this.elements.retryBtn.classList.remove('retrying');
+ this.elements.retryBtn.innerHTML = originalText;
+ }, 1000);
+ } else {
+ await this.checkStatus();
+ }
+ }
+
start() {
// Initial check
+ this.addLog('Database status monitor started', 'success');
this.checkStatus();
// Set up periodic checks
@@ -110,6 +306,7 @@ class DatabaseStatusMonitor {
if (this.intervalId) {
clearInterval(this.intervalId);
this.intervalId = null;
+ this.addLog('Database status monitor stopped', 'warning');
console.log('⏹️ Database status monitor stopped');
}
}
diff --git a/index.html b/index.html
index d367eb8..93f8aea 100644
--- a/index.html
+++ b/index.html
@@ -180,6 +180,53 @@
Last Check:
--
+
+
+
+
+
+
+
+
+ Status:
+ --
+
+
+ Host:
+ --
+
+
+ Database:
+ --
+
+
+ Error:
+ None
+
+
+
+
+
+
+