feat(alerts): live refresh table with toggle + severity colour cues #11
@@ -14,10 +14,11 @@ import (
|
|||||||
)
|
)
|
||||||
|
|
||||||
type alertsPage struct {
|
type alertsPage struct {
|
||||||
Filter store.AlertFilter
|
Filter store.AlertFilter
|
||||||
Alerts []store.Alert
|
Alerts []store.Alert
|
||||||
Counts alertCounts
|
Counts alertCounts
|
||||||
HostNames map[string]string // host_id → name for table rendering
|
HostNames map[string]string // host_id → name for table rendering
|
||||||
|
RefreshURL string // self-URL for the live-refresh poll
|
||||||
}
|
}
|
||||||
|
|
||||||
type alertCounts struct {
|
type alertCounts struct {
|
||||||
@@ -51,7 +52,12 @@ func (s *Server) handleUIAlerts(w stdhttp.ResponseWriter, r *stdhttp.Request) {
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
page := alertsPage{Filter: f, Alerts: alerts, HostNames: map[string]string{}}
|
page := alertsPage{
|
||||||
|
Filter: f,
|
||||||
|
Alerts: alerts,
|
||||||
|
HostNames: map[string]string{},
|
||||||
|
RefreshURL: r.URL.RequestURI(),
|
||||||
|
}
|
||||||
if hosts, err := s.deps.Store.ListHosts(r.Context()); err == nil {
|
if hosts, err := s.deps.Store.ListHosts(r.Context()); err == nil {
|
||||||
for _, h := range hosts {
|
for _, h := range hosts {
|
||||||
page.HostNames[h.ID] = h.Name
|
page.HostNames[h.ID] = h.Name
|
||||||
|
|||||||
@@ -90,8 +90,18 @@
|
|||||||
</form>
|
</form>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
{{/* alerts table */}}
|
{{/* alerts table — polled every 15s while the tab is visible.
|
||||||
<div class="panel mt-3.5 rounded-[7px] overflow-hidden">
|
hx-get re-fetches the same URL (so filter querystring is preserved)
|
||||||
|
and hx-select pulls just this element out of the full response,
|
||||||
|
replacing the live one. Pauses automatically when the tab is
|
||||||
|
backgrounded so we're not burning CPU on inactive tabs.
|
||||||
|
The polling lives here (not on the page root) so the filter strip
|
||||||
|
and header don't flash on each tick. */}}
|
||||||
|
<div id="alerts-table" class="panel mt-3.5 rounded-[7px] overflow-hidden"
|
||||||
|
hx-get="{{$page.RefreshURL}}"
|
||||||
|
hx-trigger="every 15s [document.visibilityState==='visible']"
|
||||||
|
hx-select="#alerts-table"
|
||||||
|
hx-swap="outerHTML">
|
||||||
|
|
||||||
{{/* header row */}}
|
{{/* header row */}}
|
||||||
<div class="alert-row head">
|
<div class="alert-row head">
|
||||||
@@ -101,7 +111,9 @@
|
|||||||
<div>Message</div>
|
<div>Message</div>
|
||||||
<div>Raised</div>
|
<div>Raised</div>
|
||||||
<div>Last seen</div>
|
<div>Last seen</div>
|
||||||
<div></div>
|
<div>
|
||||||
|
<span class="text-ink-fade" style="font-size: 10px;" title="auto-refresh every 15s">live ●</span>
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
{{if eq (len $page.Alerts) 0}}
|
{{if eq (len $page.Alerts) 0}}
|
||||||
|
|||||||
Reference in New Issue
Block a user