2026-08-23 20:39:22 +03:00
{{define "ips_page"}}
<!doctype html>
< html lang = "ru" >
< head > {{template "html_head" .}}</ head >
< body >
2026-08-23 21:58:19 +03:00
< input type = "checkbox" id = "nav-toggle" class = "nav-toggle" >
< div class = "shell" >
{{template "sidebar_nav" .}}
< div >
{{template "topbar_mobile" .}}
< main class = "main" >
2026-08-23 20:39:22 +03:00
< div id = "error-banner" > {{template "banner_inner" .Banner}}</ div >
{{template "ips_content" .}}
</ main >
2026-08-23 21:58:19 +03:00
</ div >
</ div >
2026-08-23 20:39:22 +03:00
</ body >
</ html >
{{end}}
{{define "ips_content"}}
2026-08-23 21:58:19 +03:00
< div class = "topbar" >< h1 > Очередь IP</ h1 ></ div >
2026-08-23 20:39:22 +03:00
2026-08-23 21:58:19 +03:00
< div class = "panel" >
< div class = "panel-body" >
< form hx-post = "/ips" hx-target = "#ips-table-wrap" hx-swap = "innerHTML" hx-on::after-request = "this.reset()" >
< div class = "field-row" >
< div class = "field" style = "flex: 1 1 420px;" >
< label for = "addresses" > Адреса (по одному на строку или через запятую)</ label >
< textarea id = "addresses" name = "addresses" rows = "2" placeholder = "203.0.113.10 203.0.113.11" ></ textarea >
2026-08-23 21:15:31 +03:00
</ div >
2026-08-23 21:58:19 +03:00
< button type = "submit" class = "btn btn-primary" > Добавить / перепроверить</ button >
2026-08-23 21:15:31 +03:00
</ div >
2026-08-23 20:39:22 +03:00
</ form >
2026-08-23 21:58:19 +03:00
< p class = "muted" style = "margin-top:8px" > Новый адрес встаёт в очередь; уже завершённый (done/failed) запускается заново
(тот же вызов); тот, что сейчас проверяется, не трогается.</ p >
</ div >
</ div >
2026-08-23 20:39:22 +03:00
< div id = "ips-table-wrap" >
{{template "ips_table" .}}
</ div >
{{end}}
{{define "ips_table"}}
2026-08-23 22:24:55 +03:00
< form id = "ips-form" >
2026-08-23 21:58:19 +03:00
< div class = "panel" >
2026-08-23 22:24:55 +03:00
< div class = "panel-body" style = "display:flex; gap:8px; align-items:center;" >
< button type = "button" class = "btn btn-danger-ghost btn-sm" hx-post = "/ips/delete" hx-target = "#ips-table-wrap" hx-swap = "innerHTML" hx-confirm = "Удалить выбранные адреса без возможности восстановления?" > Удалить выбранные</ button >
< button type = "button" class = "btn btn-danger-ghost btn-sm" hx-post = "/ips/clear" hx-target = "#ips-table-wrap" hx-swap = "innerHTML" hx-confirm = "Удалить ВСЕ адреса из очереди, включая те, что сейчас проверяются? Действие необратимо." > Очистить всё</ button >
</ div >
2026-08-23 21:58:19 +03:00
< div class = "table-scroll" >
< table >
2026-08-23 22:24:55 +03:00
< thead >< tr >< th >< input type = "checkbox" onclick = "this.closest('table').querySelectorAll('input[name=addresses]').forEach(cb => cb.checked = this.checked)" ></ th >< th > Адрес</ th >< th > Состояние</ th >< th > Валидатор</ th >< th > Попытка</ th >< th > Обновлено</ th >< th ></ th ></ tr ></ thead >
2026-08-23 20:39:22 +03:00
< tbody >
{{range .Items}}
2026-08-24 10:29:08 +03:00
{{$b := ipBadge .State .OverallResult .FIPAssociatedAt $.FIPSettleSeconds}}
2026-08-23 20:39:22 +03:00
{{$terminal := or (eq .State "done") (eq .State "failed")}}
< tr >
2026-08-23 22:24:55 +03:00
< td data-label = "" >< input type = "checkbox" name = "addresses" value = "{{.IPAddress}}" ></ td >
2026-08-23 21:58:19 +03:00
< td class = "addr" data-label = "Адрес" >< a href = "/ips/{{.IPAddress}}" > {{.IPAddress}}</ a ></ td >
< td data-label = "Состояние" >< span class = "pill {{$b.Class}}" > {{$b.Label}}</ span ></ td >
< td data-label = "Валидатор" > {{deref .OwnerValidatorID}}</ td >
< td class = "num" data-label = "Попытка" > {{.AttemptNumber}}</ td >
< td class = "num" data-label = "Обновлено" > {{fmtTime .UpdatedAt}}</ td >
< td data-label = "" >
< div class = "actions" >
2026-08-23 20:39:22 +03:00
{{if $terminal}}
2026-08-23 21:58:19 +03:00
< button class = "btn btn-ghost btn-sm" hx-post = "/ips/{{.IPAddress}}/recheck" hx-target = "#ips-table-wrap" hx-swap = "innerHTML" > Перепроверить</ button >
2026-08-23 20:39:22 +03:00
{{else}}
2026-08-23 21:58:19 +03:00
< button class = "btn btn-danger-ghost btn-sm" hx-post = "/ips/{{.IPAddress}}/cancel" hx-target = "#ips-table-wrap" hx-swap = "innerHTML" hx-confirm = "Остановить проверку {{.IPAddress}}?" > Отменить</ button >
2026-08-23 20:39:22 +03:00
{{end}}
2026-08-23 22:24:55 +03:00
< button class = "btn btn-danger-ghost btn-sm" hx-delete = "/ips/{{.IPAddress}}" hx-target = "#ips-table-wrap" hx-swap = "innerHTML" hx-confirm = "Удалить {{.IPAddress}} без возможности восстановления?" > Удалить</ button >
2026-08-23 21:58:19 +03:00
</ div >
2026-08-23 20:39:22 +03:00
</ td >
</ tr >
{{end}}
</ tbody >
</ table >
2026-08-23 21:15:31 +03:00
</ div >
2026-08-23 21:58:19 +03:00
</ div >
2026-08-23 22:24:55 +03:00
</ form >
2026-08-23 20:39:22 +03:00
{{if not .Items}}< p class = "muted" > Очередь пуста.</ p > {{end}}
{{end}}