@@ -61,6 +61,7 @@ func (app *app) initRouter() { | |||||
app.router.HandleFunc("/edit/{house:[A-Za-z0-9.-]{8}}.html", app.handler(getEditor)).Methods("GET").Name("edit") | 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("/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.HandleFunc("/{house:[A-Za-z0-9.-]{8}}.html", app.handler(getHouse)).Methods("GET").Name("get") | ||||
app.router.HandleFunc("/browse", app.handler(viewHouses)).Methods("GET").Name("browse") | |||||
app.router.PathPrefix("/").Handler(http.FileServer(http.Dir(app.cfg.StaticDir))) | app.router.PathPrefix("/").Handler(http.FileServer(http.Dir(app.cfg.StaticDir))) | ||||
} | } | ||||
@@ -187,3 +187,36 @@ func viewHouseStats(app *app, w http.ResponseWriter, r *http.Request) error { | |||||
return nil | return nil | ||||
} | } | ||||
func viewHouses(app *app, w http.ResponseWriter, r *http.Request) error { | |||||
houses, err := getPublicHouses(app) | |||||
if err != nil { | |||||
fmt.Fprintf(w, ":(") | |||||
return err | |||||
} | |||||
app.templates["browse"].ExecuteTemplate(w, "browse", struct{ Houses *[]PublicHouse }{houses}) | |||||
return nil | |||||
} | |||||
func getPublicHouses(app *app) (*[]PublicHouse, error) { | |||||
houses := []PublicHouse{} | |||||
rows, err := app.db.Query("SELECT house_id, title, thumb_url FROM publichouses WHERE approved = 1 ORDER BY updated DESC LIMIT 10") | |||||
switch { | |||||
case err == sql.ErrNoRows: | |||||
return nil, impart.HTTPError{http.StatusNotFound, "Return to sender. Address unknown."} | |||||
case err != nil: | |||||
fmt.Printf("Couldn't fetch: %v\n", err) | |||||
return nil, err | |||||
} | |||||
defer rows.Close() | |||||
house := &PublicHouse{} | |||||
for rows.Next() { | |||||
err = rows.Scan(&house.ID, &house.Title, &house.ThumbURL) | |||||
houses = append(houses, *house) | |||||
} | |||||
return &houses, nil | |||||
} |
@@ -1,6 +1,12 @@ | |||||
package htmlhouse | package htmlhouse | ||||
type ( | type ( | ||||
PublicHouse struct { | |||||
ID string | |||||
Title string | |||||
ThumbURL string | |||||
} | |||||
HouseStats struct { | HouseStats struct { | ||||
ID string | ID string | ||||
Stats []Stat | Stats []Stat | ||||
@@ -17,6 +17,7 @@ | |||||
<h1>HTMLlot</h1> | <h1>HTMLlot</h1> | ||||
<nav> | <nav> | ||||
<a class="home" href="/"><⌂/></a> | <a class="home" href="/"><⌂/></a> | ||||
<a href="/browse">browse</a> | |||||
<a href="/about.html">about</a> | <a href="/about.html">about</a> | ||||
<a href="/contact.html">contact</a> | <a href="/contact.html">contact</a> | ||||
</nav> | </nav> | ||||
@@ -31,6 +31,7 @@ | |||||
<h1>HTMLhouse</h1> | <h1>HTMLhouse</h1> | ||||
<nav> | <nav> | ||||
<a class="home" href="/"><⌂/></a> | <a class="home" href="/"><⌂/></a> | ||||
<a href="/browse">browse</a> | |||||
<a class="current" href="/about.html">about</a> | <a class="current" href="/about.html">about</a> | ||||
<a href="/contact.html">contact</a> | <a href="/contact.html">contact</a> | ||||
</nav> | </nav> | ||||
@@ -159,6 +159,31 @@ body { | |||||
} | } | ||||
} | } | ||||
.open-house { | |||||
display: inline; | |||||
margin: 2em; | |||||
float: left; | |||||
img { | |||||
border: 1px solid #ccc; | |||||
display: block; | |||||
max-width: 320px; | |||||
max-height: 240px; | |||||
.opacity(.6); | |||||
.transition-duration(0.3s); | |||||
} | |||||
a:hover img { | |||||
.opacity(1); | |||||
} | |||||
.house-name { | |||||
margin-top: 1em; | |||||
font-size: 1.4em; | |||||
text-align: center; | |||||
display: block; | |||||
} | |||||
} | |||||
#editor, #preview-wrap { | #editor, #preview-wrap { | ||||
position: absolute; | position: absolute; | ||||
top: 5em; | top: 5em; | ||||
@@ -31,6 +31,7 @@ | |||||
<h1>my pages</h1> | <h1>my pages</h1> | ||||
<nav> | <nav> | ||||
<a class="home" href="/"><⌂/></a> | <a class="home" href="/"><⌂/></a> | ||||
<a href="/browse">browse</a> | |||||
<a href="/about.html">about</a> | <a href="/about.html">about</a> | ||||
<a href="/contact.html">contact</a> | <a href="/contact.html">contact</a> | ||||
</nav> | </nav> | ||||
@@ -21,4 +21,5 @@ func (app *app) initTemplates() { | |||||
// Initialize dynamic pages | // Initialize dynamic pages | ||||
initTemplate(app, "editor") | initTemplate(app, "editor") | ||||
initTemplate(app, "stats") | initTemplate(app, "stats") | ||||
initTemplate(app, "browse") | |||||
} | } |
@@ -0,0 +1,55 @@ | |||||
{{define "browse"}}<!DOCTYPE HTML> | |||||
<html> | |||||
<head> | |||||
<title>Browse HTMLhouses</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="Browse HTMLhouses."> | |||||
<meta name="application-name" content="HTMLhouse"> | |||||
<meta name="application-url" content="https://html.house"> | |||||
<meta itemprop="name" content="Browse HTMLhouses"> | |||||
<meta itemprop="description" content=""> | |||||
<meta name="twitter:card" content="summary_large_image"> | |||||
<meta name="twitter:title" content="Browse HTMLhouses"> | |||||
<meta name="twitter:description" content=""> | |||||
<meta property="og:title" content="Browse HTMLhouses" /> | |||||
<meta property="og:site_name" content="HTMLhouse" /> | |||||
<meta property="og:type" content="object" /> | |||||
<meta property="og:url" content="https://browse.html.house" /> | |||||
<meta property="og:description" content="" /> | |||||
</head> | |||||
<body> | |||||
<header> | |||||
<h1>Browse</h1> | |||||
<nav> | |||||
<a class="home" href="/"><⌂/></a> | |||||
<a class="current" href="/browse">browse</a> | |||||
<a href="/about.html">about</a> | |||||
<a href="/contact.html">contact</a> | |||||
</nav> | |||||
</header> | |||||
{{ range .Houses }}<div class="open-house"> | |||||
<a href="https://html.house/{{.ID}}"><img src="http://peeper.html.house/{{.ThumbURL}}" /> | |||||
<div class="house-name">{{.Title}}</div></a> | |||||
</div>{{end}} | |||||
<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}} |
@@ -31,6 +31,7 @@ | |||||
<h1>HTMLhouse</h1> | <h1>HTMLhouse</h1> | ||||
<nav> | <nav> | ||||
{{if .ID}}<a class="home" href="/"><⌂/></a>{{end}} | {{if .ID}}<a class="home" href="/"><⌂/></a>{{end}} | ||||
<a href="/browse">browse</a> | |||||
<a href="/about.html">about</a> | <a href="/about.html">about</a> | ||||
<a href="/contact.html">contact</a> | <a href="/contact.html">contact</a> | ||||
</nav> | </nav> | ||||
@@ -31,6 +31,7 @@ | |||||
<h1>{{.ID}}.html stats</h1> | <h1>{{.ID}}.html stats</h1> | ||||
<nav> | <nav> | ||||
<a class="home" href="/"><⌂/></a> | <a class="home" href="/"><⌂/></a> | ||||
<a href="/browse">browse</a> | |||||
<a href="/about.html">about</a> | <a href="/about.html">about</a> | ||||
<a href="/contact.html">contact</a> | <a href="/contact.html">contact</a> | ||||
</nav> | </nav> | ||||