Add system for showing template render errors
Makes troubleshooting bad templates much easier. Need to convert everything over.
This commit is contained in:
parent
7b48f6eddf
commit
b4830f7684
2 changed files with 52 additions and 14 deletions
|
|
@ -173,7 +173,8 @@ func getRoot(w http.ResponseWriter, r *http.Request) {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
if has {
|
if has {
|
||||||
err = htmlDashboard(r.Context(), w, user)
|
htmlDashboard(r.Context(), w, user)
|
||||||
|
return
|
||||||
} else {
|
} else {
|
||||||
err = htmlOauthPrompt(w, user)
|
err = htmlOauthPrompt(w, user)
|
||||||
}
|
}
|
||||||
|
|
|
||||||
63
html.go
63
html.go
|
|
@ -1,12 +1,14 @@
|
||||||
package main
|
package main
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"bytes"
|
||||||
"context"
|
"context"
|
||||||
"errors"
|
"errors"
|
||||||
"fmt"
|
"fmt"
|
||||||
"html/template"
|
"html/template"
|
||||||
"io"
|
"io"
|
||||||
"log/slog"
|
"log/slog"
|
||||||
|
"net/http"
|
||||||
"os"
|
"os"
|
||||||
"strings"
|
"strings"
|
||||||
"time"
|
"time"
|
||||||
|
|
@ -42,6 +44,7 @@ var components = [...]string{"header"}
|
||||||
|
|
||||||
type BuiltTemplate struct {
|
type BuiltTemplate struct {
|
||||||
files []string
|
files []string
|
||||||
|
name string
|
||||||
template *template.Template
|
template *template.Template
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -112,33 +115,39 @@ func extractInitials(name string) string {
|
||||||
return initials.String()
|
return initials.String()
|
||||||
}
|
}
|
||||||
|
|
||||||
func htmlDashboard(ctx context.Context, w io.Writer, user *models.User) error {
|
func htmlDashboard(ctx context.Context, w http.ResponseWriter, user *models.User) {
|
||||||
org, err := user.Organization().One(ctx, PGInstance.BobDB)
|
org, err := user.Organization().One(ctx, PGInstance.BobDB)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return fmt.Errorf("Failed to get org: %v", err)
|
respondError(w, "Failed to get org", err, http.StatusInternalServerError)
|
||||||
|
return
|
||||||
}
|
}
|
||||||
var lastSync time.Time
|
var lastSync time.Time
|
||||||
sync, err := org.FieldseekerSyncs(sm.OrderBy("created")).One(ctx, PGInstance.BobDB)
|
sync, err := org.FieldseekerSyncs(sm.OrderBy("created")).One(ctx, PGInstance.BobDB)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return fmt.Errorf("Failed to get sync: %v", err)
|
respondError(w, "Failed to get syncs", err, http.StatusInternalServerError)
|
||||||
|
return
|
||||||
} else {
|
} else {
|
||||||
lastSync = sync.Created
|
lastSync = sync.Created
|
||||||
}
|
}
|
||||||
inspectionCount, err := org.FSMosquitoinspections().Count(ctx, PGInstance.BobDB)
|
inspectionCount, err := org.FSMosquitoinspections().Count(ctx, PGInstance.BobDB)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return fmt.Errorf("Failed to get inspection count: %v", err)
|
respondError(w, "Failed to get inspection count", err, http.StatusInternalServerError)
|
||||||
|
return
|
||||||
}
|
}
|
||||||
sourceCount, err := org.FSPointlocations().Count(ctx, PGInstance.BobDB)
|
sourceCount, err := org.FSPointlocations().Count(ctx, PGInstance.BobDB)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return fmt.Errorf("Failed to get inspection count: %v", err)
|
respondError(w, "Failed to get source count", err, http.StatusInternalServerError)
|
||||||
|
return
|
||||||
}
|
}
|
||||||
serviceCount, err := org.FSServicerequests().Count(ctx, PGInstance.BobDB)
|
serviceCount, err := org.FSServicerequests().Count(ctx, PGInstance.BobDB)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return fmt.Errorf("Failed to get service count: %v", err)
|
respondError(w, "Failed to get service count", err, http.StatusInternalServerError)
|
||||||
|
return
|
||||||
}
|
}
|
||||||
recentRequests, err := org.FSServicerequests(sm.OrderBy("creationdate").Desc(), sm.Limit(10)).All(ctx, PGInstance.BobDB)
|
recentRequests, err := org.FSServicerequests(sm.OrderBy("creationdate").Desc(), sm.Limit(10)).All(ctx, PGInstance.BobDB)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return fmt.Errorf("Failed to get recent service: %v", err)
|
respondError(w, "Failed to get recent service", err, http.StatusInternalServerError)
|
||||||
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
requests := make([]ServiceRequestSummary, 0)
|
requests := make([]ServiceRequestSummary, 0)
|
||||||
|
|
@ -162,7 +171,7 @@ func htmlDashboard(ctx context.Context, w io.Writer, user *models.User) error {
|
||||||
Username: user.Username,
|
Username: user.Username,
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
return dashboard.ExecuteTemplate(w, data)
|
renderOrError(w, dashboard, data)
|
||||||
}
|
}
|
||||||
|
|
||||||
func htmlOauthPrompt(w io.Writer, user *models.User) error {
|
func htmlOauthPrompt(w io.Writer, user *models.User) error {
|
||||||
|
|
@ -292,9 +301,10 @@ func makeFuncMap() template.FuncMap {
|
||||||
}
|
}
|
||||||
return funcMap
|
return funcMap
|
||||||
}
|
}
|
||||||
func newBuiltTemplate(files ...string) BuiltTemplate {
|
func newBuiltTemplate(name string, files ...string) BuiltTemplate {
|
||||||
files_on_disk := true
|
files_on_disk := true
|
||||||
for _, f := range files {
|
all_files := append([]string{name}, files...)
|
||||||
|
for _, f := range all_files {
|
||||||
full_path := "templates/" + f + ".html"
|
full_path := "templates/" + f + ".html"
|
||||||
_, err := os.Stat(full_path)
|
_, err := os.Stat(full_path)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
|
@ -304,13 +314,15 @@ func newBuiltTemplate(files ...string) BuiltTemplate {
|
||||||
}
|
}
|
||||||
if files_on_disk {
|
if files_on_disk {
|
||||||
return BuiltTemplate{
|
return BuiltTemplate{
|
||||||
files: files,
|
files: all_files,
|
||||||
|
name: name,
|
||||||
template: nil,
|
template: nil,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return BuiltTemplate{
|
return BuiltTemplate{
|
||||||
files: files,
|
files: all_files,
|
||||||
template: parseEmbedded(files),
|
name: name,
|
||||||
|
template: parseEmbedded(all_files),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -369,3 +381,28 @@ func timeSince(t time.Time) string {
|
||||||
return fmt.Sprintf("%d days ago", int(days))
|
return fmt.Sprintf("%d days ago", int(days))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
type Notification struct {
|
||||||
|
Created time.Time
|
||||||
|
Link string
|
||||||
|
Message string
|
||||||
|
}
|
||||||
|
|
||||||
|
func notificationsForUser(u *models.User) ([]Notification, error) {
|
||||||
|
return []Notification{Notification{
|
||||||
|
Created: time.Now(),
|
||||||
|
Link: "/foo/bar",
|
||||||
|
Message: "hey, your oauth is broken.",
|
||||||
|
}}, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func renderOrError(w http.ResponseWriter, template BuiltTemplate, context interface{}) {
|
||||||
|
buf := &bytes.Buffer{}
|
||||||
|
err := template.ExecuteTemplate(buf, context)
|
||||||
|
if err != nil {
|
||||||
|
slog.Error("Failed to render template", slog.String("err", err.Error()), slog.String("template", template.name))
|
||||||
|
respondError(w, "Failed to render template", err, http.StatusInternalServerError)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
buf.WriteTo(w)
|
||||||
|
}
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue