111 lines
2.5 KiB
Go
111 lines
2.5 KiB
Go
package web
|
|
|
|
import (
|
|
"fmt"
|
|
"html/template"
|
|
"io"
|
|
"strings"
|
|
"time"
|
|
|
|
assets "github.com/mattnite/cairn/web"
|
|
)
|
|
|
|
var funcMap = template.FuncMap{
|
|
"timeAgo": func(t time.Time) string {
|
|
d := time.Since(t)
|
|
switch {
|
|
case d < time.Minute:
|
|
return "just now"
|
|
case d < time.Hour:
|
|
return fmt.Sprintf("%dm ago", int(d.Minutes()))
|
|
case d < 24*time.Hour:
|
|
return fmt.Sprintf("%dh ago", int(d.Hours()))
|
|
default:
|
|
return fmt.Sprintf("%dd ago", int(d.Hours()/24))
|
|
}
|
|
},
|
|
"shortSHA": func(sha string) string {
|
|
if len(sha) > 8 {
|
|
return sha[:8]
|
|
}
|
|
return sha
|
|
},
|
|
"formatSize": func(size int64) string {
|
|
switch {
|
|
case size < 1024:
|
|
return fmt.Sprintf("%d B", size)
|
|
case size < 1024*1024:
|
|
return fmt.Sprintf("%.1f KB", float64(size)/1024)
|
|
default:
|
|
return fmt.Sprintf("%.1f MB", float64(size)/(1024*1024))
|
|
}
|
|
},
|
|
"deref": func(s *string) string {
|
|
if s == nil {
|
|
return ""
|
|
}
|
|
return *s
|
|
},
|
|
"truncate": func(s string, n int) string {
|
|
if len(s) <= n {
|
|
return s
|
|
}
|
|
return s[:n] + "..."
|
|
},
|
|
"join": strings.Join,
|
|
"derefTime": func(t *time.Time) time.Time {
|
|
if t == nil {
|
|
return time.Time{}
|
|
}
|
|
return *t
|
|
},
|
|
}
|
|
|
|
type Templates struct {
|
|
layout *template.Template
|
|
pages map[string]*template.Template
|
|
}
|
|
|
|
func LoadTemplates() (*Templates, error) {
|
|
layout, err := template.New("layout").Funcs(funcMap).ParseFS(assets.Assets, "templates/layout.html")
|
|
if err != nil {
|
|
return nil, fmt.Errorf("parsing layout: %w", err)
|
|
}
|
|
|
|
pageFiles := []string{
|
|
"templates/pages/index.html",
|
|
"templates/pages/artifacts.html",
|
|
"templates/pages/artifact_detail.html",
|
|
"templates/pages/repos.html",
|
|
"templates/pages/crashgroups.html",
|
|
"templates/pages/crashgroup_detail.html",
|
|
"templates/pages/search.html",
|
|
"templates/pages/regression.html",
|
|
"templates/pages/targets.html",
|
|
"templates/pages/target_detail.html",
|
|
"templates/pages/run_detail.html",
|
|
}
|
|
|
|
pages := map[string]*template.Template{}
|
|
for _, pf := range pageFiles {
|
|
name := strings.TrimPrefix(pf, "templates/pages/")
|
|
name = strings.TrimSuffix(name, ".html")
|
|
|
|
t, err := template.Must(layout.Clone()).ParseFS(assets.Assets, pf)
|
|
if err != nil {
|
|
return nil, fmt.Errorf("parsing page %s: %w", name, err)
|
|
}
|
|
pages[name] = t
|
|
}
|
|
|
|
return &Templates{layout: layout, pages: pages}, nil
|
|
}
|
|
|
|
func (t *Templates) Render(w io.Writer, page string, data any) error {
|
|
tmpl, ok := t.pages[page]
|
|
if !ok {
|
|
return fmt.Errorf("template %q not found", page)
|
|
}
|
|
return tmpl.ExecuteTemplate(w, "layout", data)
|
|
}
|