-
Notifications
You must be signed in to change notification settings - Fork 0
/
pages.go
137 lines (108 loc) · 3.44 KB
/
pages.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
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
// Package pages provides template loading and rendering.
package pages
import (
"bytes"
"errors"
"fmt"
"net/http"
"path"
"github.com/ChristianSiegert/go-packages/forms"
"github.com/ChristianSiegert/go-packages/html"
"github.com/ChristianSiegert/go-packages/i18n/languages"
"github.com/ChristianSiegert/go-packages/sessions"
)
// ReloadTemplates is a flag for whether NewPage should reload templates on
// every request. Reloading templates is useful to see changes without
// recompiling. In production, reloading should be disabled.
var ReloadTemplates = false
// Page represents an HTML page.
type Page struct {
// BaseURL to prepend to redirect URL.
BaseURL string
// Breadcrumbs represent a hierarchical navigation.
Breadcrumbs *Breadcrumbs
// Data for populating the template.
Data map[string]interface{}
// Form helper for creating HTML input elements in the template.
Form *forms.Form
// Language to use for displaying text.
Language *languages.Language
// Name of the page. Useful for styling links to the current page
// differently.
Name string
request *http.Request
// Session associated with the request.
Session sessions.Session
// Template to render when calling Serve.
Template *Template
// Title of the page. Useful for populating the HTML title element.
Title string
writer http.ResponseWriter
}
// NewPage returns a new Page.
func NewPage(writer http.ResponseWriter, request *http.Request, tpl *Template) *Page {
page := &Page{
Breadcrumbs: &Breadcrumbs{},
Data: make(map[string]interface{}),
Form: forms.New(request),
request: request,
Template: tpl,
writer: writer,
}
return page
}
// FlashAll returns all flashes, removes them from session and saves the session
// if necessary.
func (p *Page) FlashAll() ([]sessions.Flash, error) {
if p.Session == nil {
return nil, errors.New("pages: session is nil")
}
flashes := p.Session.Flashes().GetAll()
if len(flashes) == 0 {
return flashes, nil
}
p.Session.Flashes().RemoveAll()
if p.Session.IsStored() {
if err := p.Session.Save(p.writer); err != nil {
return nil, errors.New("pages: saving session failed: " + err.Error())
}
}
return flashes, nil
}
// Redirect redirects the client to destination, using code as HTTP status code.
// If args is provided, destination is formatted with fmt.Sprintf, to which args
// is passed. destination is automatically prefixed with p.BaseURL.
func (p *Page) Redirect(code int, destination string, args ...interface{}) error {
if len(args) > 0 {
destination = fmt.Sprintf(destination, args...)
}
http.Redirect(p.writer, p.request, p.BaseURL+destination, code)
return nil
}
// Serve serves the page.
func (p *Page) Serve() error {
buffer := bytes.NewBuffer([]byte{})
if p.Template == nil {
return errors.New("pages: template is nil")
}
if ReloadTemplates {
if err := p.Template.Reload(); err != nil {
return err
}
}
templateName := path.Base(p.Template.paths[0])
if err := p.Template.template.ExecuteTemplate(buffer, templateName, p); err != nil {
return err
}
b := html.RemoveWhitespace(buffer.Bytes())
_, err := bytes.NewBuffer(b).WriteTo(p.writer)
return err
}
// T returns the translation associated with translationID. If none is
// associated, it returns translationID.
func (p *Page) T(translationID string, templateData ...map[string]interface{}) string {
if p.Language == nil {
return translationID
}
return p.Language.T(translationID, templateData...)
}