Browse Source

Use responsive skeleton

Andy Hochhaus 2 years ago
parent
commit
c98c52f2bf
11 changed files with 148 additions and 61 deletions
  1. 1 1
      .gitignore
  2. 4 1
      Makefile
  3. 64 8
      src/www/gss/base.gss
  4. 22 15
      src/www/login.htm
  5. 1 1
      src/www/mail.htm
  6. 3 1
      src/www/not_found.htm
  7. 36 29
      src/www/register.htm
  8. 2 0
      src/www/resource.go
  9. BIN
      src/www/roboto.woff
  10. 1 0
      src/www/skeleton.htm
  11. 14 5
      src/www/www.go

+ 1 - 1
.gitignore

@@ -1,4 +1,4 @@
1
-# Copyright (c) 2013 Andy Hochhaus. All Rights Reserved.
1
+# Copyright (c) 2013-2016 Andy Hochhaus. All Rights Reserved.
2 2
 # Use of this source code is governed by the "GNU AFFERO GENERAL PUBLIC
3 3
 # LICENSE" license that can be found in the LICENSE file. See the AUTHORS file
4 4
 # for names of contributors.

+ 4 - 1
Makefile

@@ -17,7 +17,7 @@ GSS := $(wildcard src/www/gss/*.gss) \
17 17
 JS := $(wildcard src/www/js/*.js)
18 18
 
19 19
 all: go $(RDIR)/compiled.css $(RDIR)/compiled.js $(RDIR)/sprite.png \
20
-	$(RDIR)/favicon.ico
20
+	$(RDIR)/favicon.ico $(RDIR)/roboto.woff
21 21
 
22 22
 $(RDIR)/compiled.css: | $(RDIR)
23 23
 
@@ -69,6 +69,9 @@ $(RDIR)/sprite.png: src/www/img/sprite.png
69 69
 $(RDIR)/favicon.ico: src/www/img/favicon.ico
70 70
 	cp src/www/img/favicon.ico $(RDIR)/favicon.ico
71 71
 
72
+$(RDIR)/roboto.woff: src/www/roboto.woff
73
+	cp src/www/img/favicon.ico $(RDIR)/favicon.ico
74
+
72 75
 lint:
73 76
 	find src/mail src/mammoth src/www -name *.go -type f | \
74 77
 		xargs -I {} go fmt {}

+ 64 - 8
src/www/gss/base.gss

@@ -1,35 +1,91 @@
1 1
 /**
2
- * Copyright (c) 2013 Andy Hochhaus. All Rights Reserved.
2
+ * Copyright (c) 2013-2016 Andy Hochhaus. All Rights Reserved.
3 3
  * Use of this source code is governed by the "GNU AFFERO GENERAL PUBLIC
4 4
  * LICENSE" license that can be found in the LICENSE file. See the AUTHORS file
5 5
  * for names of contributors.
6 6
  */
7 7
 
8
+@font-face {
9
+  font-family: 'Roboto';
10
+  font-style: normal;
11
+  font-weight: 400;
12
+  src: local('Roboto'), local('Roboto-Regular'),
13
+       url(/r/roboto.woff) format('woff');
14
+}
15
+
8 16
 html, body {
9 17
   padding: 0;
10 18
   margin: 0;
19
+  font-family: 'Roboto', sans-serif;
20
+  color: #111;
21
+  box-sizing: border-box;
11 22
 }
12 23
 
13 24
 *, *:before, *:after {
14
-  -moz-box-sizing: border-box;
15
-  -webkit-box-sizing: border-box;
16
-  box-sizing: border-box;
25
+  box-sizing: inherit;
26
+}
27
+
28
+a, a:link, a:visited, a:active {
29
+  color: #1155cc;
30
+  text-decoration: none;
17 31
 }
18 32
 
19 33
 input {
20 34
   padding: 5px;
21 35
 }
22 36
 
23
-.register-form {
37
+.left {
38
+  text-align: left;
39
+}
40
+
41
+.register_form {
24 42
   background-color: #e3e3e3;
25
-  padding: 10px;
26
-  float: right;
43
+  padding: .5em;
44
+  border-radius: 3px;
45
+  margin: 1em 0;
27 46
 }
28 47
 
29 48
 .error {
30 49
   color: red;
31 50
 }
32 51
 
33
-.width-full {
52
+.input {
34 53
   width: 100%;
54
+  margin: 0 0 .5em 0;
35 55
 }
56
+
57
+.input_first {
58
+  width: 49%;
59
+  margin: 0 3px .5em 0;
60
+}
61
+
62
+.input_last {
63
+  width: 49%;
64
+  margin: 0 0 .5em 3px;
65
+}
66
+
67
+.input_button {
68
+  width: 100%;
69
+  color: white;
70
+  background: #2196f3;
71
+  border: 0;
72
+  border-radius: 3px;
73
+  font-weight: bold;
74
+}
75
+
76
+.outside_page {
77
+  padding: .5em;
78
+  width: 100%;
79
+  max-width: 340px;
80
+  margin: 0 auto;
81
+  text-align: center;
82
+}
83
+
84
+footer {
85
+  color: #555;
86
+}
87
+
88
+.outside_footer {
89
+  padding: 1em 0;
90
+  font-size: .75em;
91
+}

+ 22 - 15
src/www/login.htm

@@ -6,20 +6,27 @@ of contributors.
6 6
 */}}
7 7
 
8 8
 {{define "content"}}
9
-<form method="post" class="{{css "register-form"}}">
10
-  <noscript>
11
-    <div class="{{css "error"}}">JavaScript is required.</div>
12
-  </noscript>
13
-  <div id="unsupported" class="{{css "error"}}"></div>
14
-  <div>
15
-    <input name="email" id="email"{{if .Email}} value="{{.Email}}"{{end}} class="{{css "width-full"}}" placeholder="Email">
16
-  </div>
17
-  <div>
18
-    <input type="password" name="password" id="password" class="{{css "width-full"}}" placeholder="Password">
9
+<div class="{{css "outside_page"}}">
10
+  <header>
11
+    <a href="/" class="{{css "goog-inline-block"}} {{css "mammoth-logo"}}"></a>
12
+  </header>
13
+  <form method="post" class="{{css "register_form"}}">
14
+    <noscript>
15
+      <div class="{{css "error"}}">JavaScript is required.</div>
16
+    </noscript>
17
+    <div id="unsupported" class="{{css "error"}}"></div>
18
+    <div>
19
+      <input name="email" id="email"{{if .Email}} value="{{.Email}}"{{end}} class="{{css "input"}}" placeholder="Email">
20
+    </div>
21
+    <div>
22
+      <input type="password" name="password" id="password" class="{{css "input"}}" placeholder="Password">
19 23
     {{if .Error}}<div class="{{css "error"}}">{{.Error}}</div>{{end}}
20
-  </div>
21
-  <input type="submit" id="login" name="login" value="Sign in" disabled>
22
-</form>
23
-<a href="/" class="{{css "goog-inline-block"}} {{css "mammoth-logo"}}"></a><br>
24
-<a href="/register">Register for account</a>
24
+    </div>
25
+    <input class="{{css "input_button"}}" type="submit" id="login" name="login" value="Sign in" disabled>
26
+  </form>
27
+  <a href="/register">Create account</a>
28
+  <footer class="{{css "outside_footer"}}">
29
+    &copy; 2016 Mammoth Mail
30
+  </footer>
31
+</div>
25 32
 {{end}}

+ 1 - 1
src/www/mail.htm

@@ -6,7 +6,7 @@ of contributors.
6 6
 */}}
7 7
 
8 8
 {{define "content"}}
9
-<div>
9
+<div class="{{css "outside_page"}}">
10 10
   Loading {{.Email}}...
11 11
 </div>
12 12
 {{end}}

+ 3 - 1
src/www/not_found.htm

@@ -6,5 +6,7 @@ of contributors.
6 6
 */}}
7 7
 
8 8
 {{define "content"}}
9
-The page you're looking for could not be found.
9
+<div class="{{css "outside_page"}}">
10
+  The page you're looking for could not be found.
11
+</div>
10 12
 {{end}}

+ 36 - 29
src/www/register.htm

@@ -6,33 +6,40 @@ of contributors.
6 6
 */}}
7 7
 
8 8
 {{define "content"}}
9
-<form method="post" class="{{css "register-form"}}">
10
-  <noscript>
11
-    <div class="{{css "error"}}">JavaScript is required.</div>
12
-  </noscript>
13
-  <div id="unsupported" class="{{css "error"}}"></div>
14
-  <div>
15
-    <b>Name</b><br>
16
-    <input name="first" id="first"{{if .First}} value="{{.First}}"{{end}} placeholder="First">
17
-    <input name="last" id="last"{{if .Last}} value="{{.Last}}"{{end}} placeholder="Last">
18
-    {{if .NameError}}<div class="{{css "error"}}">{{.NameError}}</div>{{end}}
19
-  </div>
20
-  <div>
21
-    <b>Your current email address</b><br>
22
-    <input name="email" id="email"{{if .Email}} value="{{.Email}}"{{end}} class="{{css "width-full"}}">
23
-    {{if .EmailError}}<div class="{{css "error"}}">{{.EmailError}}</div>{{end}}
24
-  </div>
25
-  <div>
26
-    <b>Create a password</b><br>
27
-    <input type="password" name="password" id="password"{{if .Password}} value="{{.Password}}"{{end}} class="{{css "width-full"}}">
28
-    {{if .PasswordError}}<div class="{{css "error"}}">{{.PasswordError}}</div>{{end}}
29
-  </div>
30
-  <div>
31
-    <b>Confirm your password</b><br>
32
-    <input type="password" name="password_confirm" id="password_confirm"{{if .PasswordConfirm}} value="{{.PasswordConfirm}}"{{end}} class="{{css "width-full"}}">
33
-    {{if .PasswordConfirmError}}<div class="{{css "error"}}">{{.PasswordConfirmError}}</div>{{end}}
34
-  </div>
35
-  <input type="submit" name="register" id="register" value="Create Account" disabled>
36
-</form>
37
-<a href="/" class="{{css "goog-inline-block"}} {{css "mammoth-logo"}}"></a><br>
9
+<div class="{{css "outside_page"}}">
10
+  <header>
11
+    <a href="/" class="{{css "goog-inline-block"}} {{css "mammoth-logo"}}"></a>
12
+  </header>
13
+  <form method="post" class="{{css "register_form"}}">
14
+    <noscript>
15
+      <div class="{{css "error"}}">JavaScript is required.</div>
16
+    </noscript>
17
+    <div id="unsupported" class="{{css "error"}}"></div>
18
+    <div>
19
+      <div class="{{css "left"}}"><b>Name</b></div>
20
+      <input name="first" id="first"{{if .First}} value="{{.First}}"{{end}} placeholder="First" class="{{css "input_first"}}">
21
+      <input name="last" id="last"{{if .Last}} value="{{.Last}}"{{end}} placeholder="Last" class="{{css "input_last"}}">
22
+      {{if .NameError}}<div class="{{css "error"}}">{{.NameError}}</div>{{end}}
23
+    </div>
24
+    <div>
25
+      <div class="{{css "left"}}"><b>Your current email address</b></div>
26
+      <input name="email" id="email"{{if .Email}} value="{{.Email}}"{{end}} class="{{css "input"}}">
27
+      {{if .EmailError}}<div class="{{css "error"}}">{{.EmailError}}</div>{{end}}
28
+    </div>
29
+    <div>
30
+      <div class="{{css "left"}}"><b>Create a password</b></div>
31
+      <input type="password" name="password" id="password"{{if .Password}} value="{{.Password}}"{{end}} class="{{css "input"}}">
32
+      {{if .PasswordError}}<div class="{{css "error"}}">{{.PasswordError}}</div>{{end}}
33
+    </div>
34
+    <div>
35
+      <div class="{{css "left"}}"><b>Confirm your password</b></div>
36
+      <input type="password" name="password_confirm" id="password_confirm"{{if .PasswordConfirm}} value="{{.PasswordConfirm}}"{{end}} class="{{css "input"}}">
37
+      {{if .PasswordConfirmError}}<div class="{{css "error"}}">{{.PasswordConfirmError}}</div>{{end}}
38
+    </div>
39
+    <input class="{{css "input_button"}}" type="submit" name="register" id="register" value="Create Account" disabled>
40
+  </form>
41
+  <footer class="{{css "outside_footer"}}">
42
+    &copy; 2016 Mammoth Mail
43
+  </footer>
44
+</div>
38 45
 {{end}}

+ 2 - 0
src/www/resource.go

@@ -174,6 +174,8 @@ func setContentType(w http.ResponseWriter, r *http.Request) {
174 174
 		header.Set("Content-Type", "text/javascript")
175 175
 	case "png":
176 176
 		header.Set("Content-Type", "image/png")
177
+	case "woff":
178
+		header.Set("Content-Type", "application/font-woff")
177 179
 	}
178 180
 }
179 181
 

BIN
src/www/roboto.woff


+ 1 - 0
src/www/skeleton.htm

@@ -11,6 +11,7 @@ of contributors.
11 11
   <head>
12 12
     <meta charset="utf-8">
13 13
     <title>Mammoth Mail</title>
14
+    <meta name="viewport" content="width=device-width, user-scalable=no">
14 15
     <link rel="stylesheet" href="{{res "/r/compiled.css"}}">
15 16
     <link rel="shortcut icon" href="{{res "/r/favicon.ico"}}" sizes="16x16 32x32 48x48 64x64 128x128">
16 17
   </head>

+ 14 - 5
src/www/www.go

@@ -1,4 +1,4 @@
1
-// Copyright (c) 2013-2014 Andy Hochhaus. All Rights Reserved.
1
+// Copyright (c) 2013-2016 Andy Hochhaus. All Rights Reserved.
2 2
 // Use of this source code is governed by the "GNU AFFERO GENERAL PUBLIC
3 3
 // LICENSE" license that can be found in the LICENSE file. See the AUTHORS file
4 4
 // for names of contributors.
@@ -16,14 +16,13 @@ import (
16 16
 	"mail"
17 17
 	"net/http"
18 18
 	"strings"
19
+	"time"
19 20
 	"unicode"
20 21
 )
21 22
 
22 23
 const (
23
-	// TODO(hochhaus): Remove 'unsafe-inline' from style-src by removing inline
24
-	// CSS usage inside closure-library widgets.
25 24
 	csp = "default-src 'none'; script-src 'self'; img-src 'self'; " +
26
-		"connect-src 'self'; style-src 'self' 'unsafe-inline'; " +
25
+		"connect-src 'self'; style-src 'self'; font-src 'self'; " +
27 26
 		"report-uri /debug/errors; " +
28 27
 		"sandbox allow-forms allow-popups allow-same-origin allow-scripts;"
29 28
 )
@@ -231,7 +230,17 @@ func Serve() {
231 230
 		go serveRedirect()
232 231
 	}
233 232
 	log.Printf("Serving on: %s", mail.Config.HTTPHost)
234
-	server := &http.Server{Addr: mail.Config.HTTPHost, Handler: extHTTP}
233
+	server := &http.Server{
234
+		Addr:    mail.Config.HTTPHost,
235
+		Handler: extHTTP,
236
+		// {Read,Write}Timeout are passed to the underlying TCP connection and are
237
+		// not HTTP request aware. To allow HTTP Keep-Alive and HTTP/2 to function
238
+		// correctly, these timeouts must be large enough for the maximum length of
239
+		// a single TCP connection. Per-handler timeouts are configured with
240
+		// http.TimeoutHandler.
241
+		ReadTimeout:  30 * time.Minute,
242
+		WriteTimeout: 30 * time.Minute,
243
+	}
235 244
 	err := server.ListenAndServeTLS(
236 245
 		mail.Config.CertChainFile, mail.Config.TLSKeyFile)
237 246
 	if err != nil {