Compare commits

...

5 commits

Author SHA1 Message Date
Lilian Jónsdóttir 8a2319033e refactor how template data is handled + load template data from file
Generating template data is now handled by templatedata instead of handlers.
Renderer doesn't recieve any data, but now asks for data from templatedata.
Additionally, template data is loaded from file (too lazy to split that into its own commit).
Templates in ./templates/name.page.tmpl will have data loaded from ./templates/name.page.json
2024-01-23 16:10:15 -08:00
Lilian Jónsdóttir ffe303f1c6 generate new template cache if pulling from it fails, instead of bailing out
extreme edge case? probably
2024-01-23 14:27:50 -08:00
Lilian Jónsdóttir 9a42079ae3 refactor RenderTemplate a bit 2024-01-23 14:08:08 -08:00
Lilian Jónsdóttir 21ccdebd7a log time in format consistent with what is on the page 2024-01-23 13:54:25 -08:00
Lilian Jónsdóttir cff59fe895 don't generate cache on startup if UseCache is false 2024-01-23 13:53:59 -08:00
5 changed files with 149 additions and 80 deletions

View file

@ -2,10 +2,8 @@ package handlers
import ( import (
"net/http" "net/http"
"time"
"git.burning.moe/celediel/burning.moe/internal/config" "git.burning.moe/celediel/burning.moe/internal/config"
"git.burning.moe/celediel/burning.moe/internal/models"
"git.burning.moe/celediel/burning.moe/internal/render" "git.burning.moe/celediel/burning.moe/internal/render"
) )
@ -36,33 +34,11 @@ func Initialise(a *config.AppConfig) {
app = a app = a
} }
// makeBasicTemplateData creates a blank TemplateData containing only the // makeBasicHandler returns a simple handler that renders a template from `name`.page.tmpl
// time the related template was generated
func makeBasicTemplateData(name string) models.TemplateData {
var strMap map[string]string
if cacheItem, ok := app.TemplateCache.Cache[name]; ok {
strMap = map[string]string{
"GeneratedAt": cacheItem.GeneratedAt.Format(time.UnixDate),
}
} else {
strMap = map[string]string{
"GeneratedAt": time.Now().Format(time.UnixDate),
}
}
templateData := models.TemplateData{
StringMap: strMap,
}
return templateData
}
// makeBasicHandler creates a basic handler that builds from a .page.tmpl
// file, and sends only the time the template was generated as TemplateData
func makeBasicHandler(name string) func(w http.ResponseWriter, r *http.Request) { func makeBasicHandler(name string) func(w http.ResponseWriter, r *http.Request) {
return func(w http.ResponseWriter, r *http.Request) { return func(w http.ResponseWriter, r *http.Request) {
app.Logger.Infof("Got request for %s page", name) app.Logger.Infof("Got request for %s page", name)
pageName := name + ".page.tmpl" pageName := name + ".page.tmpl"
templateData := makeBasicTemplateData(pageName) render.RenderTemplate(w, pageName)
render.RenderTemplate(w, pageName, &templateData)
} }
} }

View file

@ -1,14 +1,63 @@
package models package models
import (
"encoding/json"
"html/template"
"os"
"strings"
"time"
)
const dataDir string = "./templates/data/"
type Link struct {
Href template.URL
Text string
Icon template.URL
}
// TemplateData holds data sent from handlers to templates. // TemplateData holds data sent from handlers to templates.
type TemplateData struct { type TemplateData struct {
StringMap map[string]string StringMap map[string]string `json:"stringMap"`
IntMap map[string]int IntMap map[string]int `json:"intMap"`
FloatMap map[string]float32 FloatMap map[string]float32 `json:"floatMap"`
Data map[string]interface{} LinkMap map[string][]Link `json:"linkMap"`
CSRFToken string Data map[string]interface{} `json:"data"`
Flash string CSRFToken string `json:"csrftoken"`
Warning string Flash string `json:"flash"`
Error string Warning string `json:"warning"`
Error string `json:"error"`
} }
// makeBasicTemplateData creates a blank TemplateData containing only the
// time the related template was generated
func MakeBasicTemplateData(when time.Time) TemplateData {
strMap := map[string]string{
"GeneratedAt": when.Format(time.UnixDate),
}
templateData := TemplateData{
StringMap: strMap,
}
return templateData
}
// LoadTemplateData loads template data from file. If that
// fails, it returns an empty TemplateData and an error
func LoadTemplateData(page string) (TemplateData, error) {
// TODO: load from something other than JSON
var data *TemplateData
output := dataDir + strings.ReplaceAll(page, "tmpl", "json")
file, err := os.ReadFile(output)
if err != nil {
return TemplateData{}, err
}
err = json.Unmarshal(file, &data)
if err != nil {
return TemplateData{}, err
}
return *data, nil
}

View file

@ -24,7 +24,9 @@ var app *config.AppConfig
func Initialise(a *config.AppConfig) { func Initialise(a *config.AppConfig) {
var err error var err error
app = a app = a
if app.UseCache {
app.TemplateCache, err = GenerateNewTemplateCache() app.TemplateCache, err = GenerateNewTemplateCache()
}
if err != nil { if err != nil {
app.Logger.Fatal("Error generating template cache, bailing out!") app.Logger.Fatal("Error generating template cache, bailing out!")
} }
@ -71,7 +73,7 @@ func GenerateNewTemplateCache() (models.TemplateCache, error) {
Template: templateSet, Template: templateSet,
GeneratedAt: generatedAt, GeneratedAt: generatedAt,
} }
app.Logger.Debugf("Generated %s at %v", name, generatedAt.String()) app.Logger.Debugf("Generated %s at %v", name, generatedAt.Format(time.UnixDate))
} }
// All was good, so return the cache, and no error // All was good, so return the cache, and no error
@ -79,29 +81,44 @@ func GenerateNewTemplateCache() (models.TemplateCache, error) {
} }
// RenderTemplate renders requested template (t), pulling from cache. // RenderTemplate renders requested template (t), pulling from cache.
func RenderTemplate(w http.ResponseWriter, filename string, data *models.TemplateData) { func RenderTemplate(w http.ResponseWriter, filename string) {
var cache models.TemplateCache if !app.UseCache {
if app.UseCache { c, err := GenerateNewTemplateCache()
cache = app.TemplateCache
} else {
var err error
cache, err = GenerateNewTemplateCache()
if err != nil { if err != nil {
app.Logger.Fatal("Error generating template cache, bailing out!") app.Logger.Fatal("Error generating template cache, bailing out!")
} }
app.TemplateCache = cache app.TemplateCache = c
} }
// Get templates from cache // Get templates from cache
template, ok := cache.Cache[filename] template, ok := app.TemplateCache.Cache[filename]
if !ok { if !ok {
app.Logger.Fatal(fmt.Sprintf("Couldn't get %s from template cache, bailing out!", filename)) app.Logger.Errorf("Couldn't get %s from template cache, dunno what happened, but we're gonna generate a new one", filename)
c, err := GenerateNewTemplateCache()
if err != nil {
app.Logger.Fatal("Error generating template cache, bailing out!")
} }
app.TemplateCache = c
template = app.TemplateCache.Cache[filename]
}
// Get template data from file, or generate simple
data, err := models.LoadTemplateData(filename)
if err == nil {
app.Logger.Debug(fmt.Sprintf("Loaded data for template %s.", filename), "data", data)
if _, ok := data.StringMap["GeneratedAt"]; !ok {
data.StringMap["GeneratedAt"] = app.TemplateCache.Cache[filename].GeneratedAt.Format(time.UnixDate)
}
} else {
app.Logger.Info(fmt.Sprintf("Loading template data for %s failed, using default template data.", filename), "err", err)
data = models.MakeBasicTemplateData(template.GeneratedAt)
}
l := data.LinkMap["Personal"]
app.Logger.Debugf("%[1]v is %[1]T", l)
// Execute templates in a new buffer // Execute templates in a new buffer
buf := new(bytes.Buffer) buf := new(bytes.Buffer)
err := template.Template.Execute(buf, data) err = template.Template.Execute(buf, data)
if err != nil { if err != nil {
app.Logger.Fatal(fmt.Sprintf("Error executing template %s! Goodbye!", filename), "err", err) app.Logger.Fatal(fmt.Sprintf("Error executing template %s! Goodbye!", filename), "err", err)
} }

View file

@ -4,46 +4,27 @@
<span id="words"> <span id="words">
<h4>celediel</h4> <h4>celediel</h4>
<span id="bigwords"> <span id="bigwords">
she/her, 1989, queer anarchist, self-taught aspiring developer {{ index .StringMap "about" }}
</span> </span>
<h4>links</h4>
<!-- personal links --> <!-- personal links -->
<a href="https://matrix.to/#/@celediel:burning.moe"> <h4>links</h4>
<span class="iconify" data-icon="tabler:brand-matrix"></span> {{ range (index .LinkMap "Personal") }}
matrix <a href="{{ .Href }}">
</a><br /> <span class="iconify" data-icon="{{ .Icon }}"></span>
{{ .Text }}
<a href="https://slrpnk.net/u/Celediel">
<span class="iconify" data-icon="simple-icons:lemmy"></span>
lemmy
</a><br />
<a href="https://git.burning.moe/celediel">
<span class="iconify" data-icon="mdi:git"></span>
self-hosted git
</a><br />
<a href="https://github.com/celediel">
<span class="iconify" data-icon="bi:github"></span>
github
</a><br /> </a><br />
{{ end }}
<!-- web app links --> <!-- web app links -->
<h4>hosted apps</h4> <h4>hosted apps</h4>
<a href="https://git.burning.moe/"> {{ range (index .LinkMap "HostedApps") }}
<span class="iconify" data-icon="mdi:git"></span> <a href="{{ .Href }}">
self-hosted git <span class="iconify" data-icon="{{ .Icon }}"></span>
{{ .Text }}
</a><br /> </a><br />
<a href="https://bin.burning.moe/"> {{ end }}
<span class="iconify" data-icon="fluent:bin-recycle-20-filled"></span> <br />
wastebin
</a><br />
<a href="https://gist.burning.moe/">
<span class="iconify" data-icon="carbon:paste"></span>
gist
</a>
<br /><br />
<a href="/">back</a> <a href="/">back</a>
</span> </span>
{{ end -}} {{ end -}}

View file

@ -0,0 +1,46 @@
{
"StringMap": {
"about": "she/her, 1989, queer anarchist, self-taught aspiring developer and sysadmin"
},
"LinkMap": {
"Personal": [
{
"href": "https://matrix.to/#/@celediel:burning.moe",
"text": "matrix",
"icon": "tabler:brand-matrix"
},
{
"href": "https://slrpnk.net/u/Celediel",
"text": "lemmy",
"icon": "simple-icons:lemmy"
},
{
"href": "https://git.burning.moe/celediel",
"text": "self-hosted git",
"icon": "mdi:git"
},
{
"href": "https://github.com/celediel",
"text": "github",
"icon": "bi:github"
}
],
"HostedApps": [
{
"href": "https://git.burning.moe/",
"text": "self-hosted git",
"icon": "mdi:git"
},
{
"href": "https://bin.burning.moe/",
"text": "wastebin",
"icon": "fluent:bin-recycle-20-filled"
},
{
"href": "https://gist.burning.moe/",
"text": "gist",
"icon": "carbon:paste"
}
]
}
}