Enha: sse update on actions
This commit is contained in:
		| @@ -41,7 +41,7 @@ | ||||
| 	</style> | ||||
| </head> | ||||
| <body> | ||||
| <div id=ancestor> | ||||
| <div id="ancestor" hx-ext="sse" sse-connect="/sub/sse"> | ||||
| 	{{template "main" .}} | ||||
| </div> | ||||
| </body> | ||||
|   | ||||
| @@ -22,7 +22,7 @@ | ||||
|     color: white; | ||||
|     text-shadow: 0 2px 4px rgba(0,0,0,0.8); | ||||
|     cursor: pointer;" | ||||
|     hx-get="/word/show-color?word={{.Word}}" hx-trigger="click" hx-swap="outerHTML transition:true swap:.1s"> | ||||
|     hx-get="/word/show-color?word={{.Word}}" hx-trigger="click" hx-swap="outerHTML transition:true swap:.05s"> | ||||
|     {{.Word}} | ||||
| </div> | ||||
| {{end}} | ||||
|   | ||||
| @@ -1,8 +1,4 @@ | ||||
| {{define "main"}} | ||||
| 	<div hx-ext="sse" sse-connect="/sub/sse" sse-swap="test"> | ||||
| 	    Contents of this box will be updated in real time | ||||
| 	    with every SSE message received from the chatroom. | ||||
| 	</div> | ||||
| 	<!-- user has no username -> login form --> | ||||
| 	{{ if not . }} | ||||
| 	{{template "login"}} | ||||
|   | ||||
| @@ -1,12 +1,12 @@ | ||||
| {{define "teamlist"}} | ||||
| <div class="playerlist border border-gray-300 rounded mb-2"> | ||||
| <div class="playerlist border border-gray-300 text-{{.Color}}-500 rounded mb-2"> | ||||
|     <p class=border>Guessers</p> | ||||
| {{range .Guessers}} | ||||
|     <p>{{.}}</p> | ||||
| {{end}} | ||||
| </div> | ||||
| <hr /> | ||||
| <div class="playerlist border border-gray-300 rounded mb-2"> | ||||
| <div class="playerlist border border-gray-300 rounded mb-2 text-{{.Color}}-700"> | ||||
|     <p class=border>Mime</p> | ||||
|     <p>{{.Mime}}</p> | ||||
| </div> | ||||
|   | ||||
| @@ -1,5 +1,6 @@ | ||||
| {{define "room"}} | ||||
| <div id="hello-user"> | ||||
| <div id="interier" hx-get="/" hx-trigger="sse:roomupdate_{{.State.RoomID}}"> | ||||
|   <div id="meta"> | ||||
|     <p>Hello {{.State.Username}};</p> | ||||
|     <p>Room created by {{.Room.CreatorName}};</p> | ||||
|     <p>Game is running: {{.Room.IsRunning}}</p> | ||||
| @@ -8,12 +9,12 @@ | ||||
|         <button hx-get="/start-game" hx-target="#room" class="bg-amber-100 text-black px-4 py-2 rounded">Start Game</button> | ||||
|       {{end}} | ||||
|     </p> | ||||
|   <p>Turn of the {{.Room.TeamTurn}} team</p> | ||||
|     <p>Turn of the <span class="text-{{.Room.TeamTurn}}-500">{{.Room.TeamTurn}}</span> team</p> | ||||
|     <p> | ||||
|       {{if eq .State.Team ""}} | ||||
|       join the team! | ||||
|       {{else}} | ||||
|     you're on the team {{.State.Team}}! | ||||
|       you're on the team <span class="text-{{.State.Team}}-500">{{.State.Team}}</span>! | ||||
|       {{end}} | ||||
|     </p> | ||||
|   </div> | ||||
| @@ -21,11 +22,11 @@ | ||||
|   <div class="flex justify-center"> | ||||
|     <!-- Left Panel --> | ||||
|     {{template "teamlist" .Room.BlueTeam}} | ||||
|   {{if ne .State.Team "blue"}} | ||||
|     {{if and (ne .State.Team "blue") (not .Room.IsRunning)}} | ||||
|     {{template "teampew" "blue"}} | ||||
|     {{end}} | ||||
|     <!-- Right Panel --> | ||||
|   {{if ne .State.Team "red"}} | ||||
|     {{if and (ne .State.Team "red") (not .Room.IsRunning)}} | ||||
|     {{template "teampew" "red"}} | ||||
|     {{end}} | ||||
|     {{template "teamlist" .Room.RedTeam}} | ||||
| @@ -35,10 +36,11 @@ | ||||
|     {{template "cardtable" .Room}} | ||||
|   </div> | ||||
|   <div> | ||||
|   {{if eq .State.Role "guesser"}} | ||||
|     {{if and (eq .State.Role "guesser") (eq .State.Team .Room.TeamTurn)}} | ||||
|     <button hx-get="/end-turn" hx-target="#room" class="bg-amber-100 text-black px-4 py-2 rounded">End Turn</button> | ||||
|     {{else if eq .State.Role "mime"}} | ||||
|     {{template "mimeclue"}} | ||||
|     {{end}} | ||||
|   </div> | ||||
| </div> | ||||
| {{end}} | ||||
|   | ||||
| @@ -4,6 +4,7 @@ import ( | ||||
| 	"context" | ||||
| 	"encoding/json" | ||||
| 	"errors" | ||||
| 	"golias/broker" | ||||
| 	"golias/models" | ||||
| 	"golias/utils" | ||||
| 	"strings" | ||||
| @@ -168,6 +169,7 @@ func joinTeam(ctx context.Context, role, team string) (*models.FullInfo, error) | ||||
| 				return fi, err | ||||
| 			} | ||||
| 			fi.Room.BlueTeam.Mime = fi.State.Username | ||||
| 			fi.Room.BlueTeam.Color = "blue" | ||||
| 			fi.State.Team = "blue" | ||||
| 			fi.State.Role = "mime" | ||||
| 			if fi.Room.RedTeam.Mime == fi.State.Username { | ||||
| @@ -180,6 +182,7 @@ func joinTeam(ctx context.Context, role, team string) (*models.FullInfo, error) | ||||
| 				return fi, err | ||||
| 			} | ||||
| 			fi.Room.RedTeam.Mime = fi.State.Username | ||||
| 			fi.Room.RedTeam.Color = "red" | ||||
| 			fi.State.Team = "red" | ||||
| 			fi.State.Role = "mime" | ||||
| 			if fi.Room.BlueTeam.Mime == fi.State.Username { | ||||
| @@ -192,10 +195,12 @@ func joinTeam(ctx context.Context, role, team string) (*models.FullInfo, error) | ||||
| 	} else if role == "guesser" { | ||||
| 		if team == "blue" { | ||||
| 			fi.Room.BlueTeam.Guessers = append(fi.Room.BlueTeam.Guessers, fi.State.Username) | ||||
| 			fi.Room.BlueTeam.Color = "blue" | ||||
| 			fi.State.Team = "blue" | ||||
| 			fi.State.Role = "guesser" | ||||
| 		} else if team == "red" { | ||||
| 			fi.Room.RedTeam.Guessers = append(fi.Room.RedTeam.Guessers, fi.State.Username) | ||||
| 			fi.Room.RedTeam.Color = "red" | ||||
| 			fi.State.Team = "red" | ||||
| 			fi.State.Role = "guesser" | ||||
| 		} else { | ||||
| @@ -232,3 +237,10 @@ func listPublicRooms() []*models.Room { | ||||
| 	} | ||||
| 	return publicRooms | ||||
| } | ||||
|  | ||||
| func notify(event, msg string) { | ||||
| 	Notifier.Notifier <- broker.NotificationEvent{ | ||||
| 		EventName: event, | ||||
| 		Payload:   msg, | ||||
| 	} | ||||
| } | ||||
|   | ||||
| @@ -35,24 +35,23 @@ func HandleShowColor(w http.ResponseWriter, r *http.Request) { | ||||
| 		abortWithError(w, err.Error()) | ||||
| 		return | ||||
| 	} | ||||
| 	session, ok := ctx.Value(models.CtxSessionKey).(*models.Session) | ||||
| 	if !ok { | ||||
| 		// trying to get color without a session -> error | ||||
| 		http.Redirect(w, r, "/", 302) | ||||
| 		return | ||||
| 	} | ||||
| 	state, err := loadState(session.Username) | ||||
| 	fi, err := getFullInfoByCtx(ctx) | ||||
| 	if err != nil { | ||||
| 		abortWithError(w, err.Error()) | ||||
| 		return | ||||
| 	} | ||||
| 	// TODO: whos move it is? | ||||
| 	if state.Role != "guesser" { | ||||
| 	if fi.State.Role != "guesser" { | ||||
| 		err = errors.New("need to guesser to open the card") | ||||
| 		abortWithError(w, err.Error()) | ||||
| 		return | ||||
| 	} | ||||
| 	log.Debug("got state", "state", state) | ||||
| 	// whos move it is? | ||||
| 	if fi.State.Team != models.UserTeam(fi.Room.TeamTurn) { | ||||
| 		err = errors.New("not your team's move") | ||||
| 		abortWithError(w, err.Error()) | ||||
| 		return | ||||
| 	} | ||||
| 	log.Debug("got state", "state", fi) | ||||
| 	// TODO: update room score | ||||
| 	color, exists := roundWords[word] | ||||
| 	log.Debug("got show-color request", "word", word, "color", color) | ||||
| @@ -65,5 +64,11 @@ func HandleShowColor(w http.ResponseWriter, r *http.Request) { | ||||
| 		Color:    models.StrToWordColor(color), | ||||
| 		Revealed: true, | ||||
| 	} | ||||
| 	fi.Room.RevealSpecificWord(word) | ||||
| 	if err := saveFullInfo(fi); err != nil { | ||||
| 		abortWithError(w, err.Error()) | ||||
| 		return | ||||
| 	} | ||||
| 	notify(models.NotifyRoomUpdatePrefix+fi.Room.ID, "") | ||||
| 	tmpl.ExecuteTemplate(w, "cardword", cardword) | ||||
| } | ||||
|   | ||||
| @@ -149,6 +149,7 @@ func HandleJoinTeam(w http.ResponseWriter, r *http.Request) { | ||||
| 		abortWithError(w, err.Error()) | ||||
| 		return | ||||
| 	} | ||||
| 	notify(models.NotifyRoomUpdatePrefix+fi.Room.ID, "") | ||||
| 	tmpl.ExecuteTemplate(w, "base", fi) | ||||
| } | ||||
|  | ||||
| @@ -176,6 +177,7 @@ func HandleEndTurn(w http.ResponseWriter, r *http.Request) { | ||||
| 		abortWithError(w, err.Error()) | ||||
| 		return | ||||
| 	} | ||||
| 	notify(models.NotifyRoomUpdatePrefix+fi.Room.ID, "") | ||||
| 	tmpl.ExecuteTemplate(w, "base", fi) | ||||
| } | ||||
|  | ||||
| @@ -204,6 +206,8 @@ func HandleStartGame(w http.ResponseWriter, r *http.Request) { | ||||
| 		abortWithError(w, err.Error()) | ||||
| 		return | ||||
| 	} | ||||
| 	// to update only the room that should be updated | ||||
| 	notify(models.NotifyRoomUpdatePrefix+fi.Room.ID, "") | ||||
| 	tmpl.ExecuteTemplate(w, "room", fi) | ||||
| } | ||||
|  | ||||
|   | ||||
| @@ -1,7 +1,6 @@ | ||||
| package handlers | ||||
|  | ||||
| import ( | ||||
| 	"fmt" | ||||
| 	"golias/broker" | ||||
| 	"golias/config" | ||||
| 	"golias/pkg/cache" | ||||
| @@ -9,7 +8,6 @@ import ( | ||||
| 	"log/slog" | ||||
| 	"net/http" | ||||
| 	"os" | ||||
| 	"time" | ||||
| ) | ||||
|  | ||||
| var ( | ||||
| @@ -28,18 +26,6 @@ func init() { | ||||
| 	cfg = config.LoadConfigOrDefault("") | ||||
| 	Notifier = broker.NewBroker() | ||||
| 	go Notifier.Listen() | ||||
| 	ticker := time.NewTicker(2 * time.Second) | ||||
| 	go func() { | ||||
| 		counter := 0 | ||||
| 		for { | ||||
| 			<-ticker.C | ||||
| 			Notifier.Notifier <- broker.NotificationEvent{ | ||||
| 				EventName: "test", | ||||
| 				Payload:   fmt.Sprintf("%v test call of notifier", counter), | ||||
| 			} | ||||
| 			counter++ | ||||
| 		} | ||||
| 	}() | ||||
| } | ||||
|  | ||||
| var roundWords = map[string]string{ | ||||
|   | ||||
| @@ -7,4 +7,6 @@ var ( | ||||
| 	// cache | ||||
| 	CacheRoomPrefix  = "room#" | ||||
| 	CacheStatePrefix = "state-" | ||||
| 	// sse | ||||
| 	NotifyRoomUpdatePrefix = "roomupdate_" | ||||
| ) | ||||
|   | ||||
| @@ -34,6 +34,7 @@ func StrToWordColor(s string) WordColor { | ||||
| type Team struct { | ||||
| 	Guessers []string | ||||
| 	Mime     string | ||||
| 	Color    string | ||||
| } | ||||
|  | ||||
| type Room struct { | ||||
| @@ -109,6 +110,14 @@ func (r *Room) RevealAllCards() { | ||||
| 	} | ||||
| } | ||||
|  | ||||
| func (r *Room) RevealSpecificWord(word string) { | ||||
| 	for i, card := range r.Cards { | ||||
| 		if card.Word == word { | ||||
| 			r.Cards[i].Revealed = true | ||||
| 		} | ||||
| 	} | ||||
| } | ||||
|  | ||||
| type WordCard struct { | ||||
| 	Word     string | ||||
| 	Color    WordColor | ||||
|   | ||||
| @@ -75,8 +75,8 @@ func MakeTestState(creatorName string) *FullInfo { | ||||
| 		{Word: "tomato", Color: "red"}, | ||||
| 		{Word: "cloud", Color: "white"}, | ||||
| 	} | ||||
| 	redTeam := Team{Guessers: []string{"Adam", "Eve"}, Mime: "Serpent"} | ||||
| 	blueTeam := Team{Guessers: []string{"Abel", "Kain"}} | ||||
| 	redTeam := Team{Guessers: []string{"Adam", "Eve"}, Mime: "Serpent", Color: "red"} | ||||
| 	blueTeam := Team{Guessers: []string{"Abel", "Kain"}, Color: "blue"} | ||||
| 	room := &Room{ | ||||
| 		ID:          "test-id", | ||||
| 		CreatedAt:   time.Now(), | ||||
|   | ||||
		Reference in New Issue
	
	Block a user
	 Grail Finder
					Grail Finder