Öffentliche Dateiansicht: Raw-Dateien, Tree, Releases und Issues sind ohne Login verfügbar.
admin/templates/layout.html
  1
  2
  3
  4
  5
  6
  7
  8
  9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
 30
 31
 32
 33
 34
 35
 36
 37
 38
 39
 40
 41
 42
 43
 44
 45
 46
 47
 48
 49
 50
 51
 52
 53
 54
 55
 56
 57
 58
 59
 60
 61
 62
 63
 64
 65
 66
 67
 68
 69
 70
 71
 72
 73
 74
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
{{define "layout"}}
<!DOCTYPE html>
<html lang="de">
<head>
  <meta charset="UTF-8">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <title>Noxway Admin</title>
  <script src="https://unpkg.com/htmx.org@2.0.4" integrity="sha384-HGfztofotfshcF7+8n44JQL2oJmowVChPTg48S+jvZoztPfvwD79OC/LTtG6dMp+" crossorigin="anonymous"></script>
  <style>
    *, *::before, *::after { box-sizing: border-box; margin: 0; padding: 0; }
    :root {
      --sidebar-bg: #1e2235;
      --sidebar-width: 210px;
      --accent: #4f7ef8;
      --accent-hover: #3a6ae0;
      --bg: #f0f2f7;
      --card: #ffffff;
      --text: #2d3142;
      --text-muted: #6b7280;
      --border: #e2e8f0;
      --danger: #ef4444;
      --success: #22c55e;
      --warning: #f59e0b;
    }
    body { font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', sans-serif; font-size: 14px; background: var(--bg); color: var(--text); display: flex; min-height: 100vh; }
    /* Sidebar */
    .sidebar { width: var(--sidebar-width); background: var(--sidebar-bg); display: flex; flex-direction: column; position: fixed; top: 0; left: 0; height: 100vh; z-index: 100; }
    .sidebar-logo { padding: 20px 16px 16px; border-bottom: 1px solid rgba(255,255,255,.08); }
    .sidebar-logo h1 { color: #fff; font-size: 18px; font-weight: 700; letter-spacing: .5px; }
    .sidebar-logo small { color: rgba(255,255,255,.4); font-size: 11px; }
    .sidebar nav { flex: 1; padding: 12px 0; }
    .sidebar nav a { display: flex; align-items: center; gap: 10px; padding: 10px 16px; color: rgba(255,255,255,.65); text-decoration: none; font-size: 13px; font-weight: 500; transition: all .15s; border-left: 3px solid transparent; }
    .sidebar nav a:hover, .sidebar nav a.active { color: #fff; background: rgba(255,255,255,.07); border-left-color: var(--accent); }
    .sidebar nav a svg { width: 16px; height: 16px; flex-shrink: 0; }
    .sidebar-footer { padding: 12px 16px; border-top: 1px solid rgba(255,255,255,.08); }
    .sidebar-footer a { color: rgba(255,255,255,.45); font-size: 12px; text-decoration: none; }
    .sidebar-footer a:hover { color: #fff; }
    /* Main */
    .main { margin-left: var(--sidebar-width); flex: 1; display: flex; flex-direction: column; min-height: 100vh; }
    .topbar { background: var(--card); border-bottom: 1px solid var(--border); padding: 12px 24px; display: flex; align-items: center; justify-content: space-between; position: sticky; top: 0; z-index: 50; }
    .topbar-title { font-size: 16px; font-weight: 600; color: var(--text); }
    .page { padding: 24px; flex: 1; }
    /* Cards */
    .card { background: var(--card); border-radius: 10px; border: 1px solid var(--border); padding: 20px; }
    .card-title { font-size: 13px; font-weight: 600; color: var(--text-muted); text-transform: uppercase; letter-spacing: .5px; margin-bottom: 12px; }
    .stat-grid { display: grid; grid-template-columns: repeat(auto-fit, minmax(180px, 1fr)); gap: 16px; margin-bottom: 20px; }
    .stat-card { background: var(--card); border-radius: 10px; border: 1px solid var(--border); padding: 16px 20px; }
    .stat-value { font-size: 26px; font-weight: 700; color: var(--text); line-height: 1.1; }
    .stat-label { font-size: 12px; color: var(--text-muted); margin-top: 4px; }
    /* Tables */
    .table-wrap { overflow-x: auto; border-radius: 10px; border: 1px solid var(--border); }
    table { width: 100%; border-collapse: collapse; background: var(--card); }
    th { background: #f8fafc; font-size: 11px; font-weight: 600; color: var(--text-muted); text-transform: uppercase; letter-spacing: .5px; padding: 10px 14px; text-align: left; border-bottom: 1px solid var(--border); }
    td { padding: 10px 14px; border-bottom: 1px solid var(--border); font-size: 13px; vertical-align: middle; }
    tr:last-child td { border-bottom: none; }
    tr:hover td { background: #fafbfc; }
    /* Buttons */
    .btn { display: inline-flex; align-items: center; gap: 6px; padding: 7px 14px; border-radius: 6px; font-size: 13px; font-weight: 500; cursor: pointer; border: none; text-decoration: none; transition: all .15s; }
    .btn-primary { background: var(--accent); color: #fff; }
    .btn-primary:hover { background: var(--accent-hover); }
    .btn-secondary { background: #f1f5f9; color: var(--text); border: 1px solid var(--border); }
    .btn-secondary:hover { background: #e8edf3; }
    .btn-danger { background: #fef2f2; color: var(--danger); border: 1px solid #fecaca; }
    .btn-danger:hover { background: #fee2e2; }
    .btn-sm { padding: 4px 10px; font-size: 12px; }
    .btn-icon { padding: 5px 8px; }
    /* Forms */
    .form-group { margin-bottom: 16px; }
    .form-group label { display: block; font-size: 12px; font-weight: 600; color: var(--text-muted); margin-bottom: 5px; text-transform: uppercase; letter-spacing: .4px; }
    .form-control { width: 100%; padding: 8px 12px; border: 1px solid var(--border); border-radius: 6px; font-size: 13px; color: var(--text); background: var(--card); transition: border-color .15s; }
    .form-control:focus { outline: none; border-color: var(--accent); }
    textarea.form-control { font-family: 'SFMono-Regular', Consolas, monospace; font-size: 12px; resize: vertical; min-height: 80px; }
    .form-check { display: flex; align-items: center; gap: 8px; padding: 4px 0; }
    .form-check input[type=checkbox] { width: 16px; height: 16px; accent-color: var(--accent); cursor: pointer; }
    .form-check label { font-size: 13px; font-weight: 500; cursor: pointer; }
    .form-row { display: grid; grid-template-columns: 1fr 1fr; gap: 16px; }
    .form-row-3 { display: grid; grid-template-columns: 1fr 1fr 1fr; gap: 16px; }
    /* Badges */
    .badge { display: inline-block; padding: 2px 8px; border-radius: 4px; font-size: 11px; font-weight: 600; }
    .badge-green { background: #dcfce7; color: #166534; }
    .badge-red { background: #fef2f2; color: #991b1b; }
    .badge-gray { background: #f1f5f9; color: var(--text-muted); }
    .badge-blue { background: #eff6ff; color: #1d4ed8; }
    /* Toast */
    .toast { position: fixed; bottom: 24px; right: 24px; padding: 12px 20px; border-radius: 8px; font-size: 13px; font-weight: 500; z-index: 999; animation: fadeIn .2s ease; }
    .toast.success { background: #dcfce7; color: #166534; border: 1px solid #86efac; }
    .toast.error { background: #fef2f2; color: #991b1b; border: 1px solid #fca5a5; }
    @keyframes fadeIn { from { opacity: 0; transform: translateY(8px); } to { opacity: 1; transform: translateY(0); } }
    /* Utils */
    .mb-4 { margin-bottom: 16px; }
    .mb-6 { margin-bottom: 24px; }
    .flex { display: flex; }
    .items-center { align-items: center; }
    .gap-2 { gap: 8px; }
    .gap-3 { gap: 12px; }
    .justify-between { justify-content: space-between; }
    .text-muted { color: var(--text-muted); }
    .text-sm { font-size: 12px; }
    .font-mono { font-family: 'SFMono-Regular', Consolas, monospace; }
    .waf-on { background: #dcfce7 !important; color: #166534 !important; border-color: #86efac !important; }
    .htmx-indicator { display: none; }
    .htmx-request .htmx-indicator { display: inline; }
    #editor { margin-top: 20px; }
    #toast-area { position: fixed; bottom: 24px; right: 24px; z-index: 999; }
  </style>
</head>
<body>
  <aside class="sidebar">
    <div class="sidebar-logo">
      <h1>Noxway</h1>
      <small>Admin Panel</small>
    </div>
    <nav>
      <a href="/admin/dashboard">
        <svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"><rect x="3" y="3" width="7" height="7"/><rect x="14" y="3" width="7" height="7"/><rect x="3" y="14" width="7" height="7"/><rect x="14" y="14" width="7" height="7"/></svg>
        Dashboard
      </a>
      <a href="/admin/endpoints">
        <svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"><circle cx="12" cy="12" r="3"/><path d="M19.07 4.93a10 10 0 0 1 0 14.14M4.93 4.93a10 10 0 0 0 0 14.14"/></svg>
        Endpoints
      </a>
      <a href="/admin/gateway">
        <svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"><path d="M12 2L2 7l10 5 10-5-10-5z"/><path d="M2 17l10 5 10-5"/><path d="M2 12l10 5 10-5"/></svg>
        Gateway
      </a>
      <a href="/admin/logs">
        <svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"><path d="M14 2H6a2 2 0 0 0-2 2v16a2 2 0 0 0 2 2h12a2 2 0 0 0 2-2V8z"/><polyline points="14 2 14 8 20 8"/><line x1="16" y1="13" x2="8" y2="13"/><line x1="16" y1="17" x2="8" y2="17"/><line x1="10" y1="9" x2="8" y2="9"/></svg>
        Logs
      </a>
    </nav>
    <div class="sidebar-footer">
      <a href="/admin/logout">Logout</a>
    </div>
  </aside>
  <main class="main">
    <div class="topbar">
      <span class="topbar-title">{{template "page_title" .}}</span>
      <span class="text-muted text-sm">Gateway: {{template "gateway_name" .}}</span>
    </div>
    <div class="page">
      {{template "content" .}}
    </div>
  </main>
  <div id="toast-area"></div>
  <script>
    // Highlight active nav link
    document.querySelectorAll('.sidebar nav a').forEach(a => {
      if (location.pathname.startsWith(a.getAttribute('href'))) a.classList.add('active');
    });
    // Auto-dismiss toasts
    document.body.addEventListener('htmx:afterSwap', () => {
      document.querySelectorAll('.toast').forEach(t => {
        setTimeout(() => t.remove(), 3000);
      });
    });
  </script>
</body>
</html>
{{end}}

{{define "page_title"}}Admin{{end}}
{{define "gateway_name"}}{{end}}
Sprachen
Go 46%
JavaScript 45%
Markdown 3.3%
HTML 2.5%
YAML 1.7%
JSON 1.1%
Klonen
HTTPS