Files
p2ns/includes/admin/admin-frontend/ui/peers.js
T
2025-12-17 20:05:50 -05:00

192 lines
7.1 KiB
JavaScript

// 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 = `
<div class="space-y-4">
<div>
<h4 class="font-semibold mb-2">Peer Information</h4>
<div class="bg-gray-100 dark:bg-gray-700 p-3 rounded">
<p><strong>ID:</strong> <span class="font-mono text-sm break-all">${peer.id}</span></p>
<p><strong>Status:</strong> ${peer.connected ? '<span class="text-green-600">Connected</span>' : '<span class="text-gray-600">Disconnected</span>'}</p>
<p><strong>Uptime:</strong> ${uptime}</p>
<p><strong>Connected At:</strong> ${connectTime}</p>
<p><strong>Blocked:</strong> ${peer.isBlocked ? '<span class="text-red-600">Yes</span>' : '<span class="text-green-600">No</span>'}</p>
</div>
</div>
<div>
<h4 class="font-semibold mb-2">Metrics</h4>
<div class="bg-gray-100 dark:bg-gray-700 p-3 rounded">
<p><strong>Total Connections:</strong> ${peer.metrics?.connections || 0}</p>
<p><strong>Total Duration:</strong> ${peer.metrics?.totalDuration ? (window.formatDuration ? window.formatDuration(peer.metrics.totalDuration) : `${Math.floor(peer.metrics.totalDuration / 1000)}s`) : '0s'}</p>
<p><strong>Average Duration:</strong> ${peer.metrics?.avgDuration ? (window.formatDuration ? window.formatDuration(peer.metrics.avgDuration) : `${Math.floor(peer.metrics.avgDuration / 1000)}s`) : 'N/A'}</p>
<p><strong>Last Seen:</strong> ${lastSeen}</p>
</div>
</div>
<div>
<h4 class="font-semibold mb-2">Connection History (Last 50)</h4>
<div class="bg-gray-100 dark:bg-gray-700 p-3 rounded max-h-64 overflow-y-auto">
${history.length === 0
? '<p class="text-gray-500">No history available</p>'
: history.slice(-50).reverse().map(event => `
<div class="mb-2 pb-2 border-b border-gray-300 dark:border-gray-600">
<div class="flex justify-between">
<span class="font-semibold ${event.type === 'connect' ? 'text-green-600' : 'text-red-600'}">${event.type === 'connect' ? 'Connected' : 'Disconnected'}</span>
<span class="text-sm text-gray-600 dark:text-gray-400">${new Date(event.timestamp).toLocaleString()}</span>
</div>
${event.duration ? `<div class="text-sm text-gray-600 dark:text-gray-400">Duration: ${window.formatDuration ? window.formatDuration(event.duration) : `${Math.floor(event.duration / 1000)}s`}</div>` : ''}
${event.error ? `<div class="text-sm text-red-600">Error: ${event.error}</div>` : ''}
</div>
`).join('')
}
</div>
</div>
</div>
`;
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;