package webui
import (
"context"
"database/sql"
"fmt"
"html"
"io"
"strings"
"time"
"github.com/a-h/templ"
"satoru/internal/store"
)
type RuntimeCheck struct {
Name string
Installed bool
Details string
}
type WorkflowStage struct {
Title string
Description string
}
type DashboardData struct {
Now time.Time
User store.User
Sites []store.Site
RuntimeChecks []RuntimeCheck
WorkflowStages []WorkflowStage
FlashMessage string
}
func Dashboard(data DashboardData) templ.Component {
return templ.ComponentFunc(func(_ context.Context, w io.Writer) error {
role := "Operator"
if data.User.IsAdmin {
role = "Admin"
}
var checks strings.Builder
for _, c := range data.RuntimeChecks {
status := "missing"
if c.Installed {
status = "installed"
}
checks.WriteString(fmt.Sprintf(`
%s%s
`,
status,
html.EscapeString(c.Name),
html.EscapeString(c.Details)))
}
var flows strings.Builder
for _, s := range data.WorkflowStages {
flows.WriteString(fmt.Sprintf(`
%s
%s
`,
html.EscapeString(s.Title),
html.EscapeString(s.Description)))
}
var sites strings.Builder
if len(data.Sites) == 0 {
sites.WriteString(`
No sites added yet. Add your first Linux SSH site below.
`)
}
for _, site := range data.Sites {
last := "Never run"
if site.LastRunAt.Valid {
last = site.LastRunAt.Time.Local().Format(time.RFC1123)
}
runStatus := "pending"
if site.LastRunStatus.Valid {
runStatus = site.LastRunStatus.String
}
runOutput := "(no output yet)"
if site.LastRunOutput.Valid && strings.TrimSpace(site.LastRunOutput.String) != "" {
runOutput = site.LastRunOutput.String
}
scanState := "pending"
if site.LastScanState.Valid && site.LastScanState.String != "" {
scanState = site.LastScanState.String
}
lastScan := "Never"
if site.LastScanAt.Valid {
lastScan = site.LastScanAt.Time.Local().Format(time.RFC1123)
}
scanNotes := "No scan yet."
if site.LastScanNotes.Valid && site.LastScanNotes.String != "" {
scanNotes = site.LastScanNotes.String
}
var targets strings.Builder
if len(site.Targets) == 0 {
targets.WriteString(`
none(no targets)
`)
}
for _, t := range site.Targets {
sizeOrErr := "size pending"
if t.LastError.Valid && t.LastError.String != "" {
sizeOrErr = "error: " + t.LastError.String
} else if t.LastSizeByte.Valid {
sizeOrErr = formatBytes(t.LastSizeByte.Int64)
}
targets.WriteString(fmt.Sprintf(`