81 lines
5.5 KiB
HTML
81 lines
5.5 KiB
HTML
{{/* html/template requires {{template "name"}} names to be string
|
|
literals, not dynamic pipelines — so a single "layout" wrapper that
|
|
dispatches to a per-page content block by name isn't possible within
|
|
one shared template set. Instead, layout.html provides small named
|
|
partials (html_head, sidebar_nav, topbar_mobile, banner_inner,
|
|
error_banner) that each page's *_page template (see e.g.
|
|
overview.html) assembles around its own *_content block explicitly.
|
|
A few lines of boilerplate are duplicated per page as a result — see
|
|
any *_page define for the pattern. */}}
|
|
|
|
{{define "html_head"}}
|
|
<meta charset="utf-8">
|
|
<meta name="viewport" content="width=device-width, initial-scale=1">
|
|
<title>Cloud IP Validator — Admin</title>
|
|
<link rel="stylesheet" href="/static/vendor/fonts.css">
|
|
<link rel="stylesheet" href="/static/dashboard.css">
|
|
<script src="/static/vendor/htmx.min.js"></script>
|
|
<script src="/static/vendor/alpine.min.js" defer></script>
|
|
{{end}}
|
|
|
|
{{define "sidebar_nav"}}
|
|
<aside class="sidebar">
|
|
<div class="brand">
|
|
<span class="brand-chrome"><i></i><i></i><i></i></span>
|
|
<span class="brand-mark">
|
|
<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="M12 2v6M12 16v6M2 12h6M16 12h6"/><circle cx="12" cy="12" r="3"/></svg>
|
|
</span>
|
|
<span class="brand-name">Cloud IP Validator<small>admin</small></span>
|
|
</div>
|
|
|
|
<nav class="nav-groups">
|
|
<a class="nav-link{{if eq .ActiveNav "overview"}} active{{end}}" {{if eq .ActiveNav "overview"}}aria-current="page"{{end}} href="/overview">
|
|
<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><rect x="3" y="3" width="7" height="9" rx="1.5"/><rect x="14" y="3" width="7" height="5" rx="1.5"/><rect x="14" y="12" width="7" height="9" rx="1.5"/><rect x="3" y="16" width="7" height="5" rx="1.5"/></svg>
|
|
Обзор
|
|
</a>
|
|
<a class="nav-link{{if eq .ActiveNav "ips"}} active{{end}}" {{if eq .ActiveNav "ips"}}aria-current="page"{{end}} href="/ips">
|
|
<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><rect x="3" y="4" width="18" height="16" rx="2"/><path d="M3 10h18M8 4v16"/></svg>
|
|
Очередь IP
|
|
</a>
|
|
<a class="nav-link{{if eq .ActiveNav "validators"}} active{{end}}" {{if eq .ActiveNav "validators"}}aria-current="page"{{end}} href="/validators">
|
|
<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><rect x="4" y="3" width="16" height="7" rx="1.5"/><rect x="4" y="14" width="16" height="7" rx="1.5"/><circle cx="8" cy="6.5" r="1"/><circle cx="8" cy="17.5" r="1"/></svg>
|
|
Валидаторы
|
|
</a>
|
|
<a class="nav-link{{if eq .ActiveNav "sites"}} active{{end}}" {{if eq .ActiveNav "sites"}}aria-current="page"{{end}} href="/sites">
|
|
<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="M12 2 3 7l9 5 9-5-9-5Z"/><path d="m3 12 9 5 9-5M3 17l9 5 9-5"/></svg>
|
|
Площадки
|
|
</a>
|
|
<a class="nav-link{{if eq .ActiveNav "targets"}} active{{end}}" {{if eq .ActiveNav "targets"}}aria-current="page"{{end}} href="/targets">
|
|
<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><circle cx="12" cy="12" r="9"/><circle cx="12" cy="12" r="4.5"/><circle cx="12" cy="12" r=".6" fill="currentColor"/></svg>
|
|
Цели
|
|
</a>
|
|
<a class="nav-link{{if eq .ActiveNav "check-types"}} active{{end}}" {{if eq .ActiveNav "check-types"}}aria-current="page"{{end}} href="/check-types">
|
|
<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="M9 11l3 3L22 4"/><path d="M21 12v7a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2V5a2 2 0 0 1 2-2h11"/></svg>
|
|
Типы проверок
|
|
</a>
|
|
<a class="nav-link{{if eq .ActiveNav "settings"}} active{{end}}" {{if eq .ActiveNav "settings"}}aria-current="page"{{end}} href="/settings">
|
|
<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><circle cx="12" cy="12" r="3"/><path d="M19.4 15a1.65 1.65 0 0 0 .33 1.82l.06.06a2 2 0 1 1-2.83 2.83l-.06-.06a1.65 1.65 0 0 0-1.82-.33 1.65 1.65 0 0 0-1 1.51V21a2 2 0 0 1-4 0v-.09A1.65 1.65 0 0 0 9 19.4a1.65 1.65 0 0 0-1.82.33l-.06.06a2 2 0 1 1-2.83-2.83l.06-.06a1.65 1.65 0 0 0 .33-1.82 1.65 1.65 0 0 0-1.51-1H3a2 2 0 0 1 0-4h.09A1.65 1.65 0 0 0 4.6 9a1.65 1.65 0 0 0-.33-1.82l-.06-.06a2 2 0 1 1 2.83-2.83l.06.06a1.65 1.65 0 0 0 1.82.33H9a1.65 1.65 0 0 0 1-1.51V3a2 2 0 0 1 4 0v.09a1.65 1.65 0 0 0 1 1.51 1.65 1.65 0 0 0 1.82-.33l.06-.06a2 2 0 1 1 2.83 2.83l-.06.06a1.65 1.65 0 0 0-.33 1.82V9a1.65 1.65 0 0 0 1.51 1H21a2 2 0 0 1 0 4h-.09a1.65 1.65 0 0 0-1.51 1Z"/></svg>
|
|
Настройки
|
|
</a>
|
|
</nav>
|
|
|
|
<div class="sidebar-foot">
|
|
<span class="pulse-dot"></span>
|
|
control-api
|
|
</div>
|
|
</aside>
|
|
{{end}}
|
|
|
|
{{define "topbar_mobile"}}
|
|
<div class="topbar-mobile">
|
|
<label class="burger" for="nav-toggle">
|
|
<svg width="17" height="17" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round"><path d="M4 7h16M4 12h16M4 17h16"/></svg>
|
|
</label>
|
|
<strong>Cloud IP Validator</strong>
|
|
</div>
|
|
{{end}}
|
|
|
|
{{define "banner_inner"}}{{if .Message}}<div class="alert {{if .Client}}alert-warning{{else}}alert-danger{{end}}" role="alert">{{.Message}}</div>{{end}}{{end}}
|
|
|
|
{{define "error_banner"}}<div id="error-banner" hx-swap-oob="true">{{template "banner_inner" .}}</div>{{end}}
|