Files

169 lines
6.4 KiB
HTML

<!DOCTYPE html>
<html lang="vi">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Tailscale Custom - Admin</title>
<link rel="stylesheet" href="style.css">
</head>
<body>
<!-- Login screen -->
<div id="login-screen" class="login-container">
<div class="login-box">
<div class="login-logo">
<svg width="48" height="48" viewBox="0 0 24 24" fill="none" stroke="#60a5fa" stroke-width="2"><circle cx="12" cy="12" r="10"/><path d="M8 12l2 2 4-4"/></svg>
</div>
<h1>Tailscale Custom</h1>
<p class="login-subtitle">VPN Management Panel</p>
<div class="form-group">
<label>Username</label>
<input type="text" id="login-username" placeholder="admin" autofocus>
</div>
<div class="form-group">
<label>Password</label>
<input type="password" id="login-password" placeholder="********">
</div>
<button class="btn btn-primary btn-block" onclick="doLogin()">Sign In</button>
<div id="login-error" class="error-msg" style="display:none"></div>
</div>
</div>
<!-- Main app -->
<div id="main-app" style="display:none">
<!-- Sidebar -->
<nav class="sidebar">
<div class="sidebar-header">
<svg width="28" height="28" viewBox="0 0 24 24" fill="none" stroke="#60a5fa" stroke-width="2"><circle cx="12" cy="12" r="10"/><path d="M8 12l2 2 4-4"/></svg>
<span class="brand">Tailscale Custom</span>
</div>
<div class="sidebar-user">
<div class="avatar" id="user-avatar">A</div>
<div class="user-info">
<span class="username" id="user-display"></span>
<span class="role-badge" id="user-role-badge"></span>
</div>
</div>
<ul class="nav-links">
<!-- Admin tabs -->
<li class="nav-item admin-only" data-tab="dashboard"><span class="nav-icon">&#x2630;</span> Dashboard</li>
<li class="nav-item admin-only" data-tab="nodes"><span class="nav-icon">&#x25B6;</span> All Nodes</li>
<li class="nav-item admin-only" data-tab="accounts"><span class="nav-icon">&#x2605;</span> Accounts</li>
<li class="nav-item admin-only" data-tab="users"><span class="nav-icon">&#x2666;</span> Headscale Users</li>
<li class="nav-item admin-only" data-tab="keys"><span class="nav-icon">&#x25C6;</span> Auth Keys</li>
<!-- User tabs -->
<li class="nav-item user-only" data-tab="my-nodes"><span class="nav-icon">&#x25B6;</span> My Nodes</li>
<!-- Common -->
<li class="nav-item" data-tab="download"><span class="nav-icon">&#x2913;</span> Download Client</li>
</ul>
<div class="sidebar-footer">
<button class="btn btn-outline btn-sm" onclick="showPasswordModal()">&#x26BF; Change Password</button>
<button class="btn btn-danger btn-sm" onclick="doLogout()">Logout</button>
</div>
</nav>
<!-- Content area -->
<main class="content">
<!-- Dashboard (admin) -->
<section id="tab-dashboard" class="tab-content">
<h2>Dashboard</h2>
<div class="stats-grid" id="stats-grid"></div>
</section>
<!-- All Nodes (admin) -->
<section id="tab-nodes" class="tab-content" style="display:none">
<div class="section-header">
<h2>All Nodes</h2>
<button class="btn btn-primary btn-sm" onclick="showRegisterModal()">+ Register Node</button>
</div>
<div class="table-container">
<table id="nodes-table">
<thead><tr><th>Name</th><th>IP</th><th>User</th><th>Status</th><th>Last Seen</th><th>Actions</th></tr></thead>
<tbody></tbody>
</table>
</div>
</section>
<!-- Accounts (admin) -->
<section id="tab-accounts" class="tab-content" style="display:none">
<div class="section-header">
<h2>Login Accounts</h2>
<button class="btn btn-primary btn-sm" onclick="showCreateAccountModal()">+ Create Account</button>
</div>
<div class="table-container">
<table id="accounts-table">
<thead><tr><th>Username</th><th>Role</th><th>Created</th><th>Actions</th></tr></thead>
<tbody></tbody>
</table>
</div>
</section>
<!-- Headscale Users (admin) -->
<section id="tab-users" class="tab-content" style="display:none">
<div class="section-header">
<h2>Headscale Users</h2>
<button class="btn btn-primary btn-sm" onclick="showCreateUserModal()">+ Create User</button>
</div>
<div class="table-container">
<table id="users-table">
<thead><tr><th>Name</th><th>Created</th><th>Actions</th></tr></thead>
<tbody></tbody>
</table>
</div>
</section>
<!-- Auth Keys (admin) -->
<section id="tab-keys" class="tab-content" style="display:none">
<div class="section-header">
<h2>Pre-Auth Keys</h2>
<button class="btn btn-primary btn-sm" onclick="showCreateKeyModal()">+ Create Key</button>
</div>
<div class="table-container">
<table id="keys-table">
<thead><tr><th>Key</th><th>User</th><th>Reusable</th><th>Ephemeral</th><th>Used</th><th>Expiration</th></tr></thead>
<tbody></tbody>
</table>
</div>
</section>
<!-- My Nodes (user) -->
<section id="tab-my-nodes" class="tab-content" style="display:none">
<div class="section-header">
<h2>My Nodes</h2>
<button class="btn btn-primary btn-sm" onclick="showUserRegisterModal()">+ Register Node</button>
</div>
<div class="table-container">
<table id="my-nodes-table">
<thead><tr><th>Name</th><th>IP</th><th>Status</th><th>Last Seen</th></tr></thead>
<tbody></tbody>
</table>
</div>
</section>
<!-- Download -->
<section id="tab-download" class="tab-content" style="display:none">
<h2>Download Client</h2>
<p class="section-desc">Download the Tailscale Custom VPN client for your platform.</p>
<div id="downloads-list" class="downloads-grid"></div>
</section>
</main>
</div>
<!-- Toast -->
<div id="toast" class="toast" style="display:none"></div>
<!-- Modals -->
<div id="modal-overlay" class="modal-overlay" style="display:none" onclick="closeModal()">
<div class="modal" onclick="event.stopPropagation()">
<div class="modal-header">
<h3 id="modal-title">Modal</h3>
<button class="modal-close" onclick="closeModal()">&times;</button>
</div>
<div class="modal-body" id="modal-body"></div>
</div>
</div>
<script src="app.js"></script>
</body>
</html>