17ec55cb85
Remove ~126 lines of orphaned CSS from tile slim-down and old detail layout. Consolidate 4 duplicate duration formatters into shared elapsed()/fmtElapsed() helpers. Break 160-line Result handler into focused sub-functions. Implement real Hub.Shutdown() (was a no-op). Standardize agent error responses to JSON. Replace panic() in router init with error return. Extract magic numbers as named constants. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
60 lines
1.8 KiB
Plaintext
60 lines
1.8 KiB
Plaintext
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 <div> 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) {
|
||
<div
|
||
id={ fmt.Sprintf("substep-%d-%s-%d", ss.RunID, ss.StageName, ss.Ordinal) }
|
||
class={ "substep", "substep-" + string(ss.State) }
|
||
sse-swap={ fmt.Sprintf("substep-%d-%s-%d", ss.RunID, ss.StageName, ss.Ordinal) }
|
||
hx-swap="outerHTML"
|
||
>
|
||
<span class={ "substep-badge", "substep-badge-" + string(ss.State) }>{ subStepMarker(ss.State) }</span>
|
||
<span class="substep-name">{ ss.Name }</span>
|
||
<span class="substep-duration">{ subStepDuration(ss) }</span>
|
||
</div>
|
||
}
|
||
|
||
// 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()
|
||
}
|