refactor: simplify handler and template

This commit is contained in:
log101 2024-05-29 17:55:49 +03:00
parent 34ddac1454
commit 4c0cbfd731
3 changed files with 68 additions and 49 deletions

2
.gitignore vendored
View File

@ -21,3 +21,5 @@
# Go workspace file # Go workspace file
go.work go.work
gin-bin
TODO

106
main.go
View File

@ -2,6 +2,7 @@ package main
import ( import (
"database/sql" "database/sql"
"errors"
"fmt" "fmt"
"log" "log"
"net/http" "net/http"
@ -15,11 +16,55 @@ import (
var db *sql.DB var db *sql.DB
// Emoji counts for each post are retrieved in this format
type EmojiCount struct { type EmojiCount struct {
Emoji string Emoji string
TotalCount int TotalCount int
} }
// Emojis' order should be like this
var emojis = [6]string{"👍", "👎", "😀", "😑", "🤢", "👀"}
// Get the emoji counts foe a given post id
func countEmojis(postId string) ([]EmojiCount, error) {
emojiList := []EmojiCount{}
// This will hold the total counts for each emoji
// for a given post
var emojiCounter = map[string]int{
"👍": 0,
"👎": 0,
"😀": 0,
"😑": 0,
"🤢": 0,
"👀": 0,
}
// Get the emoji counts for each emoji
rows, err := db.Query("SELECT emoji, COUNT(*) FROM emoji_clicks WHERE post_id = ? GROUP BY emoji;", postId)
if err != nil {
return emojiList, errors.New("couldn't get emoji counts")
}
defer rows.Close()
// Read the rows and update the counter
for rows.Next() {
var ec EmojiCount
if err := rows.Scan(&ec.Emoji, &ec.TotalCount); err != nil {
return emojiList, errors.New("DB results couldn't read")
}
emojiCounter[ec.Emoji] = ec.TotalCount
}
// Emojis are returned as an ordered list
// as maps are randomly iterated
for _, emoji := range emojis {
var count = EmojiCount{emoji, emojiCounter[emoji]}
emojiList = append(emojiList, count)
}
return emojiList, nil
}
func main() { func main() {
cfg := mysql.Config{ cfg := mysql.Config{
User: os.Getenv("DBUSER"), User: os.Getenv("DBUSER"),
@ -35,6 +80,7 @@ func main() {
log.Fatal(err) log.Fatal(err)
} }
// Check db connection
pingErr := db.Ping() pingErr := db.Ping()
if pingErr != nil { if pingErr != nil {
log.Fatal(pingErr) log.Fatal(pingErr)
@ -44,85 +90,59 @@ func main() {
r := gin.Default() r := gin.Default()
r.LoadHTMLGlob("templates/*") r.LoadHTMLGlob("templates/*")
// CORS configuration
corsConfig := cors.DefaultConfig() corsConfig := cors.DefaultConfig()
corsConfig.AllowOrigins = []string{"*"} corsConfig.AllowOrigins = []string{"*"}
corsConfig.AllowHeaders = []string{"hx-current-url", "hx-request"} corsConfig.AllowHeaders = []string{"hx-current-url", "hx-request"}
r.Use(cors.New(corsConfig)) r.Use(cors.New(corsConfig))
// Get the emoji form, you must provide postId query parameter
r.GET("/forms/emoji", func(c *gin.Context) { r.GET("/forms/emoji", func(c *gin.Context) {
var emojiCounts = map[string]int{
"👍": 0,
"👎": 0,
"😀": 0,
"😑": 0,
"🤢": 0,
"👀": 0,
}
postId := c.Query("postId") postId := c.Query("postId")
rows, err := db.Query("SELECT emoji, COUNT(*) FROM emoji_clicks WHERE post_id = ? GROUP BY emoji;", postId) // get emoji counts for each emoji
emojiCounter, err := countEmojis(postId)
if err != nil { if err != nil {
c.HTML(http.StatusOK, "emoji_form.tmpl", gin.H{"error": err.Error(), "postId": postId}) c.HTML(http.StatusOK, "emoji_form.tmpl", gin.H{"error": "error getting the emoji counts", "postId": postId})
return return
} }
defer rows.Close()
for rows.Next() {
var ec EmojiCount
if err := rows.Scan(&ec.Emoji, &ec.TotalCount); err != nil {
c.HTML(http.StatusOK, "emoji_form.tmpl", gin.H{"error": "error getting emoji rows", "postId": postId})
return
}
emojiCounts[ec.Emoji] = ec.TotalCount
}
// Return the html template
c.HTML(http.StatusOK, "emoji_form.tmpl", gin.H{ c.HTML(http.StatusOK, "emoji_form.tmpl", gin.H{
"postId": c.Query("postId"), "postId": c.Query("postId"),
"results": emojiCounts, "results": emojiCounter,
}) })
}) })
// Update the emoji counter, this handler will
// add a new entry to the database with anonymized ip
// then sums the results to get the emoji counter
r.POST("/forms/emoji/post", func(c *gin.Context) { r.POST("/forms/emoji/post", func(c *gin.Context) {
postId := c.PostForm("postId") postId := c.PostForm("postId")
emoji := c.PostForm("emojiInput") emoji := c.PostForm("emojiInput")
var emojiCounts = map[string]int{ // Check if parameters are missing
"👍": 0,
"👎": 0,
"😀": 0,
"😑": 0,
"🤢": 0,
"👀": 0,
}
if postId == "" || emoji == "" { if postId == "" || emoji == "" {
c.HTML(http.StatusOK, "emoji_form.tmpl", gin.H{"error": "missing parameters", "postId": postId}) c.HTML(http.StatusOK, "emoji_form.tmpl", gin.H{"error": "missing parameters", "postId": postId})
return return
} }
// Add the new emoji entry to the database
_, err := db.Exec("INSERT INTO emoji_clicks (post_id, emoji) VALUES (?, ?)", postId, emoji) _, err := db.Exec("INSERT INTO emoji_clicks (post_id, emoji) VALUES (?, ?)", postId, emoji)
if err != nil { if err != nil {
c.HTML(http.StatusOK, "emoji_form.tmpl", gin.H{"error": "error writing to database", "postId": postId}) c.HTML(http.StatusOK, "emoji_form.tmpl", gin.H{"error": "error writing to database", "postId": postId})
return return
} }
rows, err := db.Query("SELECT emoji, COUNT(*) FROM emoji_clicks WHERE post_id = ? GROUP BY emoji;", postId) // get emoji counts for each emoji
emojiCounter, err := countEmojis(postId)
if err != nil { if err != nil {
c.HTML(http.StatusOK, "emoji_form.tmpl", gin.H{"error": err.Error(), "postId": postId}) c.HTML(http.StatusOK, "emoji_form.tmpl", gin.H{"error": "error getting the emoji counts", "postId": postId})
return return
} }
defer rows.Close()
for rows.Next() { // Return the html with the updated emoji counter
var ec EmojiCount c.HTML(http.StatusOK, "emoji_form.tmpl", gin.H{"postId": postId, "results": emojiCounter})
if err := rows.Scan(&ec.Emoji, &ec.TotalCount); err != nil {
c.HTML(http.StatusOK, "emoji_form.tmpl", gin.H{"error": "error getting emoji rows", "postId": postId})
return
}
emojiCounts[ec.Emoji] = ec.TotalCount
}
c.HTML(http.StatusOK, "emoji_form.tmpl", gin.H{"postId": postId, "results": emojiCounts})
}) })
r.Run(":3001") r.Run(":3001")

View File

@ -1,12 +1,9 @@
<form hx-post="http://localhost:8000/forms/emoji/post" hx-swap="outerHTML"> <form hx-post="http://localhost:8000/forms/emoji/post" hx-swap="outerHTML">
<input type="hidden" name="postId" value="{{.postId}}"> <input type="hidden" name="postId" value="{{.postId}}">
<div class="emoji-buttons-container"> <div class="emoji-buttons-container">
<button name="emojiInput" value="👍" type="submit" class="emoji-button">👍&nbsp; {{ if gt (index .results "👍") 0 }} {{ index .results "👍"}} {{ end }}</button> {{ range .results }}
<button name="emojiInput" value="👎" type="submit" class="emoji-button">👎&nbsp; {{ if gt (index .results "👎") 0 }} {{ index .results "👎"}} {{ end }}</button> <button name="emojiInput" value={{ .Emoji }} type="submit" class="emoji-button">{{ .Emoji }} {{ if gt .TotalCount 0 }} &nbsp; {{ .TotalCount }} {{ end }}</button>
<button name="emojiInput" value="😀" type="submit" class="emoji-button">😀&nbsp; {{ if gt (index .results "😀") 0 }} {{ index .results "😀"}} {{ end }}</button> {{ end }}
<button name="emojiInput" value="😑" type="submit" class="emoji-button">😑&nbsp; {{ if gt (index .results "😑") 0 }} {{ index .results "😑"}} {{ end }}</button>
<button name="emojiInput" value="🤢" type="submit" class="emoji-button">🤢&nbsp; {{ if gt (index .results "🤢") 0 }} {{ index .results "🤢"}} {{ end }}</button>
<button name="emojiInput" value="👀" type="submit" class="emoji-button">👀&nbsp; {{ if gt (index .results "👀") 0 }} {{ index .results "👀"}} {{ end }}</button>
</div> </div>
</form> </form>
<p>{{.error}}</p> <p>{{.error}}</p>