package main import ( "embed" "fmt" "html/template" "log" "net/http" "sync" "time" ) // version is set at build time via -ldflags="-X main.version=..." var version = "dev" var importerMu sync.Mutex var importerRunning bool //go:embed index.html.tmpl var tmplFS embed.FS var tmpl = template.Must( template.New("index.html.tmpl"). Funcs(template.FuncMap{ // duration formats the elapsed time between two timestamps. "duration": func(start, end time.Time) string { if end.IsZero() { return "" } d := end.Sub(start).Round(time.Second) if d < time.Minute { return d.String() } return fmt.Sprintf("%dm %ds", int(d.Minutes()), int(d.Seconds())%60) }, // not is needed because Go templates have no built-in boolean negation. "not": func(b bool) bool { return !b }, // stepCell renders a uniform step status cell. // fatalStep is AlbumResult.FatalStep; when it matches the step's key // the cell is marked fatal rather than a warning. "stepCell": func(label string, s StepStatus, fatalStep string) template.HTML { var statusClass, statusText, errHTML string switch { case s.Err != nil && fatalStep != "" && stepKey(label) == fatalStep: statusClass = "step-fatal" statusText = "✗ fatal" errHTML = `` + template.HTMLEscapeString(s.Err.Error()) + `` case s.Err != nil: statusClass = "step-warn" statusText = "⚠ error" errHTML = `` + template.HTMLEscapeString(s.Err.Error()) + `` case s.Skipped: statusClass = "step-warn" statusText = "– skipped" default: statusClass = "step-ok" statusText = "✓ ok" } return template.HTML(`