Files
mangaBookmark/backend/internal/web/templates/lanes.html
T
sulthan f85908d3b4 web: a failure names itself on the page (issue #167)
The Series list row's fact line gains the failure word and its age in one
mark before the Notes chips, spelled through outcomeWord — the one
vocabulary shared with the Lanes chips. The detail page adds one sentence
beside the correction control while a Reader's number stands behind a
failure past the owner window, without naming the Reader. Each Lanes Site
name is a plain link to that Site's failing Series; the outcome chips stay
unlinked, and outcomeChips records why the promise is withdrawn.
2026-08-23 00:36:12 +07:00

60 lines
3.2 KiB
HTML

{{/* Poll Lane status: one row per Site's latest durable pass, refreshing
itself so a run can be watched rather than sampled by reloading. The
refresh is one attribute on the fragment root and the endpoint answers
with this same fragment, so the swap replaces the element that asked.
Every figure is read from poll_passes, never from a running poller: a
restart answers from the database the moment it is up (issue #145). The
browser fact is a deployment-config fact plus a reachability derived from
the pass log; the cause chips and the state phrase are decided in Go,
this template only prints them. */}}
{{define "lanes"}}
<section class="lanes" id="lanes"
hx-get="/ui/admin/lanes" hx-trigger="every 30s" hx-swap="outerHTML">
<div class="sechead">
<h2 class="sec">Poll Lanes</h2>
<p class="statusline">
{{if .PollerOff}}Polling: <span class="mark-faint">off</span>
{{else}}Browser: {{if not .BrowserConfigured}}<span class="mark-faint">not configured</span>{{else if .BrowserReachable}}<span class="mark mark-strong">reachable</span>{{else}}<span class="mark bad">unreachable</span>{{end}}{{end}}
</p>
</div>
{{if .Rows}}
<div class="tbl lanes">
<div class="thead">
<span>Site</span><span>Due</span><span>Checked</span><span>Gap</span>
<span>Last pass</span><span>Outcomes · state</span><span></span>
</div>
{{range .Rows}}
<div class="trow{{if .Attention}} attention{{end}}">
<a class="c-site" href="{{.FailingHref}}">{{.Site}}</a>
<span>{{.Due}}</span>
<span>{{.Checked}}</span>
<span>{{.Gap}}</span>
<span>ran {{.Ran}}</span>
<span class="c-skip">{{if .HasChips}}{{range $i, $c := .Chips}}{{if $i}}<span class="mark-faint"> · </span>{{end}}<span class="mark">{{$c.Name}} {{$c.Count}}</span>{{end}}{{else}}<span class="mark-faint">none observed</span>{{end}}{{if .StatePhrase}} · <span class="{{if .StateGood}}ok{{else}}bad{{end}}">{{.StatePhrase}}</span>{{end}}</span>
{{/* The pause control lives in the one slot the design leaves for it:
a running Lane offers the three durations and Pause; a paused Lane
offers Resume in the same place. Pause is not destruction — it
takes nothing away and reverses in one press — so neither wears a
confirm row or the danger accent. The form wraps the select so the
offered duration travels with the press. */}}
<span class="c-ctrl">{{if .Paused}}<span class="pausebar">
<form hx-post="/admin/lanes/{{.Site}}/resume" hx-target="#lanes" hx-swap="outerHTML">
<button type="submit" class="ghost">Resume</button>
</form>
</span>{{else}}<span class="pausebar">
<form hx-post="/admin/lanes/{{.Site}}/pause" hx-target="#lanes" hx-swap="outerHTML">
<select name="duration" aria-label="Pause duration">
<option>1h</option><option selected>6h</option><option>24h</option>
</select>
<button type="submit" class="ghost">Pause</button>
</form>
</span>{{end}}</span>
</div>
{{end}}
</div>
{{else}}
<p class="empty">No data yet — no Lane has recorded a pass.</p>
{{end}}
</section>
{{end}}