Files
warpbox/templates/admin/alerts.html

322 lines
26 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/alerts.html" }}
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1">
<title>WarpBox Admin Alerts</title>
<link rel="icon" type="image/png" href="/static/WarpBoxLogo.png">
<link rel="stylesheet" href="/static/css/app.css">
<link rel="stylesheet" href="/static/css/window.css">
<link rel="stylesheet" href="/static/css/components/buttons.css">
<link rel="stylesheet" href="/static/css/components/toast.css">
<link rel="stylesheet" href="/static/css/admin.css">
<link rel="stylesheet" href="/static/css/alerts.css">
</head>
<body>
<div class="admin-shell">
<div class="admin-frame">
{{ template "admin/header.html" . }}
<div class="win98-window admin-workspace-window" role="main">
<div class="win98-titlebar">
<div class="win98-titlebar-label">
<img class="win98-titlebar-icon" src="/static/WarpBoxLogo.png" alt="" aria-hidden="true">
<h1>WarpBox Alerts</h1>
</div>
<div class="win98-window-controls" aria-hidden="true">
<button class="win98-control" type="button">_</button>
<button class="win98-control" type="button"></button>
<button class="win98-control" type="button">x</button>
</div>
</div>
<nav class="menu-bar" aria-label="Alerts toolbar">
<div class="menu-item">
<button class="menu-button" type="button" aria-expanded="false">File</button>
<div class="menu-popup">
<button class="menu-action" type="button" data-command="refresh"><span>R</span><span>Refresh alerts</span><span class="shortcut">F5</span></button>
<button class="menu-action" type="button" data-command="export"><span>E</span><span>Export visible alerts</span><span></span></button>
</div>
</div>
<div class="menu-item">
<button class="menu-button" type="button" aria-expanded="false">Alerts</button>
<div class="menu-popup">
<button class="menu-action" type="button" data-command="ack"><span>A</span><span>Acknowledge selected</span><span></span></button>
<button class="menu-action" type="button" data-command="close"><span>C</span><span>Close selected</span><span></span></button>
<div class="menu-separator"></div>
<button class="menu-action" type="button" data-command="open-only"><span>O</span><span>Show open only</span><span></span></button>
</div>
</div>
<div class="menu-item">
<button class="menu-button" type="button" aria-expanded="false">Help</button>
<div class="menu-popup">
<button class="menu-action" type="button" data-command="help-codes"><span>?</span><span>Tracing and codes</span><span></span></button>
<button class="menu-action" type="button" data-command="help-meta"><span>I</span><span>Metadata preview</span><span></span></button>
</div>
</div>
</nav>
<div class="admin-workspace-body alerts-page-body">
<section class="alerts-summary-grid" aria-label="Alerts summary">
<article class="alerts-stat-card is-danger">
<p class="alerts-stat-label">Open alerts</p>
<p class="alerts-stat-value" data-open-count>5</p>
<p class="alerts-stat-note">Requires attention</p>
</article>
<article class="alerts-stat-card is-warning">
<p class="alerts-stat-label">High severity</p>
<p class="alerts-stat-value" data-high-count>2</p>
<p class="alerts-stat-note">Escalate first</p>
</article>
<article class="alerts-stat-card is-info">
<p class="alerts-stat-label">Acknowledged</p>
<p class="alerts-stat-value" data-ack-count>3</p>
<p class="alerts-stat-note">Seen but not closed</p>
</article>
<article class="alerts-stat-card is-info">
<p class="alerts-stat-label">Closed today</p>
<p class="alerts-stat-value" data-closed-count>2</p>
<p class="alerts-stat-note">History stays lightweight</p>
</article>
</section>
<section class="alerts-content-grid">
<div class="alerts-column">
<section class="alerts-panel alerts-list-panel">
<div class="alerts-panel-header">
<div class="alerts-panel-title">Alert list <span class="alerts-panel-sub">search, filter, review</span></div>
<div class="alerts-panel-tools">
<button class="win98-button alerts-tool-button" type="button" data-command="ack">Acknowledge</button>
<button class="win98-button alerts-tool-button" type="button" data-command="close">Close</button>
</div>
</div>
<div class="alerts-panel-body">
<div class="alerts-toolbar-grid">
<input class="alerts-input" id="search-input" type="search" placeholder="Search title, code, trace or text">
<select class="alerts-select" id="severity-filter">
<option value="all" selected>All severities</option>
<option value="low">Low</option>
<option value="medium">Medium</option>
<option value="high">High</option>
</select>
<select class="alerts-select" id="status-filter">
<option value="all" selected>All statuses</option>
<option value="open">Open</option>
<option value="acked">Acknowledged</option>
<option value="closed">Closed</option>
</select>
<select class="alerts-select" id="source-filter">
<option value="all" selected>All groups</option>
<option value="thumbnails">Thumbnails</option>
<option value="storage">Storage</option>
<option value="uploads">Uploads</option>
<option value="auth">Auth</option>
</select>
<select class="alerts-select" id="sort-filter">
<option value="newest" selected>Newest first</option>
<option value="severity">Severity first</option>
<option value="oldest">Oldest first</option>
</select>
</div>
<div class="alerts-table-wrap">
<table class="alerts-table">
<thead>
<tr>
<th class="alerts-col-check"><input type="checkbox" id="select-all"></th>
<th>Title</th>
<th class="alerts-col-severity">Severity</th>
<th class="alerts-col-status">Status</th>
<th class="alerts-col-code">Code</th>
<th>Trace</th>
<th class="alerts-col-time">Created</th>
<th class="alerts-col-actions">Actions</th>
</tr>
</thead>
<tbody id="alerts-body">
<tr data-id="10" data-severity="high" data-status="open" data-group="storage" data-title="Storage connector unavailable" data-description="Primary local storage connector failed health check and new writes are paused." data-code="301" data-trace="storage.connector.health_failed" data-time="today 14:08" data-metadata='{"connector":"local-main","mode":"read_only","retry_in":"30s"}'>
<td><input type="checkbox" class="row-check"></td>
<td>Storage connector unavailable</td>
<td><span class="alerts-pill high">high</span></td>
<td><span class="alerts-pill open">open</span></td>
<td>301</td>
<td>storage.connector.health_failed</td>
<td>today 14:08</td>
<td><button class="win98-button alerts-row-button row-open" type="button">Open</button></td>
</tr>
<tr data-id="9" data-severity="medium" data-status="open" data-group="thumbnails" data-title="Thumbnail generation failed" data-description="Thumbnail generation failed for one uploaded image. Original file remains available." data-code="601" data-trace="thumbnail.generate.failed" data-time="today 13:40" data-metadata='{"box":"bx_49aa","file":"poster.png","worker":"thumb-2"}'>
<td><input type="checkbox" class="row-check"></td>
<td>Thumbnail generation failed</td>
<td><span class="alerts-pill medium">medium</span></td>
<td><span class="alerts-pill open">open</span></td>
<td>601</td>
<td>thumbnail.generate.failed</td>
<td>today 13:40</td>
<td><button class="win98-button alerts-row-button row-open" type="button">Open</button></td>
</tr>
<tr data-id="8" data-severity="low" data-status="acked" data-group="uploads" data-title="Large upload nearing account cap" data-description="A user is close to their daily upload budget." data-code="124" data-trace="upload.quota.nearing_cap" data-time="today 12:58" data-metadata='{"user":"geo","used":"44 GB","limit":"50 GB"}'>
<td><input type="checkbox" class="row-check"></td>
<td>Large upload nearing account cap</td>
<td><span class="alerts-pill low">low</span></td>
<td><span class="alerts-pill acked">acked</span></td>
<td>124</td>
<td>upload.quota.nearing_cap</td>
<td>today 12:58</td>
<td><button class="win98-button alerts-row-button row-open" type="button">Open</button></td>
</tr>
<tr data-id="7" data-severity="high" data-status="open" data-group="auth" data-title="Repeated admin login failures" data-description="Multiple failed admin login attempts were detected from the same source." data-code="211" data-trace="auth.admin.failed_login_burst" data-time="today 12:10" data-metadata='{"ip":"198.51.100.4","attempts":7,"window":"10m"}'>
<td><input type="checkbox" class="row-check"></td>
<td>Repeated admin login failures</td>
<td><span class="alerts-pill high">high</span></td>
<td><span class="alerts-pill open">open</span></td>
<td>211</td>
<td>auth.admin.failed_login_burst</td>
<td>today 12:10</td>
<td><button class="win98-button alerts-row-button row-open" type="button">Open</button></td>
</tr>
<tr data-id="6" data-severity="medium" data-status="acked" data-group="storage" data-title="Cleanup skipped locked files" data-description="Cleanup job encountered locked files and skipped them." data-code="342" data-trace="cleanup.skip.locked_files" data-time="today 10:22" data-metadata='{"count":3,"connector":"local-main"}'>
<td><input type="checkbox" class="row-check"></td>
<td>Cleanup skipped locked files</td>
<td><span class="alerts-pill medium">medium</span></td>
<td><span class="alerts-pill acked">acked</span></td>
<td>342</td>
<td>cleanup.skip.locked_files</td>
<td>today 10:22</td>
<td><button class="win98-button alerts-row-button row-open" type="button">Open</button></td>
</tr>
<tr data-id="5" data-severity="low" data-status="closed" data-group="uploads" data-title="Archive completed with warnings" data-description="ZIP archive completed but excluded one unreadable temporary file." data-code="145" data-trace="archive.complete.with_warning" data-time="today 09:02" data-metadata='{"box":"bx_3901","skipped":1}'>
<td><input type="checkbox" class="row-check"></td>
<td>Archive completed with warnings</td>
<td><span class="alerts-pill low">low</span></td>
<td><span class="alerts-pill closed">closed</span></td>
<td>145</td>
<td>archive.complete.with_warning</td>
<td>today 09:02</td>
<td><button class="win98-button alerts-row-button row-open" type="button">Open</button></td>
</tr>
<tr data-id="4" data-severity="medium" data-status="open" data-group="uploads" data-title="Upload session expired mid-transfer" data-description="A long-running upload lost session validity before final commit." data-code="156" data-trace="upload.session.expired_mid_transfer" data-time="yesterday" data-metadata='{"user":"teo","partial_bytes":"1.2 GB"}'>
<td><input type="checkbox" class="row-check"></td>
<td>Upload session expired mid-transfer</td>
<td><span class="alerts-pill medium">medium</span></td>
<td><span class="alerts-pill open">open</span></td>
<td>156</td>
<td>upload.session.expired_mid_transfer</td>
<td>yesterday</td>
<td><button class="win98-button alerts-row-button row-open" type="button">Open</button></td>
</tr>
<tr data-id="3" data-severity="low" data-status="closed" data-group="thumbnails" data-title="Thumbnail worker restarted" data-description="Thumbnail worker restarted after a normal watchdog recycle." data-code="602" data-trace="thumbnail.worker.restarted" data-time="yesterday" data-metadata='{"worker":"thumb-1","reason":"watchdog"}'>
<td><input type="checkbox" class="row-check"></td>
<td>Thumbnail worker restarted</td>
<td><span class="alerts-pill low">low</span></td>
<td><span class="alerts-pill closed">closed</span></td>
<td>602</td>
<td>thumbnail.worker.restarted</td>
<td>yesterday</td>
<td><button class="win98-button alerts-row-button row-open" type="button">Open</button></td>
</tr>
<tr data-id="2" data-severity="medium" data-status="acked" data-group="auth" data-title="User invited without email delivery confirmation" data-description="Invite creation succeeded but email delivery confirmation was not returned." data-code="224" data-trace="auth.invite.delivery_unknown" data-time="2 days ago" data-metadata='{"user":"reo","provider":"smtp-primary"}'>
<td><input type="checkbox" class="row-check"></td>
<td>User invited without email delivery confirmation</td>
<td><span class="alerts-pill medium">medium</span></td>
<td><span class="alerts-pill acked">acked</span></td>
<td>224</td>
<td>auth.invite.delivery_unknown</td>
<td>2 days ago</td>
<td><button class="win98-button alerts-row-button row-open" type="button">Open</button></td>
</tr>
<tr data-id="1" data-severity="low" data-status="closed" data-group="storage" data-title="Secondary connector caught up" data-description="Delayed sync on a secondary storage connector completed successfully." data-code="329" data-trace="storage.secondary.sync_recovered" data-time="2 days ago" data-metadata='{"connector":"bucket-archive","lag":"0"}'>
<td><input type="checkbox" class="row-check"></td>
<td>Secondary connector caught up</td>
<td><span class="alerts-pill low">low</span></td>
<td><span class="alerts-pill closed">closed</span></td>
<td>329</td>
<td>storage.secondary.sync_recovered</td>
<td>2 days ago</td>
<td><button class="win98-button alerts-row-button row-open" type="button">Open</button></td>
</tr>
</tbody>
</table>
</div>
</div>
</section>
</div>
<div class="alerts-column alerts-column-side">
<section class="alerts-panel">
<div class="alerts-panel-header">
<div class="alerts-panel-title">Alert details <span class="alerts-panel-sub">selected alert preview</span></div>
</div>
<div class="alerts-panel-body">
<ul class="alerts-info-list">
<li class="alerts-info-item"><strong>Title</strong><span id="detail-title">Storage connector unavailable</span></li>
<li class="alerts-info-item"><strong>Severity</strong><span id="detail-severity">high</span></li>
<li class="alerts-info-item"><strong>Status</strong><span id="detail-status">open</span></li>
<li class="alerts-info-item"><strong>Code</strong><span id="detail-code">301</span></li>
<li class="alerts-info-item"><strong>Trace</strong><span id="detail-trace">storage.connector.health_failed</span></li>
<li class="alerts-info-item"><strong>Created</strong><span id="detail-time">today 14:08</span></li>
<li class="alerts-info-item"><strong>Description</strong><span id="detail-description">Primary local storage connector failed health check and new writes are paused.</span></li>
</ul>
<div class="alerts-mini-note">
TO-DO: later, limited alert access should only show alerts scoped to the users permissions, tags, or groups.
</div>
</div>
</section>
<section class="alerts-panel">
<div class="alerts-panel-header">
<div class="alerts-panel-title">Metadata <span class="alerts-panel-sub">simple JSON preview</span></div>
<div class="alerts-panel-tools">
<button class="win98-button alerts-tool-button" type="button" data-command="copy-meta">Copy</button>
</div>
</div>
<div class="alerts-panel-body">
<pre class="alerts-json-box" id="detail-metadata">{
"connector": "local-main",
"mode": "read_only",
"retry_in": "30s"
}</pre>
</div>
</section>
<section class="alerts-panel alerts-actions-panel">
<div class="alerts-panel-header">
<div class="alerts-panel-title">Actions <span class="alerts-panel-sub">simple first version</span></div>
</div>
<div class="alerts-panel-body">
<div class="alerts-action-stack">
<button class="win98-button alerts-action-button" type="button" data-command="ack">Acknowledge selected</button>
<button class="win98-button alerts-action-button" type="button" data-command="close">Close selected</button>
<button class="win98-button alerts-action-button" type="button" data-command="refresh">Refresh alerts</button>
</div>
<div class="alerts-mini-note">
CURRENTLY_MOCKED_LEAVE_AS_IS: alerts use a lightweight lifecycle for now: open, acknowledged, closed.
</div>
</div>
</section>
</div>
</section>
</div>
<div class="alerts-footerbar">
<div class="alerts-footer-left">
<span class="alerts-status-pill" id="selected-count">Selected: 0</span>
<span class="alerts-status-pill">10 mocked alerts</span>
</div>
<div class="alerts-footer-right">
<button class="win98-button alerts-footer-button" type="button" data-command="ack">Acknowledge</button>
<button class="win98-button alerts-footer-button" type="button" data-command="close">Close</button>
</div>
</div>
</div>
</div>
</div>
<div class="toast" id="toast" role="status" aria-live="polite"></div>
<script src="/static/js/warpbox-ui.js"></script>
<script src="/static/js/admin/alerts.js"></script>
</body>
</html>
{{ end }}