// Enhanced Peers UI functions let peerChart = null; // Render peers list - uses generic pagination system async function renderPeers() { if (window.genericFetch) { await window.genericFetch('peers', true); } renderPeerGraph(); } // Filter peers - uses generic filter system function filterPeers() { if (window.genericFilter) { window.genericFilter('peers'); } } // Show peer details modal async function showPeerDetails(peerId) { try { const [peerRes, historyRes] = await Promise.all([ fetch(`/api/peers/${encodeURIComponent(peerId)}`), fetch(`/api/peers/${encodeURIComponent(peerId)}/history`) ]); if (!peerRes.ok || !historyRes.ok) { throw new Error('Failed to fetch peer details'); } const peer = await peerRes.json(); const history = await historyRes.json(); const modal = document.getElementById('peerDetailsModal'); if (!modal) return; const content = document.getElementById('peer-details-content'); if (!content) return; const uptime = peer.uptime ? (window.formatUptime ? window.formatUptime(peer.uptime) : `${Math.floor(peer.uptime / 1000)}s`) : 'N/A'; const connectTime = peer.connectTime ? new Date(peer.connectTime).toLocaleString() : 'N/A'; const lastSeen = peer.metrics?.lastSeen ? new Date(peer.metrics.lastSeen).toLocaleString() : 'N/A'; content.innerHTML = `

Peer Information

ID: ${peer.id}

Status: ${peer.connected ? 'Connected' : 'Disconnected'}

Uptime: ${uptime}

Connected At: ${connectTime}

Blocked: ${peer.isBlocked ? 'Yes' : 'No'}

Metrics

Total Connections: ${peer.metrics?.connections || 0}

Total Duration: ${peer.metrics?.totalDuration ? (window.formatDuration ? window.formatDuration(peer.metrics.totalDuration) : `${Math.floor(peer.metrics.totalDuration / 1000)}s`) : '0s'}

Average Duration: ${peer.metrics?.avgDuration ? (window.formatDuration ? window.formatDuration(peer.metrics.avgDuration) : `${Math.floor(peer.metrics.avgDuration / 1000)}s`) : 'N/A'}

Last Seen: ${lastSeen}

Connection History (Last 50)

${history.length === 0 ? '

No history available

' : history.slice(-50).reverse().map(event => `
${event.type === 'connect' ? 'Connected' : 'Disconnected'} ${new Date(event.timestamp).toLocaleString()}
${event.duration ? `
Duration: ${window.formatDuration ? window.formatDuration(event.duration) : `${Math.floor(event.duration / 1000)}s`}
` : ''} ${event.error ? `
Error: ${event.error}
` : ''}
`).join('') }
`; modal.showModal(); } catch (err) { console.error('Failed to fetch peer details:', err); if (window.showNotification) window.showNotification('Failed to load peer details: ' + err.message, 'error'); } } // Block peer async function blockPeer(peerId) { if (window.showConfirm) { window.showConfirm(`Block peer ${peerId.substring(0, 16)}...?`, async () => { try { const response = await fetch(`/api/peers/${encodeURIComponent(peerId)}/block`, { method: 'POST' }); if (!response.ok) { throw new Error('Failed to block peer'); } if (window.showNotification) window.showNotification('Peer blocked successfully'); await renderPeers(); } catch (err) { console.error('Failed to block peer:', err); if (window.showNotification) window.showNotification('Failed to block peer: ' + err.message, 'error'); } }); } } // Unblock peer async function unblockPeer(peerId) { if (window.showConfirm) { window.showConfirm(`Unblock peer ${peerId.substring(0, 16)}...?`, async () => { try { const response = await fetch(`/api/peers/${encodeURIComponent(peerId)}/unblock`, { method: 'POST' }); if (!response.ok) { throw new Error('Failed to unblock peer'); } if (window.showNotification) window.showNotification('Peer unblocked successfully'); await renderPeers(); } catch (err) { console.error('Failed to unblock peer:', err); if (window.showNotification) window.showNotification('Failed to unblock peer: ' + err.message, 'error'); } }); } } // Render peer connection graph function renderPeerGraph() { const canvas = document.getElementById('peer-graph-chart'); if (!canvas) return; const ctx = canvas.getContext('2d'); if (peerChart) { peerChart.destroy(); } // Get peers data from global state const peersData = window.peersData || []; // Group peers by connection status over time (simplified - using current data) const connected = peersData.filter(p => p.connected).length; const disconnected = peersData.filter(p => !p.connected).length; const blocked = peersData.filter(p => p.isBlocked).length; peerChart = new Chart(ctx, { type: 'doughnut', data: { labels: ['Connected', 'Disconnected', 'Blocked'], datasets: [{ data: [connected, disconnected, blocked], backgroundColor: [ 'rgb(34, 197, 94)', 'rgb(107, 114, 128)', 'rgb(239, 68, 68)' ] }] }, options: { responsive: true, maintainAspectRatio: false, plugins: { legend: { position: 'bottom', labels: { color: '#f1f5f9' // White text for better readability on dark background } } } } }); } // Make functions globally accessible window.renderPeers = renderPeers; window.showPeerDetails = showPeerDetails; window.blockPeer = blockPeer; window.unblockPeer = unblockPeer; window.filterPeers = filterPeers;