package templates import ( "fmt" "vetting/internal/model" "vetting/internal/store" ) // HostDetailData is the full payload the detail handler hands to the // HostDetail template. Tile carries host + latest-run enrichment (same // shape the dashboard tile uses), Stages/SpecDiffs drive the pipeline // and diff list. LogReplay is the pre-rendered history fragment // produced by logs.Hub.Replay on the initial page render so the operator // sees prior output without waiting for a fresh SSE event. type HostDetailData struct { Tile TileData Stages []model.Stage SpecDiffs []model.SpecDiff LogReplay string } templ HostDetail(d HostDetailData) { @Layout(d.Tile.Host.Name) {

{ d.Tile.Host.Name }

{ lastSeenLabel(d.Tile.LastSeenAt) } { tileStatus(d.Tile.Latest) }
MAC
{ d.Tile.Host.MAC }
WoL
{ fmt.Sprintf("%s:%d", d.Tile.Host.WoLBroadcastIP, d.Tile.Host.WoLPort) }
if d.Tile.Latest != nil && d.Tile.Latest.FailedStage != "" {
Failed at
{ d.Tile.Latest.FailedStage }
} if d.Tile.SpecDiffCritical > 0 {
Spec diffs
{ fmt.Sprintf("%d critical", d.Tile.SpecDiffCritical) }
}
if d.Tile.Latest != nil {

Pipeline

@Pipeline(BuildPipeline(d.Tile.Latest, d.Stages))
} else {

Pipeline

@Pipeline(BuildPipeline(nil, nil))
} if d.Tile.Latest != nil && d.Tile.Latest.State == model.StateFailedHolding && d.Tile.Latest.HoldIP != "" {

Host is holding — SSH available

{ sshInvocation(d.Tile.HoldKeyPath, d.Tile.Latest.HoldIP) }
}

Actions

if canStart(d.Tile) {
} else if canStartIfOnline(d.Tile.Latest) { } else { } if canOverrideWipe(d.Tile.Latest) {
} if hasReport(d.Tile.Latest) { View report }
if len(d.SpecDiffs) > 0 {

Spec diffs ({ fmt.Sprintf("%d", len(d.SpecDiffs)) })

    for _, diff := range d.SpecDiffs {
  • { diff.Field }
    expected: { diff.Expected }
    actual: { diff.Actual }
  • }
} if d.Tile.Latest != nil { @LogTabs(d.Tile.Latest.ID, d.LogReplay) }

Host details

if d.Tile.Host.Notes != "" {

Notes

{ d.Tile.Host.Notes }

}

Expected spec

{ d.Tile.Host.ExpectedSpecYAML }
} } // hasCriticalDiff opens the spec-diff
by default when any // diff is critical — operator shouldn't have to click to see the blocker. func hasCriticalDiff(diffs []model.SpecDiff) bool { for _, d := range diffs { if d.Severity == "critical" && !d.Ignored { return true } } return false } // LogTabs renders an "All" tab plus one tab per stage in DefaultStageOrder. // Switching is pure CSS: hidden radio inputs drive sibling-selector // visibility on the panes. Each pane carries its own sse-swap target so // live events append only to the relevant pane. The All pane is seeded // with replay HTML so reload on an in-flight run still shows history. templ LogTabs(runID int64, replay string) {

Log

for _, s := range store.DefaultStageOrder { }
@templ.Raw(replay)
for _, s := range store.DefaultStageOrder {
}
}