Add /recent, a page that displays the last 20 tries.

Also broke out CSS as a separate file and added a title bar across both pages to easily navigate between Home and Recent.

BUG=skia:
R=mtklein@google.com

Author: jcgregorio@google.com

Review URL: https://codereview.chromium.org/236193011

git-svn-id: http://skia.googlecode.com/svn/trunk@14190 2bbb7eff-a529-9590-31e7-b0007b416f81
diff --git a/experimental/webtry/css/webtry.css b/experimental/webtry/css/webtry.css
new file mode 100644
index 0000000..ee87b94
--- /dev/null
+++ b/experimental/webtry/css/webtry.css
@@ -0,0 +1,60 @@
+body {
+  font-family: helvetica arial sans-serif;
+  margin: 0;
+  padding: 0;
+}
+
+img {
+  box-shadow: 2px 2px 5px gray;
+}
+
+h1 {
+  font-size: 18px;
+}
+
+h2 {
+  font-size: 16px;
+}
+
+.waiting, .waiting * {
+  cursor: wait;
+}
+
+textarea {
+    margin-left: 0;
+    border: solid 1px #ccc;
+    color: green;
+}
+
+pre, code {
+    padding: 0;
+    color: green;
+}
+
+#output {
+    color: #333;
+}
+
+.tries {
+  margin: 1em;
+  float: left;
+}
+
+#title {
+  color: #ddd;
+  background: #444;
+  margin: 0;
+  padding: 0.5em;
+}
+
+#title a:link,
+#title a:visited,
+#title a:hover,
+#title a:active
+{
+  color: #ddd;
+}
+
+#content {
+  padding: 1em;
+}
diff --git a/experimental/webtry/templates/index.html b/experimental/webtry/templates/index.html
index 3e0bd42..d2ba859 100644
--- a/experimental/webtry/templates/index.html
+++ b/experimental/webtry/templates/index.html
@@ -3,25 +3,15 @@
 <head>
     <title>Skia WebTry</title>
     <meta charset='utf-8' />
-    <style type="text/css" media="screen">
-        .waiting, .waiting * {
-          cursor: wait;
-        }
-        textarea {
-            margin-left: 0;
-            border: solid 1px #ccc;
-            color: green;
-        }
-        pre, code {
-            padding: 0;
-            color: green;
-        }
-        #output {
-            color: #333;
-        }
-    </style>
+    <link rel="stylesheet" href="/css/" type="text/css" media="screen">
 </head>
 <body>
+  <section id=title>
+    <a href="/">Home</a>
+    <a href="/recent">Recent</a>
+    <a href="https://github.com/google/skia/tree/master/experimental/webtry">Code</a>
+  </section>
+  <section id=content>
   <pre><code>#include "SkCanvas.h"
 
 void draw(SkCanvas* canvas) {
@@ -36,6 +26,7 @@
 
   <pre><code id='output'></code></pre>
 
+  </section>
   <script type='text/javascript' charset='utf-8'>
       var run = document.getElementById('run');
       var code = document.getElementById('code');
diff --git a/experimental/webtry/templates/recent.html b/experimental/webtry/templates/recent.html
new file mode 100644
index 0000000..051ac3f
--- /dev/null
+++ b/experimental/webtry/templates/recent.html
@@ -0,0 +1,26 @@
+<!DOCTYPE html>
+<html>
+<head>
+    <title>Recent SkFiddles</title>
+    <meta charset='utf-8' />
+    <link rel="stylesheet" href="/css/" type="text/css" media="screen">
+</head>
+<body>
+  <section id=title>
+    <a href="/">Home</a>
+    <a href="/recent">Recent</a>
+    <a href="https://github.com/google/skia/tree/master/experimental/webtry">Code</a>
+  </section>
+  <section id=content>
+  <h1>Recent Activity</h1>
+  {{range .Tries}}
+    <section class=tries>
+    <h2><a href="/c/{{.Hash}}">{{.CreateTS}}</a></h2>
+    <a href="/c/{{.Hash}}">
+      <img width=100 height=100 src="/i/{{.Hash}}.png">
+    </a>
+    </section>
+  {{end}}
+  </section>
+</body>
+</html>
diff --git a/experimental/webtry/webtry.go b/experimental/webtry/webtry.go
index 02c245a..008ea82 100644
--- a/experimental/webtry/webtry.go
+++ b/experimental/webtry/webtry.go
@@ -20,6 +20,7 @@
 	"regexp"
 	"strings"
 	"text/template"
+	"time"
 )
 
 const (
@@ -39,14 +40,20 @@
 	// codeTemplate is the cpp code template the user's code is copied into.
 	codeTemplate *template.Template = nil
 
-	// index is the main index.html page we serve.
-	index *htemplate.Template = nil
+	// indexTemplate is the main index.html page we serve.
+	indexTemplate *htemplate.Template = nil
+
+	// recentTemplate is a list of recent  images.
+	recentTemplate *htemplate.Template = nil
 
 	// db is the database, nil if we don't have an SQL database to store data into.
 	db *sql.DB = nil
 
 	// directLink is the regex that matches URLs paths that are direct links.
-	directLink = regexp.MustCompile("^c/([a-a0-9]+)$")
+	directLink = regexp.MustCompile("^/c/([a-f0-9]+)$")
+
+	// imageLink is the regex that matches URLs paths that are direct links to PNGs.
+	imageLink = regexp.MustCompile("^/i/([a-f0-9]+.png)$")
 )
 
 // flags
@@ -81,7 +88,12 @@
 		panic(err)
 	}
 	// Convert index.html into a template, which is expanded with the code.
-	index, err = htemplate.ParseFiles(filepath.Join(cwd, "templates/index.html"))
+	indexTemplate, err = htemplate.ParseFiles(filepath.Join(cwd, "templates/index.html"))
+	if err != nil {
+		panic(err)
+	}
+
+	recentTemplate, err = htemplate.ParseFiles(filepath.Join(cwd, "templates/recent.html"))
 	if err != nil {
 		panic(err)
 	}
@@ -226,13 +238,67 @@
 	}
 }
 
+func cssHandler(w http.ResponseWriter, r *http.Request) {
+	http.ServeFile(w, r, "css/webtry.css")
+}
+
+// imageHandler serves up the PNG of a specific try.
+func imageHandler(w http.ResponseWriter, r *http.Request) {
+	log.Printf("Image Handler: %q\n", r.URL.Path)
+	if r.Method != "GET" {
+		http.NotFound(w, r)
+		return
+	}
+	match := imageLink.FindStringSubmatch(r.URL.Path)
+	if len(match) != 2 {
+		http.NotFound(w, r)
+		return
+	}
+	filename := match[1]
+	http.ServeFile(w, r, fmt.Sprintf("../../../inout/%s", filename))
+}
+
+type Try struct {
+	Hash     string
+	CreateTS string
+}
+
+type Recent struct {
+	Tries []Try
+}
+
+// recentHandler shows the last 20 tries.
+func recentHandler(w http.ResponseWriter, r *http.Request) {
+	log.Printf("Recent Handler: %q\n", r.URL.Path)
+
+	var err error
+	rows, err := db.Query("SELECT create_ts, hash FROM webtry ORDER BY create_ts DESC LIMIT 20")
+	if err != nil {
+		http.NotFound(w, r)
+		return
+	}
+	recent := []Try{}
+	for rows.Next() {
+		var hash string
+		var create_ts time.Time
+		if err := rows.Scan(&create_ts, &hash); err != nil {
+			log.Printf("Error: failed to fetch from database: %q", err)
+			continue
+		}
+		recent = append(recent, Try{Hash: hash, CreateTS: create_ts.Format("2006-02-01")})
+	}
+	if err := recentTemplate.Execute(w, Recent{Tries: recent}); err != nil {
+		log.Printf("ERROR: Failed to expand template: %q\n", err)
+	}
+}
+
 // mainHandler handles the GET and POST of the main page.
 func mainHandler(w http.ResponseWriter, r *http.Request) {
+	log.Printf("Main Handler: %q\n", r.URL.Path)
 	if r.Method == "GET" {
 		code := DEFAULT_SAMPLE
-		directLink := regexp.MustCompile("^/c/([a-f0-9]+)$")
 		match := directLink.FindStringSubmatch(r.URL.Path)
-		if len(match) == 2 {
+		if len(match) == 2 && r.URL.Path != "/" {
 			hash := match[1]
 			if db == nil {
 				http.NotFound(w, r)
@@ -245,7 +311,7 @@
 			}
 		}
 		// Expand the template.
-		if err := index.Execute(w, userCode{UserCode: code}); err != nil {
+		if err := indexTemplate.Execute(w, userCode{UserCode: code}); err != nil {
 			log.Printf("ERROR: Failed to expand template: %q\n", err)
 		}
 	} else if r.Method == "POST" {
@@ -312,7 +378,9 @@
 
 func main() {
 	flag.Parse()
-
+	http.HandleFunc("/i/", imageHandler)
+	http.HandleFunc("/recent/", recentHandler)
+	http.HandleFunc("/css/", cssHandler)
 	http.HandleFunc("/", mainHandler)
 	log.Fatal(http.ListenAndServe(*port, nil))
 }