Compare commits

...

2 Commits

Author SHA1 Message Date
77527bfb05 chore(templates): add better template loading
All checks were successful
continuous-integration/drone/push Build is passing
2024-05-27 20:20:47 -04:00
8de6fed5df fix(ui): document add styling 2024-05-27 14:01:10 -04:00
2 changed files with 78 additions and 38 deletions

View File

@ -6,6 +6,7 @@ import (
"html/template" "html/template"
"io/fs" "io/fs"
"net/http" "net/http"
"path"
"path/filepath" "path/filepath"
"strings" "strings"
"time" "time"
@ -15,6 +16,7 @@ import (
"github.com/gin-contrib/sessions/cookie" "github.com/gin-contrib/sessions/cookie"
"github.com/gin-gonic/gin" "github.com/gin-gonic/gin"
"github.com/microcosm-cc/bluemonday" "github.com/microcosm-cc/bluemonday"
"github.com/pkg/errors"
log "github.com/sirupsen/logrus" log "github.com/sirupsen/logrus"
"reichard.io/antholume/config" "reichard.io/antholume/config"
"reichard.io/antholume/database" "reichard.io/antholume/database"
@ -37,6 +39,7 @@ func NewApi(db *database.DBManager, c *config.Config, assets fs.FS) *API {
db: db, db: db,
cfg: c, cfg: c,
assets: assets, assets: assets,
templates: make(map[string]*template.Template),
userAuthCache: make(map[string]string), userAuthCache: make(map[string]string),
} }
@ -223,8 +226,8 @@ func (api *API) registerOPDSRoutes(apiGroup *gin.RouterGroup) {
func (api *API) generateTemplates() *multitemplate.Renderer { func (api *API) generateTemplates() *multitemplate.Renderer {
// Define templates & helper functions // Define templates & helper functions
templates := make(map[string]*template.Template)
render := multitemplate.NewRenderer() render := multitemplate.NewRenderer()
templates := make(map[string]*template.Template)
helperFuncs := template.FuncMap{ helperFuncs := template.FuncMap{
"dict": dict, "dict": dict,
"slice": slice, "slice": slice,
@ -236,55 +239,92 @@ func (api *API) generateTemplates() *multitemplate.Renderer {
"niceSeconds": niceSeconds, "niceSeconds": niceSeconds,
} }
// Load base // Load Base
b, _ := fs.ReadFile(api.assets, "templates/base.tmpl") b, err := fs.ReadFile(api.assets, "templates/base.tmpl")
baseTemplate := template.Must(template.New("base").Funcs(helperFuncs).Parse(string(b))) if err != nil {
log.Errorf("error reading base template: %v", err)
return &render
}
// Parse Base
baseTemplate, err := template.New("base").Funcs(helperFuncs).Parse(string(b))
if err != nil {
log.Errorf("error parsing base template: %v", err)
return &render
}
// Load SVGs // Load SVGs
svgs, _ := fs.ReadDir(api.assets, "templates/svgs") err = api.loadTemplates("svg", baseTemplate, templates, false)
for _, item := range svgs { if err != nil {
basename := item.Name() log.Errorf("error loading svg templates: %v", err)
path := fmt.Sprintf("templates/svgs/%s", basename) return &render
name := strings.TrimSuffix(basename, filepath.Ext(basename))
b, _ := fs.ReadFile(api.assets, path)
baseTemplate = template.Must(baseTemplate.New("svg/" + name).Parse(string(b)))
templates["svg/"+name] = baseTemplate
} }
// Load components // Load Components
components, _ := fs.ReadDir(api.assets, "templates/components") err = api.loadTemplates("component", baseTemplate, templates, false)
for _, item := range components { if err != nil {
basename := item.Name() log.Errorf("error loading component templates: %v", err)
path := fmt.Sprintf("templates/components/%s", basename) return &render
name := strings.TrimSuffix(basename, filepath.Ext(basename))
// Clone Base Template
b, _ := fs.ReadFile(api.assets, path)
baseTemplate = template.Must(baseTemplate.New("component/" + name).Parse(string(b)))
render.Add("component/"+name, baseTemplate)
templates["component/"+name] = baseTemplate
} }
// Load pages // Load Pages
pages, _ := fs.ReadDir(api.assets, "templates/pages") err = api.loadTemplates("page", baseTemplate, templates, true)
for _, item := range pages { if err != nil {
basename := item.Name() log.Errorf("error loading page templates: %v", err)
path := fmt.Sprintf("templates/pages/%s", basename) return &render
name := strings.TrimSuffix(basename, filepath.Ext(basename))
// Clone Base Template
b, _ := fs.ReadFile(api.assets, path)
pageTemplate, _ := template.Must(baseTemplate.Clone()).New("page/" + name).Parse(string(b))
render.Add("page/"+name, pageTemplate)
templates["page/"+name] = pageTemplate
} }
// Populate Renderer
api.templates = templates api.templates = templates
for templateName, templateValue := range templates {
render.Add(templateName, templateValue)
}
return &render return &render
} }
func (api *API) loadTemplates(
basePath string,
baseTemplate *template.Template,
allTemplates map[string]*template.Template,
cloneBase bool,
) error {
// Load Templates (Pluralize)
templateDirectory := fmt.Sprintf("templates/%ss", basePath)
allFiles, err := fs.ReadDir(api.assets, templateDirectory)
if err != nil {
return errors.Wrap(err, fmt.Sprintf("unable to read template dir: %s", templateDirectory))
}
// Generate Templates
for _, item := range allFiles {
templateFile := item.Name()
templatePath := path.Join(templateDirectory, templateFile)
templateName := fmt.Sprintf("%s/%s", basePath, strings.TrimSuffix(templateFile, filepath.Ext(templateFile)))
// Read Template
b, err := fs.ReadFile(api.assets, templatePath)
if err != nil {
return errors.Wrap(err, fmt.Sprintf("unable to read template: %s", templateName))
}
// Clone? (Pages - Don't Stomp)
if cloneBase {
baseTemplate = template.Must(baseTemplate.Clone())
}
// Parse Template
baseTemplate, err = baseTemplate.New(templateName).Parse(string(b))
if err != nil {
return errors.Wrap(err, fmt.Sprintf("unable to parse template: %s", templateName))
}
allTemplates[templateName] = baseTemplate
}
return nil
}
func loggingMiddleware(c *gin.Context) { func loggingMiddleware(c *gin.Context) {
// Start timer // Start timer
startTime := time.Now() startTime := time.Now()

View File

@ -43,7 +43,7 @@
</div> </div>
<div class="fixed bottom-6 right-6 rounded-full flex items-center justify-center"> <div class="fixed bottom-6 right-6 rounded-full flex items-center justify-center">
<input type="checkbox" id="upload-file-button" class="hidden css-button" /> <input type="checkbox" id="upload-file-button" class="hidden css-button" />
<div class="rounded p-4 bg-gray-800 dark:bg-gray-200 text-white dark:text-black w-72 text-sm flex flex-col gap-2"> <div class="absolute right-0 z-10 bottom-0 rounded p-4 bg-gray-800 dark:bg-gray-200 text-white dark:text-black w-72 text-sm flex flex-col gap-2">
<form method="POST" <form method="POST"
enctype="multipart/form-data" enctype="multipart/form-data"
action="./documents" action="./documents"