2024-02-11 19:28:00 +00:00
|
|
|
package templates
|
2024-02-10 11:59:58 +00:00
|
|
|
|
|
|
|
import (
|
|
|
|
"embed"
|
2024-02-20 10:24:04 +00:00
|
|
|
"io"
|
2024-05-29 14:39:50 +00:00
|
|
|
"io/fs"
|
|
|
|
"log/slog"
|
2024-02-22 19:20:34 +00:00
|
|
|
"strings"
|
2024-02-20 10:24:04 +00:00
|
|
|
"text/template"
|
2024-02-29 14:12:20 +00:00
|
|
|
"time"
|
2024-02-20 10:24:04 +00:00
|
|
|
|
|
|
|
"github.com/labstack/echo/v4"
|
2024-05-23 16:33:30 +00:00
|
|
|
"github.com/mentos1386/zdravko/pkg/script"
|
2024-02-10 11:59:58 +00:00
|
|
|
)
|
|
|
|
|
2024-02-11 10:56:21 +00:00
|
|
|
//go:embed *
|
2024-02-20 10:24:04 +00:00
|
|
|
var templates embed.FS
|
|
|
|
|
|
|
|
const base = "components/base.tmpl"
|
|
|
|
|
|
|
|
type Templates struct {
|
2024-05-29 14:39:50 +00:00
|
|
|
logger *slog.Logger
|
2024-02-20 10:24:04 +00:00
|
|
|
templates map[string]*template.Template
|
|
|
|
}
|
|
|
|
|
2024-06-07 09:43:32 +00:00
|
|
|
func load(version string, files ...string) *template.Template {
|
2024-02-20 10:24:04 +00:00
|
|
|
files = append(files, base)
|
2024-02-22 19:20:34 +00:00
|
|
|
|
|
|
|
t := template.New("default").Funcs(
|
|
|
|
template.FuncMap{
|
2024-05-27 18:44:40 +00:00
|
|
|
"MathDivide": func(a, b int) float64 {
|
|
|
|
if b == 0 {
|
|
|
|
return 0
|
|
|
|
}
|
|
|
|
return float64(a) / float64(b)
|
|
|
|
},
|
2024-05-25 17:52:37 +00:00
|
|
|
"DurationRoundSecond": func(d time.Duration) time.Duration {
|
|
|
|
return d.Round(time.Second)
|
|
|
|
},
|
|
|
|
"DurationRoundMillisecond": func(d time.Duration) time.Duration {
|
|
|
|
return d.Round(time.Millisecond)
|
|
|
|
},
|
2024-05-14 19:38:45 +00:00
|
|
|
"StringsJoin": strings.Join,
|
|
|
|
"Now": time.Now,
|
|
|
|
"ScriptUnescapeString": script.UnescapeString,
|
|
|
|
"ScriptEscapeString": script.EscapeString,
|
2024-06-07 09:43:32 +00:00
|
|
|
"Version": func() string {
|
|
|
|
return version
|
|
|
|
},
|
2024-02-22 19:20:34 +00:00
|
|
|
})
|
|
|
|
|
|
|
|
return template.Must(t.ParseFS(templates, files...))
|
2024-02-20 10:24:04 +00:00
|
|
|
}
|
|
|
|
|
2024-06-07 09:43:32 +00:00
|
|
|
func loadSettings(version string, files ...string) *template.Template {
|
2024-02-20 10:24:04 +00:00
|
|
|
files = append(files, "components/settings.tmpl")
|
2024-06-07 09:43:32 +00:00
|
|
|
return load(version, files...)
|
2024-02-20 10:24:04 +00:00
|
|
|
}
|
|
|
|
|
2024-06-07 09:43:32 +00:00
|
|
|
func NewTemplates(version string, logger *slog.Logger) (*Templates, error) {
|
2024-05-29 14:39:50 +00:00
|
|
|
t := Templates{
|
|
|
|
logger: logger,
|
|
|
|
templates: map[string]*template.Template{},
|
2024-02-20 10:24:04 +00:00
|
|
|
}
|
2024-05-29 14:39:50 +00:00
|
|
|
|
|
|
|
err := fs.WalkDir(templates, "pages", func(path string, d fs.DirEntry, err error) error {
|
|
|
|
if err != nil {
|
|
|
|
return err
|
|
|
|
}
|
|
|
|
if strings.Contains(path, ".tmpl") {
|
|
|
|
t.logger.Debug("Loading template", "path", path)
|
|
|
|
pathWithoutPrefix := strings.TrimPrefix(path, "pages/")
|
|
|
|
|
|
|
|
if strings.Contains(path, "settings") {
|
2024-06-07 09:43:32 +00:00
|
|
|
t.templates[pathWithoutPrefix] = loadSettings(version, path)
|
2024-05-29 14:39:50 +00:00
|
|
|
} else {
|
2024-06-07 09:43:32 +00:00
|
|
|
t.templates[pathWithoutPrefix] = load(version, path)
|
2024-05-29 14:39:50 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
return nil
|
|
|
|
})
|
|
|
|
|
|
|
|
return &t, err
|
2024-02-20 10:24:04 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
func (t *Templates) Render(w io.Writer, name string, data interface{}, c echo.Context) error {
|
|
|
|
if t.templates[name] == nil {
|
2024-05-29 14:39:50 +00:00
|
|
|
t.logger.Error("template not found", "template", name)
|
2024-02-20 10:24:04 +00:00
|
|
|
return echo.ErrNotFound
|
|
|
|
}
|
|
|
|
|
|
|
|
err := t.templates[name].ExecuteTemplate(w, "base", data)
|
|
|
|
if err != nil {
|
2024-05-29 14:39:50 +00:00
|
|
|
t.logger.Error("error rendering template", "template", err)
|
2024-02-20 10:24:04 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
return err
|
|
|
|
}
|