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
ScanInterval time.Duration
User store.User
Sites []store.Site
RuntimeChecks []RuntimeCheck
WorkflowStages []WorkflowStage
FlashMessage string
ShowB2InitButton bool
B2Repo string
ResticRepoPath string
ResticRepoSize string
ResticSnapshots []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
var siteNav strings.Builder
if len(data.Sites) == 0 {
sites.WriteString(`
No sites added yet. Add your first Linux SSH site below.
`)
siteNav.WriteString(`
No sites yet.
`)
}
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
}
siteNav.WriteString(fmt.Sprintf(``,
site.ID,
html.EscapeString(site.SSHUser),
html.EscapeString(site.Host),
html.EscapeString(runStatus),
site.ID,
html.EscapeString(runStatus),
html.EscapeString(scanState),
site.ID,
html.EscapeString(scanState),
))
var targets strings.Builder
if len(site.Targets) == 0 {
targets.WriteString(`
`, html.EscapeString(formatFlash(data.FlashMessage)))
}
b2Init := ""
if data.ShowB2InitButton {
b2Init = fmt.Sprintf(``, html.EscapeString(data.B2Repo))
}
var resticSnaps strings.Builder
for _, s := range data.ResticSnapshots {
resticSnaps.WriteString(fmt.Sprintf(`
%s
`, html.EscapeString(s)))
}
if len(data.ResticSnapshots) == 0 {
resticSnaps.WriteString(`