Browse Source

Add messages system (for {error,success,info,...} messages)

Morgan Bazalgette 2 years ago
parent
commit
8f02dbb22d
10 changed files with 179 additions and 6 deletions
  1. 5
    1
      context.go
  2. 1
    1
      homepage.go
  3. 32
    3
      main.go
  4. 41
    0
      messages.go
  5. 1
    1
      not_found.go
  6. 50
    0
      sessions.go
  7. 14
    0
      static/ripple.css
  8. 10
    0
      static/ripple.js
  9. 14
    0
      templates.go
  10. 11
    0
      templates/base.html

+ 5
- 1
context.go View File

@@ -1,6 +1,10 @@
1 1
 package main
2 2
 
3 3
 type context struct {
4
-	User struct{ Username string }
4
+	User  sessionUser
5 5
 	Token string
6 6
 }
7
+type sessionUser struct {
8
+	ID       int
9
+	Username string
10
+}

+ 1
- 1
homepage.go View File

@@ -9,7 +9,7 @@ type homePageData struct {
9 9
 
10 10
 func homePage(c *gin.Context) {
11 11
 	posts := getBlogPosts(5)
12
-	resp(c, 200, "homepage.html", homePageData{
12
+	resp(c, 200, "homepage.html", &homePageData{
13 13
 		baseTemplateData: baseTemplateData{
14 14
 			TitleBar:  "Home Page",
15 15
 			KyutGrill: "homepage.jpg",

+ 32
- 3
main.go View File

@@ -2,6 +2,7 @@ package main
2 2
 
3 3
 import (
4 4
 	"database/sql"
5
+	"encoding/gob"
5 6
 	"fmt"
6 7
 
7 8
 	"git.zxq.co/ripple/schiavolib"
@@ -14,13 +15,18 @@ import (
14 15
 
15 16
 var (
16 17
 	c struct {
17
-		DSN                 string
18
-		CookieSecret        string
18
+		DSN string
19
+
20
+		CookieSecret string
21
+
19 22
 		RedisEnable         bool
20 23
 		RedisMaxConnections int
21 24
 		RedisNetwork        string
22 25
 		RedisAddress        string
23 26
 		RedisPassword       string
27
+
28
+		AvatarURL string
29
+		BaseURL   string
24 30
 	}
25 31
 	db *sql.DB
26 32
 )
@@ -43,6 +49,12 @@ func main() {
43 49
 	if c.CookieSecret == "" {
44 50
 		c.CookieSecret = rs.String(46)
45 51
 	}
52
+	if c.AvatarURL == "" {
53
+		c.AvatarURL = "https://a.ripple.moe"
54
+	}
55
+	if c.BaseURL == "" {
56
+		c.BaseURL = "https://ripple.moe"
57
+	}
46 58
 
47 59
 	db, err = sql.Open("mysql", c.DSN)
48 60
 	if err != nil {
@@ -77,6 +89,17 @@ func main() {
77 89
 	} else {
78 90
 		store = sessions.NewCookieStore([]byte(c.CookieSecret))
79 91
 	}
92
+	gobRegisters := []interface{}{
93
+		[]message{},
94
+		errorMessage{},
95
+		infoMessage{},
96
+		neutralMessage{},
97
+		warningMessage{},
98
+		successMessage{},
99
+	}
100
+	for _, el := range gobRegisters {
101
+		gob.Register(el)
102
+	}
80 103
 
81 104
 	fmt.Println("Importing templates...")
82 105
 	loadTemplates()
@@ -85,11 +108,17 @@ func main() {
85 108
 
86 109
 	r := gin.Default()
87 110
 
88
-	r.Use(sessions.Sessions("session", store))
111
+	r.Use(
112
+		sessions.Sessions("session", store),
113
+		sessionInitializer(),
114
+	)
89 115
 
90 116
 	r.Static("/static", "static")
91 117
 
92 118
 	r.GET("/", homePage)
119
+	r.GET("/test", func(c *gin.Context) {
120
+		addMessage(c, errorMessage{"test"})
121
+	})
93 122
 
94 123
 	r.NoRoute(notFound)
95 124
 

+ 41
- 0
messages.go View File

@@ -0,0 +1,41 @@
1
+package main
2
+
3
+type message interface {
4
+	Type() string
5
+	Content() string
6
+}
7
+
8
+type errorMessage struct {
9
+	C string
10
+}
11
+
12
+func (errorMessage) Type() string      { return "error" }
13
+func (m errorMessage) Content() string { return m.C }
14
+
15
+type neutralMessage struct {
16
+	C string
17
+}
18
+
19
+func (neutralMessage) Type() string      { return "" }
20
+func (m neutralMessage) Content() string { return m.C }
21
+
22
+type infoMessage struct {
23
+	C string
24
+}
25
+
26
+func (infoMessage) Type() string      { return "info" }
27
+func (m infoMessage) Content() string { return m.C }
28
+
29
+type successMessage struct {
30
+	C string
31
+}
32
+
33
+func (successMessage) Type() string      { return "positive" }
34
+func (m successMessage) Content() string { return m.C }
35
+
36
+type warningMessage struct {
37
+	C string
38
+}
39
+
40
+func (warningMessage) Type() string      { return "warning" }
41
+func (m warningMessage) Content() string { return m.C }

+ 1
- 1
not_found.go View File

@@ -3,7 +3,7 @@ package main
3 3
 import "github.com/gin-gonic/gin"
4 4
 
5 5
 func notFound(c *gin.Context) {
6
-	resp(c, 200, "not_found.html", baseTemplateData{
6
+	resp(c, 200, "not_found.html", &baseTemplateData{
7 7
 		TitleBar:  "Not Found",
8 8
 		KyutGrill: "not_found.jpg",
9 9
 	})

+ 50
- 0
sessions.go View File

@@ -0,0 +1,50 @@
1
+package main
2
+
3
+import (
4
+	"github.com/gin-gonic/contrib/sessions"
5
+	"github.com/gin-gonic/gin"
6
+)
7
+
8
+func sessionInitializer() func(c *gin.Context) {
9
+	return func(c *gin.Context) {
10
+		sess := sessions.Default(c)
11
+
12
+		var ctx context
13
+		tok := sess.Get("token")
14
+		if tok, ok := tok.(string); ok {
15
+			ctx.Token = tok
16
+		}
17
+		userid := sess.Get("userid")
18
+		if userid, ok := userid.(int); ok {
19
+			ctx.User.ID = userid
20
+			db.QueryRow("SELECT username FROM users WHERE id = ?", userid).Scan(&ctx.User.Username)
21
+		}
22
+		c.Set("context", ctx)
23
+		c.Set("session", sess)
24
+
25
+		c.Next()
26
+	}
27
+}
28
+
29
+func addMessage(c *gin.Context, m message) {
30
+	sess := c.MustGet("session").(sessions.Session)
31
+	var messages []message
32
+	messagesRaw := sess.Get("messages")
33
+	if messagesRaw != nil {
34
+		messages = messagesRaw.([]message)
35
+	}
36
+	messages = append(messages, m)
37
+	sess.Set("messages", messages)
38
+	sess.Save()
39
+}
40
+
41
+func getMessages(c *gin.Context) []message {
42
+	sess := c.MustGet("session").(sessions.Session)
43
+	messagesRaw := sess.Get("messages")
44
+	if messagesRaw == nil {
45
+		return nil
46
+	}
47
+	sess.Delete("messages")
48
+	sess.Save()
49
+	return messagesRaw.([]message)
50
+}

+ 14
- 0
static/ripple.css View File

@@ -48,3 +48,17 @@ a.inherit {
48 48
 a.inherit:hover {
49 49
 	opacity: 1;
50 50
 }
51
+
52
+.autopad {
53
+	margin: 1rem 0;
54
+}
55
+.autopad:first-child {
56
+	margin-top: 0;
57
+}
58
+.autopad:last-child {
59
+	margin-bottom: 0;
60
+}
61
+
62
+.margined.container {
63
+	margin: 1rem;
64
+}

+ 10
- 0
static/ripple.js View File

@@ -0,0 +1,10 @@
1
+// Ripple custom JS that goes on all pages
2
+
3
+$('.message .close')
4
+  .on('click', function() {
5
+    $(this)
6
+      .closest('.message')
7
+      .transition('fade')
8
+    ;
9
+  })
10
+;

+ 14
- 0
templates.go View File

@@ -66,10 +66,15 @@ func resp(c *gin.Context, statusCode int, tpl string, data interface{}) {
66 66
 		c.String(500, "Template not found! Please tell this to a dev!")
67 67
 		return
68 68
 	}
69
+	// dirty hack to allow SetMessages to work if needed
70
+	if corrected, ok := data.(messageSetter); ok {
71
+		corrected.SetMessages(getMessages(c))
72
+	}
69 73
 	c.Status(statusCode)
70 74
 	err := t.ExecuteTemplate(c.Writer, "base", data)
71 75
 	if err != nil {
72 76
 		c.Writer.WriteString("What on earth? Please tell this to a dev!")
77
+		fmt.Println(err)
73 78
 		schiavo.Bunker.Send(err.Error())
74 79
 	}
75 80
 }
@@ -80,6 +85,15 @@ type baseTemplateData struct {
80 85
 	KyutGrill string
81 86
 	Context   context
82 87
 	Path      string
88
+	Messages  []message
89
+}
90
+
91
+func (b *baseTemplateData) SetMessages(m []message) {
92
+	b.Messages = m
93
+}
94
+
95
+type messageSetter interface {
96
+	SetMessages(m []message)
83 97
 }
84 98
 
85 99
 func reloader() error {

+ 11
- 0
templates/base.html View File

@@ -19,12 +19,23 @@
19 19
 			</div>
20 20
 		
21 21
 			<div class="h-container">
22
+				{{ if .Messages }}
23
+					<div class="ui padded margined container">
24
+						{{ range $i, $v := .Messages }}
25
+							<div class="ui {{ $v.Type }} message">
26
+								<i class="close icon"></i>
27
+								{{ $v.Content }}
28
+							</div>
29
+						{{ end }}
30
+					</div>
31
+				{{ end }}
22 32
 				{{ template "tpl" . }}
23 33
 			</div>
24 34
 	
25 35
 		</div>
26 36
 		<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.0.0-rc1/jquery.min.js"></script>
27 37
 		<script src="static/semantic.min.js"></script>
38
+		<script src="static/ripple.js"></script>
28 39
 		{{/* If we got some more scripts to print, print'em */}}
29 40
 		{{ if .Scripts }}
30 41
 			{{ range .Scripts }}

Loading…
Cancel
Save