package web
import (
"embed"
"fmt"
"html/template"
"time"
)
//go:embed templates/*.html templates/fragments/*.html
var templateFS embed.FS
type templateSet struct {
dashboard *template.Template
sessionDetail *template.Template
}
func templateFuncMap() template.FuncMap {
return template.FuncMap{
"formatTime": func(t time.Time) string {
return t.Format("2006-01-02 15:04:05 UTC")
},
"truncateID": func(id string) string {
if len(id) > 8 {
return id[:8]
}
return id
},
"derefTime": func(t *time.Time) time.Time {
if t == nil {
return time.Time{}
}
return *t
},
"derefFloat": func(f *float64) float64 {
if f == nil {
return 0
}
return *f
},
"formatScore": func(f *float64) string {
if f == nil {
return "-"
}
return fmt.Sprintf("%.0f%%", *f*100)
},
"derefString": func(s *string) string {
if s == nil {
return ""
}
return *s
},
"truncateCommand": func(s string) string {
if len(s) > 50 {
return s[:50] + "..."
}
return s
},
"formatBytes": func(b int64) string {
const (
kb = 1024
mb = 1024 * kb
)
switch {
case b >= mb:
return fmt.Sprintf("%.1f MB", float64(b)/float64(mb))
case b >= kb:
return fmt.Sprintf("%.1f KB", float64(b)/float64(kb))
default:
return fmt.Sprintf("%d B", b)
}
},
}
}
func loadTemplates() (*templateSet, error) {
funcMap := templateFuncMap()
dashboard, err := template.New("").Funcs(funcMap).ParseFS(templateFS,
"templates/layout.html",
"templates/dashboard.html",
"templates/fragments/stats.html",
"templates/fragments/active_sessions.html",
"templates/fragments/recent_sessions.html",
)
if err != nil {
return nil, fmt.Errorf("parsing dashboard templates: %w", err)
}
sessionDetail, err := template.New("").Funcs(funcMap).ParseFS(templateFS,
"templates/layout.html",
"templates/session_detail.html",
)
if err != nil {
return nil, fmt.Errorf("parsing session detail templates: %w", err)
}
return &templateSet{
dashboard: dashboard,
sessionDetail: sessionDetail,
}, nil
}