Files
warpbox-dev/backend/templates/pages/admin_logs.html
Daniel Legt ffa2d9636b
All checks were successful
Build and Publish Docker Image / deploy (push) Successful in 1m40s
feat(admin): add dashboard overview charts and log pagination
Enhance the admin panel by introducing visual overview charts for upload and storage trends, along with status bars for system metrics.

Additionally, implement pagination for the admin logs view, allowing users to navigate through log entries with configurable page sizes. Corresponding CSS styles have been added for the new charts, metrics grid, and pagination controls.
2026-06-01 04:22:38 +03:00

122 lines
6.2 KiB
HTML
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
{{define "admin_logs.html"}}{{template "base" .}}{{end}}
{{define "content"}}
<section class="app-shell admin-shell" aria-labelledby="admin-logs-title">
<aside class="app-sidebar">
<nav class="sidebar-nav">
<a class="sidebar-link" href="/admin">{{template "icon-dashboard" .}}<span>Overview</span></a>
<a class="sidebar-link" href="/admin/files">{{template "icon-folder" .}}<span>Files</span></a>
<a class="sidebar-link" href="/admin/users">{{template "icon-user-circle" .}}<span>Users</span></a>
<a class="sidebar-link" href="/admin/settings">{{template "icon-settings" .}}<span>Settings</span></a>
<a class="sidebar-link" href="/admin/storage">{{template "icon-database" .}}<span>Storage</span></a>
<a class="sidebar-link is-active" href="/admin/logs">{{template "icon-database" .}}<span>Logs</span></a>
<a class="sidebar-link" href="/admin/bans">{{template "icon-settings" .}}<span>Bans</span></a>
</nav>
<hr class="sidebar-sep">
<nav class="sidebar-nav"><a class="sidebar-link" href="/app">{{template "icon-home-simple" .}}<span>My Files</span></a></nav>
<hr class="sidebar-sep">
<form class="sidebar-logout" action="/admin/logout" method="post">
<input type="hidden" name="csrf_token" value="{{.CSRFToken}}">
<button class="button button-outline" type="submit">{{template "icon-log-out" .}}<span>Sign out</span></button>
</form>
</aside>
<div class="app-main">
<div class="admin-header">
<div>
<p class="kicker">Operator console</p>
<h1 id="admin-logs-title">{{.Data.PageTitle}}</h1>
<p class="muted-copy">Browse JSON log lines from the local log files.</p>
</div>
</div>
<form class="logs-filter-card" method="get" action="/admin/logs">
<label><span>Date</span>
<select name="date">
<option value="all" {{if eq .Data.Logs.Date "all"}}selected{{end}}>All dates</option>
{{range .Data.Logs.Dates}}<option value="{{.}}" {{if eq $.Data.Logs.Date .}}selected{{end}}>{{.}}</option>{{end}}
</select>
</label>
<label><span>Severity</span>
<select name="severity">
<option value="" {{if eq .Data.Logs.Severity ""}}selected{{end}}>All</option>
<option value="dev" {{if eq .Data.Logs.Severity "dev"}}selected{{end}}>dev</option>
<option value="user_activity" {{if eq .Data.Logs.Severity "user_activity"}}selected{{end}}>user_activity</option>
<option value="warn" {{if eq .Data.Logs.Severity "warn"}}selected{{end}}>warn</option>
<option value="error" {{if eq .Data.Logs.Severity "error"}}selected{{end}}>error</option>
</select>
</label>
<label><span>Source</span><input name="source" value="{{.Data.Logs.Source}}" placeholder="auth, admin, upload"></label>
<label><span>Search</span><input name="q" value="{{.Data.Logs.Query}}" placeholder="message, IP, path, user id"></label>
<label><span>Sort</span>
<select name="sort">
<option value="desc" {{if eq .Data.Logs.Sort "desc"}}selected{{end}}>Newest first</option>
<option value="asc" {{if eq .Data.Logs.Sort "asc"}}selected{{end}}>Oldest first</option>
</select>
</label>
<input type="hidden" name="per" value="{{.Data.Logs.PerPage}}">
<button class="button button-primary" type="submit">Filter</button>
</form>
<div class="card admin-table-card">
<div class="card-content">
<div class="table-header">
<div>
<h2>Log entries</h2>
<p>{{.Data.Logs.Total}} entries match these filters.</p>
</div>
</div>
<div class="admin-table-wrap">
<table class="admin-table logs-table">
<thead>
<tr>
<th>Time</th>
<th>Severity</th>
<th>Source</th>
<th>Code</th>
<th>Message</th>
<th>Actor/IP</th>
<th>Route</th>
</tr>
</thead>
<tbody>
{{range .Data.Logs.Entries}}
<tr>
<td><span class="log-time">{{.Date}} {{.Time}}</span></td>
<td><span class="badge">{{.Severity}}</span></td>
<td>{{.Source}}</td>
<td>{{.Code}}</td>
<td>
<strong>{{.Message}}</strong>
{{if .Details}}<details><summary>Details</summary><code>{{.Details}}</code></details>{{end}}
</td>
<td>{{if .UserID}}<code>{{.UserID}}</code>{{end}}{{if .IP}}<br><span>{{.IP}}</span>{{end}}</td>
<td>{{if .Method}}{{.Method}}{{end}} {{if .Path}}<code>{{.Path}}</code>{{end}}{{if .Status}}<br><span>Status {{.Status}}</span>{{end}}</td>
</tr>
{{else}}
<tr><td colspan="7">No log entries match those filters.</td></tr>
{{end}}
</tbody>
</table>
</div>
<div class="pagination-bar">
<nav class="pagination" aria-label="Pagination">
{{if .Data.Logs.HasPrev}}<a class="button button-outline button-sm" href="{{.Data.Logs.PrevHref}}">← Prev</a>{{else}}<span class="button button-outline button-sm is-disabled" aria-disabled="true">← Prev</span>{{end}}
{{range .Data.Logs.PageLinks}}<a class="button button-sm {{if .Active}}is-active{{else}}button-outline{{end}}" href="{{.Href}}">{{.Page}}</a>{{end}}
{{if .Data.Logs.HasNext}}<a class="button button-outline button-sm" href="{{.Data.Logs.NextHref}}">Next →</a>{{else}}<span class="button button-outline button-sm is-disabled" aria-disabled="true">Next →</span>{{end}}
</nav>
<label class="per-page-control">
<span>Per page</span>
<select data-per-page="logs" aria-label="Items per page">
{{range .Data.Logs.PerPageOptions}}<option value="{{.}}" {{if eq . $.Data.Logs.PerPage}}selected{{end}}>{{.}}</option>{{end}}
</select>
</label>
</div>
<p class="pagination-summary">Showing {{.Data.Logs.RangeFrom}}{{.Data.Logs.RangeTo}} of {{.Data.Logs.Total}} · Page {{.Data.Logs.Page}} of {{.Data.Logs.TotalPages}}</p>
</div>
</div>
</div>
</section>
{{end}}