feat: ent ORM, admin UI, client auth, Fyne GUI, Windows/MSI packaging
This commit is contained in:
@@ -0,0 +1,87 @@
|
||||
<!DOCTYPE html>
|
||||
<html lang="en">
|
||||
<head>
|
||||
<meta charset="UTF-8">
|
||||
<meta name="viewport" content="width=device-width,initial-scale=1">
|
||||
<title>{{if .Title}}{{.Title}} — {{end}}frp Admin</title>
|
||||
<script src="https://unpkg.com/htmx.org@2.0.4"></script>
|
||||
<style>
|
||||
*,*::before,*::after{box-sizing:border-box;margin:0;padding:0}
|
||||
:root{--bg:#fff;--bg2:#f5f5f5;--fg:#000;--fg2:#888;--border:#ddd;--accent:#000;--font:-apple-system,BlinkMacSystemFont,"Segoe UI",Roboto,sans-serif;--radius:0}
|
||||
@media(prefers-color-scheme:dark){
|
||||
:root{--bg:#000;--bg2:#111;--fg:#fff;--fg2:#666;--border:#333;--accent:#fff}
|
||||
}
|
||||
html,body{height:100%}
|
||||
body{font-family:var(--font);background:var(--bg);color:var(--fg);font-size:14px;line-height:1.5}
|
||||
a{color:var(--fg);text-decoration:underline}
|
||||
a:hover{text-decoration:none}
|
||||
table{width:100%;border-collapse:collapse}
|
||||
th,td{padding:10px 12px;text-align:left;border-bottom:1px solid var(--border);font-size:13px}
|
||||
th{font-weight:600;font-size:11px;letter-spacing:.3px;color:var(--fg2)}
|
||||
tr:hover td{background:var(--bg2)}
|
||||
input,select,textarea{padding:8px 12px;border:1px solid var(--border);background:var(--bg);color:var(--fg);font-size:13px;border-radius:var(--radius);width:100%;-webkit-appearance:none;appearance:none}
|
||||
input:focus,select:focus,textarea:focus{outline:1px solid var(--fg)}
|
||||
button,.btn{padding:8px 16px;border:1px solid var(--fg);background:var(--fg);color:var(--bg);font-size:13px;cursor:pointer;border-radius:var(--radius);font-family:var(--font)}
|
||||
button:hover,.btn:hover{opacity:.8}
|
||||
.btn-outline{background:transparent;color:var(--fg)}
|
||||
.btn-outline:hover{background:var(--fg);color:var(--bg)}
|
||||
.btn-sm{padding:4px 10px;font-size:12px}
|
||||
.card{background:var(--bg2);border:1px solid var(--border);padding:20px}
|
||||
.card h3{margin-bottom:8px;font-size:12px;font-weight:600;letter-spacing:.3px;color:var(--fg2)}
|
||||
.card .value{font-size:28px;font-weight:700;color:var(--fg)}
|
||||
.layout{display:flex;min-height:100vh}
|
||||
.sidebar{width:220px;background:var(--bg2);border-right:1px solid var(--border);padding:24px 0;flex-shrink:0}
|
||||
.sidebar .brand{padding:0 20px 24px;font-size:16px;font-weight:700;letter-spacing:-.5px;border-bottom:1px solid var(--border);margin-bottom:8px}
|
||||
.sidebar nav a{display:block;padding:8px 20px;color:var(--fg2);font-size:13px;text-decoration:none}
|
||||
.sidebar nav a:hover{color:var(--fg);background:var(--border)}
|
||||
.main{flex:1;padding:24px 32px;max-width:1200px}
|
||||
.main>h1{font-size:22px;font-weight:700;margin-bottom:24px}
|
||||
.login-page{display:flex;align-items:center;justify-content:center;min-height:100vh;background:var(--bg2)}
|
||||
.login-card{width:360px;padding:32px;background:var(--bg);border:1px solid var(--border)}
|
||||
.login-card h1{font-size:20px;margin-bottom:24px;text-align:center;letter-spacing:-.5px}
|
||||
.login-card .field{margin-bottom:16px}
|
||||
.login-card .field label{display:block;font-size:12px;color:var(--fg2);margin-bottom:4px}
|
||||
.login-card .error{color:var(--fg);font-size:13px;margin-bottom:12px;text-align:center}
|
||||
.grid-2{display:grid;grid-template-columns:1fr 1fr;gap:16px;margin-bottom:24px}
|
||||
.grid-3{display:grid;grid-template-columns:1fr 1fr 1fr;gap:16px;margin-bottom:24px}
|
||||
.grid-4{display:grid;grid-template-columns:repeat(4,1fr);gap:16px;margin-bottom:24px}
|
||||
.toolbar{display:flex;gap:8px;margin-bottom:16px;align-items:center}
|
||||
.toolbar .spacer{flex:1}
|
||||
.flex{display:flex;gap:8px;align-items:center}
|
||||
.text-right{text-align:right}
|
||||
.text-mono{font-family:"SFMono-Regular",Consolas,"Liberation Mono",monospace;font-size:12px}
|
||||
.mb-8{margin-bottom:8px;margin-top:0!important}
|
||||
.mt-8{margin-top:8px}
|
||||
.mb-16{margin-bottom:16px}
|
||||
.empty{padding:40px;text-align:center;color:var(--fg2);font-size:14px}
|
||||
@media(max-width:768px){
|
||||
.sidebar{width:56px;overflow:hidden}
|
||||
.sidebar .brand{font-size:0;padding:12px 16px}
|
||||
.sidebar .brand::after{content:"F";font-size:20px}
|
||||
.sidebar nav a{font-size:0;padding:12px 16px;text-align:center}
|
||||
.sidebar nav a::after{content:attr(data-label);font-size:13px;display:block;text-align:center}
|
||||
.sidebar nav a[data-label]::first-letter{font-size:14px}
|
||||
.main{padding:16px}
|
||||
.grid-2,.grid-3,.grid-4{grid-template-columns:1fr}
|
||||
}
|
||||
</style>
|
||||
</head>
|
||||
<body>
|
||||
<div class="layout">
|
||||
<aside class="sidebar">
|
||||
<div class="brand">frp Admin</div>
|
||||
<nav>
|
||||
<a href="/admin/dashboard" data-label="Dashboard" hx-get="/admin/dashboard" hx-target="#main-content" hx-push-url="true">Dashboard</a>
|
||||
<a href="/admin/clients" data-label="Clients" hx-get="/admin/clients" hx-target="#main-content" hx-push-url="true">Clients</a>
|
||||
<a href="/admin/proxies" data-label="Proxies" hx-get="/admin/proxies" hx-target="#main-content" hx-push-url="true">Proxies</a>
|
||||
<a href="/admin/settings" data-label="Settings" hx-get="/admin/settings" hx-target="#main-content" hx-push-url="true">Settings</a>
|
||||
<hr style="border:none;border-top:1px solid var(--border);margin:8px 20px">
|
||||
<a href="/admin/logout" data-label="Logout" hx-post="/admin/logout" hx-trigger="click" hx-target="body" hx-push-url="true">Logout</a>
|
||||
</nav>
|
||||
</aside>
|
||||
<main class="main" id="main-content">
|
||||
{{.Content}}
|
||||
</main>
|
||||
</div>
|
||||
</body>
|
||||
</html>
|
||||
Reference in New Issue
Block a user