1
0
mirror of https://github.com/writeas/htmlhouse synced 2025-07-18 21:08:16 +00:00

Add post stats page

This commit is contained in:
Matt Baer 2015-10-26 16:56:51 -04:00
parent 980da45b4f
commit 8c5afe3945
6 changed files with 144 additions and 0 deletions

1
app.go
View File

@ -59,6 +59,7 @@ func (app *app) initRouter() {
app.router.HandleFunc("/", app.handler(getEditor)).Methods("GET").Name("index")
app.router.HandleFunc("/edit/{house:[A-Za-z0-9.-]{8}}.html", app.handler(getEditor)).Methods("GET").Name("edit")
app.router.HandleFunc("/stats/{house:[A-Za-z0-9.-]{8}}.html", app.handler(viewHouseStats)).Methods("GET").Name("stats")
app.router.HandleFunc("/{house:[A-Za-z0-9.-]{8}}.html", app.handler(getHouse)).Methods("GET").Name("get")
app.router.PathPrefix("/").Handler(http.FileServer(http.Dir(app.cfg.StaticDir)))
}

View File

@ -7,10 +7,12 @@ import (
"net/http"
"regexp"
"strings"
"time"
"github.com/gorilla/mux"
"github.com/writeas/impart"
"github.com/writeas/nerds/store"
"github.com/writeas/web-core/bots"
)
func createHouse(app *app, w http.ResponseWriter, r *http.Request) error {
@ -66,6 +68,21 @@ func renovateHouse(app *app, w http.ResponseWriter, r *http.Request) error {
return impart.WriteSuccess(w, resUser, http.StatusOK)
}
func getHouseStats(app *app, houseID string) (*time.Time, int64, error) {
var created time.Time
var views int64
err := app.db.QueryRow("SELECT created, view_count FROM houses WHERE id = ?", houseID).Scan(&created, &views)
switch {
case err == sql.ErrNoRows:
return nil, 0, impart.HTTPError{http.StatusNotFound, "Return to sender. Address unknown."}
case err != nil:
fmt.Printf("Couldn't fetch: %v\n", err)
return nil, 0, err
}
return &created, views, nil
}
func getHouseHTML(app *app, houseID string) (string, error) {
var html string
err := app.db.QueryRow("SELECT html FROM houses WHERE id = ?", houseID).Scan(&html)
@ -127,6 +144,46 @@ func getHouse(app *app, w http.ResponseWriter, r *http.Request) error {
if r.Method != "HEAD" && !bots.IsBot(r.UserAgent()) {
app.db.Exec("UPDATE houses SET view_count = view_count + 1 WHERE id = ?", houseID)
}
return nil
}
func viewHouseStats(app *app, w http.ResponseWriter, r *http.Request) error {
vars := mux.Vars(r)
houseID := vars["house"]
created, views, err := getHouseStats(app, houseID)
if err != nil {
if err, ok := err.(impart.HTTPError); ok {
if err.Status == http.StatusNotFound {
// TODO: put this logic in one place (shared with getHouse func)
page, err := ioutil.ReadFile(app.cfg.StaticDir + "/404.html")
if err != nil {
page = []byte("<!DOCTYPE html><html><body>HTMLlot.</body></html>")
}
fmt.Fprintf(w, "%s", page)
return nil
}
}
return err
}
viewsLbl := "view"
if views != 1 {
viewsLbl = "views"
}
app.templates["stats"].ExecuteTemplate(w, "stats", &HouseStats{
ID: houseID,
Stats: []Stat{
Stat{
Data: fmt.Sprintf("%d", views),
Label: viewsLbl,
},
Stat{
Data: created.Format(time.RFC1123),
Label: "created",
},
},
})
return nil
}

13
models.go Normal file
View File

@ -0,0 +1,13 @@
package htmlhouse
type (
HouseStats struct {
ID string
Stats []Stat
}
Stat struct {
Data string
Label string
}
)

View File

@ -288,6 +288,22 @@ code {
max-width: 50em;
}
.stat {
display: inline-block;
font-size: 1.2em;
&+.stat {
margin-left: 1em;
}
.num {
font-weight: bold;
}
.label {
font-size: 0.9em;
color: #999;
}
}
@media all and (min-width: 1280px) {
body#promo {
div.heading {

View File

@ -20,4 +20,5 @@ func (app *app) initTemplates() {
// Initialize dynamic pages
initTemplate(app, "editor")
initTemplate(app, "stats")
}

56
templates/stats.html Normal file
View File

@ -0,0 +1,56 @@
{{define "stats"}}<!DOCTYPE HTML>
<html>
<head>
<title>{{.ID}}.html stats | HTMLhouse</title>
<link rel="stylesheet" type="text/css" href="/css/house.css" />
<link rel="shortcut icon" href="/favicon.ico" />
<link rel="icon" type="image/png" href="/img/favicon-chrome.png" sizes="192x192">
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<meta name="theme-color" content="#888888" />
<meta name="description" content="Page stats for {{.ID}}.html">
<meta name="application-name" content="HTMLhouse">
<meta name="application-url" content="https://html.house">
<meta itemprop="name" content="{{.ID}}.html stats | HTMLhouse">
<meta itemprop="description" content="Page stats for {{.ID}}.html">
<meta name="twitter:card" content="summary_large_image">
<meta name="twitter:title" content="{{.ID}}.html stats | HTMLhouse">
<meta name="twitter:description" content="Page stats for {{.ID}}.html">
<meta property="og:title" content="{{.ID}}.html stats | HTMLhouse" />
<meta property="og:site_name" content="HTMLhouse" />
<meta property="og:type" content="object" />
<meta property="og:url" content="https://html.house/stats/{{.ID}}.html" />
<meta property="og:description" content="Page stats for {{.ID}}.html" />
</head>
<body>
<header>
<h1>{{.ID}}.html stats</h1>
<nav>
<a class="home" href="/">&lt;&#8962;/&gt;</a>
</nav>
<a href="/{{.ID}}.html">view</a>
<a href="/edit/{{.ID}}.html">edit</a>
</header>
<div id="wrapper">
{{ range .Stats }}<div class="stat">
<span class="num">{{.Data}}</span>
<span class="label">{{.Label}}</span>
</div>{{end}}
</div>
<script type="text/javascript">
(function(i,s,o,g,r,a,m){i['GoogleAnalyticsObject']=r;i[r]=i[r]||function(){
(i[r].q=i[r].q||[]).push(arguments)},i[r].l=1*new Date();a=s.createElement(o),
m=s.getElementsByTagName(o)[0];a.async=1;a.src=g;m.parentNode.insertBefore(a,m)
})(window,document,'script','//www.google-analytics.com/analytics.js','ga');
ga('create', 'UA-47877053-8', 'auto');
ga('send', 'pageview');
</script>
</body>
</html>{{end}}