-
Notifications
You must be signed in to change notification settings - Fork 0
/
view.go
executable file
·111 lines (100 loc) · 2.55 KB
/
view.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
package views
import (
"bytes"
"errors"
"html/template"
"io"
"log"
"net/http"
"path/filepath"
"github.com/TerrenceHo/simplephotohost.com/context"
"github.com/gorilla/csrf"
)
var (
LayoutDir string = "views/layouts/"
TemplateDir string = "views/"
TemplateExt string = ".gohtml"
)
func NewView(layout string, files ...string) *View {
addTemplatePath(files)
addTemplateExt(files)
files = append(files, layoutFiles()...)
t, err := template.New("").Funcs(template.FuncMap{
"csrfField": func() (template.HTML, error) {
return "", errors.New("csrfField is not implemented")
},
}).ParseFiles(files...)
if err != nil {
panic(err)
}
return &View{
Template: t,
Layout: layout,
}
}
type View struct {
Template *template.Template
Layout string
}
func (v *View) ServeHTTP(w http.ResponseWriter, r *http.Request) {
v.Render(w, r, nil)
}
// Render is used to render the view with the predefined layout.
func (v *View) Render(w http.ResponseWriter, r *http.Request, data interface{}) {
w.Header().Set("Content-Type", "text/html")
var vd Data
switch d := data.(type) {
case Data:
vd = d
// do nothing
default:
vd = Data{
Yield: data,
}
}
vd.User = context.User(r.Context())
var buf bytes.Buffer
csrfField := csrf.TemplateField(r)
tpl := v.Template.Funcs(template.FuncMap{
"csrfField": func() template.HTML {
return csrfField
},
})
if err := tpl.ExecuteTemplate(&buf, v.Layout, vd); err != nil {
log.Println(err)
http.Error(w, "Something went wrong. If the problem persists, please email support@simplephotohost.com", http.StatusInternalServerError)
return
}
io.Copy(w, &buf)
}
// layoutFiles returns a slice of strings representing
// the layout files used in our application.
func layoutFiles() []string {
files, err := filepath.Glob(LayoutDir + "*" + TemplateExt)
if err != nil {
panic(err)
}
return files
}
// addTemplatePath takes in a slice of strings
// representing file paths for templates, and it prepends
// the TemplateDir directory to each string in the slice
//
// Eg the input {"home"} would result in the output
// {"views/home"} if TemplateDir == "views/"
func addTemplatePath(files []string) {
for i, f := range files {
files[i] = TemplateDir + f
}
}
// addTemplateExt takes in a slice of strings
// representing file paths for templates and it appends
// the TemplateExt extension to each string in the slice
//
// Eg the input {"home"} would result in the output
// {"home.gohtml"} if TemplateExt == ".gohtml"
func addTemplateExt(files []string) {
for i, f := range files {
files[i] = f + TemplateExt
}
}