forked from snxraven/p2ns
800 lines
47 KiB
HTML
800 lines
47 KiB
HTML
<!DOCTYPE html>
|
|
<html lang="en" class="dark">
|
|
<head>
|
|
<meta charset="UTF-8">
|
|
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
|
<title>P2NS Admin Panel</title>
|
|
<link rel="stylesheet" href="/tailwind.css">
|
|
<link rel="stylesheet" href="styles.css">
|
|
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.4.0/css/all.min.css" integrity="sha512-iecdLmaskl7CVkqkXNQ/ZH/XLlvWZOJyj7Yy7tcenmpD1ypASozpmT/E0iPtmFIB46ZmdtAc9eNBvH0H/ZpiBw==" crossorigin="anonymous" referrerpolicy="no-referrer" />
|
|
<script src="https://cdn.jsdelivr.net/npm/[email protected]/lib/xterm.min.js"></script>
|
|
<link href="https://cdn.jsdelivr.net/npm/[email protected]/css/xterm.min.css" rel="stylesheet">
|
|
<script src="https://cdn.jsdelivr.net/npm/[email protected]/dist/chart.umd.min.js"></script>
|
|
</head>
|
|
<body class="bg-gray-100 dark:bg-gray-900 text-gray-900 dark:text-white min-h-screen transition-colors duration-300">
|
|
<div class="container mx-auto p-6 max-w-7xl">
|
|
<h1 class="text-4xl font-extrabold text-center mb-8">P2NS Admin Panel</h1>
|
|
|
|
<nav class="flex justify-center mb-8 space-x-4 flex-wrap">
|
|
<button onclick="location.hash = 'domains';" class="px-4 py-2 bg-primary text-white rounded hover:bg-primary-hover m-1">Domains</button>
|
|
<button onclick="location.hash = 'host';" class="px-4 py-2 bg-primary text-white rounded hover:bg-primary-hover m-1">Host</button>
|
|
<button onclick="location.hash = 'local-dns';" class="px-4 py-2 bg-primary text-white rounded hover:bg-primary-hover m-1">Local DNS</button>
|
|
<button onclick="location.hash = 'entries';" class="px-4 py-2 bg-primary text-white rounded hover:bg-primary-hover m-1">Entries</button>
|
|
<button onclick="location.hash = 'peers';" class="px-4 py-2 bg-primary text-white rounded hover:bg-primary-hover m-1">Peers</button>
|
|
<button onclick="location.hash = 'certs';" class="px-4 py-2 bg-primary text-white rounded hover:bg-primary-hover m-1">Certificates</button>
|
|
<button onclick="location.hash = 'interfaces';" class="px-4 py-2 bg-primary text-white rounded hover:bg-primary-hover m-1">Interfaces</button>
|
|
<button onclick="location.hash = 'logs';" class="px-4 py-2 bg-primary text-white rounded hover:bg-primary-hover m-1">Logs</button>
|
|
<button onclick="location.hash = 'stats';" class="px-4 py-2 bg-primary text-white rounded hover:bg-primary-hover m-1">Stats</button>
|
|
<button onclick="location.hash = 'settings';" class="px-4 py-2 bg-primary text-white rounded hover:bg-primary-hover m-1">Settings</button>
|
|
</nav>
|
|
|
|
<div id="domains" class="tab-content hidden">
|
|
<h2 class="text-2xl font-bold mb-4 flex items-center gap-2">
|
|
Domains
|
|
<button onclick="openInfoModal('domains')" class="text-sm px-3 py-1 bg-gray-200 dark:bg-gray-700 text-gray-700 dark:text-gray-300 rounded hover:bg-gray-300 dark:hover:bg-gray-600 transition-colors">Info</button>
|
|
</h2>
|
|
<div class="mb-6">
|
|
<input id="search-domains" type="text" placeholder="Search domains..." class="w-full p-3 rounded-lg border border-gray-300 dark:border-gray-700 bg-white dark:bg-gray-800 text-gray-900 dark:text-white focus:outline-none focus:ring-2 focus:ring-primary" oninput="filterDomains()">
|
|
</div>
|
|
<div class="overflow-x-auto">
|
|
<table class="w-full bg-white dark:bg-gray-800 rounded-lg shadow-md">
|
|
<thead class="bg-gray-200 dark:bg-gray-700">
|
|
<tr>
|
|
<th class="p-3 text-left">Domain</th>
|
|
<th class="p-3 text-left">Hash</th>
|
|
<th class="p-3 text-left">Actions</th>
|
|
</tr>
|
|
</thead>
|
|
<tbody id="domainsTable"></tbody>
|
|
</table>
|
|
</div>
|
|
<div id="domainsPagination" class="flex justify-center mt-4 space-x-2"></div>
|
|
<button onclick="openAddModal()" class="mt-4 px-4 py-2 bg-primary text-white rounded hover:bg-primary-hover">Add Domain</button>
|
|
</div>
|
|
|
|
<div id="local-dns" class="tab-content hidden">
|
|
<h2 class="text-2xl font-bold mb-4 flex items-center gap-2">
|
|
Custom Local DNS Records
|
|
<button onclick="openInfoModal('local-dns')" class="text-sm px-3 py-1 bg-gray-200 dark:bg-gray-700 text-gray-700 dark:text-gray-300 rounded hover:bg-gray-300 dark:hover:bg-gray-600 transition-colors">Info</button>
|
|
</h2>
|
|
<div class="mb-6">
|
|
<input id="search-local-dns" type="text" placeholder="Search records..." class="w-full p-3 rounded-lg border border-gray-300 dark:border-gray-700 bg-white dark:bg-gray-800 text-gray-900 dark:text-white focus:outline-none focus:ring-2 focus:ring-primary" oninput="filterLocalDNS()">
|
|
</div>
|
|
<div class="overflow-x-auto">
|
|
<table class="w-full bg-white dark:bg-gray-800 rounded-lg shadow-md">
|
|
<thead class="bg-gray-200 dark:bg-gray-700">
|
|
<tr>
|
|
<th class="p-3 text-left">Name</th>
|
|
<th class="p-3 text-left">Type</th>
|
|
<th class="p-3 text-left">Value</th>
|
|
<th class="p-3 text-left">TTL</th>
|
|
<th class="p-3 text-left">Actions</th>
|
|
</tr>
|
|
</thead>
|
|
<tbody id="localDnsTable"></tbody>
|
|
</table>
|
|
</div>
|
|
<div id="localDnsPagination" class="flex justify-center mt-4 space-x-2"></div>
|
|
<button onclick="openLocalDnsModal()" class="mt-4 px-4 py-2 bg-primary text-white rounded hover:bg-primary-hover">Add Record</button>
|
|
|
|
<h2 class="text-2xl font-bold mt-8 mb-4 flex items-center gap-2">
|
|
DNS Conflict Selector
|
|
<button onclick="openInfoModal('dns-conflicts')" class="text-sm px-3 py-1 bg-gray-200 dark:bg-gray-700 text-gray-700 dark:text-gray-300 rounded hover:bg-gray-300 dark:hover:bg-gray-600 transition-colors">Info</button>
|
|
</h2>
|
|
<div class="mb-6">
|
|
<input id="search-dns-conflicts" type="text" placeholder="Search conflicts..." class="w-full p-3 rounded-lg border border-gray-300 dark:border-gray-700 bg-white dark:bg-gray-800 text-gray-900 dark:text-white focus:outline-none focus:ring-2 focus:ring-primary" oninput="filterDnsConflicts()">
|
|
</div>
|
|
<div class="overflow-x-auto">
|
|
<table class="w-full bg-white dark:bg-gray-800 rounded-lg shadow-md">
|
|
<thead class="bg-gray-200 dark:bg-gray-700">
|
|
<tr>
|
|
<th class="p-3 text-left">Domain</th>
|
|
<th class="p-3 text-left">Public IP</th>
|
|
<th class="p-3 text-left">Mode</th>
|
|
</tr>
|
|
</thead>
|
|
<tbody id="dnsConflictsTable"></tbody>
|
|
</table>
|
|
</div>
|
|
<div id="dnsConflictsPagination" class="flex justify-center mt-4 space-x-2"></div>
|
|
</div>
|
|
|
|
<div id="entries" class="tab-content hidden">
|
|
<h2 class="text-2xl font-bold mb-4 flex items-center gap-2">
|
|
Autopass Entries
|
|
<button onclick="openInfoModal('entries')" class="text-sm px-3 py-1 bg-gray-200 dark:bg-gray-700 text-gray-700 dark:text-gray-300 rounded hover:bg-gray-300 dark:hover:bg-gray-600 transition-colors">Info</button>
|
|
</h2>
|
|
<div class="mb-6">
|
|
<input id="search-entries" type="text" placeholder="Search entries..." class="w-full p-3 rounded-lg border border-gray-300 dark:border-gray-700 bg-white dark:bg-gray-800 text-gray-900 dark:text-white focus:outline-none focus:ring-2 focus:ring-primary" oninput="filterEntries()">
|
|
</div>
|
|
<div class="overflow-x-auto">
|
|
<table class="w-full bg-white dark:bg-gray-800 rounded-lg shadow-md">
|
|
<thead class="bg-gray-200 dark:bg-gray-700">
|
|
<tr>
|
|
<th class="p-3 text-left">Key</th>
|
|
<th class="p-3 text-left">Value</th>
|
|
</tr>
|
|
</thead>
|
|
<tbody id="entriesTable"></tbody>
|
|
</table>
|
|
</div>
|
|
<div id="entriesPagination" class="flex justify-center mt-4 space-x-2"></div>
|
|
</div>
|
|
|
|
<div id="peers" class="tab-content hidden">
|
|
<h2 class="text-2xl font-bold mb-4 flex items-center gap-2">
|
|
Connected Peers <span id="peers-count" class="text-lg"></span>
|
|
<button onclick="openInfoModal('peers')" class="text-sm px-3 py-1 bg-gray-200 dark:bg-gray-700 text-gray-700 dark:text-gray-300 rounded hover:bg-gray-300 dark:hover:bg-gray-600 transition-colors">Info</button>
|
|
</h2>
|
|
<div class="mb-6">
|
|
<input id="search-peers" type="text" placeholder="Search peers..." class="w-full p-3 rounded-lg border border-gray-300 dark:border-gray-700 bg-white dark:bg-gray-800 text-gray-900 dark:text-white focus:outline-none focus:ring-2 focus:ring-primary" oninput="filterPeers()">
|
|
</div>
|
|
<ul id="peersList" class="space-y-3"></ul>
|
|
<div id="peersPagination" class="flex justify-center mt-4 space-x-2"></div>
|
|
</div>
|
|
|
|
<div id="certs" class="tab-content hidden">
|
|
<h2 class="text-2xl font-bold mb-4 flex items-center gap-2">
|
|
Domain Certificates
|
|
<button onclick="openInfoModal('certs')" class="text-sm px-3 py-1 bg-gray-200 dark:bg-gray-700 text-gray-700 dark:text-gray-300 rounded hover:bg-gray-300 dark:hover:bg-gray-600 transition-colors">Info</button>
|
|
</h2>
|
|
<div class="mb-6">
|
|
<input id="search-certs" type="text" placeholder="Search certificates..." class="w-full p-3 rounded-lg border border-gray-300 dark:border-gray-700 bg-white dark:bg-gray-800 text-gray-900 dark:text-white focus:outline-none focus:ring-2 focus:ring-primary" oninput="filterCerts()">
|
|
</div>
|
|
<ul id="certsList" class="space-y-3"></ul>
|
|
<div id="certsPagination" class="flex justify-center mt-4 space-x-2"></div>
|
|
<div class="mt-4">
|
|
<input id="cert-domain" placeholder="Domain for Cert" class="p-3 border border-gray-300 dark:border-gray-700 bg-white dark:bg-gray-800 text-gray-900 dark:text-white rounded-lg focus:outline-none focus:ring-2 focus:ring-primary">
|
|
<button onclick="generateCert()" class="ml-2 px-4 py-3 bg-primary text-white rounded-lg hover:bg-primary-hover">Generate Cert</button>
|
|
</div>
|
|
<h2 class="text-2xl font-bold mt-8 mb-4 flex items-center gap-2">
|
|
CA Management
|
|
<button onclick="openInfoModal('ca-management')" class="text-sm px-3 py-1 bg-gray-200 dark:bg-gray-700 text-gray-700 dark:text-gray-300 rounded hover:bg-gray-300 dark:hover:bg-gray-600 transition-colors">Info</button>
|
|
</h2>
|
|
<button onclick="regenerateCA()" class="px-6 py-3 bg-primary text-white rounded-lg hover:bg-primary-hover mr-4">Regenerate Root CA</button>
|
|
<button onclick="installCA()" class="px-6 py-3 bg-primary text-white rounded-lg hover:bg-primary-hover">Install Root CA</button>
|
|
</div>
|
|
|
|
<div id="interfaces" class="tab-content hidden flex flex-col overflow-hidden">
|
|
<h2 class="text-2xl font-bold mb-4 flex items-center gap-2 flex-shrink-0">
|
|
Virtual Interfaces
|
|
<button onclick="openInfoModal('interfaces')" class="text-sm px-3 py-1 bg-gray-200 dark:bg-gray-700 text-gray-700 dark:text-gray-300 rounded hover:bg-gray-300 dark:hover:bg-gray-600 transition-colors">Info</button>
|
|
</h2>
|
|
<div class="mb-6 flex-shrink-0">
|
|
<input id="search-interfaces" type="text" placeholder="Search interfaces..." class="w-full p-3 rounded-lg border border-gray-300 dark:border-gray-700 bg-white dark:bg-gray-800 text-gray-900 dark:text-white focus:outline-none focus:ring-2 focus:ring-primary" oninput="filterInterfaces()">
|
|
</div>
|
|
<div class="flex-1 overflow-hidden flex flex-col min-h-0">
|
|
<div class="overflow-x-auto overflow-y-auto flex-1">
|
|
<table class="w-full bg-white dark:bg-gray-800 rounded-lg shadow-md">
|
|
<thead class="bg-gray-200 dark:bg-gray-700 sticky top-0">
|
|
<tr>
|
|
<th class="p-3 text-left">Domain</th>
|
|
<th class="p-3 text-left">IP</th>
|
|
</tr>
|
|
</thead>
|
|
<tbody id="interfacesTable"></tbody>
|
|
</table>
|
|
</div>
|
|
<div id="interfacesPagination" class="flex justify-center mt-4 space-x-2 flex-shrink-0"></div>
|
|
</div>
|
|
</div>
|
|
|
|
<div id="logs" class="tab-content hidden">
|
|
<h2 class="text-2xl font-bold mb-4 flex items-center gap-2">
|
|
Logs
|
|
<button onclick="openInfoModal('logs')" class="text-sm px-3 py-1 bg-gray-200 dark:bg-gray-700 text-gray-700 dark:text-gray-300 rounded hover:bg-gray-300 dark:hover:bg-gray-600 transition-colors">Info</button>
|
|
</h2>
|
|
<div id="terminal" class="bg-black rounded-lg overflow-hidden h-96"></div>
|
|
</div>
|
|
|
|
<div id="host" class="tab-content hidden">
|
|
<h2 class="text-2xl font-bold mb-4 flex items-center gap-2">
|
|
Holesail Servers
|
|
<button onclick="openInfoModal('holesail-servers')" class="text-sm px-3 py-1 bg-gray-200 dark:bg-gray-700 text-gray-700 dark:text-gray-300 rounded hover:bg-gray-300 dark:hover:bg-gray-600 transition-colors">Info</button>
|
|
</h2>
|
|
<div class="mb-6">
|
|
<input id="search-holesail" type="text" placeholder="Search servers..." class="w-full p-3 rounded-lg border border-gray-300 dark:border-gray-700 bg-white dark:bg-gray-800 text-gray-900 dark:text-white focus:outline-none focus:ring-2 focus:ring-primary" oninput="filterHolesailServers()">
|
|
</div>
|
|
<div class="overflow-x-auto">
|
|
<table class="w-full bg-white dark:bg-gray-800 rounded-lg shadow-md">
|
|
<thead class="bg-gray-200 dark:bg-gray-700">
|
|
<tr>
|
|
<th class="p-3 text-left">Name/ID</th>
|
|
<th class="p-3 text-left">Port</th>
|
|
<th class="p-3 text-left">Host</th>
|
|
<th class="p-3 text-left">URL</th>
|
|
<th class="p-3 text-left">Protocol</th>
|
|
<th class="p-3 text-left">Status</th>
|
|
<th class="p-3 text-left">Actions</th>
|
|
</tr>
|
|
</thead>
|
|
<tbody id="holesailTable"></tbody>
|
|
</table>
|
|
</div>
|
|
<div id="holesailPagination" class="flex justify-center mt-4 space-x-2"></div>
|
|
<button onclick="openCreateHolesailModal()" class="mt-4 px-4 py-2 bg-primary text-white rounded hover:bg-primary-hover">Create Server</button>
|
|
|
|
<h2 class="text-2xl font-bold mt-8 mb-4 flex items-center gap-2">
|
|
Holesail Clients
|
|
<button onclick="openInfoModal('holesail-clients')" class="text-sm px-3 py-1 bg-gray-200 dark:bg-gray-700 text-gray-700 dark:text-gray-300 rounded hover:bg-gray-300 dark:hover:bg-gray-600 transition-colors">Info</button>
|
|
</h2>
|
|
<div class="mb-6">
|
|
<input id="search-holesail-clients" type="text" placeholder="Search clients..." class="w-full p-3 rounded-lg border border-gray-300 dark:border-gray-700 bg-white dark:bg-gray-800 text-gray-900 dark:text-white focus:outline-none focus:ring-2 focus:ring-primary" oninput="filterHolesailClients()">
|
|
</div>
|
|
<div class="overflow-x-auto">
|
|
<table class="w-full bg-white dark:bg-gray-800 rounded-lg shadow-md">
|
|
<thead class="bg-gray-200 dark:bg-gray-700">
|
|
<tr>
|
|
<th class="p-3 text-left">Domain</th>
|
|
<th class="p-3 text-left">Key</th>
|
|
<th class="p-3 text-left">Port</th>
|
|
<th class="p-3 text-left">Protocol</th>
|
|
<th class="p-3 text-left">Status</th>
|
|
<th class="p-3 text-left">Actions</th>
|
|
</tr>
|
|
</thead>
|
|
<tbody id="holesailClientsTable"></tbody>
|
|
</table>
|
|
</div>
|
|
<div id="holesailClientsPagination" class="flex justify-center mt-4 space-x-2"></div>
|
|
<button onclick="openCreateClientModal()" class="mt-4 px-4 py-2 bg-primary text-white rounded hover:bg-primary-hover">Create Client</button>
|
|
</div>
|
|
|
|
<div id="settings" class="tab-content hidden">
|
|
<div class="flex justify-between items-center mb-4">
|
|
<h2 class="text-2xl font-bold flex items-center gap-2">
|
|
Settings
|
|
<button onclick="openInfoModal('settings')" class="text-sm px-3 py-1 bg-gray-200 dark:bg-gray-700 text-gray-700 dark:text-gray-300 rounded hover:bg-gray-300 dark:hover:bg-gray-600 transition-colors">Info</button>
|
|
</h2>
|
|
<button onclick="saveSettings()" class="px-4 py-2 bg-primary text-white rounded hover:bg-primary-hover">Save Settings</button>
|
|
</div>
|
|
<div class="mb-6">
|
|
<input id="search-settings" type="text" placeholder="Search settings..." class="w-full p-3 rounded-lg border border-gray-300 dark:border-gray-700 bg-white dark:bg-gray-800 text-gray-900 dark:text-white focus:outline-none focus:ring-2 focus:ring-primary" oninput="filterSettings()">
|
|
</div>
|
|
<div id="settingsContainer" class="space-y-6"></div>
|
|
</div>
|
|
|
|
<div id="stats" class="tab-content hidden">
|
|
<div class="flex justify-between items-center mb-6">
|
|
<h2 class="text-2xl font-bold flex items-center gap-2">
|
|
Statistics & Metrics
|
|
<button onclick="openInfoModal('stats')" class="text-sm px-3 py-1 bg-gray-200 dark:bg-gray-700 text-gray-700 dark:text-gray-300 rounded hover:bg-gray-300 dark:hover:bg-gray-600 transition-colors">Info</button>
|
|
</h2>
|
|
<div class="flex items-center space-x-4">
|
|
<label class="flex items-center">
|
|
<input type="checkbox" id="auto-refresh-stats" checked class="mr-2">
|
|
<span>Auto-refresh:</span>
|
|
</label>
|
|
<select id="refresh-interval-selector" class="px-3 py-2 border border-gray-300 dark:border-gray-700 bg-white dark:bg-gray-800 rounded-lg">
|
|
<option value="1000">Realtime (1s)</option>
|
|
<option value="2000">Fast (2s)</option>
|
|
<option value="5000" selected>Normal (5s)</option>
|
|
<option value="10000">Slow (10s)</option>
|
|
<option value="30000">Very Slow (30s)</option>
|
|
</select>
|
|
<select id="time-range-selector" class="px-3 py-2 border border-gray-300 dark:border-gray-700 bg-white dark:bg-gray-800 rounded-lg">
|
|
<option value="60">Last 1 hour</option>
|
|
<option value="360">Last 6 hours</option>
|
|
<option value="1440" selected>Last 24 hours</option>
|
|
</select>
|
|
<button onclick="exportStats()" class="px-4 py-2 bg-green-600 text-white rounded hover:bg-green-700">Export Data</button>
|
|
</div>
|
|
</div>
|
|
|
|
<!-- System Overview Cards -->
|
|
<div class="grid grid-cols-1 md:grid-cols-2 lg:grid-cols-4 gap-4 mb-6">
|
|
<div class="bg-white dark:bg-gray-800 rounded-lg shadow-md p-4 overflow-hidden min-h-[140px] flex flex-col">
|
|
<h3 class="text-sm font-semibold text-gray-500 dark:text-gray-400 mb-2">System Uptime</h3>
|
|
<p id="uptime-display" class="text-2xl font-bold whitespace-nowrap">-</p>
|
|
</div>
|
|
<div class="bg-white dark:bg-gray-800 rounded-lg shadow-md p-4 overflow-hidden min-h-[140px] flex flex-col">
|
|
<h3 class="text-sm font-semibold text-gray-500 dark:text-gray-400 mb-2">Node Type</h3>
|
|
<p id="node-type-display" class="text-2xl font-bold mb-1 whitespace-nowrap">-</p>
|
|
<p id="connection-status" class="text-sm text-gray-600 dark:text-gray-400 whitespace-nowrap">-</p>
|
|
</div>
|
|
<div class="bg-white dark:bg-gray-800 rounded-lg shadow-md p-4 overflow-hidden min-h-[140px] flex flex-col">
|
|
<h3 class="text-sm font-semibold text-gray-500 dark:text-gray-400 mb-2">Connected Peers</h3>
|
|
<p id="peers-current" class="text-2xl font-bold whitespace-nowrap">-</p>
|
|
</div>
|
|
<div class="bg-white dark:bg-gray-800 rounded-lg shadow-md p-4 overflow-hidden min-h-[140px] flex flex-col">
|
|
<h3 class="text-sm font-semibold text-gray-500 dark:text-gray-400 mb-2">Total Domains</h3>
|
|
<p id="domains-current" class="text-2xl font-bold whitespace-nowrap">-</p>
|
|
</div>
|
|
</div>
|
|
|
|
<!-- DNS Statistics Section -->
|
|
<div class="bg-white dark:bg-gray-800 rounded-lg shadow-md p-6 mb-6">
|
|
<h3 class="text-xl font-bold mb-4">DNS Statistics</h3>
|
|
<div class="grid grid-cols-1 md:grid-cols-2 lg:grid-cols-4 gap-4 mb-4">
|
|
<div class="text-center">
|
|
<p class="text-sm text-gray-500 dark:text-gray-400">Total Queries</p>
|
|
<p id="dns-queries-total" class="text-2xl font-bold">-</p>
|
|
</div>
|
|
<div class="text-center">
|
|
<p class="text-sm text-gray-500 dark:text-gray-400">Success Rate</p>
|
|
<p id="dns-success-rate" class="text-2xl font-bold">-</p>
|
|
</div>
|
|
<div class="text-center">
|
|
<p class="text-sm text-gray-500 dark:text-gray-400">Avg Response Time</p>
|
|
<p id="dns-avg-response" class="text-2xl font-bold">-</p>
|
|
</div>
|
|
<div class="text-center">
|
|
<p class="text-sm text-gray-500 dark:text-gray-400">P2P Rate</p>
|
|
<p id="dns-p2p-rate" class="text-2xl font-bold">-</p>
|
|
</div>
|
|
</div>
|
|
<div class="grid grid-cols-1 lg:grid-cols-2 gap-4">
|
|
<div>
|
|
<canvas id="dns-queries-chart"></canvas>
|
|
</div>
|
|
<div>
|
|
<canvas id="dns-types-chart"></canvas>
|
|
</div>
|
|
</div>
|
|
<div class="mt-4">
|
|
<h4 class="text-lg font-semibold mb-2">Top Queried Domains</h4>
|
|
<div id="top-domains-list" class="space-y-2"></div>
|
|
</div>
|
|
</div>
|
|
|
|
<!-- Network & Peers Section -->
|
|
<div class="bg-white dark:bg-gray-800 rounded-lg shadow-md p-6 mb-6">
|
|
<h3 class="text-xl font-bold mb-4">Network & Peers</h3>
|
|
<div class="grid grid-cols-1 md:grid-cols-3 gap-4 mb-4">
|
|
<div class="text-center">
|
|
<p class="text-sm text-gray-500 dark:text-gray-400">Connected</p>
|
|
<p id="peers-connected-count" class="text-2xl font-bold">-</p>
|
|
</div>
|
|
<div class="text-center">
|
|
<p class="text-sm text-gray-500 dark:text-gray-400">Total Connections</p>
|
|
<p id="peers-total-connections" class="text-2xl font-bold">-</p>
|
|
</div>
|
|
<div class="text-center">
|
|
<p class="text-sm text-gray-500 dark:text-gray-400">Avg Duration</p>
|
|
<p id="peers-avg-duration" class="text-2xl font-bold">-</p>
|
|
</div>
|
|
</div>
|
|
<div>
|
|
<canvas id="peer-events-chart"></canvas>
|
|
</div>
|
|
</div>
|
|
|
|
<!-- Holesail Statistics Section -->
|
|
<div class="bg-white dark:bg-gray-800 rounded-lg shadow-md p-6 mb-6">
|
|
<h3 class="text-xl font-bold mb-4">Holesail Statistics</h3>
|
|
<div class="grid grid-cols-1 md:grid-cols-2 lg:grid-cols-4 gap-4 mb-4">
|
|
<div class="text-center">
|
|
<p class="text-sm text-gray-500 dark:text-gray-400">Active Connections</p>
|
|
<p id="holesail-active" class="text-2xl font-bold">-</p>
|
|
</div>
|
|
<div class="text-center">
|
|
<p class="text-sm text-gray-500 dark:text-gray-400">Clients Started</p>
|
|
<p id="holesail-clients-started" class="text-2xl font-bold">-</p>
|
|
</div>
|
|
<div class="text-center">
|
|
<p class="text-sm text-gray-500 dark:text-gray-400">Servers Started</p>
|
|
<p id="holesail-servers-started" class="text-2xl font-bold">-</p>
|
|
</div>
|
|
<div class="text-center">
|
|
<p class="text-sm text-gray-500 dark:text-gray-400">Avg Duration</p>
|
|
<p id="holesail-avg-duration" class="text-2xl font-bold">-</p>
|
|
</div>
|
|
</div>
|
|
<div class="grid grid-cols-1 lg:grid-cols-2 gap-4">
|
|
<div>
|
|
<canvas id="holesail-events-chart"></canvas>
|
|
</div>
|
|
<div>
|
|
<canvas id="holesail-protocol-chart"></canvas>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
|
|
<!-- Holesail Children Section -->
|
|
<div class="bg-white dark:bg-gray-800 rounded-lg shadow-md p-6 mb-6">
|
|
<h3 class="text-xl font-bold mb-4">Holesail Children</h3>
|
|
<div id="holesail-children-container" class="space-y-4">
|
|
<p class="text-gray-500 dark:text-gray-400 text-center">Loading children data...</p>
|
|
</div>
|
|
</div>
|
|
|
|
<!-- API & Requests Section -->
|
|
<div class="bg-white dark:bg-gray-800 rounded-lg shadow-md p-6 mb-6">
|
|
<h3 class="text-xl font-bold mb-4">API & Requests</h3>
|
|
<div class="grid grid-cols-1 md:grid-cols-4 gap-4 mb-4">
|
|
<div class="text-center">
|
|
<p class="text-sm text-gray-500 dark:text-gray-400">Total Requests</p>
|
|
<p id="requests-total" class="text-2xl font-bold">-</p>
|
|
</div>
|
|
<div class="text-center">
|
|
<p class="text-sm text-gray-500 dark:text-gray-400">Success Rate</p>
|
|
<p id="requests-success-rate" class="text-2xl font-bold">-</p>
|
|
</div>
|
|
<div class="text-center">
|
|
<p class="text-sm text-gray-500 dark:text-gray-400">Avg Response Time</p>
|
|
<p id="requests-avg-response" class="text-2xl font-bold">-</p>
|
|
</div>
|
|
<div class="text-center">
|
|
<p class="text-sm text-gray-500 dark:text-gray-400">Failed Requests</p>
|
|
<p id="requests-failed" class="text-2xl font-bold">-</p>
|
|
</div>
|
|
</div>
|
|
<div class="grid grid-cols-1 lg:grid-cols-2 gap-4">
|
|
<div>
|
|
<canvas id="requests-timeline-chart"></canvas>
|
|
</div>
|
|
<div>
|
|
<canvas id="endpoint-usage-chart"></canvas>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
|
|
<!-- Resource Usage Section -->
|
|
<div class="bg-white dark:bg-gray-800 rounded-lg shadow-md p-6 mb-6">
|
|
<h3 class="text-xl font-bold mb-4">Resource Usage</h3>
|
|
<div class="grid grid-cols-1 md:grid-cols-4 gap-4 mb-4">
|
|
<div class="text-center">
|
|
<p class="text-sm text-gray-500 dark:text-gray-400">Active Sockets</p>
|
|
<p id="resources-sockets" class="text-2xl font-bold">-</p>
|
|
</div>
|
|
<div class="text-center">
|
|
<p class="text-sm text-gray-500 dark:text-gray-400">Active Servers</p>
|
|
<p id="resources-servers" class="text-2xl font-bold">-</p>
|
|
</div>
|
|
<div class="text-center">
|
|
<p class="text-sm text-gray-500 dark:text-gray-400">Holesail Connections</p>
|
|
<p id="resources-holesails" class="text-2xl font-bold">-</p>
|
|
</div>
|
|
<div class="text-center">
|
|
<p class="text-sm text-gray-500 dark:text-gray-400">Peer Channels</p>
|
|
<p id="resources-channels" class="text-2xl font-bold">-</p>
|
|
</div>
|
|
</div>
|
|
<div>
|
|
<canvas id="resources-timeline-chart"></canvas>
|
|
</div>
|
|
</div>
|
|
|
|
<!-- Domain Management Section -->
|
|
<div class="bg-white dark:bg-gray-800 rounded-lg shadow-md p-6 mb-6">
|
|
<h3 class="text-xl font-bold mb-4">Domain Management</h3>
|
|
<div class="grid grid-cols-1 md:grid-cols-3 gap-4 mb-4">
|
|
<div class="text-center">
|
|
<p class="text-sm text-gray-500 dark:text-gray-400">Total Added</p>
|
|
<p id="domains-added" class="text-2xl font-bold">-</p>
|
|
</div>
|
|
<div class="text-center">
|
|
<p class="text-sm text-gray-500 dark:text-gray-400">Total Removed</p>
|
|
<p id="domains-removed" class="text-2xl font-bold">-</p>
|
|
</div>
|
|
<div class="text-center">
|
|
<p class="text-sm text-gray-500 dark:text-gray-400">Net Change</p>
|
|
<p id="domains-net" class="text-2xl font-bold">-</p>
|
|
</div>
|
|
</div>
|
|
<div>
|
|
<canvas id="domain-events-chart"></canvas>
|
|
</div>
|
|
</div>
|
|
|
|
<!-- Process Usage Section -->
|
|
<div class="bg-white dark:bg-gray-800 rounded-lg shadow-md p-6 mb-6">
|
|
<h3 class="text-xl font-bold mb-4">Process Usage Statistics</h3>
|
|
|
|
<!-- Process Info Cards -->
|
|
<div class="grid grid-cols-1 md:grid-cols-2 lg:grid-cols-4 gap-4 mb-6">
|
|
<div class="bg-gray-50 dark:bg-gray-700 rounded-lg p-4">
|
|
<h4 class="text-sm font-semibold text-gray-500 dark:text-gray-400 mb-2">Node.js Version</h4>
|
|
<p id="process-node-version" class="text-lg font-bold">-</p>
|
|
</div>
|
|
<div class="bg-gray-50 dark:bg-gray-700 rounded-lg p-4">
|
|
<h4 class="text-sm font-semibold text-gray-500 dark:text-gray-400 mb-2">Platform</h4>
|
|
<p id="process-platform" class="text-lg font-bold">-</p>
|
|
</div>
|
|
<div class="bg-gray-50 dark:bg-gray-700 rounded-lg p-4">
|
|
<h4 class="text-sm font-semibold text-gray-500 dark:text-gray-400 mb-2">Architecture</h4>
|
|
<p id="process-arch" class="text-lg font-bold">-</p>
|
|
</div>
|
|
<div class="bg-gray-50 dark:bg-gray-700 rounded-lg p-4">
|
|
<h4 class="text-sm font-semibold text-gray-500 dark:text-gray-400 mb-2">Process Uptime</h4>
|
|
<p id="process-uptime" class="text-lg font-bold">-</p>
|
|
</div>
|
|
</div>
|
|
|
|
<!-- Memory Usage -->
|
|
<div class="mb-6">
|
|
<h4 class="text-lg font-semibold mb-4">Memory Usage</h4>
|
|
<div class="grid grid-cols-1 md:grid-cols-2 lg:grid-cols-5 gap-4 mb-4">
|
|
<div class="text-center">
|
|
<p class="text-sm text-gray-500 dark:text-gray-400">Heap Used</p>
|
|
<p id="process-memory-heap-used" class="text-xl font-bold">-</p>
|
|
</div>
|
|
<div class="text-center">
|
|
<p class="text-sm text-gray-500 dark:text-gray-400">Heap Total</p>
|
|
<p id="process-memory-heap-total" class="text-xl font-bold">-</p>
|
|
</div>
|
|
<div class="text-center">
|
|
<p class="text-sm text-gray-500 dark:text-gray-400">RSS</p>
|
|
<p id="process-memory-rss" class="text-xl font-bold">-</p>
|
|
</div>
|
|
<div class="text-center">
|
|
<p class="text-sm text-gray-500 dark:text-gray-400">External</p>
|
|
<p id="process-memory-external" class="text-xl font-bold">-</p>
|
|
</div>
|
|
<div class="text-center">
|
|
<p class="text-sm text-gray-500 dark:text-gray-400">Array Buffers</p>
|
|
<p id="process-memory-array-buffers" class="text-xl font-bold">-</p>
|
|
</div>
|
|
</div>
|
|
<div>
|
|
<canvas id="process-memory-chart"></canvas>
|
|
</div>
|
|
</div>
|
|
|
|
<!-- CPU Usage -->
|
|
<div class="mb-6">
|
|
<h4 class="text-lg font-semibold mb-4">CPU Usage</h4>
|
|
<div class="grid grid-cols-1 md:grid-cols-3 gap-4 mb-4">
|
|
<div class="text-center">
|
|
<p class="text-sm text-gray-500 dark:text-gray-400">Current CPU %</p>
|
|
<p id="process-cpu-current" class="text-2xl font-bold">-</p>
|
|
</div>
|
|
<div class="text-center">
|
|
<p class="text-sm text-gray-500 dark:text-gray-400">Average CPU %</p>
|
|
<p id="process-cpu-avg" class="text-2xl font-bold">-</p>
|
|
</div>
|
|
<div class="text-center">
|
|
<p class="text-sm text-gray-500 dark:text-gray-400">Active Handles</p>
|
|
<p id="process-handles-active" class="text-2xl font-bold">-</p>
|
|
</div>
|
|
</div>
|
|
<div>
|
|
<canvas id="process-cpu-chart"></canvas>
|
|
</div>
|
|
</div>
|
|
|
|
<!-- System Resources -->
|
|
<div class="mb-6">
|
|
<h4 class="text-lg font-semibold mb-4">System Resources</h4>
|
|
<div class="grid grid-cols-1 md:grid-cols-4 gap-4 mb-4">
|
|
<div class="text-center">
|
|
<p class="text-sm text-gray-500 dark:text-gray-400">Total Memory</p>
|
|
<p id="process-system-total-memory" class="text-xl font-bold">-</p>
|
|
</div>
|
|
<div class="text-center">
|
|
<p class="text-sm text-gray-500 dark:text-gray-400">Free Memory</p>
|
|
<p id="process-system-free-memory" class="text-xl font-bold">-</p>
|
|
</div>
|
|
<div class="text-center">
|
|
<p class="text-sm text-gray-500 dark:text-gray-400">Used Memory %</p>
|
|
<p id="process-system-used-percent" class="text-xl font-bold">-</p>
|
|
</div>
|
|
<div class="text-center">
|
|
<p class="text-sm text-gray-500 dark:text-gray-400">Load Average</p>
|
|
<p id="process-system-load-avg" class="text-xl font-bold">-</p>
|
|
</div>
|
|
</div>
|
|
<div>
|
|
<canvas id="process-system-chart"></canvas>
|
|
</div>
|
|
</div>
|
|
|
|
<!-- Event Loop Performance -->
|
|
<div class="mb-6">
|
|
<h4 class="text-lg font-semibold mb-4">Event Loop Performance</h4>
|
|
<div class="grid grid-cols-1 md:grid-cols-3 gap-4 mb-4">
|
|
<div class="text-center">
|
|
<p class="text-sm text-gray-500 dark:text-gray-400">Current Lag</p>
|
|
<p id="process-eventloop-current" class="text-xl font-bold">-</p>
|
|
</div>
|
|
<div class="text-center">
|
|
<p class="text-sm text-gray-500 dark:text-gray-400">Average Lag</p>
|
|
<p id="process-eventloop-avg" class="text-xl font-bold">-</p>
|
|
</div>
|
|
<div class="text-center">
|
|
<p class="text-sm text-gray-500 dark:text-gray-400">Max Lag</p>
|
|
<p id="process-eventloop-max" class="text-xl font-bold">-</p>
|
|
</div>
|
|
</div>
|
|
<div>
|
|
<canvas id="process-eventloop-chart"></canvas>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
|
|
<dialog id="addDomainModal" class="p-6 bg-white dark:bg-gray-800 rounded-lg shadow-xl w-full max-w-md">
|
|
<h3 class="text-xl font-bold mb-4">Add New Domain</h3>
|
|
<input id="modal-domain" placeholder="Domain" class="w-full p-3 mb-4 border border-gray-300 dark:border-gray-700 bg-white dark:bg-gray-800 rounded-lg focus:outline-none focus:ring-2 focus:ring-primary">
|
|
<input id="modal-hash" placeholder="Hash" class="w-full p-3 mb-4 border border-gray-300 dark:border-gray-700 bg-white dark:bg-gray-800 rounded-lg focus:outline-none focus:ring-2 focus:ring-primary">
|
|
<label class="flex items-center mb-4">
|
|
<input id="modal-ssl" type="checkbox" class="mr-2">
|
|
<span>This Holesail Connection Uses SSL/TLS</span>
|
|
</label>
|
|
<div class="flex justify-end space-x-2">
|
|
<button onclick="document.getElementById('addDomainModal').close()" class="px-4 py-2 bg-gray-300 dark:bg-gray-600 text-gray-900 dark:text-white rounded hover:bg-gray-400 dark:hover:bg-gray-500">Cancel</button>
|
|
<button onclick="submitAddDomain()" class="px-4 py-2 bg-primary text-white rounded hover:bg-primary-hover">Add</button>
|
|
</div>
|
|
</dialog>
|
|
|
|
<dialog id="localDnsModal" class="p-6 bg-white dark:bg-gray-800 rounded-lg shadow-xl w-full max-w-md">
|
|
<h3 id="local-dns-title" class="text-xl font-bold mb-4">Add Local DNS Record</h3>
|
|
<input id="local-name" placeholder="Name (domain)" class="w-full p-3 mb-4 border border-gray-300 dark:border-gray-700 bg-white dark:bg-gray-800 rounded-lg focus:outline-none focus:ring-2 focus:ring-primary">
|
|
<select id="local-type" onchange="updateLocalForm()" class="w-full p-3 mb-4 border border-gray-300 dark:border-gray-700 bg-white dark:bg-gray-800 rounded-lg focus:outline-none focus:ring-2 focus:ring-primary">
|
|
<option value="A">A</option>
|
|
<option value="AAAA">AAAA</option>
|
|
<option value="CNAME">CNAME</option>
|
|
<option value="MX">MX</option>
|
|
<option value="TXT">TXT</option>
|
|
<option value="SRV">SRV</option>
|
|
<option value="SOA">SOA</option>
|
|
<option value="CAA">CAA</option>
|
|
<option value="NS">NS</option>
|
|
<option value="PTR">PTR</option>
|
|
<option value="OTHER">OTHER</option>
|
|
</select>
|
|
<div id="local-value-fields" class="mb-4"></div>
|
|
<input id="local-ttl" type="number" placeholder="TTL" value="3600" class="w-full p-3 mb-4 border border-gray-300 dark:border-gray-700 bg-white dark:bg-gray-800 rounded-lg focus:outline-none focus:ring-2 focus:ring-primary">
|
|
<div class="flex justify-end space-x-2">
|
|
<button onclick="document.getElementById('localDnsModal').close()" class="px-4 py-2 bg-gray-300 dark:bg-gray-600 text-gray-900 dark:text-white rounded hover:bg-gray-400 dark:hover:bg-gray-500">Cancel</button>
|
|
<button id="local-submit" onclick="submitLocalDns()" class="px-4 py-2 bg-primary text-white rounded hover:bg-primary-hover">Add</button>
|
|
</div>
|
|
</dialog>
|
|
|
|
<dialog id="certDetailsModal" class="p-6 bg-white dark:bg-gray-800 rounded-lg shadow-xl w-full max-w-4xl max-h-[90vh] overflow-hidden flex flex-col">
|
|
<div class="flex justify-between items-center mb-4">
|
|
<h3 class="text-2xl font-bold text-gray-900 dark:text-white">Certificate Details</h3>
|
|
<button onclick="document.getElementById('certDetailsModal').close()" class="text-gray-500 dark:text-gray-400 hover:text-gray-700 dark:hover:text-gray-200 text-3xl leading-none font-bold">×</button>
|
|
</div>
|
|
<div class="flex-1 overflow-y-auto mb-4">
|
|
<div class="bg-gray-50 dark:bg-gray-900 rounded-lg p-4 border border-gray-200 dark:border-gray-700">
|
|
<pre id="cert-details-content" class="whitespace-pre-wrap break-all text-sm font-mono text-gray-800 dark:text-gray-200 leading-relaxed"></pre>
|
|
</div>
|
|
</div>
|
|
<div class="flex justify-end space-x-2 pt-4 border-t border-gray-200 dark:border-gray-700">
|
|
<button onclick="copyCertDetails()" class="px-4 py-2 bg-blue-600 hover:bg-blue-700 text-white rounded transition-colors">Copy</button>
|
|
<button onclick="document.getElementById('certDetailsModal').close()" class="px-4 py-2 bg-gray-300 dark:bg-gray-600 text-gray-900 dark:text-white rounded hover:bg-gray-400 dark:hover:bg-gray-500 transition-colors">Close</button>
|
|
</div>
|
|
</dialog>
|
|
|
|
<!-- Confirmation modal is created dynamically by confirmation-modal.js -->
|
|
|
|
<dialog id="createHolesailModal" class="p-6 bg-white dark:bg-gray-800 rounded-lg shadow-xl w-full max-w-md">
|
|
<h3 class="text-xl font-bold mb-4">Create Holesail Server</h3>
|
|
<input id="holesail-name" placeholder="Name (optional)" class="w-full p-3 mb-4 border border-gray-300 dark:border-gray-700 bg-white dark:bg-gray-800 rounded-lg focus:outline-none focus:ring-2 focus:ring-primary">
|
|
<input id="holesail-port" type="number" placeholder="Port (required)" class="w-full p-3 mb-4 border border-gray-300 dark:border-gray-700 bg-white dark:bg-gray-800 rounded-lg focus:outline-none focus:ring-2 focus:ring-primary">
|
|
<input id="holesail-host" placeholder="Host (default 0.0.0.0)" class="w-full p-3 mb-4 border border-gray-300 dark:border-gray-700 bg-white dark:bg-gray-800 rounded-lg focus:outline-none focus:ring-2 focus:ring-primary">
|
|
<input id="holesail-key" placeholder="Key (optional)" class="w-full p-3 mb-4 border border-gray-300 dark:border-gray-700 bg-white dark:bg-gray-800 rounded-lg focus:outline-none focus:ring-2 focus:ring-primary">
|
|
<input id="holesail-domain" placeholder="Assign to domain (optional)" class="w-full p-3 mb-4 border border-gray-300 dark:border-gray-700 bg-white dark:bg-gray-800 rounded-lg focus:outline-none focus:ring-2 focus:ring-primary">
|
|
<label class="flex items-center mb-4"><input id="holesail-secure" type="checkbox" class="mr-2"> Secure</label>
|
|
<label class="flex items-center mb-4"><input id="holesail-udp" type="checkbox" checked class="mr-2"> UDP</label>
|
|
<select id="holesail-log" class="w-full p-3 mb-4 border border-gray-300 dark:border-gray-700 bg-white dark:bg-gray-800 rounded-lg focus:outline-none focus:ring-2 focus:ring-primary">
|
|
<option value="false">No Logs</option>
|
|
<option value="0">Debug</option>
|
|
<option value="1" selected>Info</option>
|
|
<option value="2">Warn</option>
|
|
<option value="3">Error</option>
|
|
</select>
|
|
<div class="flex justify-end space-x-2">
|
|
<button onclick="document.getElementById('createHolesailModal').close()" class="px-4 py-2 bg-gray-300 dark:bg-gray-600 text-gray-900 dark:text-white rounded hover:bg-gray-400 dark:hover:bg-gray-500">Cancel</button>
|
|
<button id="create-holesail-btn" onclick="submitCreateHolesail()" class="px-4 py-2 bg-primary text-white rounded hover:bg-primary-hover">Create</button>
|
|
</div>
|
|
</dialog>
|
|
|
|
<dialog id="createClientModal" class="p-6 bg-white dark:bg-gray-800 rounded-lg shadow-xl w-full max-w-md">
|
|
<h3 class="text-xl font-bold mb-4">Create Holesail Client</h3>
|
|
<select id="client-domain" class="w-full p-3 mb-4 border border-gray-300 dark:border-gray-700 bg-white dark:bg-gray-800 rounded-lg focus:outline-none focus:ring-2 focus:ring-primary"></select>
|
|
<input id="client-key" placeholder="Key (required)" class="w-full p-3 mb-4 border border-gray-300 dark:border-gray-700 bg-white dark:bg-gray-800 rounded-lg focus:outline-none focus:ring-2 focus:ring-primary">
|
|
<input id="client-port" type="number" placeholder="Local Port (required)" class="w-full p-3 mb-4 border border-gray-300 dark:border-gray-700 bg-white dark:bg-gray-800 rounded-lg focus:outline-none focus:ring-2 focus:ring-primary">
|
|
<div class="flex justify-end space-x-2">
|
|
<button onclick="document.getElementById('createClientModal').close()" class="px-4 py-2 bg-gray-300 dark:bg-gray-600 text-gray-900 dark:text-white rounded hover:bg-gray-400 dark:hover:bg-gray-500">Cancel</button>
|
|
<button id="create-client-btn" onclick="submitCreateClient()" class="px-4 py-2 bg-primary text-white rounded hover:bg-primary-hover">Create</button>
|
|
</div>
|
|
</dialog>
|
|
|
|
<dialog id="holesailLogModal" class="p-6 bg-white dark:bg-gray-800 rounded-lg shadow-xl w-full max-w-4xl">
|
|
<h3 id="holesail-log-title" class="text-xl font-bold mb-4">Holesail Logs</h3>
|
|
<div id="holesail-terminal" class="bg-black rounded-lg overflow-hidden h-96"></div>
|
|
<div class="flex justify-end mt-4">
|
|
<button onclick="document.getElementById('holesailLogModal').close()" class="px-4 py-2 bg-gray-300 dark:bg-gray-600 text-gray-900 dark:text-white rounded hover:bg-gray-400 dark:hover:bg-gray-500">Close</button>
|
|
</div>
|
|
</dialog>
|
|
|
|
<dialog id="infoModal" class="p-6 bg-white dark:bg-gray-800 rounded-lg shadow-xl w-full max-w-3xl max-h-[90vh] overflow-y-auto">
|
|
<div class="flex justify-between items-start mb-4">
|
|
<h3 id="info-modal-title" class="text-2xl font-bold"></h3>
|
|
<button onclick="document.getElementById('infoModal').close()" class="text-gray-500 dark:text-gray-400 hover:text-gray-700 dark:hover:text-gray-200 text-2xl leading-none">×</button>
|
|
</div>
|
|
<div id="info-modal-content" class="mb-6 space-y-4"></div>
|
|
<div class="flex justify-end space-x-2">
|
|
<button onclick="document.getElementById('infoModal').close()" class="px-4 py-2 bg-gray-300 dark:bg-gray-600 text-gray-900 dark:text-white rounded hover:bg-gray-400 dark:hover:bg-gray-500">Close</button>
|
|
</div>
|
|
</dialog>
|
|
|
|
<dialog id="subnetModal" class="p-6 bg-white dark:bg-gray-800 rounded-lg shadow-xl w-full max-w-md">
|
|
<h3 id="subnet-modal-title" class="text-xl font-bold mb-4">Add Subnet</h3>
|
|
|
|
<div class="mb-4">
|
|
<label for="subnet-name" class="block text-sm font-medium text-gray-900 dark:text-white mb-2">Subnet Name</label>
|
|
<input id="subnet-name" placeholder="e.g., Primary Subnet" class="w-full p-3 border border-gray-300 dark:border-gray-700 bg-white dark:bg-gray-800 rounded-lg focus:outline-none focus:ring-2 focus:ring-primary">
|
|
<p class="text-xs text-gray-500 dark:text-gray-400 mt-1">A descriptive name for this subnet</p>
|
|
</div>
|
|
|
|
<div class="mb-4">
|
|
<label for="subnet-base" class="block text-sm font-medium text-gray-900 dark:text-white mb-2">Base IP Address</label>
|
|
<input id="subnet-base" placeholder="e.g., 192.168.3.0" class="w-full p-3 border border-gray-300 dark:border-gray-700 bg-white dark:bg-gray-800 rounded-lg focus:outline-none focus:ring-2 focus:ring-primary">
|
|
<p class="text-xs text-gray-500 dark:text-gray-400 mt-1">The network address of the subnet (typically ends in .0)</p>
|
|
</div>
|
|
|
|
<div class="mb-4">
|
|
<label for="subnet-cidr" class="block text-sm font-medium text-gray-900 dark:text-white mb-2">CIDR Notation</label>
|
|
<input id="subnet-cidr" type="number" min="1" max="32" placeholder="24" value="24" class="w-full p-3 border border-gray-300 dark:border-gray-700 bg-white dark:bg-gray-800 rounded-lg focus:outline-none focus:ring-2 focus:ring-primary">
|
|
<p class="text-xs text-gray-500 dark:text-gray-400 mt-1">Subnet mask in CIDR notation (1-32). /24 = 255.255.255.0 (254 usable IPs)</p>
|
|
</div>
|
|
|
|
<div class="mb-4">
|
|
<label for="subnet-startIndex" class="block text-sm font-medium text-gray-900 dark:text-white mb-2">Start IP Index</label>
|
|
<input id="subnet-startIndex" type="number" min="1" max="254" placeholder="2" value="2" class="w-full p-3 border border-gray-300 dark:border-gray-700 bg-white dark:bg-gray-800 rounded-lg focus:outline-none focus:ring-2 focus:ring-primary">
|
|
<p class="text-xs text-gray-500 dark:text-gray-400 mt-1">First usable IP address index (1-254). IPs will be assigned starting from this number</p>
|
|
</div>
|
|
|
|
<div class="flex justify-end space-x-2">
|
|
<button onclick="document.getElementById('subnetModal').close()" class="px-4 py-2 bg-gray-300 dark:bg-gray-600 text-gray-900 dark:text-white rounded hover:bg-gray-400 dark:hover:bg-gray-500">Cancel</button>
|
|
<button id="subnet-submit" onclick="submitSubnet()" class="px-4 py-2 bg-primary text-white rounded hover:bg-primary-hover">Add</button>
|
|
</div>
|
|
</dialog>
|
|
</div>
|
|
|
|
<div id="status-indicator" class="fixed top-4 right-4 px-4 py-2 bg-blue-500 text-white rounded-lg shadow-md"></div>
|
|
<div id="notifications" class="fixed bottom-4 right-4 flex flex-col-reverse space-y-2 z-50"></div>
|
|
|
|
<script src="https://cdn.jsdelivr.net/npm/[email protected]/lib/xterm.js"></script>
|
|
<script src="https://cdn.jsdelivr.net/npm/@xterm/[email protected]/lib/addon-fit.js"></script>
|
|
<!-- Load modules in order: config -> state -> utils -> core -> notifications -> ws-client -> ui modules -> main -->
|
|
<script src="ui/config.js"></script>
|
|
<script src="ui/state.js"></script>
|
|
<script src="utils.js"></script>
|
|
<script src="ui/core.js"></script>
|
|
<script src="ui/notifications.js"></script>
|
|
<script src="ui/confirmation-modal.js"></script>
|
|
<script src="ws-client.js"></script>
|
|
<script src="ui/domains.js"></script>
|
|
<script src="ui/certs.js"></script>
|
|
<script src="ui/interfaces.js"></script>
|
|
<script src="ui/local-dns.js"></script>
|
|
<!-- Note: holesail, settings, logs, stats modules still need to be extracted from original -->
|
|
<script src="admin.js"></script>
|
|
<script>
|
|
function handleHashChange() {
|
|
var tabId = location.hash.substring(1);
|
|
if (tabId && document.getElementById(tabId) && typeof showTab === 'function') {
|
|
showTab(tabId);
|
|
}
|
|
}
|
|
window.addEventListener('hashchange', handleHashChange);
|
|
window.addEventListener('load', function() {
|
|
// Wait for admin.js to load
|
|
if (typeof showTab === 'function') {
|
|
var tabId = location.hash.substring(1);
|
|
if (tabId && document.getElementById(tabId)) {
|
|
showTab(tabId);
|
|
} else {
|
|
showTab('domains');
|
|
}
|
|
} else {
|
|
// Retry after a short delay if script hasn't loaded
|
|
setTimeout(function() {
|
|
if (typeof showTab === 'function') {
|
|
var tabId = location.hash.substring(1);
|
|
if (tabId && document.getElementById(tabId)) {
|
|
showTab(tabId);
|
|
} else {
|
|
showTab('domains');
|
|
}
|
|
}
|
|
}, 100);
|
|
}
|
|
});
|
|
</script>
|
|
</body>
|
|
</html> |