Feat: add namecheck and tailwind css
This commit is contained in:
		
							
								
								
									
										8
									
								
								assets/tailwind.css
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										8
									
								
								assets/tailwind.css
									
									
									
									
									
										Normal file
									
								
							
										
											
												File diff suppressed because one or more lines are too long
											
										
									
								
							| @@ -6,6 +6,7 @@ | |||||||
| 	<script src="https://unpkg.com/htmx.org@2.0.4" integrity="sha384-HGfztofotfshcF7+8n44JQL2oJmowVChPTg48S+jvZoztPfvwD79OC/LTtG6dMp+" crossorigin="anonymous"></script> | 	<script src="https://unpkg.com/htmx.org@2.0.4" integrity="sha384-HGfztofotfshcF7+8n44JQL2oJmowVChPTg48S+jvZoztPfvwD79OC/LTtG6dMp+" crossorigin="anonymous"></script> | ||||||
| 	<script src="/assets/htmx.min.js"></script> | 	<script src="/assets/htmx.min.js"></script> | ||||||
| 	<script src="/assets/htmx.sse.js"></script> | 	<script src="/assets/htmx.sse.js"></script> | ||||||
|  |         <script src="/assets/tailwind.css"></script> | ||||||
| 	<link rel="stylesheet" href="/assets/style.css"/> | 	<link rel="stylesheet" href="/assets/style.css"/> | ||||||
| 	<meta charset="utf-8" name="viewport" content="width=device-width,initial-scale=1"/> | 	<meta charset="utf-8" name="viewport" content="width=device-width,initial-scale=1"/> | ||||||
| 	<link rel="icon" sizes="64x64" href="favicon.ico"/> | 	<link rel="icon" sizes="64x64" href="favicon.ico"/> | ||||||
|   | |||||||
| @@ -1,8 +1,17 @@ | |||||||
| {{define "main"}} | {{define "main"}} | ||||||
|  | 	<!-- user has no username -> login form --> | ||||||
|  | 	{{ if eq .Username "" }} | ||||||
| 	{{template "login"}} | 	{{template "login"}} | ||||||
|  | 	<!-- user has name but no room id => suggest to create room --> | ||||||
|  | 	{{ else if eq .Room.ID "" }} | ||||||
|  | 	<div id="hello-user"> | ||||||
|  | 		<p>Hello {{.Username}}</p> | ||||||
|  | 	</div> | ||||||
| 	<div id="create-room" class="create-room-div"> | 	<div id="create-room" class="create-room-div"> | ||||||
| 	    <button button id="create-form-btn" type="submit" class="justify-center rounded-md bg-indigo-600 px-3 py-1.5 text-sm font-semibold leading-6 text-white shadow-sm hover:bg-indigo-500 focus-visible:outline focus-visible:outline-2 focus-visible:outline-offset-2 focus-visible:outline-indigo-600" hx-get="/room/createform" hx-swap="outerHTML">SHOW ROOM CREATE FORM</button> | 	    <button button id="create-form-btn" type="submit" class="justify-center rounded-md bg-indigo-600 px-3 py-1.5 text-sm font-semibold leading-6 text-white shadow-sm hover:bg-indigo-500 focus-visible:outline focus-visible:outline-2 focus-visible:outline-offset-2 focus-visible:outline-indigo-600" hx-get="/room/createform" hx-swap="outerHTML">SHOW ROOM CREATE FORM</button> | ||||||
| 	</div> | 	</div> | ||||||
| 	<!-- check if user in the room --> | 	{{else}} | ||||||
|  | 	<!-- user has room id => send him to his room --> | ||||||
| 	{{template "room" .}} | 	{{template "room" .}} | ||||||
| {{end}} | {{end}} | ||||||
|  | {{end}} | ||||||
|   | |||||||
							
								
								
									
										17
									
								
								components/namecheck.html
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										17
									
								
								components/namecheck.html
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,17 @@ | |||||||
|  | {{define "namecheck"}} | ||||||
|  | {{ if eq . 0 }} | ||||||
|  | <div id="login_notice">this name looks available</div> | ||||||
|  | {{ else if eq . 1 }} | ||||||
|  | <a href="/"> | ||||||
|  | <div id="login_notice" class="bg-orange-100 border-l-4 border-orange-500 text-orange-700 p-4" role="alert"> | ||||||
|  |   <p class="font-bold">Be Warned</p> | ||||||
|  |   <p>This Name is already taken. You won't be able to login with it until other person leaves.</p> | ||||||
|  | </div> | ||||||
|  | </a> | ||||||
|  | {{ else }} | ||||||
|  | <div id="login_notice" class="bg-orange-100 border-l-4 border-orange-500 text-orange-700 p-4" role="alert"> | ||||||
|  |   <p class="font-bold">Be Warned</p> | ||||||
|  |   <p>This Name is already taken. You won't be able to login with it until other person leaves.</p> | ||||||
|  | </div> | ||||||
|  | {{end}} | ||||||
|  | {{end}} | ||||||
| @@ -1,5 +1,8 @@ | |||||||
| {{define "room"}} | {{define "room"}} | ||||||
| <div class="flex h-screen"> | <div class="flex h-screen"> | ||||||
|  |   <div id="hello-user"> | ||||||
|  |     <p>Hello {{.Username}}</p> | ||||||
|  |   </div> | ||||||
|   <!-- Left Panel --> |   <!-- Left Panel --> | ||||||
|   {{template "teampew" "blue"}} |   {{template "teampew" "blue"}} | ||||||
|   {{template "cardtable" .}} |   {{template "cardtable" .}} | ||||||
|   | |||||||
| @@ -4,12 +4,12 @@ | |||||||
| <form hx-post="/join-team" hx-target="#room-content"> | <form hx-post="/join-team" hx-target="#room-content"> | ||||||
|     <input type="hidden" name="team" value="{{.}}"> |     <input type="hidden" name="team" value="{{.}}"> | ||||||
|   <div class="mb-2"> |   <div class="mb-2"> | ||||||
|     <button type="submit" name="role" value="guesser" class="w-full bg-blue-500 text-white py-2 px-4 rounded"> |       <button type="submit" name="role" value="guesser" class="w-full bg-{{.}}-500 text-white py-2 px-4 rounded"> | ||||||
|       Join as Guesser |       Join as Guesser | ||||||
|     </button> |     </button> | ||||||
|   </div> |   </div> | ||||||
|   <div> |   <div> | ||||||
|     <button type="submit" name="role" value="mime" class="w-full bg-blue-700 text-white py-2 px-4 rounded"> |       <button type="submit" name="role" value="mime" class="w-full bg-{{.}}-700 text-white py-2 px-4 rounded"> | ||||||
|       Join as Mime |       Join as Mime | ||||||
|     </button> |     </button> | ||||||
|   </div> |   </div> | ||||||
|   | |||||||
| @@ -27,3 +27,24 @@ func getRoomIDFromCtx(ctx context.Context) string { | |||||||
| 	id, _ := ctx.Value(models.CtxRoomIDKey).(string) | 	id, _ := ctx.Value(models.CtxRoomIDKey).(string) | ||||||
| 	return id | 	return id | ||||||
| } | } | ||||||
|  |  | ||||||
|  | // cache | ||||||
|  | func getAllNames() []string { | ||||||
|  | 	names := []string{} | ||||||
|  | 	// will not scale | ||||||
|  | 	wholeMemStore := memcache.GetAll() | ||||||
|  | 	session := &models.Session{} | ||||||
|  | 	// filter by key size only sessions | ||||||
|  | 	for k, v := range wholeMemStore { | ||||||
|  | 		// xid is 20 in len | ||||||
|  | 		if len(k) != 20 { | ||||||
|  | 			continue | ||||||
|  | 		} | ||||||
|  | 		if err := json.Unmarshal(v, &session); err != nil { | ||||||
|  | 			log.Error("failed to unmarshal", "error", err) | ||||||
|  | 			continue | ||||||
|  | 		} | ||||||
|  | 		names = append(names, session.Username) | ||||||
|  | 	} | ||||||
|  | 	return names | ||||||
|  | } | ||||||
|   | |||||||
| @@ -7,6 +7,7 @@ import ( | |||||||
| 	"encoding/base64" | 	"encoding/base64" | ||||||
| 	"encoding/json" | 	"encoding/json" | ||||||
| 	"errors" | 	"errors" | ||||||
|  | 	"fmt" | ||||||
| 	"golias/models" | 	"golias/models" | ||||||
| 	"golias/utils" | 	"golias/utils" | ||||||
| 	"html/template" | 	"html/template" | ||||||
| @@ -21,6 +22,32 @@ func abortWithError(w http.ResponseWriter, msg string) { | |||||||
| 	tmpl.ExecuteTemplate(w, "error", msg) | 	tmpl.ExecuteTemplate(w, "error", msg) | ||||||
| } | } | ||||||
|  |  | ||||||
|  | func HandleNameCheck(w http.ResponseWriter, r *http.Request) { | ||||||
|  | 	r.ParseForm() | ||||||
|  | 	username := r.PostFormValue("username") | ||||||
|  | 	if username == "" { | ||||||
|  | 		msg := "username not provided" | ||||||
|  | 		log.Error(msg) | ||||||
|  | 		abortWithError(w, msg) | ||||||
|  | 		return | ||||||
|  | 	} | ||||||
|  | 	cleanName := utils.RemoveSpacesFromStr(username) | ||||||
|  | 	allNames := getAllNames() | ||||||
|  | 	log.Info("names check", "taken_names", allNames, "trying_name", cleanName) | ||||||
|  | 	tmpl, err := template.ParseGlob("components/*.html") | ||||||
|  | 	if err != nil { | ||||||
|  | 		abortWithError(w, err.Error()) | ||||||
|  | 		return | ||||||
|  | 	} | ||||||
|  | 	if utils.StrInSlice(cleanName, allNames) { | ||||||
|  | 		err := fmt.Errorf("name: %s already taken", cleanName) | ||||||
|  | 		log.Warn("already taken", "error", err) | ||||||
|  | 		tmpl.ExecuteTemplate(w, "namecheck", 2) | ||||||
|  | 		return | ||||||
|  | 	} | ||||||
|  | 	tmpl.ExecuteTemplate(w, "namecheck", 0) | ||||||
|  | } | ||||||
|  |  | ||||||
| func HandleFrontLogin(w http.ResponseWriter, r *http.Request) { | func HandleFrontLogin(w http.ResponseWriter, r *http.Request) { | ||||||
| 	r.ParseForm() | 	r.ParseForm() | ||||||
| 	username := r.PostFormValue("username") | 	username := r.PostFormValue("username") | ||||||
| @@ -46,14 +73,21 @@ func HandleFrontLogin(w http.ResponseWriter, r *http.Request) { | |||||||
| 		abortWithError(w, err.Error()) | 		abortWithError(w, err.Error()) | ||||||
| 		return | 		return | ||||||
| 	} | 	} | ||||||
| 	tmpl.ExecuteTemplate(w, "base", roundWords) | 	// session, ok :=r.Context().Value(models.CtxSessionKey).(*models.Session) | ||||||
|  | 	// if !ok{ | ||||||
|  | 	// 	abortWithError(w, "failed to extract session from ctx") | ||||||
|  | 	// 	return | ||||||
|  | 	// } | ||||||
|  | 	// state := models.InitState(cleanName) | ||||||
|  | 	state := models.MakeTestState() | ||||||
|  | 	tmpl.ExecuteTemplate(w, "base", state) | ||||||
| } | } | ||||||
|  |  | ||||||
| func makeCookie(username string, remote string) (*http.Cookie, error) { | func makeCookie(username string, remote string) (*http.Cookie, error) { | ||||||
| 	// secret | 	// secret | ||||||
| 	// Create a new random session token | 	// Create a new random session token | ||||||
| 	// sessionToken := xid.New().String() | 	// sessionToken := xid.New().String() | ||||||
| 	sessionToken := "token" | 	sessionToken := "sessionprefix_" + username | ||||||
| 	expiresAt := time.Now().Add(time.Duration(cfg.SessionLifetime) * time.Second) | 	expiresAt := time.Now().Add(time.Duration(cfg.SessionLifetime) * time.Second) | ||||||
| 	// Set the token in the session map, along with the session information | 	// Set the token in the session map, along with the session information | ||||||
| 	session := &models.Session{ | 	session := &models.Session{ | ||||||
|   | |||||||
							
								
								
									
										1
									
								
								main.go
									
									
									
									
									
								
							
							
						
						
									
										1
									
								
								main.go
									
									
									
									
									
								
							| @@ -27,6 +27,7 @@ func ListenToRequests(port string) error { | |||||||
| 	mux.HandleFunc("GET /room/createform", handlers.HandleShowCreateForm) | 	mux.HandleFunc("GET /room/createform", handlers.HandleShowCreateForm) | ||||||
| 	mux.HandleFunc("GET /room/hideform", handlers.HandleHideCreateForm) | 	mux.HandleFunc("GET /room/hideform", handlers.HandleHideCreateForm) | ||||||
| 	mux.HandleFunc("GET /word/show-color", handlers.HandleShowColor) | 	mux.HandleFunc("GET /word/show-color", handlers.HandleShowColor) | ||||||
|  | 	mux.HandleFunc("POST /check/name", handlers.HandleNameCheck) | ||||||
| 	slog.Info("Listening", "addr", port) | 	slog.Info("Listening", "addr", port) | ||||||
| 	return server.ListenAndServe() | 	return server.ListenAndServe() | ||||||
| } | } | ||||||
|   | |||||||
| @@ -73,3 +73,11 @@ func MakeTestState() *UserState { | |||||||
| 		Room:     room, | 		Room:     room, | ||||||
| 	} | 	} | ||||||
| } | } | ||||||
|  |  | ||||||
|  | func InitState(username string) *UserState { | ||||||
|  | 	return &UserState{ | ||||||
|  | 		Username: username, | ||||||
|  | 		Team:     UserTeamNone, | ||||||
|  | 		Role:     UserRoleNone, | ||||||
|  | 	} | ||||||
|  | } | ||||||
|   | |||||||
		Reference in New Issue
	
	Block a user
	 Grail Finder
					Grail Finder