diff --git a/cmd/web/handlers.go b/cmd/web/handlers.go
index e33839e..379d168 100644
--- a/cmd/web/handlers.go
+++ b/cmd/web/handlers.go
@@ -4,7 +4,6 @@ import (
"errors"
"fmt"
"net/http"
- "text/template"
"git.32bit.cafe/yequari/webring/internal/models"
)
@@ -15,21 +14,14 @@ func (app *application) home(w http.ResponseWriter, r *http.Request) {
return
}
- files := []string{
- "./ui/html/base.tmpl.html",
- "./ui/html/pages/home.tmpl.html",
- }
-
- ts, err := template.ParseFiles(files...)
- if err != nil {
- app.serverError(w, err)
- return
- }
-
- err = ts.ExecuteTemplate(w, "base", nil)
+ sites, err := app.siteEntries.Latest()
if err != nil {
app.serverError(w, err)
}
+
+ app.render(w, http.StatusOK, "home.tmpl.html", &templateData{
+ SiteEntries: sites,
+ })
}
func (app *application) webmasterView(w http.ResponseWriter, r *http.Request) {
@@ -52,18 +44,12 @@ func (app *application) webmasterCreate(w http.ResponseWriter, r *http.Request)
}
func (app *application) siteEntryView(w http.ResponseWriter, r *http.Request) {
- if r.URL.Path == "/sites/view" {
- entries, err := app.siteEntries.Latest()
- if err != nil {
- app.serverError(w, err)
- return
- }
- for _, entry := range entries {
- fmt.Fprintf(w, "%+v\n", entry)
- }
+ id := models.SiteId(r.URL.Query().Get("id"))
+
+ if id == "" {
+ app.notFound(w)
return
}
- id := models.SiteId(r.URL.Query().Get("id"))
siteEntry, err := app.siteEntries.Get(id)
if err != nil {
@@ -75,7 +61,20 @@ func (app *application) siteEntryView(w http.ResponseWriter, r *http.Request) {
return
}
- fmt.Fprintf(w, "%+v", siteEntry)
+ webmaster, err := app.webmasters.Get(siteEntry.Webmaster)
+ if err != nil {
+ if errors.Is(err, models.ErrNoRecord) {
+ app.notFound(w)
+ } else {
+ app.serverError(w, err)
+ }
+ return
+ }
+
+ app.render(w, http.StatusOK, "view.tmpl.html", &templateData{
+ SiteEntry: siteEntry,
+ Webmaster: webmaster,
+ })
}
func (app *application) siteEntryCreate(w http.ResponseWriter, r *http.Request) {
diff --git a/cmd/web/helpers.go b/cmd/web/helpers.go
index 505665c..25d2b22 100644
--- a/cmd/web/helpers.go
+++ b/cmd/web/helpers.go
@@ -1,6 +1,7 @@
package main
import (
+ "bytes"
"fmt"
"net/http"
"path"
@@ -30,3 +31,26 @@ func (app *application) cleanUrl(url string) string {
s = "http://" + s
return s
}
+
+func (app *application) render(w http.ResponseWriter, status int, page string, data *templateData) {
+ ts, ok := app.templateCache[page]
+ if !ok {
+ err := fmt.Errorf("the template %s does not exist", page)
+ app.serverError(w, err)
+ return
+ }
+
+ // a buffer to attempt to write the template to
+ // before writing it to the ResponseWriter w
+ buf := new(bytes.Buffer)
+
+ err := ts.ExecuteTemplate(buf, "base", data)
+ if err != nil {
+ app.serverError(w, err)
+ return
+ }
+
+ w.WriteHeader(status)
+
+ buf.WriteTo(w)
+}
diff --git a/cmd/web/main.go b/cmd/web/main.go
index 2f8a994..a909bf7 100644
--- a/cmd/web/main.go
+++ b/cmd/web/main.go
@@ -1,15 +1,16 @@
package main
import (
+ "database/sql"
"flag"
"log"
"net/http"
"os"
- "database/sql"
+ "text/template"
"git.32bit.cafe/yequari/webring/internal/models"
- _ "modernc.org/sqlite"
+ _ "modernc.org/sqlite"
)
type application struct {
@@ -17,6 +18,7 @@ type application struct {
infoLog *log.Logger
siteEntries *models.SiteEntryModel
webmasters *models.WebmasterModel
+ templateCache map[string]*template.Template
}
func main() {
@@ -33,11 +35,17 @@ func main() {
}
defer db.Close()
+ templateCache, err := newTemplateCache()
+ if err != nil {
+ errorLog.Fatal(err)
+ }
+
app := &application{
errorLog: errorLog,
infoLog: infoLog,
siteEntries: &models.SiteEntryModel{DB: db},
webmasters: &models.WebmasterModel{DB: db},
+ templateCache: templateCache,
}
srv := &http.Server{
diff --git a/cmd/web/templates.go b/cmd/web/templates.go
new file mode 100644
index 0000000..bac2753
--- /dev/null
+++ b/cmd/web/templates.go
@@ -0,0 +1,48 @@
+package main
+
+import (
+ "path/filepath"
+ "text/template"
+
+ "git.32bit.cafe/yequari/webring/internal/models"
+)
+
+type templateData struct {
+ SiteEntry *models.SiteEntry
+ Webmaster *models.Webmaster
+ SiteEntries []*models.SiteEntry
+}
+
+func newTemplateCache() (map[string]*template.Template, error) {
+ cache := map[string]*template.Template{}
+
+ pages, err := filepath.Glob("./ui/html/pages/*.tmpl.html")
+ if err != nil {
+ return nil, err
+ }
+
+ for _, page := range pages {
+ name := filepath.Base(page)
+
+ ts, err := template.ParseFiles("./ui/html/base.tmpl.html")
+ if err != nil {
+ return nil, err
+ }
+
+ // parse all partials into the template set
+ ts, err = ts.ParseGlob("./ui/html/partials/*.tmpl.html")
+ if err != nil {
+ return nil, err
+ }
+
+ // parse the page template last
+ ts, err = ts.ParseFiles(page)
+ if err != nil {
+ return nil, err
+ }
+
+ cache[name] = ts
+ }
+
+ return cache, nil
+}
diff --git a/internal/models/siteentry.go b/internal/models/siteentry.go
index c307e13..b74fc09 100644
--- a/internal/models/siteentry.go
+++ b/internal/models/siteentry.go
@@ -47,8 +47,7 @@ func (m *SiteEntryModel) Get(id SiteId) (*SiteEntry, error) {
s := &SiteEntry{}
- var timeStr string
- err := row.Scan(&s.Id, &s.Name, &s.Url, &s.Webmaster, &timeStr, &s.Next, &s.Prev)
+ err := row.Scan(&s.Id, &s.Name, &s.Url, &s.Webmaster, &s.DateAdded, &s.Next, &s.Prev)
if err != nil {
if errors.Is(err, sql.ErrNoRows) {
return nil, ErrNoRecord
@@ -56,13 +55,6 @@ func (m *SiteEntryModel) Get(id SiteId) (*SiteEntry, error) {
return nil, err
}
}
- // time is stored as a string in sqlite, so we need to parse it
- // probably is something taken care of in the driver
- dateAdded, err := time.Parse(time.DateTime, timeStr)
- if err != nil {
- return nil, err
- }
- s.DateAdded = dateAdded
return s, nil
}
@@ -76,8 +68,7 @@ func (m *SiteEntryModel) GetByUrl(url string) (*SiteEntry, error) {
s := &SiteEntry{}
- var timeStr string
- err := row.Scan(&s.Id, &s.Name, &s.Url, &s.Webmaster, &timeStr, &s.Next, &s.Prev)
+ err := row.Scan(&s.Id, &s.Name, &s.Url, &s.Webmaster, &s.DateAdded, &s.Next, &s.Prev)
if err != nil {
if errors.Is(err, sql.ErrNoRows) {
return nil, ErrNoRecord
@@ -85,15 +76,8 @@ func (m *SiteEntryModel) GetByUrl(url string) (*SiteEntry, error) {
return nil, err
}
}
- // time is stored as a string in sqlite, so we need to parse it
- // probably is something taken care of in the driver
- s.DateAdded, err = time.Parse(time.DateTime, timeStr)
- if err != nil {
- return nil, err
- }
return s, nil
-
}
// Update existing SiteEntry with the values of passed entry
@@ -119,15 +103,14 @@ func (m *SiteEntryModel) Latest() ([]*SiteEntry, error) {
defer rows.Close()
entries := []*SiteEntry{}
- var timeStr string
+ // var timeStr string
for rows.Next() {
s := &SiteEntry{}
- err = rows.Scan(&s.Id, &s.Name, &s.Url, &s.Webmaster, &timeStr)
+ err = rows.Scan(&s.Id, &s.Name, &s.Url, &s.Webmaster, &s.DateAdded)
if err != nil {
return nil, err
}
- s.DateAdded, err = time.Parse(time.DateTime, timeStr)
if err != nil {
return nil, err
}
diff --git a/ui/html/base.tmpl.html b/ui/html/base.tmpl.html
index 8f42e53..2957ff9 100644
--- a/ui/html/base.tmpl.html
+++ b/ui/html/base.tmpl.html
@@ -8,6 +8,7 @@
Webring
+ {{template "nav" .}}
{{template "main" .}}
diff --git a/ui/html/pages/home.tmpl.html b/ui/html/pages/home.tmpl.html
index 48c09ef..5710007 100644
--- a/ui/html/pages/home.tmpl.html
+++ b/ui/html/pages/home.tmpl.html
@@ -2,5 +2,13 @@
{{define "main"}}
Latest Websites
+{{ if .SiteEntries }}
+
+{{ else }}
There's nothing to see here yet!
+{{ end }}
{{end}}
diff --git a/ui/html/pages/view.tmpl.html b/ui/html/pages/view.tmpl.html
new file mode 100644
index 0000000..6e83c19
--- /dev/null
+++ b/ui/html/pages/view.tmpl.html
@@ -0,0 +1,13 @@
+{{define "title"}}Site Entry #{{.SiteEntry.Id}}{{end}}
+{{define "main"}}
+
+
+ {{.SiteEntry.Name}}
+ #{{.SiteEntry.Id}}
+
+
+
+{{end}}
diff --git a/ui/html/partials/nav.tmpl.html b/ui/html/partials/nav.tmpl.html
new file mode 100644
index 0000000..83045a1
--- /dev/null
+++ b/ui/html/partials/nav.tmpl.html
@@ -0,0 +1,5 @@
+{{define "nav"}}
+
+{{end}}