fix: fix cellar-go templates
5196f668
5 file(s) · +56 −14
| 15 | 15 | type App struct { |
|
| 16 | 16 | DB *sql.DB |
|
| 17 | 17 | Log *slog.Logger |
|
| 18 | - | Templates *template.Template |
|
| 18 | + | Templates map[string]*template.Template |
|
| 19 | 19 | Sessions *auth.Store |
|
| 20 | 20 | AppPassword string |
|
| 21 | 21 | CookieSecure bool |
| 11 | 11 | ||
| 12 | 12 | func (a *App) loginGet(w http.ResponseWriter, r *http.Request) { |
|
| 13 | 13 | q := r.URL.Query() |
|
| 14 | - | web.Render(a.Templates, w, "login.html", loginPageData{Error: q.Get("error"), Next: q.Get("next")}, a.Log) |
|
| 14 | + | a.renderPage(w, "login.html", loginPageData{Error: q.Get("error"), Next: q.Get("next")}) |
|
| 15 | 15 | } |
|
| 16 | 16 | ||
| 17 | 17 | func (a *App) loginPost(w http.ResponseWriter, r *http.Request) { |
|
| 57 | 57 | http.Error(w, "Server error", http.StatusInternalServerError) |
|
| 58 | 58 | return |
|
| 59 | 59 | } |
|
| 60 | - | web.Render(a.Templates, w, "admin.html", adminPageData{Wines: wines}, a.Log) |
|
| 60 | + | a.renderPage(w, "admin.html", adminPageData{Wines: wines}) |
|
| 61 | 61 | } |
|
| 62 | 62 | ||
| 63 | 63 | func (a *App) newWineGet(w http.ResponseWriter, r *http.Request) { |
|
| 64 | - | web.Render(a.Templates, w, "wine_form.html", wineFormPageData{Error: r.URL.Query().Get("error"), HasAnthropicKey: a.AnthropicAPIKey != ""}, a.Log) |
|
| 64 | + | a.renderPage(w, "wine_form.html", wineFormPageData{Error: r.URL.Query().Get("error"), HasAnthropicKey: a.AnthropicAPIKey != ""}) |
|
| 65 | 65 | } |
|
| 66 | 66 | ||
| 67 | 67 | func (a *App) editWineGet(w http.ResponseWriter, r *http.Request) { |
|
| 75 | 75 | http.Error(w, "Wine not found", http.StatusNotFound) |
|
| 76 | 76 | return |
|
| 77 | 77 | } |
|
| 78 | - | web.Render(a.Templates, w, "wine_form.html", wineFormPageData{Wine: wine, Error: r.URL.Query().Get("error"), HasAnthropicKey: a.AnthropicAPIKey != ""}, a.Log) |
|
| 78 | + | a.renderPage(w, "wine_form.html", wineFormPageData{Wine: wine, Error: r.URL.Query().Get("error"), HasAnthropicKey: a.AnthropicAPIKey != ""}) |
|
| 79 | 79 | } |
|
| 80 | 80 | ||
| 81 | 81 | func (a *App) newWinePost(w http.ResponseWriter, r *http.Request) { |
|
| 129 | 129 | } |
|
| 130 | 130 | ||
| 131 | 131 | func (a *App) newWishlistGet(w http.ResponseWriter, r *http.Request) { |
|
| 132 | - | web.Render(a.Templates, w, "wishlist_form.html", wineFormPageData{Error: r.URL.Query().Get("error"), HasAnthropicKey: a.AnthropicAPIKey != ""}, a.Log) |
|
| 132 | + | a.renderPage(w, "wishlist_form.html", wineFormPageData{Error: r.URL.Query().Get("error"), HasAnthropicKey: a.AnthropicAPIKey != ""}) |
|
| 133 | 133 | } |
|
| 134 | 134 | ||
| 135 | 135 | func (a *App) editWishlistGet(w http.ResponseWriter, r *http.Request) { |
|
| 142 | 142 | http.Error(w, "Wine not found", http.StatusNotFound) |
|
| 143 | 143 | return |
|
| 144 | 144 | } |
|
| 145 | - | web.Render(a.Templates, w, "wishlist_form.html", wineFormPageData{Wine: wine, Error: r.URL.Query().Get("error"), HasAnthropicKey: a.AnthropicAPIKey != ""}, a.Log) |
|
| 145 | + | a.renderPage(w, "wishlist_form.html", wineFormPageData{Wine: wine, Error: r.URL.Query().Get("error"), HasAnthropicKey: a.AnthropicAPIKey != ""}) |
|
| 146 | 146 | } |
|
| 147 | 147 | ||
| 148 | 148 | func (a *App) newWishlistPost(w http.ResponseWriter, r *http.Request) { |
|
| 5 | 5 | "net/http" |
|
| 6 | 6 | "strings" |
|
| 7 | 7 | "time" |
|
| 8 | - | ||
| 9 | - | "github.com/stevedylandev/andromeda/crates-go/web" |
|
| 10 | 8 | ) |
|
| 11 | 9 | ||
| 12 | 10 | func (a *App) indexHandler(w http.ResponseWriter, r *http.Request) { |
|
| 21 | 19 | svg := buildPentagonSVG(wine.Sweetness, wine.Acidity, wine.Tannin, wine.Alcohol, wine.Body, 80.0, false) |
|
| 22 | 20 | out = append(out, wineWithSVG{Wine: wine, PentagonSVG: template.HTML(svg)}) |
|
| 23 | 21 | } |
|
| 24 | - | web.Render(a.Templates, w, "index.html", indexPageData{Wines: out}, a.Log) |
|
| 22 | + | a.renderPage(w, "index.html", indexPageData{Wines: out}) |
|
| 25 | 23 | } |
|
| 26 | 24 | ||
| 27 | 25 | func (a *App) wineDetail(w http.ResponseWriter, r *http.Request) { |
|
| 36 | 34 | } |
|
| 37 | 35 | pentagon := buildPentagonSVG(wine.Sweetness, wine.Acidity, wine.Tannin, wine.Alcohol, wine.Body, 250.0, true) |
|
| 38 | 36 | bars := buildBarsSVG(wine.Clarity, wine.ColorIntensity, wine.AromaIntensity, wine.NoseComplexity, 250.0) |
|
| 39 | - | web.Render(a.Templates, w, "wine.html", wineDetailPageData{Wine: *wine, PentagonSVG: template.HTML(pentagon), BarsSVG: template.HTML(bars)}, a.Log) |
|
| 37 | + | a.renderPage(w, "wine.html", wineDetailPageData{Wine: *wine, PentagonSVG: template.HTML(pentagon), BarsSVG: template.HTML(bars)}) |
|
| 40 | 38 | } |
|
| 41 | 39 | ||
| 42 | 40 | func (a *App) wineImage(w http.ResponseWriter, r *http.Request) { |
|
| 62 | 60 | http.Error(w, "Server error", http.StatusInternalServerError) |
|
| 63 | 61 | return |
|
| 64 | 62 | } |
|
| 65 | - | web.Render(a.Templates, w, "wishlist.html", wishlistPageData{Wines: wines, IsAdmin: a.Sessions.HasValid(r)}, a.Log) |
|
| 63 | + | a.renderPage(w, "wishlist.html", wishlistPageData{Wines: wines, IsAdmin: a.Sessions.HasValid(r)}) |
|
| 66 | 64 | } |
|
| 67 | 65 | ||
| 68 | 66 | func xmlEscape(s string) string { |
|
| 1 | 1 | package main |
|
| 2 | 2 | ||
| 3 | 3 | import ( |
|
| 4 | - | "html/template" |
|
| 5 | 4 | "log" |
|
| 6 | 5 | "log/slog" |
|
| 7 | 6 | "net/http" |
|
| 36 | 35 | } |
|
| 37 | 36 | sessions.PruneExpired() |
|
| 38 | 37 | ||
| 39 | - | tmpl := template.Must(template.ParseFS(appFS, "templates/*.html")) |
|
| 38 | + | tmpl, err := buildTemplates() |
|
| 39 | + | if err != nil { |
|
| 40 | + | log.Fatal(err) |
|
| 41 | + | } |
|
| 40 | 42 | app := &App{ |
|
| 41 | 43 | DB: db, |
|
| 42 | 44 | Log: logger, |
|
| 1 | + | package main |
|
| 2 | + | ||
| 3 | + | import ( |
|
| 4 | + | "fmt" |
|
| 5 | + | "html/template" |
|
| 6 | + | "io/fs" |
|
| 7 | + | "net/http" |
|
| 8 | + | "path" |
|
| 9 | + | "strings" |
|
| 10 | + | ||
| 11 | + | "github.com/stevedylandev/andromeda/crates-go/web" |
|
| 12 | + | ) |
|
| 13 | + | ||
| 14 | + | func buildTemplates() (map[string]*template.Template, error) { |
|
| 15 | + | pages, err := fs.Glob(appFS, "templates/*.html") |
|
| 16 | + | if err != nil { |
|
| 17 | + | return nil, err |
|
| 18 | + | } |
|
| 19 | + | ||
| 20 | + | out := make(map[string]*template.Template, len(pages)) |
|
| 21 | + | for _, page := range pages { |
|
| 22 | + | if strings.HasSuffix(page, "/base.html") { |
|
| 23 | + | continue |
|
| 24 | + | } |
|
| 25 | + | tmpl, err := template.ParseFS(appFS, "templates/base.html", page) |
|
| 26 | + | if err != nil { |
|
| 27 | + | return nil, fmt.Errorf("parse %s: %w", page, err) |
|
| 28 | + | } |
|
| 29 | + | out[path.Base(page)] = tmpl |
|
| 30 | + | } |
|
| 31 | + | return out, nil |
|
| 32 | + | } |
|
| 33 | + | ||
| 34 | + | func (a *App) renderPage(w http.ResponseWriter, name string, data any) { |
|
| 35 | + | tmpl, ok := a.Templates[name] |
|
| 36 | + | if !ok { |
|
| 37 | + | a.Log.Error("template missing", "name", name) |
|
| 38 | + | http.Error(w, "template missing", http.StatusInternalServerError) |
|
| 39 | + | return |
|
| 40 | + | } |
|
| 41 | + | web.Render(tmpl, w, name, data, a.Log) |
|
| 42 | + | } |