Blogstats with months (on click)

This commit is contained in:
Jan-Lukas Else 2021-04-23 20:52:12 +02:00
parent 9d63d0632e
commit 47ddcc4028
7 changed files with 82 additions and 22 deletions

View File

@ -2,15 +2,17 @@ package main
import ( import (
"net/http" "net/http"
"strconv"
) )
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)
// Build query // Build query
query, params := buildPostsQuery(&postsRequestConfig{ prq := &postsRequestConfig{
blog: blog, blog: blog,
status: statusPublished, status: statusPublished,
}) }
query, params := buildPostsQuery(prq)
// Count total posts // Count total posts
row, err := appDbQueryRow("select count(distinct path) from ("+query+")", params...) row, err := appDbQueryRow("select count(distinct path) from ("+query+")", params...)
if err != nil { if err != nil {
@ -28,21 +30,55 @@ func serveBlogStats(w http.ResponseWriter, r *http.Request) {
serveError(w, r, err.Error(), http.StatusInternalServerError) serveError(w, r, err.Error(), http.StatusInternalServerError)
return return
} }
var years, counts []int var years []stringPair
for rows.Next() { for rows.Next() {
var year, count int var year, count string
if err = rows.Scan(&year, &count); err == nil { if err = rows.Scan(&year, &count); err == nil {
years = append(years, year) years = append(years, stringPair{year, count})
counts = append(counts, count) } else {
serveError(w, r, err.Error(), http.StatusInternalServerError)
return
}
}
// Count posts without date
row, err = appDbQueryRow("select count(distinct path) from ("+query+") where published = ''", params...)
if err != nil {
serveError(w, r, err.Error(), http.StatusInternalServerError)
return
}
var noDateCount int
if err = row.Scan(&noDateCount); err != nil {
serveError(w, r, err.Error(), http.StatusInternalServerError)
return
}
// Count posts per month per year
months := map[string][]stringPair{}
for _, year := range years {
prq.publishedYear, _ = strconv.Atoi(year.First)
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 {
serveError(w, r, err.Error(), http.StatusInternalServerError)
return
}
for rows.Next() {
var month, count string
if err = rows.Scan(&month, &count); err == nil {
months[year.First] = append(months[year.First], stringPair{month, count})
} else {
serveError(w, r, err.Error(), http.StatusInternalServerError)
return
}
} }
} }
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": totalCount,
"years": years, "years": years,
"counts": counts, "withoutdate": noDateCount,
"months": months,
}, },
}) })
} }

View File

@ -36,10 +36,10 @@ func checkAllExternalLinks() {
wg.Add(1) wg.Add(1)
for postLinkPair := range linkChan { for postLinkPair := range linkChan {
rm.RLock() rm.RLock()
_, ok := responses[postLinkPair.second] _, ok := responses[postLinkPair.Second]
rm.RUnlock() rm.RUnlock()
if !ok { if !ok {
req, err := http.NewRequest(http.MethodGet, postLinkPair.second, nil) req, err := http.NewRequest(http.MethodGet, postLinkPair.Second, nil)
if err != nil { if err != nil {
fmt.Println(err.Error()) fmt.Println(err.Error())
continue continue
@ -50,19 +50,19 @@ func checkAllExternalLinks() {
req.Header.Set("Accept-Language", "en-US,en;q=0.5") req.Header.Set("Accept-Language", "en-US,en;q=0.5")
resp, err := client.Do(req) resp, err := client.Do(req)
if err != nil { if err != nil {
fmt.Println(postLinkPair.second+" ("+postLinkPair.first+"):", err.Error()) fmt.Println(postLinkPair.Second+" ("+postLinkPair.First+"):", err.Error())
continue continue
} }
status := resp.StatusCode status := resp.StatusCode
_, _ = io.Copy(io.Discard, resp.Body) _, _ = io.Copy(io.Discard, resp.Body)
resp.Body.Close() resp.Body.Close()
rm.Lock() rm.Lock()
responses[postLinkPair.second] = status responses[postLinkPair.Second] = status
rm.Unlock() rm.Unlock()
} }
rm.RLock() rm.RLock()
if response, ok := responses[postLinkPair.second]; ok && !checkSuccessStatus(response) { if response, ok := responses[postLinkPair.Second]; ok && !checkSuccessStatus(response) {
fmt.Println(postLinkPair.second+" ("+postLinkPair.first+"):", response) fmt.Println(postLinkPair.Second+" ("+postLinkPair.First+"):", response)
} }
rm.RUnlock() rm.RUnlock()
} }

View File

@ -0,0 +1,11 @@
(function () {
Array.from(document.getElementsByClassName('statsyear')).forEach(element => {
element.addEventListener('click', function () {
Array.from(document.getElementsByClassName('statsmonth')).forEach(c => {
if (element.dataset.year == c.dataset.year) {
c.classList.contains('hide') ? c.classList.remove('hide') : c.classList.add('hide')
}
})
})
})
})()

View File

@ -14,19 +14,30 @@
</tr> </tr>
</thead> </thead>
<tbody> <tbody>
{{ $counts := .Data.counts }} {{ $months := .Data.months }}
{{ range $i, $year := .Data.years }} {{ range $year := .Data.years }}
<tr> <tr class="statsyear" data-year="{{ $year.First }}">
<td class="tal">{{ $year }}</td> <td class="tal"><b>{{ $year.First }}</b></td>
<td class="tar">{{ index $counts $i }}</td> <td class="tar">{{ $year.Second }}</td>
</tr> </tr>
{{ range $month := (index $months $year.First) }}
<tr class="statsmonth hide" data-year="{{ $year.First }}">
<td class="tal">{{ $month.First }}</td>
<td class="tar">{{ $month.Second }}</td>
</tr>
{{ end }}
{{ end }} {{ end }}
<tr> <tr>
<td class="tal"><b>{{ string .Blog.Lang "total" }}</b></td> <td class="tal"><b>{{ string .Blog.Lang "withoutdate" }}</b></td>
<td class="tar">{{ .Data.withoutdate }}</td>
</tr>
<tr>
<td class="tal"><u><b>{{ string .Blog.Lang "total" }}</b></u></td>
<td class="tar">{{ .Data.total }}</td> <td class="tar">{{ .Data.total }}</td>
</tr> </tr>
</tbody> </tbody>
</table> </table>
<script defer src="{{ asset "js/blogstats.js" }}"></script>
</main> </main>
{{ end }} {{ end }}

View File

@ -29,4 +29,5 @@ update: "Aktualisieren"
updatedon: "Aktualisiert am" updatedon: "Aktualisiert am"
upload: "Hochladen" upload: "Hochladen"
view: "Anschauen" view: "Anschauen"
withoutdate: "Ohne Datum"
year: "Jahr" year: "Jahr"

View File

@ -47,4 +47,5 @@ verified: "Verified"
view: "View" view: "View"
webmentions: "Webmentions" webmentions: "Webmentions"
websiteopt: "Website (optional)" websiteopt: "Website (optional)"
withoutdate: "Without date"
year: "Year" year: "Year"

View File

@ -162,5 +162,5 @@ func dateFormat(date string, format string) string {
} }
type stringPair struct { type stringPair struct {
first, second string First, Second string
} }