forked from snxraven/p2ns
- Centralized common formatting, DOM, and status utilities in `includes/plugins/sdk.js` - Created `sdk.utils.format`, `sdk.utils.dom`, and `sdk.utils.status` namespaces - Refactored `domain.consensus` and `peer.visualize` plugins to use the global SDK - Updated `plugin-handler` to serve SDK utilities globally via `/sdk-utils.js` - Enhanced SDK validation by delegating to the core validation infrastructure - Fixed bugs in metric rendering and missing frontend utility functions
191 lines
7.9 KiB
HTML
191 lines
7.9 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="#000000">
|
|
<title>Domain Consensus - P2NS</title>
|
|
<link rel="manifest" href="/manifest.json">
|
|
<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">
|
|
<script src="https://cdn.jsdelivr.net/npm/[email protected]/dist/chart.umd.min.js"></script>
|
|
</head>
|
|
<body>
|
|
<div class="container">
|
|
<!-- Header -->
|
|
<header class="header">
|
|
<div class="header-content">
|
|
<h1>Domain Consensus</h1>
|
|
</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-layout">
|
|
<!-- Sidebar -->
|
|
<aside class="sidebar">
|
|
<!-- View Tabs -->
|
|
<div class="sidebar-section">
|
|
<h2>Views</h2>
|
|
<div>
|
|
<a href="#overview" class="view-tab active" data-view="overview">Overview</a>
|
|
<a href="#domains" class="view-tab" data-view="domain-list">Domain List</a>
|
|
<a href="#domain-detail" class="view-tab hidden" data-view="domain-detail" id="domainDetailTab">Domain Details</a>
|
|
</div>
|
|
</div>
|
|
|
|
<!-- Stats -->
|
|
<div class="sidebar-section">
|
|
<h2>Quick Stats</h2>
|
|
<div class="stats-list">
|
|
<div class="stat-item">
|
|
<span class="stat-label">Total Domains:</span>
|
|
<span id="statTotalDomains" class="stat-value">0</span>
|
|
</div>
|
|
<div class="stat-item">
|
|
<span class="stat-label">Resolved:</span>
|
|
<span id="statResolved" class="stat-value success">0</span>
|
|
</div>
|
|
<div class="stat-item">
|
|
<span class="stat-label">Active Peers:</span>
|
|
<span id="statActivePeers" class="stat-value primary">0</span>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</aside>
|
|
|
|
<!-- Main Visualization Area -->
|
|
<main class="main-content">
|
|
<!-- View Container -->
|
|
<div id="viewContainer" class="view-container">
|
|
<!-- Overview View -->
|
|
<div id="overview-view" class="view-content active">
|
|
<div class="view-content-inner">
|
|
<div id="overviewContent">
|
|
<div class="text-center py-12">
|
|
<div class="spinner"></div>
|
|
<p class="mt-4 text-tertiary">Loading overview...</p>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
|
|
<!-- Domain List View -->
|
|
<div id="domain-list-view" class="view-content">
|
|
<div class="view-content-inner">
|
|
<div id="domainListContent">
|
|
<div class="text-center py-12">
|
|
<div class="spinner"></div>
|
|
<p class="mt-4 text-tertiary">Loading domains...</p>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
|
|
<!-- Domain Detail View -->
|
|
<div id="domain-detail-view" class="view-content">
|
|
<div class="view-content-inner">
|
|
<div id="domainDetailContent">
|
|
<div class="text-center py-12">
|
|
<div class="spinner"></div>
|
|
<p class="mt-4 text-tertiary">Loading domain details...</p>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</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/api.js"></script>
|
|
<script src="/js/websocket.js"></script>
|
|
<script src="https://global.profile/js/profile-modal.js"></script>
|
|
<script src="/js/views/overview.js"></script>
|
|
<script src="/js/views/domain-list.js"></script>
|
|
<script src="/js/views/domain-detail.js"></script>
|
|
<script src="/js/app.js"></script>
|
|
</body>
|
|
</html>
|
|
|