hub: shared host_detail_body sub-template + customer Host tab (v0.47.0 part 3)

- host_detail_body.html: {{define}}'d body sections extracted from
  host_detail.html; the standalone page is now chrome + the sub-template
- hosts.go: hostDetailData(host, r) view-model builder extracted from
  handleHostDetail (reused by both surfaces)
- store: ListHostsByCustomer (host_id order; the Host tab is a list by
  design - N hosts for a future HA cluster)
- customer Host tab renders one host_detail_body per host + cross-link;
  empty state when no host is enrolled
- tests: TestTemplates_CustomerHostTab(+_Empty), TestListHostsByCustomer

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01Vvz1NCu22p8dGkRCpeX9re
This commit is contained in:
2026-07-11 21:17:44 +02:00
parent 9f29bf34c0
commit ae950e5933
8 changed files with 400 additions and 242 deletions
@@ -862,14 +862,21 @@
</div>
<!-- ═══ Host ═══ -->
<!-- ═══ Host ═══ (a LIST by design — 1 host today, N for a later HA cluster) -->
<div class="tab-panel" data-tab="host">
{{if .Hosts}}
{{range .Hosts}}
<p style="margin: 0 0 0.5rem;"><a href="/hosts/{{.HostID}}" class="back-link">Open host page: {{.HostID}} &rarr;</a></p>
{{template "host_detail_body" .}}
{{end}}
{{else}}
<section class="card">
<div class="empty-state" style="border: none;">
<p>No host enrolled yet.</p>
<p class="hint">A host appears here once it enrolls via the Day-0 bootstrap.</p>
</div>
</section>
{{end}}
</div>
<footer>