app/format, ui/jobs_view: DisplayStats summary + Statistics detail row (T2.6, T2.7)

Add DisplayStats to format.go: returns "No runs recorded" when RunCount is
zero, otherwise a one-line "N runs, M failed, last X ms, avg Y ms, max Z ms"
summary.  Wire a Statistics detail row into the jobs panel that refreshes via
updateDetails alongside the other runtime fields.

Tests: TestDisplayStats (nil/zero/normal/no-fail), TestUpdateStats (three
sequential fake runs through updateStats verifying all aggregate fields), and
five seed tests in runner/seed_test.go covering basic aggregation,
duration-less legacy logs, maxFiles capping, missing directory, and
unmatched log files.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
mixeme
2026-06-24 08:24:48 +03:00
parent 6c69f323bd
commit 886d0d9caa
6 changed files with 231 additions and 2 deletions
+4
View File
@@ -65,6 +65,7 @@ func newJobsView(w fyne.Window, svc *app.Service) (fyne.CanvasObject, func()) {
lastRunLabel := newJobDetailLabel(selectedRuntime.LastRun)
nextRunLabel := newJobDetailLabel(selectedRuntime.NextRun)
stateLabel := newJobDetailLabel(selectedRuntime.LastState)
statsLabel := newJobDetailLabel(app.DisplayStats(selectedRuntime))
schedulerState := widget.NewLabel("Scheduler running")
commandOutput := widget.NewTextGrid()
commandOutput.SetText(selectedRuntime.Output)
@@ -100,6 +101,7 @@ func newJobsView(w fyne.Window, svc *app.Service) (fyne.CanvasObject, func()) {
lastRunLabel.SetText("")
nextRunLabel.SetText("")
stateLabel.SetText("")
statsLabel.SetText("")
commandOutput.SetText("")
selectedLogs = nil
return
@@ -116,6 +118,7 @@ func newJobsView(w fyne.Window, svc *app.Service) (fyne.CanvasObject, func()) {
lastRunLabel.SetText(rt.LastRun)
nextRunLabel.SetText(rt.NextRun)
stateLabel.SetText(rt.LastState)
statsLabel.SetText(app.DisplayStats(rt))
commandOutput.SetText(rt.Output)
selectedLogs = append(selectedLogs[:0], rt.Logs...)
}
@@ -343,6 +346,7 @@ func newJobsView(w fyne.Window, svc *app.Service) (fyne.CanvasObject, func()) {
detailRow("Last run", lastRunLabel),
detailRow("Next run", nextRunLabel),
detailRow("State", stateLabel),
detailRow("Statistics", statsLabel),
widget.NewSeparator(),
widget.NewLabelWithStyle("Command output", fyne.TextAlignLeading, fyne.TextStyle{Bold: true}),
commandOutputScroll,