mirror of https://github.com/jlelse/GoBlog
Advance the blogstats even more
This commit is contained in:
parent
47ddcc4028
commit
e15d33b0dd
54
blogstats.go
54
blogstats.go
|
@ -1,83 +1,95 @@
|
||||||
package main
|
package main
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"database/sql"
|
||||||
"net/http"
|
"net/http"
|
||||||
"strconv"
|
|
||||||
|
servertiming "github.com/mitchellh/go-server-timing"
|
||||||
)
|
)
|
||||||
|
|
||||||
func serveBlogStats(w http.ResponseWriter, r *http.Request) {
|
func serveBlogStats(w http.ResponseWriter, r *http.Request) {
|
||||||
blog := r.Context().Value(blogContextKey).(string)
|
blog := r.Context().Value(blogContextKey).(string)
|
||||||
|
// Start timing
|
||||||
|
t := servertiming.FromContext(r.Context()).NewMetric("sq").Start()
|
||||||
// Build query
|
// Build query
|
||||||
prq := &postsRequestConfig{
|
prq := &postsRequestConfig{
|
||||||
blog: blog,
|
blog: blog,
|
||||||
status: statusPublished,
|
status: statusPublished,
|
||||||
}
|
}
|
||||||
query, params := buildPostsQuery(prq)
|
query, params := buildPostsQuery(prq)
|
||||||
|
postCount := "count(distinct path) as postcount"
|
||||||
|
charCount := "sum(length(distinct content))"
|
||||||
|
wordCount := "sum(wordcount(distinct content)) as wordcount"
|
||||||
|
wordsPerPost := "round(wordcount/postcount,0)"
|
||||||
|
type statsTableType struct {
|
||||||
|
Name, Posts, Chars, Words, WordsPerPost string
|
||||||
|
}
|
||||||
// Count total posts
|
// Count total posts
|
||||||
row, err := appDbQueryRow("select count(distinct path) from ("+query+")", params...)
|
row, err := appDbQueryRow("select *, "+wordsPerPost+" from (select "+postCount+", "+charCount+", "+wordCount+" from ("+query+"))", params...)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
serveError(w, r, err.Error(), http.StatusInternalServerError)
|
serveError(w, r, err.Error(), http.StatusInternalServerError)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
var totalCount int
|
total := statsTableType{}
|
||||||
if err = row.Scan(&totalCount); err != nil {
|
if err = row.Scan(&total.Posts, &total.Chars, &total.Words, &total.WordsPerPost); err != nil {
|
||||||
serveError(w, r, err.Error(), http.StatusInternalServerError)
|
serveError(w, r, err.Error(), http.StatusInternalServerError)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
// Count posts per year
|
// Count posts per year
|
||||||
rows, err := appDbQuery("select substr(published, 1, 4) as year, count(distinct path) as count from ("+query+") where published != '' group by year order by year desc", params...)
|
rows, err := appDbQuery("select *, "+wordsPerPost+" from (select substr(published, 1, 4) as year, "+postCount+", "+charCount+", "+wordCount+" from ("+query+") where published != '' group by year order by year desc)", params...)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
serveError(w, r, err.Error(), http.StatusInternalServerError)
|
serveError(w, r, err.Error(), http.StatusInternalServerError)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
var years []stringPair
|
var years []statsTableType
|
||||||
|
year := statsTableType{}
|
||||||
for rows.Next() {
|
for rows.Next() {
|
||||||
var year, count string
|
if err = rows.Scan(&year.Name, &year.Posts, &year.Chars, &year.Words, &year.WordsPerPost); err == nil {
|
||||||
if err = rows.Scan(&year, &count); err == nil {
|
years = append(years, year)
|
||||||
years = append(years, stringPair{year, count})
|
|
||||||
} else {
|
} else {
|
||||||
serveError(w, r, err.Error(), http.StatusInternalServerError)
|
serveError(w, r, err.Error(), http.StatusInternalServerError)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
// Count posts without date
|
// Count posts without date
|
||||||
row, err = appDbQueryRow("select count(distinct path) from ("+query+") where published = ''", params...)
|
row, err = appDbQueryRow("select *, "+wordsPerPost+" from (select "+postCount+", "+charCount+", "+wordCount+" from ("+query+") where published = '')", params...)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
serveError(w, r, err.Error(), http.StatusInternalServerError)
|
serveError(w, r, err.Error(), http.StatusInternalServerError)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
var noDateCount int
|
noDate := statsTableType{}
|
||||||
if err = row.Scan(&noDateCount); err != nil {
|
if err = row.Scan(&noDate.Posts, &noDate.Chars, &noDate.Words, &noDate.WordsPerPost); err != nil {
|
||||||
serveError(w, r, err.Error(), http.StatusInternalServerError)
|
serveError(w, r, err.Error(), http.StatusInternalServerError)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
// Count posts per month per year
|
// Count posts per month per year
|
||||||
months := map[string][]stringPair{}
|
months := map[string][]statsTableType{}
|
||||||
|
month := statsTableType{}
|
||||||
for _, year := range years {
|
for _, year := range years {
|
||||||
prq.publishedYear, _ = strconv.Atoi(year.First)
|
rows, err = appDbQuery("select *, "+wordsPerPost+" from (select substr(published, 6, 2) as month, "+postCount+", "+charCount+", "+wordCount+" from ("+query+") where published != '' and substr(published, 1, 4) = @year group by month order by month desc)", append(params, sql.Named("year", year.Name))...)
|
||||||
query, params = buildPostsQuery(prq)
|
|
||||||
rows, err = appDbQuery("select substr(published, 6, 2) as month, count(distinct path) as count from ("+query+") where published != '' group by month order by month desc", params...)
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
serveError(w, r, err.Error(), http.StatusInternalServerError)
|
serveError(w, r, err.Error(), http.StatusInternalServerError)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
for rows.Next() {
|
for rows.Next() {
|
||||||
var month, count string
|
if err = rows.Scan(&month.Name, &month.Posts, &month.Chars, &month.Words, &month.WordsPerPost); err == nil {
|
||||||
if err = rows.Scan(&month, &count); err == nil {
|
months[year.Name] = append(months[year.Name], month)
|
||||||
months[year.First] = append(months[year.First], stringPair{month, count})
|
|
||||||
} else {
|
} else {
|
||||||
serveError(w, r, err.Error(), http.StatusInternalServerError)
|
serveError(w, r, err.Error(), http.StatusInternalServerError)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
// Stop timing
|
||||||
|
t.Stop()
|
||||||
|
// Render
|
||||||
render(w, r, templateBlogStats, &renderData{
|
render(w, r, templateBlogStats, &renderData{
|
||||||
BlogString: blog,
|
BlogString: blog,
|
||||||
Canonical: blogPath(blog) + appConfig.Blogs[blog].BlogStats.Path,
|
Canonical: blogPath(blog) + appConfig.Blogs[blog].BlogStats.Path,
|
||||||
Data: map[string]interface{}{
|
Data: map[string]interface{}{
|
||||||
"total": totalCount,
|
"total": total,
|
||||||
"years": years,
|
"years": years,
|
||||||
"withoutdate": noDateCount,
|
"withoutdate": noDate,
|
||||||
"months": months,
|
"months": months,
|
||||||
},
|
},
|
||||||
})
|
})
|
||||||
|
|
|
@ -22,6 +22,9 @@ func initDatabase() (err error) {
|
||||||
if err := c.RegisterFunc("tolocal", toLocalSafe, true); err != nil {
|
if err := c.RegisterFunc("tolocal", toLocalSafe, true); err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
if err := c.RegisterFunc("wordcount", wordCount, true); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
return nil
|
return nil
|
||||||
},
|
},
|
||||||
})
|
})
|
||||||
|
|
7
go.mod
7
go.mod
|
@ -13,6 +13,7 @@ require (
|
||||||
github.com/dgraph-io/ristretto v0.0.4-0.20210311064603-e4f298c8aa88
|
github.com/dgraph-io/ristretto v0.0.4-0.20210311064603-e4f298c8aa88
|
||||||
github.com/dgrijalva/jwt-go v3.2.0+incompatible
|
github.com/dgrijalva/jwt-go v3.2.0+incompatible
|
||||||
github.com/elnormous/contenttype v1.0.0
|
github.com/elnormous/contenttype v1.0.0
|
||||||
|
github.com/felixge/httpsnoop v1.0.2 // indirect
|
||||||
github.com/go-chi/chi/v5 v5.0.2
|
github.com/go-chi/chi/v5 v5.0.2
|
||||||
github.com/go-fed/httpsig v1.1.0
|
github.com/go-fed/httpsig v1.1.0
|
||||||
github.com/go-sql-driver/mysql v1.5.0 // indirect
|
github.com/go-sql-driver/mysql v1.5.0 // indirect
|
||||||
|
@ -47,7 +48,7 @@ require (
|
||||||
github.com/spf13/jwalterweatherman v1.1.0 // indirect
|
github.com/spf13/jwalterweatherman v1.1.0 // indirect
|
||||||
github.com/spf13/viper v1.7.1
|
github.com/spf13/viper v1.7.1
|
||||||
github.com/tdewolff/minify/v2 v2.9.16
|
github.com/tdewolff/minify/v2 v2.9.16
|
||||||
github.com/tdewolff/parse/v2 v2.5.15 // indirect
|
github.com/tdewolff/parse/v2 v2.5.16 // indirect
|
||||||
github.com/thoas/go-funk v0.8.0
|
github.com/thoas/go-funk v0.8.0
|
||||||
github.com/tomnomnom/linkheader v0.0.0-20180905144013-02ca5825eb80
|
github.com/tomnomnom/linkheader v0.0.0-20180905144013-02ca5825eb80
|
||||||
github.com/vcraescu/go-paginator v1.0.1-0.20201114172518-2cfc59fe05c2
|
github.com/vcraescu/go-paginator v1.0.1-0.20201114172518-2cfc59fe05c2
|
||||||
|
@ -58,9 +59,9 @@ require (
|
||||||
golang.org/x/crypto v0.0.0-20210421170649-83a5a9bb288b // indirect
|
golang.org/x/crypto v0.0.0-20210421170649-83a5a9bb288b // indirect
|
||||||
golang.org/x/lint v0.0.0-20201208152925-83fdc39ff7b5 // indirect
|
golang.org/x/lint v0.0.0-20201208152925-83fdc39ff7b5 // indirect
|
||||||
golang.org/x/mod v0.4.1 // indirect
|
golang.org/x/mod v0.4.1 // indirect
|
||||||
golang.org/x/net v0.0.0-20210421230115-4e50805a0758
|
golang.org/x/net v0.0.0-20210428140749-89ef3d95e781
|
||||||
golang.org/x/sync v0.0.0-20210220032951-036812b2e83c
|
golang.org/x/sync v0.0.0-20210220032951-036812b2e83c
|
||||||
golang.org/x/sys v0.0.0-20210423082822-04245dca01da // indirect
|
golang.org/x/sys v0.0.0-20210426230700-d19ff857e887 // indirect
|
||||||
golang.org/x/term v0.0.0-20201210144234-2321bbc49cbf // indirect
|
golang.org/x/term v0.0.0-20201210144234-2321bbc49cbf // indirect
|
||||||
gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c // indirect
|
gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c // indirect
|
||||||
gopkg.in/ini.v1 v1.62.0 // indirect
|
gopkg.in/ini.v1 v1.62.0 // indirect
|
||||||
|
|
13
go.sum
13
go.sum
|
@ -73,8 +73,9 @@ github.com/elnormous/contenttype v1.0.0 h1:cTLou7K7uQMsPEmRiTJosAznsPcYuoBmXMrFA
|
||||||
github.com/elnormous/contenttype v1.0.0/go.mod h1:ngVcyGGU8pnn4QJ5sL4StrNgc/wmXZXy5IQSBuHOFPg=
|
github.com/elnormous/contenttype v1.0.0/go.mod h1:ngVcyGGU8pnn4QJ5sL4StrNgc/wmXZXy5IQSBuHOFPg=
|
||||||
github.com/fatih/color v1.7.0/go.mod h1:Zm6kSWBoL9eyXnKyktHP6abPY2pDugNf5KwzbycvMj4=
|
github.com/fatih/color v1.7.0/go.mod h1:Zm6kSWBoL9eyXnKyktHP6abPY2pDugNf5KwzbycvMj4=
|
||||||
github.com/felixge/httpsnoop v1.0.0/go.mod h1:3+D9sFq0ahK/JeJPhCBUV1xlf4/eIYrUQaxulT0VzX8=
|
github.com/felixge/httpsnoop v1.0.0/go.mod h1:3+D9sFq0ahK/JeJPhCBUV1xlf4/eIYrUQaxulT0VzX8=
|
||||||
github.com/felixge/httpsnoop v1.0.1 h1:lvB5Jl89CsZtGIWuTcDM1E/vkVs49/Ml7JJe07l8SPQ=
|
|
||||||
github.com/felixge/httpsnoop v1.0.1/go.mod h1:m8KPJKqk1gH5J9DgRY2ASl2lWCfGKXixSwevea8zH2U=
|
github.com/felixge/httpsnoop v1.0.1/go.mod h1:m8KPJKqk1gH5J9DgRY2ASl2lWCfGKXixSwevea8zH2U=
|
||||||
|
github.com/felixge/httpsnoop v1.0.2 h1:+nS9g82KMXccJ/wp0zyRW9ZBHFETmMGtkk+2CTTrW4o=
|
||||||
|
github.com/felixge/httpsnoop v1.0.2/go.mod h1:m8KPJKqk1gH5J9DgRY2ASl2lWCfGKXixSwevea8zH2U=
|
||||||
github.com/fsnotify/fsnotify v1.4.3-0.20170329110642-4da3e2cfbabc/go.mod h1:jwhsz4b93w/PPRr/qN1Yymfu8t87LnFCMoQvtojpjFo=
|
github.com/fsnotify/fsnotify v1.4.3-0.20170329110642-4da3e2cfbabc/go.mod h1:jwhsz4b93w/PPRr/qN1Yymfu8t87LnFCMoQvtojpjFo=
|
||||||
github.com/fsnotify/fsnotify v1.4.7/go.mod h1:jwhsz4b93w/PPRr/qN1Yymfu8t87LnFCMoQvtojpjFo=
|
github.com/fsnotify/fsnotify v1.4.7/go.mod h1:jwhsz4b93w/PPRr/qN1Yymfu8t87LnFCMoQvtojpjFo=
|
||||||
github.com/fsnotify/fsnotify v1.4.9 h1:hsms1Qyu0jgnwNXIxa+/V/PDsU6CfLf6CNO8H7IWoS4=
|
github.com/fsnotify/fsnotify v1.4.9 h1:hsms1Qyu0jgnwNXIxa+/V/PDsU6CfLf6CNO8H7IWoS4=
|
||||||
|
@ -325,8 +326,8 @@ github.com/subosito/gotenv v1.2.0/go.mod h1:N0PQaV/YGNqwC0u51sEeR/aUtSLEXKX9iv69
|
||||||
github.com/tdewolff/minify/v2 v2.9.16 h1:2Pv8pFRX/ZfjTRYX2xzcuNrkEJqU5TfriNJJYOeN3rI=
|
github.com/tdewolff/minify/v2 v2.9.16 h1:2Pv8pFRX/ZfjTRYX2xzcuNrkEJqU5TfriNJJYOeN3rI=
|
||||||
github.com/tdewolff/minify/v2 v2.9.16/go.mod h1:cjMkr4ZgFjqxXAQ1kR9Fm4l1046mmONd2g6yMzGuN/w=
|
github.com/tdewolff/minify/v2 v2.9.16/go.mod h1:cjMkr4ZgFjqxXAQ1kR9Fm4l1046mmONd2g6yMzGuN/w=
|
||||||
github.com/tdewolff/parse/v2 v2.5.14/go.mod h1:WzaJpRSbwq++EIQHYIRTpbYKNA3gn9it1Ik++q4zyho=
|
github.com/tdewolff/parse/v2 v2.5.14/go.mod h1:WzaJpRSbwq++EIQHYIRTpbYKNA3gn9it1Ik++q4zyho=
|
||||||
github.com/tdewolff/parse/v2 v2.5.15 h1:hYZKJZ0KfHMGhN3+hER4R9gQM/umJThkeeyJNtsO86o=
|
github.com/tdewolff/parse/v2 v2.5.16 h1:ADVB3h2AR2jkLhY1LttDqRj3FFPDgSa0RZUBq5+q/t8=
|
||||||
github.com/tdewolff/parse/v2 v2.5.15/go.mod h1:WzaJpRSbwq++EIQHYIRTpbYKNA3gn9it1Ik++q4zyho=
|
github.com/tdewolff/parse/v2 v2.5.16/go.mod h1:WzaJpRSbwq++EIQHYIRTpbYKNA3gn9it1Ik++q4zyho=
|
||||||
github.com/tdewolff/test v1.0.6 h1:76mzYJQ83Op284kMT+63iCNCI7NEERsIN8dLM+RiKr4=
|
github.com/tdewolff/test v1.0.6 h1:76mzYJQ83Op284kMT+63iCNCI7NEERsIN8dLM+RiKr4=
|
||||||
github.com/tdewolff/test v1.0.6/go.mod h1:6DAvZliBAAnD7rhVgwaM7DE5/d9NMOAJ09SqYqeK4QE=
|
github.com/tdewolff/test v1.0.6/go.mod h1:6DAvZliBAAnD7rhVgwaM7DE5/d9NMOAJ09SqYqeK4QE=
|
||||||
github.com/thoas/go-funk v0.8.0 h1:JP9tKSvnpFVclYgDM0Is7FD9M4fhPvqA0s0BsXmzSRQ=
|
github.com/thoas/go-funk v0.8.0 h1:JP9tKSvnpFVclYgDM0Is7FD9M4fhPvqA0s0BsXmzSRQ=
|
||||||
|
@ -414,8 +415,9 @@ golang.org/x/net v0.0.0-20200202094626-16171245cfb2/go.mod h1:z5CRVTTTmAJ677TzLL
|
||||||
golang.org/x/net v0.0.0-20200707034311-ab3426394381/go.mod h1:/O7V0waA8r7cgGh81Ro3o1hOxt32SMVPicZroKQ2sZA=
|
golang.org/x/net v0.0.0-20200707034311-ab3426394381/go.mod h1:/O7V0waA8r7cgGh81Ro3o1hOxt32SMVPicZroKQ2sZA=
|
||||||
golang.org/x/net v0.0.0-20201021035429-f5854403a974/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU=
|
golang.org/x/net v0.0.0-20201021035429-f5854403a974/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU=
|
||||||
golang.org/x/net v0.0.0-20210226172049-e18ecbb05110/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg=
|
golang.org/x/net v0.0.0-20210226172049-e18ecbb05110/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg=
|
||||||
golang.org/x/net v0.0.0-20210421230115-4e50805a0758 h1:aEpZnXcAmXkd6AvLb2OPt+EN1Zu/8Ne3pCqPjja5PXY=
|
|
||||||
golang.org/x/net v0.0.0-20210421230115-4e50805a0758/go.mod h1:72T/g9IO56b78aLF+1Kcs5dz7/ng1VjMUvfKvpfy+jM=
|
golang.org/x/net v0.0.0-20210421230115-4e50805a0758/go.mod h1:72T/g9IO56b78aLF+1Kcs5dz7/ng1VjMUvfKvpfy+jM=
|
||||||
|
golang.org/x/net v0.0.0-20210428140749-89ef3d95e781 h1:DzZ89McO9/gWPsQXS/FVKAlG02ZjaQ6AlZRBimEYOd0=
|
||||||
|
golang.org/x/net v0.0.0-20210428140749-89ef3d95e781/go.mod h1:OJAsFXCWl8Ukc7SiCT/9KSuxbyM7479/AVlXFRxuMCk=
|
||||||
golang.org/x/oauth2 v0.0.0-20170912212905-13449ad91cb2/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U=
|
golang.org/x/oauth2 v0.0.0-20170912212905-13449ad91cb2/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U=
|
||||||
golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U=
|
golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U=
|
||||||
golang.org/x/oauth2 v0.0.0-20190226205417-e64efc72b421/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw=
|
golang.org/x/oauth2 v0.0.0-20190226205417-e64efc72b421/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw=
|
||||||
|
@ -451,8 +453,9 @@ golang.org/x/sys v0.0.0-20201119102817-f84b799fce68/go.mod h1:h1NjWce9XRLGQEsW7w
|
||||||
golang.org/x/sys v0.0.0-20210119212857-b64e53b001e4/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
golang.org/x/sys v0.0.0-20210119212857-b64e53b001e4/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||||
golang.org/x/sys v0.0.0-20210303074136-134d130e1a04/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
golang.org/x/sys v0.0.0-20210303074136-134d130e1a04/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||||
golang.org/x/sys v0.0.0-20210420072515-93ed5bcd2bfe/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
golang.org/x/sys v0.0.0-20210420072515-93ed5bcd2bfe/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||||
golang.org/x/sys v0.0.0-20210423082822-04245dca01da h1:b3NXsE2LusjYGGjL5bxEVZZORm/YEFFrWFjR8eFrw/c=
|
|
||||||
golang.org/x/sys v0.0.0-20210423082822-04245dca01da/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
golang.org/x/sys v0.0.0-20210423082822-04245dca01da/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||||
|
golang.org/x/sys v0.0.0-20210426230700-d19ff857e887 h1:dXfMednGJh/SUUFjTLsWJz3P+TQt9qnR11GgeI3vWKs=
|
||||||
|
golang.org/x/sys v0.0.0-20210426230700-d19ff857e887/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||||
golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo=
|
golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo=
|
||||||
golang.org/x/term v0.0.0-20201210144234-2321bbc49cbf h1:MZ2shdL+ZM/XzY3ZGOnh4Nlpnxz5GSOhOmtHo3iPU6M=
|
golang.org/x/term v0.0.0-20201210144234-2321bbc49cbf h1:MZ2shdL+ZM/XzY3ZGOnh4Nlpnxz5GSOhOmtHo3iPU6M=
|
||||||
golang.org/x/term v0.0.0-20201210144234-2321bbc49cbf/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo=
|
golang.org/x/term v0.0.0-20201210144234-2321bbc49cbf/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo=
|
||||||
|
|
|
@ -10,30 +10,45 @@
|
||||||
<thead>
|
<thead>
|
||||||
<tr>
|
<tr>
|
||||||
<th class="tal">{{ string .Blog.Lang "year" }}</th>
|
<th class="tal">{{ string .Blog.Lang "year" }}</th>
|
||||||
<th class="tar">{{ string .Blog.Lang "count" }}</th>
|
<th class="tar">{{ string .Blog.Lang "posts" }}</th>
|
||||||
|
<th class="tar">~{{ string .Blog.Lang "chars" }}</th>
|
||||||
|
<th class="tar">~{{ string .Blog.Lang "words" }}</th>
|
||||||
|
<th class="tar">~{{ string .Blog.Lang "wordsperpost" }}</th>
|
||||||
</tr>
|
</tr>
|
||||||
</thead>
|
</thead>
|
||||||
<tbody>
|
<tbody>
|
||||||
{{ $months := .Data.months }}
|
{{ $months := .Data.months }}
|
||||||
{{ range $year := .Data.years }}
|
{{ range $year := .Data.years }}
|
||||||
<tr class="statsyear" data-year="{{ $year.First }}">
|
<tr class="statsyear" data-year="{{ $year.Name }}">
|
||||||
<td class="tal"><b>{{ $year.First }}</b></td>
|
<td class="tal">{{ $year.Name }}</td>
|
||||||
<td class="tar">{{ $year.Second }}</td>
|
<td class="tar">{{ $year.Posts }}</td>
|
||||||
|
<td class="tar">{{ $year.Chars }}</td>
|
||||||
|
<td class="tar">{{ $year.Words }}</td>
|
||||||
|
<td class="tar">{{ $year.WordsPerPost }}</td>
|
||||||
</tr>
|
</tr>
|
||||||
{{ range $month := (index $months $year.First) }}
|
{{ range $month := (index $months $year.Name) }}
|
||||||
<tr class="statsmonth hide" data-year="{{ $year.First }}">
|
<tr class="statsmonth hide" data-year="{{ $year.Name }}">
|
||||||
<td class="tal">{{ $month.First }}</td>
|
<td class="tal">{{ $year.Name }}-{{ $month.Name }}</td>
|
||||||
<td class="tar">{{ $month.Second }}</td>
|
<td class="tar">{{ $month.Posts }}</td>
|
||||||
|
<td class="tar">{{ $month.Chars }}</td>
|
||||||
|
<td class="tar">{{ $month.Words }}</td>
|
||||||
|
<td class="tar">{{ $month.WordsPerPost }}</td>
|
||||||
</tr>
|
</tr>
|
||||||
{{ end }}
|
{{ end }}
|
||||||
{{ end }}
|
{{ end }}
|
||||||
<tr>
|
<tr>
|
||||||
<td class="tal"><b>{{ string .Blog.Lang "withoutdate" }}</b></td>
|
<td class="tal">{{ string .Blog.Lang "withoutdate" }}</td>
|
||||||
<td class="tar">{{ .Data.withoutdate }}</td>
|
<td class="tar">{{ .Data.withoutdate.Posts }}</td>
|
||||||
|
<td class="tar">{{ .Data.withoutdate.Chars }}</td>
|
||||||
|
<td class="tar">{{ .Data.withoutdate.Words }}</td>
|
||||||
|
<td class="tar">{{ .Data.withoutdate.WordsPerPost }}</td>
|
||||||
</tr>
|
</tr>
|
||||||
<tr>
|
<tr>
|
||||||
<td class="tal"><u><b>{{ string .Blog.Lang "total" }}</b></u></td>
|
<td class="tal"><b>{{ string .Blog.Lang "total" }}</b></td>
|
||||||
<td class="tar">{{ .Data.total }}</td>
|
<td class="tar">{{ .Data.total.Posts }}</td>
|
||||||
|
<td class="tar">{{ .Data.total.Chars }}</td>
|
||||||
|
<td class="tar">{{ .Data.total.Words }}</td>
|
||||||
|
<td class="tar">{{ .Data.total.WordsPerPost }}</td>
|
||||||
</tr>
|
</tr>
|
||||||
</tbody>
|
</tbody>
|
||||||
</table>
|
</table>
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
acommentby: "Ein Kommentar von"
|
acommentby: "Ein Kommentar von"
|
||||||
|
chars: "Buchstaben"
|
||||||
comment: "Kommentar"
|
comment: "Kommentar"
|
||||||
comments: "Kommentare"
|
comments: "Kommentare"
|
||||||
count: "Anzahl"
|
|
||||||
create: "Erstellen"
|
create: "Erstellen"
|
||||||
delete: "Löschen"
|
delete: "Löschen"
|
||||||
docomment: "Kommentieren"
|
docomment: "Kommentieren"
|
||||||
|
@ -13,6 +13,7 @@ likeof: "Gefällt mir von"
|
||||||
next: "Weiter"
|
next: "Weiter"
|
||||||
noposts: "Hier sind keine Posts."
|
noposts: "Hier sind keine Posts."
|
||||||
oldcontent: "⚠️ Dieser Eintrag ist bereits über ein Jahr alt. Er ist möglicherweise nicht mehr aktuell. Meinungen können sich geändert haben."
|
oldcontent: "⚠️ Dieser Eintrag ist bereits über ein Jahr alt. Er ist möglicherweise nicht mehr aktuell. Meinungen können sich geändert haben."
|
||||||
|
posts: "Posts"
|
||||||
prev: "Zurück"
|
prev: "Zurück"
|
||||||
publishedon: "Veröffentlicht am"
|
publishedon: "Veröffentlicht am"
|
||||||
replyto: "Antwort an"
|
replyto: "Antwort an"
|
||||||
|
@ -30,4 +31,6 @@ updatedon: "Aktualisiert am"
|
||||||
upload: "Hochladen"
|
upload: "Hochladen"
|
||||||
view: "Anschauen"
|
view: "Anschauen"
|
||||||
withoutdate: "Ohne Datum"
|
withoutdate: "Ohne Datum"
|
||||||
|
words: "Wörter"
|
||||||
|
wordsperpost: "Wörter pro Post"
|
||||||
year: "Jahr"
|
year: "Jahr"
|
|
@ -4,9 +4,9 @@ approved: "Approved"
|
||||||
authenticate: "Authenticate"
|
authenticate: "Authenticate"
|
||||||
captcha: "Captcha"
|
captcha: "Captcha"
|
||||||
captchainstructions: "Please enter the digits from the image above"
|
captchainstructions: "Please enter the digits from the image above"
|
||||||
|
chars: "Characters"
|
||||||
comment: "Comment"
|
comment: "Comment"
|
||||||
comments: "Comments"
|
comments: "Comments"
|
||||||
count: "Count"
|
|
||||||
create: "Create"
|
create: "Create"
|
||||||
delete: "Delete"
|
delete: "Delete"
|
||||||
docomment: "Comment"
|
docomment: "Comment"
|
||||||
|
@ -24,6 +24,7 @@ noposts: "There are no posts here."
|
||||||
notifications: "Notifications"
|
notifications: "Notifications"
|
||||||
oldcontent: "⚠️ This entry is already over one year old. It may no longer be up to date. Opinions may have changed."
|
oldcontent: "⚠️ This entry is already over one year old. It may no longer be up to date. Opinions may have changed."
|
||||||
password: "Password"
|
password: "Password"
|
||||||
|
posts: "Posts"
|
||||||
prev: "Previous"
|
prev: "Previous"
|
||||||
publishedon: "Published on"
|
publishedon: "Published on"
|
||||||
replyto: "Reply to"
|
replyto: "Reply to"
|
||||||
|
@ -48,4 +49,6 @@ view: "View"
|
||||||
webmentions: "Webmentions"
|
webmentions: "Webmentions"
|
||||||
websiteopt: "Website (optional)"
|
websiteopt: "Website (optional)"
|
||||||
withoutdate: "Without date"
|
withoutdate: "Without date"
|
||||||
|
words: "Words"
|
||||||
|
wordsperpost: "Words per post"
|
||||||
year: "Year"
|
year: "Year"
|
Loading…
Reference in New Issue