aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorFelix Hanley <felix@userspace.com.au>2020-02-19 02:17:11 +0000
committerFelix Hanley <felix@userspace.com.au>2020-02-19 02:17:11 +0000
commitee02835f27fc7bd222a34d86cafbd723b05946c0 (patch)
treed918b796f7552ec8f81dea740670659d254c9b90
parent5c23a2bfb751f2435d9d6ebfa4e168b115988f0b (diff)
downloadsws-ee02835f27fc7bd222a34d86cafbd723b05946c0.tar.gz
sws-ee02835f27fc7bd222a34d86cafbd723b05946c0.tar.bz2
Update templates to nest correctly
-rw-r--r--cmd/server/handlers.go15
-rw-r--r--cmd/server/main.go40
-rw-r--r--cmd/server/sites.go15
-rw-r--r--go.mod21
-rw-r--r--public/default.css70
-rw-r--r--templates/charts.tmpl (renamed from templates/partials/barChart.tmpl)2
-rw-r--r--templates/gen.go4
-rw-r--r--templates/home.tmpl5
-rw-r--r--templates/layouts/base.tmpl24
-rw-r--r--templates/layouts/public.tmpl16
-rw-r--r--templates/partials/navMain.tmpl8
-rw-r--r--templates/partials/navService.tmpl5
-rw-r--r--templates/partials/pageFoot.tmpl4
-rw-r--r--templates/partials/pageForList.tmpl7
-rw-r--r--templates/partials/pageHead.tmpl10
-rw-r--r--templates/partials/siteForList.tmpl7
-rw-r--r--templates/site.tmpl27
-rw-r--r--templates/sites.tmpl31
18 files changed, 191 insertions, 120 deletions
diff --git a/cmd/server/handlers.go b/cmd/server/handlers.go
index de3bfa3..e47fd30 100644
--- a/cmd/server/handlers.go
+++ b/cmd/server/handlers.go
@@ -1,20 +1,25 @@
package main
import (
- "html/template"
"net/http"
)
-func handleIndex(tmpls *template.Template) http.HandlerFunc {
+func handleIndex(rndr Renderer) http.HandlerFunc {
return func(w http.ResponseWriter, r *http.Request) {
w.Header().Set("Content-Type", "text/html")
- tmpls.ExecuteTemplate(w, "home", nil)
+ if err := rndr.Render(w, "home", nil); err != nil {
+ log(err)
+ http.Error(w, http.StatusText(500), 500)
+ }
}
}
-func handleExample(tmpls *template.Template) http.HandlerFunc {
+func handleExample(rndr Renderer) http.HandlerFunc {
return func(w http.ResponseWriter, r *http.Request) {
w.Header().Set("Content-Type", "text/html")
- tmpls.ExecuteTemplate(w, "example", nil)
+ if err := rndr.Render(w, "example", nil); err != nil {
+ log(err)
+ http.Error(w, http.StatusText(500), 500)
+ }
}
}
diff --git a/cmd/server/main.go b/cmd/server/main.go
index 386247e..d23fb8f 100644
--- a/cmd/server/main.go
+++ b/cmd/server/main.go
@@ -4,7 +4,6 @@ import (
"context"
"flag"
"fmt"
- "html/template"
"net/http"
"os"
"path/filepath"
@@ -19,6 +18,7 @@ import (
_ "github.com/mattn/go-sqlite3"
"src.userspace.com.au/sws"
"src.userspace.com.au/sws/store"
+ "src.userspace.com.au/templates"
)
// Flags
@@ -44,6 +44,10 @@ func init() {
debug = func(v ...interface{}) {}
}
+type Renderer interface {
+ Render(http.ResponseWriter, string, interface{}) error
+}
+
func main() {
flag.Parse()
@@ -91,18 +95,18 @@ func main() {
st = store.NewSqlite3Store(db)
}
- tmpls := template.Must(loadTemplateHTML([]string{
- "home",
- "sites",
- "example",
- "partials/navMain",
- "partials/pageHead",
- "partials/pageFoot",
- "partials/siteForList",
- "partials/pageForList",
- "partials/barChart",
- }, funcMap))
- debug(tmpls.DefinedTemplates())
+ tmpls, err := LoadHTMLTemplateMap(map[string][]string{
+ "sites": []string{"layouts/base", "sites", "charts"},
+ "site": []string{"layouts/base", "site", "charts"},
+ "home": []string{"layouts/public", "home"},
+ "example": []string{"example"},
+ }, funcMap)
+ if err != nil {
+ log(err)
+ os.Exit(1)
+ }
+ //debug(tmpls.DefinedTemplates())
+ renderer := templates.NewRenderer(tmpls)
r := chi.NewRouter()
r.Use(middleware.RequestID)
@@ -121,10 +125,10 @@ func main() {
// For UI
r.Get("/hits", handleHits(st))
r.Route("/sites", func(r chi.Router) {
- r.Get("/", handleSites(st, tmpls))
+ r.Get("/", handleSites(st, renderer))
r.Route("/{siteID}", func(r chi.Router) {
r.Use(siteCtx)
- r.Get("/", handleSite(st, tmpls))
+ r.Get("/", handleSite(st, renderer))
r.Route("/sparklines", func(r chi.Router) {
r.Get("/{b:\\d+}-{e:\\d+}.svg", sparklineHandler(st))
})
@@ -143,11 +147,11 @@ func main() {
}
// Example
- r.Get("/test.html", handleExample(tmpls))
- r.Get("/test-again.html", handleExample(tmpls))
+ r.Get("/test.html", handleExample(renderer))
+ r.Get("/test-again.html", handleExample(renderer))
r.Route("/", func(r chi.Router) {
- r.Get("/", handleIndex(tmpls))
+ r.Get("/", handleIndex(renderer))
fileServer(r, filepath.Dir(staticPath), "/", http.Dir(staticPath))
})
diff --git a/cmd/server/sites.go b/cmd/server/sites.go
index 7e5cacd..1dc265e 100644
--- a/cmd/server/sites.go
+++ b/cmd/server/sites.go
@@ -1,14 +1,13 @@
package main
import (
- "html/template"
"net/http"
"time"
"src.userspace.com.au/sws"
)
-func handleSites(db sws.SiteStore, tmpls *template.Template) http.HandlerFunc {
+func handleSites(db sws.SiteStore, rndr Renderer) http.HandlerFunc {
return func(w http.ResponseWriter, r *http.Request) {
sites, err := db.GetSites()
if err != nil {
@@ -20,11 +19,14 @@ func handleSites(db sws.SiteStore, tmpls *template.Template) http.HandlerFunc {
}{
Sites: sites,
}
- tmpls.ExecuteTemplate(w, "sites", payload)
+ if err := rndr.Render(w, "sites", payload); err != nil {
+ log(err)
+ http.Error(w, http.StatusText(500), 500)
+ }
}
}
-func handleSite(db sws.SiteStore, tmpls *template.Template) http.HandlerFunc {
+func handleSite(db sws.SiteStore, rndr Renderer) http.HandlerFunc {
return func(w http.ResponseWriter, r *http.Request) {
ctx := r.Context()
site, ok := ctx.Value("site").(*sws.Site)
@@ -64,6 +66,9 @@ func handleSite(db sws.SiteStore, tmpls *template.Template) http.HandlerFunc {
Pages: pages,
Hits: buckets,
}
- tmpls.ExecuteTemplate(w, "site", payload)
+ if err := rndr.Render(w, "site", payload); err != nil {
+ log(err)
+ http.Error(w, http.StatusText(500), 500)
+ }
}
}
diff --git a/go.mod b/go.mod
index ef97b34..c7fdeeb 100644
--- a/go.mod
+++ b/go.mod
@@ -1,26 +1,19 @@
module src.userspace.com.au/sws
require (
- github.com/blend/go-sdk v2.0.0+incompatible // indirect
- github.com/cockroachdb/apd v1.1.0 // indirect
- github.com/go-chi/chi v3.3.3+incompatible
+ github.com/go-chi/chi v4.0.3+incompatible
github.com/golang/freetype v0.0.0-20170609003504-e2365dfdc4a0 // indirect
- github.com/jackc/fake v0.0.0-20150926172116-812a484cc733 // indirect
- github.com/jackc/pgx v3.3.0+incompatible
+ github.com/jackc/pgx v3.6.2+incompatible
github.com/jmoiron/sqlx v1.2.0
- github.com/kr/pretty v0.2.0 // indirect
- github.com/lib/pq v1.3.0 // indirect
- github.com/mattn/go-sqlite3 v1.10.0
- github.com/pkg/errors v0.8.0 // indirect
- github.com/satori/go.uuid v1.2.0 // indirect
- github.com/shopspring/decimal v0.0.0-20200105231215-408a2507e114 // indirect
+ github.com/mattn/go-sqlite3 v2.0.3+incompatible
+ github.com/pkg/errors v0.9.1 // indirect
github.com/speps/go-hashids v2.0.0+incompatible
github.com/wcharczuk/go-chart v2.0.1+incompatible
+ golang.org/x/crypto v0.0.0-20200214034016-1d94cc7ab1c6 // indirect
golang.org/x/image v0.0.0-20200119044424-58c23975cae1 // indirect
- google.golang.org/appengine v1.6.5 // indirect
- gopkg.in/check.v1 v1.0.0-20190902080502-41f04d3bba15 // indirect
+ golang.org/x/text v0.3.2 // indirect
src.userspace.com.au/go-migrate v0.0.0-20200208102934-cf11cf76db3f
- src.userspace.com.au/templates v0.0.0-20200214092258-6bc0451a1d45
+ src.userspace.com.au/templates v0.0.0-20200219010204-50adadd75f25
)
go 1.13
diff --git a/public/default.css b/public/default.css
index f424a07..42f5b81 100644
--- a/public/default.css
+++ b/public/default.css
@@ -1,10 +1,53 @@
+body {
+ background-color: #fffaf7;
+ display: flex;
+ flex-direction: column;
+ font-family: Liberation Sans, Arial, sans-serif;
+ line-height: 1.5;
+ min-height: 100vh;
+ margin: 0;
+}
+ul {
+ list-style: none;
+ padding: 0;
+}
+.page {
+ display: flex;
+ display: flex;
+ flex-direction: column;
+ outline: 1px solid red;
+}
+.sidebar {
+ flex: 0 0 12em;
+ order: -1;
+ outline: 1px solid red;
+}
+main {
+ flex: 1;
+ outline: 1px solid red;
+}
+
+@media (min-width: 768px) {
+ .page {
+ flex-direction: row;
+ flex: 1;
+ }
+ main {
+ flex: 1;
+ }
+ .sidebar {
+ /* 12em is the width of the columns */
+ flex: 0 0 12em;
+ }
+}
+
.chart {
align-items: stretch;
display: flex;
- height: 200px;
- list-style: none;
+ height: 100px;
margin: 0;
- padding: 0;
+ padding-top: 2em;
+ padding-bottom: 2em;
width: 100%;
}
.chart .slot {
@@ -12,29 +55,42 @@
flex: 1 1;
position: relative;
}
+.chart .slot.midnight {
+ border-left: 1px solid #ddd;
+}
+.chart .slot:hover {
+ background: #f5f5f5;
+}
.chart .bar {
background: #4c92ff;
+ border-top-left-radius: 3px;
+ border-top-right-radius: 3px;
bottom: 0;
left: 0;
position: absolute;
right: 0;
}
+.chart .slot:hover .bar {
+ background: #88b6ff;
+}
.chart .slot:before,
.chart .slot:after {
bottom: 100%;
- content: attr(data-date);
+ content: attr(data-count);
display: none;
+ font-size: .75em;
left: 50%;
margin-bottom: .5rem;
- margin-left: -5rem;
+ margin-left: -2.5rem;
position: absolute;
text-align: center;
- width: 10rem;
+ width: 5rem;
}
+/* time */
.chart .slot:after {
+ content: attr(data-date);
margin-top: .5rem;
top: 100%;
- content: attr(data-count) " hits";
}
.chart .slot:hover:before,
.chart .slot:hover:after {
diff --git a/templates/partials/barChart.tmpl b/templates/charts.tmpl
index d8a3db8..aa4ca65 100644
--- a/templates/partials/barChart.tmpl
+++ b/templates/charts.tmpl
@@ -2,7 +2,7 @@
<ul class="chart">
{{ $max := .CountMax }}
{{ range .Buckets }}
- <li class="slot" data-date="{{ .Time|timeHour }}" data-count="{{ .Count }}">
+ <li class="slot{{ if eq .Time.Hour 0 }} midnight{{ end }}" data-date="{{ .Time|timeHour }}" data-count="{{ .Count }}" data-percent="{{ percent .Count $max }}">
<div class="bar" style="height:{{ percent .Count $max }}%" />
</li>
{{ end }}
diff --git a/templates/gen.go b/templates/gen.go
index 81811a9..5fe1f3e 100644
--- a/templates/gen.go
+++ b/templates/gen.go
@@ -9,7 +9,9 @@ import (
)
func main() {
- tmpl := templates.Must(templates.New(templates.EnableHTMLTemplates()))
+ tmpl := templates.Must(templates.New(
+ templates.EnableHTMLTemplates(),
+ ))
if _, err := tmpl.WriteTo(os.Stdout); err != nil {
panic(err)
}
diff --git a/templates/home.tmpl b/templates/home.tmpl
index d95845a..7920916 100644
--- a/templates/home.tmpl
+++ b/templates/home.tmpl
@@ -1,8 +1,5 @@
-{{ define "home" }}
- {{ template "pageHead" }}
- {{ template "navMain" }}
+{{ define "content" }}
<main>
home page
</main>
- {{ template "pageFoot" }}
{{ end }}
diff --git a/templates/layouts/base.tmpl b/templates/layouts/base.tmpl
new file mode 100644
index 0000000..1b7f9ad
--- /dev/null
+++ b/templates/layouts/base.tmpl
@@ -0,0 +1,24 @@
+<!DOCTYPE html>
+<html lang="en-au">
+ <head>
+ <meta name="viewport" content="width=device-width, initial-scale=1">
+ <title>Simple Web Stats</title>
+ <link rel="stylesheet" href="/default.css">
+ </head>
+ <body>
+ <header class="site">
+ </header>
+ <div class="page">
+ <div class="sidebar">
+ <nav>
+ <a href="/">Home</a>
+ <a href="/sites">Sites</a>
+ <a href="/sites/new">New site</a>
+ <a href="/logout">Logout</a>
+ </nav>
+ </div>
+ {{ template "content" . }}
+ </div>
+ <footer></footer>
+ </body>
+</html>
diff --git a/templates/layouts/public.tmpl b/templates/layouts/public.tmpl
new file mode 100644
index 0000000..98a03c2
--- /dev/null
+++ b/templates/layouts/public.tmpl
@@ -0,0 +1,16 @@
+<!DOCTYPE html>
+<html lang="en-au">
+ <head>
+ <meta name="viewport" content="width=device-width, initial-scale=1">
+ <title>Simple Web Stats</title>
+ <link rel="stylesheet" href="/default.css">
+ </head>
+ <body>
+ <header class="site">
+ </header>
+ <div class="page">
+ {{ template "content" . }}
+ </div>
+ <footer></footer>
+ </body>
+</html>
diff --git a/templates/partials/navMain.tmpl b/templates/partials/navMain.tmpl
deleted file mode 100644
index e74f015..0000000
--- a/templates/partials/navMain.tmpl
+++ /dev/null
@@ -1,8 +0,0 @@
-{{ define "navMain" }}
-<nav>
- <a href="/">Home</a>
- <a href="/sites">Sites</a>
- <a href="/sites/new">New site</a>
- <a href="/logout">Logout</a>
-</nav>
-{{ end }}
diff --git a/templates/partials/navService.tmpl b/templates/partials/navService.tmpl
deleted file mode 100644
index 66ef680..0000000
--- a/templates/partials/navService.tmpl
+++ /dev/null
@@ -1,5 +0,0 @@
-{{ define "navService" }}
-<nav>
- <a href="">Stats</a>
-</nav>
-{{ end }}
diff --git a/templates/partials/pageFoot.tmpl b/templates/partials/pageFoot.tmpl
deleted file mode 100644
index d054b3d..0000000
--- a/templates/partials/pageFoot.tmpl
+++ /dev/null
@@ -1,4 +0,0 @@
-{{ define "pageFoot" }}
- </body>
-</html>
-{{ end }}
diff --git a/templates/partials/pageForList.tmpl b/templates/partials/pageForList.tmpl
deleted file mode 100644
index a1d52f5..0000000
--- a/templates/partials/pageForList.tmpl
+++ /dev/null
@@ -1,7 +0,0 @@
-{{ define "pageForList" }}
-<li>
- <span class="path">{{ .Path }}</a>
- <span class="title">{{ .Title }}</span>
- <span class="last-visit">{{ .LastVisitedAt.Unix }}</span>
-</li>
-{{ end }}
diff --git a/templates/partials/pageHead.tmpl b/templates/partials/pageHead.tmpl
deleted file mode 100644
index 6605a0b..0000000
--- a/templates/partials/pageHead.tmpl
+++ /dev/null
@@ -1,10 +0,0 @@
-{{ define "pageHead" }}
-<!DOCTYPE html>
-<html lang="en-au">
- <head>
- <meta name="viewport" content="width=device-width, initial-scale=1">
- <title>Simple Web Stats</title>
- <link rel="stylesheet" href="/default.css">
- </head>
- <body>
-{{ end }}
diff --git a/templates/partials/siteForList.tmpl b/templates/partials/siteForList.tmpl
deleted file mode 100644
index 2a33d24..0000000
--- a/templates/partials/siteForList.tmpl
+++ /dev/null
@@ -1,7 +0,0 @@
-{{ define "siteForList" }}
-<li>
- <a href="/sites/{{ .ID }}/">{{ .Name }}</a>
- <span>{{ .Description }}</span>
- <img src="{{ sparkline .ID }}" />
-</li>
-{{ end }}
diff --git a/templates/site.tmpl b/templates/site.tmpl
new file mode 100644
index 0000000..f52c9cd
--- /dev/null
+++ b/templates/site.tmpl
@@ -0,0 +1,27 @@
+{{ define "content" }}
+ <main>
+ <header>
+ {{ with .Site }}
+ <h1>{{ .Name }}</h1>
+ <span>{{ .Description }}</span>
+ {{ end }}
+ </header>
+ <fig>
+ {{ template "barChart" .Hits }}
+ </fig>
+ <h2>Popular pages</h2>
+ <ul class="pages">
+ {{ range .Pages }}
+ {{ template "pageForList" . }}
+ {{ end }}
+ </ul>
+ </main>
+{{ end }}
+
+{{ define "pageForList" }}
+<li>
+ <h4 class="path">{{ .Path }}</h4>
+ <span class="title">{{ .Title }}</span>
+ <span class="last-visit">{{ .LastVisitedAt.Unix }}</span>
+</li>
+{{ end }}
diff --git a/templates/sites.tmpl b/templates/sites.tmpl
index 0a4d015..c7a2002 100644
--- a/templates/sites.tmpl
+++ b/templates/sites.tmpl
@@ -1,6 +1,4 @@
-{{ define "sites" }}
- {{ template "pageHead" }}
- {{ template "navMain" }}
+{{ define "content" }}
<main>
<header>
<h1>Sites</h1>
@@ -11,27 +9,12 @@
{{ end }}
</ul>
</main>
- {{ template "pageFoot" }}
{{ end }}
-{{ define "site" }}
- {{ template "pageHead" }}
- {{ template "navMain" }}
- <main>
- <header>
- {{ with .Site }}
- <h1>{{ .Name }}</h1>
- <span>{{ .Description }}</span>
- {{ end }}
- </header>
- <fig>
- {{ template "barChart" .Hits }}
- </fig>
- <ul class="pages">
- {{ range .Pages }}
- {{ template "pageForList" . }}
- {{ end }}
- </ul>
- </main>
- {{ template "pageFoot" }}
+{{ define "siteForList" }}
+<li>
+ <a href="/sites/{{ .ID }}/">{{ .Name }}</a>
+ <span>{{ .Description }}</span>
+ <img src="{{ sparkline .ID }}" />
+</li>
{{ end }}