package frontend import ( "html/template" "net/http" "os" "path/filepath" "strings" ) // Action ist die Aktion auf einer Card. type Action struct { Name string Link string Disabled bool } // Card ist eine Karte im Materialize-Design. type Card struct { Title string Description string Size string Actions []Action } // Renderer rendert Seiten. type Renderer struct { templates *template.Template defaultData map[string]interface{} } // RangePair für Range-Dingens. Damit man die ID weiterhin accessen kann. type RangePair struct { Index int Value interface{} } // DefaultData gibt die Standard-Daten für die Views zurück. Das ist immer eine Kopie weil Reasons. func (r *Renderer) DefaultData() map[string]interface{} { d := make(map[string]interface{}) for k, v := range r.defaultData { d[k] = v } return d } // SetDefaultData updated die standarddaten func (r *Renderer) SetDefaultData(data map[string]interface{}) { r.defaultData = data } // New erstellt einen neuen Renderer und sucht alle Templates aus dem gegebenen pfad. func New(path string, functions map[string]interface{}) *Renderer { // Custom Template Funcs funcMap := template.FuncMap{ "html": func(in string) template.HTML { return template.HTML(in) }, "add": func(a, b int) int { return a + b }, "sub": func(a, b int) int { return a - b }, "makeRangePair": func(idx int, value interface{}) RangePair { return RangePair{idx, value} }, "map": func(values ...interface{}) map[string]interface{} { m := make(map[string]interface{}, len(values)/2) for i := 0; i < len(values); i += 2 { key, _ := values[i].(string) m[key] = values[i+1] } return m }, "makeObject": func(name string, existing interface{}, newKey string, newData interface{}) map[string]interface{} { d := make(map[string]interface{}) d[name] = existing d[newKey] = newData return d }, } for k, v := range functions { funcMap[k] = v } files := make([]string, 0) filepath.Walk(path, func(path string, info os.FileInfo, err error) error { if info.IsDir() || !strings.HasSuffix(path, ".html") { return nil } files = append(files, path) return nil }) r := &Renderer{ template.Must(template.New("").Funcs(funcMap).ParseFiles(files...)), make(map[string]interface{}), } return r } // RenderPage rendert eine bestimmte Seite (basierend auf dem Template-Namen) und den gegebenen Daten. func (r *Renderer) RenderPage(name string, w http.ResponseWriter, data map[string]interface{}) { // default daten einspeisen for k, v := range r.defaultData { if _, ok := data[k]; !ok { data[k] = v } } err := r.templates.ExecuteTemplate(w, name, data) if err != nil { http.Error(w, err.Error(), http.StatusInternalServerError) } } // RenderLoginPage zeigt die Loginseite an. func (r *Renderer) RenderLoginPage(w http.ResponseWriter, data map[string]interface{}) { r.RenderPage("login", w, data) } // RenderRegistrationPage zeigt die Registrationsseite an. func (r *Renderer) RenderRegistrationPage(w http.ResponseWriter, data map[string]interface{}) { r.RenderPage("register", w, data) } // RenderUserSettingsPage zeigt die Einstellungen für den Benutzer an. func (r *Renderer) RenderUserSettingsPage(w http.ResponseWriter, data map[string]interface{}) { r.RenderPage("user_settings", w, data) } func (r *Renderer) RenderAPICouplePage(w http.ResponseWriter, data map[string]interface{}) { r.RenderPage("api_couple", w, data) }