package templates
import (
"bytes"
"context"
"fmt"
"vetting/internal/model"
)
func subStepDuration(ss model.SubStep) string {
if d := elapsed(ss.StartedAt, ss.CompletedAt); d >= 0 {
return fmtElapsed(d, false)
}
return ""
}
// subStepMarker mirrors stageMarker — a single-char glyph used inside the
// state badge. StageState values reused verbatim for sub-steps.
func subStepMarker(s model.StageState) string {
switch s {
case model.StagePassed:
return "✓"
case model.StageFailed:
return "!"
case model.StageRunning:
return "●"
case model.StageSkipped:
return "–"
}
return ""
}
// SubStepRow renders one sub-step entry for the expanded-step pane. The
// outer
carries the sse-swap target keyed by (runID, stage,
// ordinal) so the orchestrator's PublishSubStepUpdate can swap just this
// row without touching the rest of the stage panel. hx-swap="outerHTML"
// keeps the attributes intact across repeat swaps.
templ SubStepRow(ss model.SubStep) {
{ subStepMarker(ss.State) }
{ ss.Name }
{ subStepDuration(ss) }
}
// RenderSubStepRowString is the one-shot renderer the orchestrator
// registers as SubStepRenderer so it can emit substep-* SSE payloads
// without importing the templates package directly.
func RenderSubStepRowString(ss model.SubStep) string {
var buf bytes.Buffer
_ = SubStepRow(ss).Render(context.Background(), &buf)
return buf.String()
}