286 lines
12 KiB
HTML
286 lines
12 KiB
HTML
<!DOCTYPE html>
|
|
<html lang="en">
|
|
<head>
|
|
<meta charset="UTF-8">
|
|
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
|
<meta name="theme-color" content="#0a0e1a">
|
|
<title>P2NS Network Visualization</title>
|
|
<link rel="icon" href="/favicon.ico" sizes="32x32">
|
|
<link rel="icon" href="/branding/p2ns-favicon-32.png" type="image/png" sizes="32x32">
|
|
<link rel="icon" href="/branding/p2ns-favicon-192.png" type="image/png" sizes="192x192">
|
|
<link rel="apple-touch-icon" href="/branding/p2ns-favicon-192.png">
|
|
<link rel="manifest" href="/manifest.json">
|
|
<link rel="stylesheet" href="/css/branding.css">
|
|
<link rel="stylesheet" href="/css/tailwind.css">
|
|
<link rel="stylesheet" href="/css/style.css">
|
|
<link rel="stylesheet" href="https://global.profile/css/profile-modal.css">
|
|
<link rel="stylesheet" href="https://unpkg.com/vis-network@latest/styles/vis-network.min.css">
|
|
<script src="https://d3js.org/d3.v7.min.js"></script>
|
|
<script src="https://cdn.jsdelivr.net/npm/[email protected]/dist/chart.umd.min.js"></script>
|
|
<script src="https://unpkg.com/vis-network@latest/standalone/umd/vis-network.min.js"></script>
|
|
</head>
|
|
<body>
|
|
<div class="container">
|
|
<!-- Header -->
|
|
<header class="header">
|
|
<div class="header-content header-brand">
|
|
<img src="/branding/p2ns-icon.png" alt="" class="brand-lockup-logo" width="32" height="32">
|
|
<h1>P2NS Network Visualization</h1>
|
|
<p class="subtitle">Visualize and explore the P2NS network</p>
|
|
</div>
|
|
<div class="header-status">
|
|
<div class="status" role="status" aria-live="polite">
|
|
<div class="status-indicator" id="statusIndicator" aria-label="Connection status"></div>
|
|
<span id="statusText">Connecting...</span>
|
|
</div>
|
|
</div>
|
|
</header>
|
|
|
|
<!-- Main Content -->
|
|
<div class="main-content">
|
|
<!-- Sidebar -->
|
|
<aside class="sidebar">
|
|
<!-- View Tabs -->
|
|
<div class="sidebar-section">
|
|
<h2>Views</h2>
|
|
<div>
|
|
<a href="#overview" class="view-tab active" data-view="system-overview">System Overview</a>
|
|
<a href="#network-graph" class="view-tab" data-view="network-graph">Network Graph</a>
|
|
<a href="#peer-details" class="view-tab" data-view="peer-details">Peer Details</a>
|
|
<a href="#domain-map" class="view-tab" data-view="domain-map">Domain Map</a>
|
|
</div>
|
|
</div>
|
|
|
|
<!-- Controls -->
|
|
<div class="sidebar-section" style="overflow-y: auto; overflow-x: hidden; min-height: 0; flex: 1;">
|
|
<h2>Controls</h2>
|
|
|
|
<!-- Layout Options -->
|
|
<div class="control-group">
|
|
<label class="control-label" for="layoutSelect">Layout</label>
|
|
<select id="layoutSelect" class="control-select">
|
|
<option value="force">Force-Directed</option>
|
|
<option value="hierarchical">Hierarchical</option>
|
|
</select>
|
|
</div>
|
|
|
|
<!-- Filters -->
|
|
<div class="control-group">
|
|
<label class="control-label">Filters</label>
|
|
<div class="control-checkbox-group">
|
|
<label class="control-checkbox">
|
|
<input type="checkbox" id="filterConnected" checked>
|
|
<span>Connected Peers</span>
|
|
</label>
|
|
<label class="control-checkbox">
|
|
<input type="checkbox" id="filterDomains" checked>
|
|
<span>Domains</span>
|
|
</label>
|
|
<label id="filterOfflinePeersLabel" class="control-checkbox hidden">
|
|
<input type="checkbox" id="filterOfflinePeers">
|
|
<span>Show Offline Peers</span>
|
|
</label>
|
|
</div>
|
|
</div>
|
|
|
|
<!-- Search -->
|
|
<div class="control-group">
|
|
<label class="control-label" for="searchInput">Search</label>
|
|
<input type="text" id="searchInput" placeholder="Search peers/domains..." class="control-input">
|
|
</div>
|
|
</div>
|
|
|
|
<!-- Stats -->
|
|
<div class="sidebar-section">
|
|
<h2>Stats</h2>
|
|
<div class="stats-list">
|
|
<div class="stat-item">
|
|
<span class="stat-label">Peers Seen:</span>
|
|
<span id="statPeers" class="stat-value">0</span>
|
|
</div>
|
|
<div class="stat-item">
|
|
<span class="stat-label">Domains:</span>
|
|
<span id="statDomains" class="stat-value">0</span>
|
|
</div>
|
|
<div class="stat-item">
|
|
<span class="stat-label">Connections:</span>
|
|
<span id="statConnections" class="stat-value">0</span>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</aside>
|
|
|
|
<!-- Main Visualization Area -->
|
|
<main class="main-viz-area">
|
|
<!-- View Container -->
|
|
<div id="viewContainer" class="flex-1 relative">
|
|
<!-- System Overview View (Default) -->
|
|
<div id="system-overview-view" class="view-content active">
|
|
<div class="system-overview-content">
|
|
<div class="metrics-container">
|
|
<div class="metrics-grid">
|
|
<div class="metric-card">
|
|
<h3>Total Peers Seen</h3>
|
|
<p class="metric-value primary" id="metricTotalPeers">0</p>
|
|
</div>
|
|
<div class="metric-card">
|
|
<h3>Connected Peers</h3>
|
|
<p class="metric-value success" id="metricConnectedPeers">0</p>
|
|
</div>
|
|
<div class="metric-card">
|
|
<h3>Total Domains</h3>
|
|
<p class="metric-value secondary" id="metricTotalDomains">0</p>
|
|
</div>
|
|
</div>
|
|
<div class="metrics-grid-centered">
|
|
<div class="metric-card">
|
|
<h3>System Uptime</h3>
|
|
<p class="metric-value" id="metricUptime">--</p>
|
|
</div>
|
|
<div class="metric-card">
|
|
<h3>Active Connections</h3>
|
|
<p class="metric-value warning" id="metricActiveConnections">0</p>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
<div class="charts-grid">
|
|
<div class="chart-card">
|
|
<h3>Peer Connection Timeline</h3>
|
|
<div class="chart-container">
|
|
<canvas id="timelineChart"></canvas>
|
|
</div>
|
|
</div>
|
|
<div class="chart-card">
|
|
<h3>Connection Duration Distribution</h3>
|
|
<div class="chart-container">
|
|
<canvas id="durationChart"></canvas>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
|
|
<!-- Network Graph View -->
|
|
<div id="network-graph-view" class="view-content">
|
|
<div id="graphContainer"></div>
|
|
</div>
|
|
|
|
<!-- Peer Details View -->
|
|
<div id="peer-details-view" class="view-content">
|
|
<div class="peer-details-content">
|
|
<div id="peerList" class="peer-list">
|
|
<!-- Peer items will be inserted here -->
|
|
</div>
|
|
</div>
|
|
</div>
|
|
|
|
<!-- Domain Map View -->
|
|
<div id="domain-map-view" class="view-content">
|
|
<div id="domainMapContainer"></div>
|
|
</div>
|
|
|
|
</div>
|
|
|
|
<!-- Peer Details Panel (Sidebar) -->
|
|
<div id="peerDetailsPanel" class="hidden">
|
|
<div class="peer-details-header">
|
|
<h3>Peer Details</h3>
|
|
<button id="closePeerDetails" class="close-btn" aria-label="Close">✕</button>
|
|
</div>
|
|
<div id="peerDetailsContent">
|
|
<!-- Peer details will be inserted here -->
|
|
</div>
|
|
</div>
|
|
</main>
|
|
</div>
|
|
</div>
|
|
|
|
<!-- Profile Modal Component -->
|
|
<div id="profile-modal" class="profile-modal" style="display: none;">
|
|
<div class="profile-modal-backdrop"></div>
|
|
<div class="profile-modal-content">
|
|
<button class="profile-modal-close" aria-label="Close" onclick="if(window.ProfileModal){window.ProfileModal.close();}">×</button>
|
|
|
|
<div class="profile-modal-loading" id="profile-modal-loading">
|
|
<div class="loading-spinner"></div>
|
|
<p>Loading profile...</p>
|
|
</div>
|
|
|
|
<div class="profile-modal-error" id="profile-modal-error" style="display: none;">
|
|
<p>Failed to load profile</p>
|
|
</div>
|
|
|
|
<div class="profile-modal-body" id="profile-modal-body" style="display: none;">
|
|
<div class="profile-modal-header">
|
|
<div class="profile-modal-avatar-container">
|
|
<img id="profile-modal-avatar" class="profile-modal-avatar" alt="Avatar" onerror="this.style.display='none'; document.getElementById('profile-modal-avatar-placeholder').style.display='flex';">
|
|
<div id="profile-modal-avatar-placeholder" class="profile-modal-avatar-placeholder" style="display: none;">
|
|
<svg width="64" height="64" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2">
|
|
<path d="M20 21v-2a4 4 0 0 0-4-4H8a4 4 0 0 0-4 4v2"></path>
|
|
<circle cx="12" cy="7" r="4"></circle>
|
|
</svg>
|
|
</div>
|
|
</div>
|
|
<div class="profile-modal-header-info">
|
|
<h2 id="profile-modal-name" class="profile-modal-name">Loading...</h2>
|
|
<p id="profile-modal-peerid" class="profile-modal-peerid">...</p>
|
|
</div>
|
|
</div>
|
|
|
|
<div class="profile-modal-bio" id="profile-modal-bio-container" style="display: none;">
|
|
<p id="profile-modal-bio" class="profile-modal-bio-text"></p>
|
|
</div>
|
|
|
|
<div class="profile-modal-details" id="profile-modal-details">
|
|
<div class="profile-modal-detail-item" id="profile-modal-email-item" style="display: none;">
|
|
<span class="profile-modal-detail-icon">📧</span>
|
|
<a id="profile-modal-email" href="#" class="profile-modal-detail-link"></a>
|
|
</div>
|
|
<div class="profile-modal-detail-item" id="profile-modal-website-item" style="display: none;">
|
|
<span class="profile-modal-detail-icon">🌐</span>
|
|
<a id="profile-modal-website" href="#" target="_blank" rel="noopener noreferrer" class="profile-modal-detail-link"></a>
|
|
</div>
|
|
<div class="profile-modal-detail-item" id="profile-modal-x-item" style="display: none;">
|
|
<span class="profile-modal-detail-icon">🐦</span>
|
|
<a id="profile-modal-x" href="#" target="_blank" rel="noopener noreferrer" class="profile-modal-detail-link"></a>
|
|
</div>
|
|
</div>
|
|
|
|
<div class="profile-modal-actions" id="profile-modal-actions" style="display: none;">
|
|
<button id="profile-modal-block-btn" class="profile-modal-action-btn profile-modal-action-btn-block" style="display: none;">
|
|
<svg width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2">
|
|
<circle cx="12" cy="12" r="10"></circle>
|
|
<line x1="4.93" y1="4.93" x2="19.07" y2="19.07"></line>
|
|
</svg>
|
|
Block
|
|
</button>
|
|
<button id="profile-modal-unblock-btn" class="profile-modal-action-btn profile-modal-action-btn-unblock" style="display: none;">
|
|
<svg width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2">
|
|
<circle cx="12" cy="12" r="10"></circle>
|
|
<path d="M12 6v6l4 2"></path>
|
|
</svg>
|
|
Unblock
|
|
</button>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
|
|
<!-- Scripts -->
|
|
<script src="/sdk-utils.js"></script>
|
|
<script src="/js/utils.js"></script>
|
|
<script src="/js/data-processor.js"></script>
|
|
<script src="/js/websocket-client.js"></script>
|
|
<script src="https://global.profile/js/profile-modal.js"></script>
|
|
<script src="/js/visualization/dashboard.js"></script>
|
|
<script src="/js/visualization/peer-details.js"></script>
|
|
<script src="/js/visualization/network-graph.js"></script>
|
|
<script src="/js/visualization/domain-map.js"></script>
|
|
<script src="/js/app.js"></script>
|
|
</body>
|
|
</html>
|
|
|
|
|
|
|
|
|