2026-05-20 23:55:27 +02:00
from __future__ import annotations
from .html_utils import attr , escape
def _account_row ( account : dict [ str , str | int | None ], csrf : str = "" , admin_path : str = "/admin" ) -> str :
hostname = escape ( account [ "hostname" ])
username = escape ( account [ "username" ])
ipv4 = escape ( account . get ( "ipv4" ) or "-" )
ipv6 = escape ( account . get ( "ipv6" ) or "-" )
updated = escape ( account . get ( "updated_at" ) or "Never" )
safe_admin_path = attr ( admin_path )
return f """
<tr>
<td> { hostname } </td><td> { username } </td><td> { ipv4 } </td><td> { ipv6 } </td><td> { updated } </td>
<td>
<form method="post" action=" { safe_admin_path } /accounts/rotate" class="d-flex gap-2 flex-wrap">
<input type="hidden" name="csrf" value=" { attr ( csrf ) } ">
<input type="hidden" name="hostname" value=" { hostname } ">
2026-05-21 10:05:40 +02:00
<button name="action" value="update" class="btn btn-sm btn-light px-3" title="Create a new update URL" aria-label="New update URL for { hostname } ">New update URL</button>
<button name="action" value="management" class="btn btn-sm btn-light px-3" title="Create a new dashboard link" aria-label="New dashboard link for { hostname } ">New dashboard link</button>
<button name="action" value="password" class="btn btn-sm btn-light px-3" title="Create a new router password" aria-label="New password for { hostname } ">New password</button>
2026-05-20 23:55:27 +02:00
</form>
</td>
<td>
<form method="post" action=" { safe_admin_path } /accounts/delete">
<input type="hidden" name="csrf" value=" { attr ( csrf ) } ">
<input type="hidden" name="hostname" value=" { hostname } ">
2026-05-21 10:05:40 +02:00
<button class="btn btn-sm btn-outline-danger px-2" title="Delete hostname" aria-label="Delete { hostname } ">Delete</button>
2026-05-20 23:55:27 +02:00
</form>
</td>
</tr>
"""
def _admin_table_toolbar ( table_id : str , search_label : str ) -> str :
safe_id = attr ( table_id )
safe_label = attr ( search_label )
return f """
<div class="admin-table-shell mt-3" data-admin-table>
<div class="d-flex align-items-center justify-content-between gap-3 flex-column flex-md-row mb-3">
<label class="w-100 mb-0" for=" { safe_id } -search">
<span class="visually-hidden"> { safe_label } </span>
<input id=" { safe_id } -search" class="form-control" type="search" placeholder=" { safe_label } " data-table-search autocomplete="off">
</label>
<div class="d-flex align-items-center gap-2 flex-shrink-0">
<span class="small text-secondary text-nowrap" data-table-count>0-0 of 0</span>
<label class="visually-hidden" for=" { safe_id } -page-size">Rows per page</label>
<select id=" { safe_id } -page-size" class="form-select form-select-sm table-page-size" data-table-page-size>
<option value="10">10</option>
<option value="25" selected>25</option>
<option value="50">50</option>
<option value="100">100</option>
</select>
</div>
</div>
"""
def _admin_table_pagination () -> str :
return """
<nav class="mt-3" aria-label="Table pagination">
<ul class="pagination pagination-sm justify-content-end mb-0" data-table-pagination></ul>
</nav>
</div>
"""
def _event_row ( event : dict [ str , str | int | None ]) -> str :
created = escape ( event . get ( "created_at" ) or "-" )
hostname = escape ( event . get ( "hostname" ) or "-" )
status = escape ( event . get ( "status" ) or "-" )
ipv4 = escape ( event . get ( "ipv4" ) or "-" )
ipv6 = escape ( event . get ( "ipv6" ) or "-" )
count = escape ( event . get ( "count" ) or 1 )
detail = escape ( event . get ( "detail" ) or "-" )
return f "<tr><td> { created } </td><td> { hostname } </td><td> { status } </td><td> { ipv4 } </td><td> { ipv6 } </td><td> { count } </td><td> { detail } </td></tr>"