mirror of https://github.com/jlelse/GoBlog
Add blog stats with posts per year
This commit is contained in:
parent
7979fc3ef3
commit
37f36678b2
|
@ -0,0 +1,43 @@
|
|||
package main
|
||||
|
||||
import (
|
||||
"database/sql"
|
||||
"net/http"
|
||||
)
|
||||
|
||||
func serveBlogStats(blog, statsPath string) func(w http.ResponseWriter, r *http.Request) {
|
||||
return func(w http.ResponseWriter, r *http.Request) {
|
||||
var totalCount int
|
||||
row, err := appDbQueryRow("select count(path) as count from posts where blog = @blog", sql.Named("blog", blog))
|
||||
if err != nil {
|
||||
serveError(w, r, err.Error(), http.StatusInternalServerError)
|
||||
return
|
||||
}
|
||||
err = row.Scan(&totalCount)
|
||||
if err != nil {
|
||||
serveError(w, r, err.Error(), http.StatusInternalServerError)
|
||||
return
|
||||
}
|
||||
var years, counts []int
|
||||
rows, err := appDbQuery("select substr(published, 1, 4) as year, count(path) as count from posts where blog = @blog and coalesce(published, '') != '' group by year order by year desc", sql.Named("blog", blog))
|
||||
if err != nil {
|
||||
serveError(w, r, err.Error(), http.StatusInternalServerError)
|
||||
return
|
||||
}
|
||||
for rows.Next() {
|
||||
var year, count int
|
||||
rows.Scan(&year, &count)
|
||||
years = append(years, year)
|
||||
counts = append(counts, count)
|
||||
}
|
||||
render(w, templateBlogStats, &renderData{
|
||||
blogString: blog,
|
||||
Canonical: statsPath,
|
||||
Data: map[string]interface{}{
|
||||
"total": totalCount,
|
||||
"years": years,
|
||||
"counts": counts,
|
||||
},
|
||||
})
|
||||
}
|
||||
}
|
|
@ -59,6 +59,7 @@ type configBlog struct {
|
|||
Menus map[string]*menu `mapstructure:"menus"`
|
||||
Photos *photos `mapstructure:"photos"`
|
||||
Search *search `mapstructure:"search"`
|
||||
BlogStats *blogStats `mapstructure:"blogStats"`
|
||||
CustomPages []*customPage `mapstructure:"custompages"`
|
||||
Telegram *configTelegram `mapstructure:"telegram"`
|
||||
PostAsHome bool `mapstructure:"postAsHome"`
|
||||
|
@ -102,6 +103,13 @@ type search struct {
|
|||
Placeholder string `mapstructure:"placeholder"`
|
||||
}
|
||||
|
||||
type blogStats struct {
|
||||
Enabled bool `mapstructure:"enabled"`
|
||||
Path string `mapstructure:"path"`
|
||||
Title string `mapstructure:"title"`
|
||||
Description string `mapstructure:"description"`
|
||||
}
|
||||
|
||||
type customPage struct {
|
||||
Path string `mapstructure:"path"`
|
||||
Template string `mapstructure:"template"`
|
||||
|
|
10
http.go
10
http.go
|
@ -226,7 +226,7 @@ func buildHandler() (http.Handler, error) {
|
|||
}
|
||||
|
||||
// Photos
|
||||
if blogConfig.Photos.Enabled {
|
||||
if blogConfig.Photos != nil && blogConfig.Photos.Enabled {
|
||||
photoPath := blogPath + blogConfig.Photos.Path
|
||||
handler := servePhotos(blog, photoPath)
|
||||
r.With(cacheMiddleware, minifier.Middleware).Get(photoPath, handler)
|
||||
|
@ -234,7 +234,7 @@ func buildHandler() (http.Handler, error) {
|
|||
}
|
||||
|
||||
// Search
|
||||
if blogConfig.Search.Enabled {
|
||||
if blogConfig.Search != nil && blogConfig.Search.Enabled {
|
||||
searchPath := blogPath + blogConfig.Search.Path
|
||||
handler := serveSearch(blog, searchPath)
|
||||
r.With(cacheMiddleware, minifier.Middleware).Get(searchPath, handler)
|
||||
|
@ -246,6 +246,12 @@ func buildHandler() (http.Handler, error) {
|
|||
r.With(cacheMiddleware, minifier.Middleware).Get(searchResultPath+paginationPath, resultHandler)
|
||||
}
|
||||
|
||||
// Stats
|
||||
if blogConfig.BlogStats != nil && blogConfig.BlogStats.Enabled {
|
||||
statsPath := blogPath + blogConfig.BlogStats.Path
|
||||
r.With(cacheMiddleware, minifier.Middleware).Get(statsPath, serveBlogStats(blog, statsPath))
|
||||
}
|
||||
|
||||
// Year / month archives
|
||||
dates, err := allPublishedDates(blog)
|
||||
if err != nil {
|
||||
|
|
|
@ -33,6 +33,7 @@ const templatePhotosSummary = "photosummary"
|
|||
const templateEditor = "editor"
|
||||
const templateLogin = "login"
|
||||
const templateStaticHome = "statichome"
|
||||
const templateBlogStats = "blogstats"
|
||||
|
||||
var templates map[string]*template.Template
|
||||
var templateFunctions template.FuncMap
|
||||
|
|
|
@ -0,0 +1,35 @@
|
|||
{{ define "title" }}
|
||||
<title>{{ with .Blog.BlogStats.Title }}{{ . }} - {{ end }}{{ .Blog.Title }}</title>
|
||||
{{ end }}
|
||||
|
||||
{{ define "main" }}
|
||||
<main>
|
||||
{{ with .Blog.BlogStats.Title }}<h1>{{ . }}</h1>{{ end }}
|
||||
{{ with .Blog.BlogStats.Description }}{{ md . }}{{ end }}
|
||||
<table class="p">
|
||||
<thead>
|
||||
<tr>
|
||||
<th style="text-align:left">{{ string .Blog.Lang "year" }}</th>
|
||||
<th style="text-align:right">{{ string .Blog.Lang "count" }}</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
{{ $counts := .Data.counts }}
|
||||
{{ range $i, $year := .Data.years }}
|
||||
<tr>
|
||||
<td style="text-align:left">{{ $year }}</td>
|
||||
<td style="text-align:right">{{ index $counts $i }}</td>
|
||||
</tr>
|
||||
{{ end }}
|
||||
<tr>
|
||||
<td style="text-align:left"><b>{{ string .Blog.Lang "total" }}</b></td>
|
||||
<td style="text-align:right">{{ .Data.total }}</td>
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
</main>
|
||||
{{ end }}
|
||||
|
||||
{{ define "blogstats" }}
|
||||
{{ template "base" . }}
|
||||
{{ end }}
|
|
@ -11,4 +11,7 @@ speak: "Lies mir bitte vor."
|
|||
stopspeak: "Hör auf zu sprechen!"
|
||||
oldcontent: "⚠️ Dieser Eintrag ist bereits über ein Jahr alt. Er ist möglicherweise nicht mehr aktuell. Meinungen können sich geändert haben."
|
||||
search: "Suchen"
|
||||
shorturl: "Kurz-URL:"
|
||||
shorturl: "Kurz-URL:"
|
||||
year: "Jahr"
|
||||
count: "Anzahl"
|
||||
total: "Gesamt"
|
|
@ -30,4 +30,7 @@ upload: "Upload"
|
|||
login: "Login"
|
||||
username: "Username"
|
||||
password: "Password"
|
||||
shorturl: "Short URL:"
|
||||
shorturl: "Short URL:"
|
||||
year: "Year"
|
||||
count: "Count"
|
||||
total: "Total"
|
Loading…
Reference in New Issue