2026-09-23 09:52:01 +03:00
{{define "registry_page"}}
<!doctype html>
< html lang = "ru" >
< head > {{template "html_head" .}}</ head >
< body >
< div class = "bg-grid" ></ div >
< input type = "checkbox" id = "nav-toggle" class = "nav-toggle" >
< div class = "shell" >
{{template "sidebar_nav" .}}
< div >
{{template "topbar_mobile" .}}
< main class = "main" >
< div id = "error-banner" > {{template "banner_inner" .Banner}}</ div >
{{template "registry_content" .}}
</ main >
</ div >
</ div >
</ body >
</ html >
{{end}}
{{define "registry_content"}}
< div class = "topbar" >< h1 > Реестр IP</ h1 ></ div >
< p class = "muted" style = "margin-bottom:16px" > Все адреса, когда-либо поставленные на проверку — накопленная статистика
сохраняется здесь даже после удаления адреса из < a href = "/ips" > очереди</ a > и не теряется при повторном добавлении.
Глубина хранимой истории на адрес настраивается на < a href = "/settings" > странице настроек</ a > .</ p >
2026-09-23 11:58:53 +03:00
< form id = "registry-filter" class = "panel" onsubmit = "return false" style = "margin-bottom:16px" >
2026-10-03 18:36:03 +03:00
{{if .Run}}< input type = "hidden" name = "run" value = "{{.Run}}" > {{end}}
{{if .Subnet}}< input type = "hidden" name = "subnet" value = "{{.Subnet}}" > {{end}}
{{if or .Run .Subnet}}< div class = "panel-body" style = "padding-bottom:0" >
< span class = "pill pill-info" > Из аналитики:{{if .Run}} запуск {{.Run}}{{end}}{{if .Subnet}} · подсеть {{.Subnet}}{{end}}</ span >
< a href = "/registry" style = "margin-left:10px" > сбросить фильтр</ a >
{{if .Run}}< a href = "/analytics?run={{.Run}}" style = "margin-left:10px" > к аналитике</ a > {{end}}
</ div > {{end}}
2026-09-23 11:58:53 +03:00
< div class = "panel-body field-row" >
< div class = "field" style = "flex:1 1 260px" >
< label for = "registry-q" > Поиск по IP</ label >
< input type = "search" id = "registry-q" name = "q" value = "{{.Query}}" placeholder = "203.0.113.10"
hx-get = "/registry" hx-select = "#registry-table-wrap" hx-target = "#registry-table-wrap" hx-swap = "outerHTML"
hx-include = "#registry-filter" hx-trigger = "input changed delay:300ms"
hx-replace-url = "true" hx-sync = "#registry-table-wrap:queue last" >
</ div >
< div class = "field" >
< label for = "registry-status" > Статус</ label >
< select id = "registry-status" name = "status"
hx-get = "/registry" hx-select = "#registry-table-wrap" hx-target = "#registry-table-wrap" hx-swap = "outerHTML"
hx-include = "#registry-filter" hx-trigger = "change"
hx-replace-url = "true" hx-sync = "#registry-table-wrap:queue last" >
< option value = "" > Все</ option >
< option value = "pass" {{ if eq . StatusFilter " pass "}} selected {{ end }} > pass</ option >
< option value = "partial" {{ if eq . StatusFilter " partial "}} selected {{ end }} > partial</ option >
< option value = "fail" {{ if eq . StatusFilter " fail "}} selected {{ end }} > fail</ option >
< option value = "cancelled" {{ if eq . StatusFilter " cancelled "}} selected {{ end }} > cancelled</ option >
</ select >
</ div >
2026-10-01 19:31:11 +03:00
< div class = "field" style = "flex:0 0 120px" >
< label for = "registry-per-page" > На странице</ label >
< select id = "registry-per-page" name = "per_page"
hx-get = "/registry" hx-select = "#registry-table-wrap" hx-target = "#registry-table-wrap" hx-swap = "outerHTML"
hx-include = "#registry-filter" hx-trigger = "change"
hx-replace-url = "true" hx-sync = "#registry-table-wrap:queue last" >
{{$pp := .PerPage}}
{{range .PerPageOptions}}< option value = "{{.}}" {{ if eq . $ pp }} selected {{ end }} > {{.}}</ option >
{{end}}
</ select >
</ div >
2026-09-23 11:58:53 +03:00
</ div >
</ form >
< div id = "registry-table-wrap" >
{{template "registry_table" .}}
</ div >
{{end}}
2026-10-03 17:59:52 +03:00
{{define "registry_level"}}
< div class = "level" >
< span class = "level-name" > {{.Name}}</ span >
{{if .L.Total}}< span class = "stat stat-{{.L.Class}}" > {{.L.OK}} из {{.L.Total}}</ span >
< span class = "level-types" > {{range .L.ByType}}< span class = "chip chip-{{.Class}}" > {{.Type}} {{.OK}} из {{.Total}}</ span > {{end}}</ span >
{{else}}< span class = "stat stat-none" > —</ span > {{end}}
</ div >
{{end}}
2026-09-23 11:58:53 +03:00
{{define "registry_table"}}
2026-09-23 09:52:01 +03:00
{{if .Items}}
< div class = "panel" >
< div class = "table-scroll" >
< table >
< thead >< tr >< th > Адрес</ th >< th > Впервые замечен</ th >< th > Последний раз замечен</ th >< th > Циклов</ th >< th > Последний результат</ th >< th > Сейчас в очереди</ th ></ tr ></ thead >
< tbody >
{{range .Items}}
< tr >
< td class = "addr" data-label = "Адрес" >< a href = "/registry/{{.IPAddress}}" > {{.IPAddress}}</ a ></ td >
< td data-label = "Впервые замечен" > {{fmtTime .FirstSeenAt}}</ td >
< td data-label = "Последний раз замечен" > {{fmtTime .LastSeenAt}}</ td >
< td class = "num" data-label = "Циклов" > {{.TotalCycles}}</ td >
< td data-label = "Последний результат" >
{{if eq .LastResult "pass"}}< span class = "pill pill-success" > pass</ span >
2026-09-23 11:03:56 +03:00
{{else if eq .LastResult "partial"}}< span class = "pill pill-warning" > partial</ span >
2026-09-23 09:52:01 +03:00
{{else if eq .LastResult "fail"}}< span class = "pill pill-danger" > fail</ span >
2026-09-23 11:03:56 +03:00
{{else if eq .LastResult "cancelled"}}< span class = "pill pill-cancel" > cancelled</ span >
2026-09-23 09:52:01 +03:00
{{else}}< span class = "pill pill-neutral" > —</ span > {{end}}
2026-10-03 17:59:52 +03:00
{{if .LastCycleID}}< div class = "levels" title = "Считаются записанные проверки цикла {{.LastCycleID}}; вердикт учитывает ещё и недостающие результаты." >
{{template "registry_level" dict "Name" "Egress" "L" .Egress}}
{{template "registry_level" dict "Name" "Ingress" "L" .Ingress}}
</ div > {{end}}
2026-09-23 09:52:01 +03:00
</ td >
< td data-label = "Сейчас в очереди" >
{{if .InQueue}}< span class = "pill pill-info" > {{.CurrentState}}</ span > {{else}}< span class = "pill pill-neutral" > нет</ span > {{end}}
</ td >
</ tr >
{{end}}
</ tbody >
</ table >
</ div >
2026-10-01 19:31:11 +03:00
{{template "pager" .Pager}}
2026-09-23 09:52:01 +03:00
</ div >
2026-09-23 11:58:53 +03:00
{{else if or .Query .StatusFilter}}< p class = "muted" > Ничего не найдено по текущему фильтру.</ p >
2026-09-23 09:52:01 +03:00
{{else}}< p class = "muted" > Реестр пуст — ни один адрес ещё не ставился на проверку.</ p > {{end}}
{{end}}