Mirror of @tangled.org/core. Running on a Raspberry Pi Zero 2 (Please be gentle).
0
fork

Configure Feed

Select the types of activity you want to include in your feed.

appview/pages: rework signup pages

- new /signup page to enter email ID
- login page has a link to go signup
- signup page has a link to go back to login

Signed-off-by: oppiliappan <me@oppi.li>

oppiliappan 564cfdd2 fd66928f

+134 -136
+5 -3
appview/pages/pages.go
··· 262 262 return p.executePlain("user/login", w, params) 263 263 } 264 264 265 - type SignupParams struct{} 265 + func (p *Pages) Signup(w io.Writer) error { 266 + return p.executePlain("user/signup", w, nil) 267 + } 266 268 267 - func (p *Pages) CompleteSignup(w io.Writer, params SignupParams) error { 268 - return p.executePlain("user/completeSignup", w, params) 269 + func (p *Pages) CompleteSignup(w io.Writer) error { 270 + return p.executePlain("user/completeSignup", w, nil) 269 271 } 270 272 271 273 type TermsOfServiceParams struct {
+4
appview/pages/templates/layouts/topbar.html
··· 15 15 {{ block "dropDown" . }} {{ end }} 16 16 {{ else }} 17 17 <a href="/login">login</a> 18 + <span class="text-gray-500 dark:text-gray-400">or</span> 19 + <a href="/signup" class="btn-create py-0 hover:no-underline hover:text-white flex items-center gap-2"> 20 + join now {{ i "arrow-right" "size-4" }} 21 + </a> 18 22 {{ end }} 19 23 </div> 20 24 </div>
+5 -5
appview/pages/templates/user/completeSignup.html
··· 38 38 tightly-knit social coding. 39 39 </h2> 40 40 <form 41 - class="mt-4 max-w-sm mx-auto" 41 + class="mt-4 max-w-sm mx-auto flex flex-col gap-4" 42 42 hx-post="/signup/complete" 43 43 hx-swap="none" 44 44 hx-disabled-elt="#complete-signup-button" ··· 58 58 </span> 59 59 </div> 60 60 61 - <div class="flex flex-col mt-4"> 62 - <label for="username">desired username</label> 61 + <div class="flex flex-col"> 62 + <label for="username">username</label> 63 63 <input 64 64 type="text" 65 65 id="username" ··· 73 73 </span> 74 74 </div> 75 75 76 - <div class="flex flex-col mt-4"> 76 + <div class="flex flex-col"> 77 77 <label for="password">password</label> 78 78 <input 79 79 type="password" ··· 88 88 </div> 89 89 90 90 <button 91 - class="btn-create w-full my-2 mt-6" 91 + class="btn-create w-full my-2 mt-6 text-base" 92 92 type="submit" 93 93 id="complete-signup-button" 94 94 tabindex="4"
+11 -79
appview/pages/templates/user/login.html
··· 3 3 <html lang="en" class="dark:bg-gray-900"> 4 4 <head> 5 5 <meta charset="UTF-8" /> 6 - <meta 7 - name="viewport" 8 - content="width=device-width, initial-scale=1.0" 9 - /> 10 - <meta 11 - property="og:title" 12 - content="login · tangled" 13 - /> 14 - <meta 15 - property="og:url" 16 - content="https://tangled.sh/login" 17 - /> 18 - <meta 19 - property="og:description" 20 - content="login to or sign up for tangled" 21 - /> 6 + <meta name="viewport" content="width=device-width, initial-scale=1.0" /> 7 + <meta property="og:title" content="login · tangled" /> 8 + <meta property="og:url" content="https://tangled.sh/login" /> 9 + <meta property="og:description" content="login to for tangled" /> 22 10 <script src="/static/htmx.min.js"></script> 23 - <link 24 - rel="stylesheet" 25 - href="/static/tw.css?{{ cssContentHash }}" 26 - type="text/css" 27 - /> 28 - <title>login or sign up &middot; tangled</title> 11 + <link rel="stylesheet" href="/static/tw.css?{{ cssContentHash }}" type="text/css" /> 12 + <title>login &middot; tangled</title> 29 13 </head> 30 14 <body class="flex items-center justify-center min-h-screen"> 31 15 <main class="max-w-md px-6 -mt-4"> 32 - <h1 33 - class="text-center text-2xl font-semibold italic dark:text-white" 34 - > 16 + <h1 class="text-center text-2xl font-semibold italic dark:text-white" > 35 17 tangled 36 18 </h1> 37 19 <h2 class="text-center text-xl italic dark:text-white"> ··· 33 51 name="handle" 34 52 tabindex="1" 35 53 required 36 - placeholder="foo.tngl.sh" 54 + placeholder="akshay.tngl.sh" 37 55 /> 38 56 <span class="text-sm text-gray-500 mt-1"> 39 57 Use your <a href="https://atproto.com">ATProto</a> ··· 43 61 </div> 44 62 45 63 <button 46 - class="btn w-full my-2 mt-6" 64 + class="btn w-full my-2 mt-6 text-base " 47 65 type="submit" 48 66 id="login-button" 49 67 tabindex="3" ··· 51 69 <span>login</span> 52 70 </button> 53 71 </form> 54 - <hr class="my-4"> 55 - <p class="text-sm text-gray-500 mt-4"> 56 - Alternatively, you may create an account on Tangled below. You will 57 - get a <code>user.tngl.sh</code> handle. 72 + <p class="text-sm text-gray-500"> 73 + Don't have an account? <a href="/signup" class="underline">Create an account</a> on Tangled now! 58 74 </p> 59 75 60 - <details class="group"> 61 - 62 - <summary 63 - class="btn cursor-pointer w-full mt-4 flex items-center justify-center gap-2" 64 - > 65 - create an account 66 - 67 - <div class="group-open:hidden flex">{{ i "arrow-right" "w-4 h-4" }}</div> 68 - <div class="hidden group-open:flex">{{ i "arrow-down" "w-4 h-4" }}</div> 69 - </summary> 70 - <form 71 - class="mt-4 max-w-sm mx-auto" 72 - hx-post="/signup" 73 - hx-swap="none" 74 - hx-disabled-elt="#signup-button" 75 - > 76 - <div class="flex flex-col mt-2"> 77 - <label for="email">email</label> 78 - <input 79 - type="email" 80 - id="email" 81 - name="email" 82 - tabindex="4" 83 - required 84 - placeholder="jason@bourne.co" 85 - /> 86 - </div> 87 - <span class="text-sm text-gray-500 mt-1"> 88 - You will receive an email with a code. Enter that, along with your 89 - desired username and password in the next page to complete your registration. 90 - </span> 91 - <button 92 - class="btn w-full my-2 mt-6" 93 - type="submit" 94 - id="signup-button" 95 - tabindex="7" 96 - > 97 - <span>sign up</span> 98 - </button> 99 - </form> 100 - </details> 101 - <p class="text-sm text-gray-500 mt-6"> 102 - Join our <a href="https://chat.tangled.sh">Discord</a> or 103 - IRC channel: 104 - <a href="https://web.libera.chat/#tangled" 105 - ><code>#tangled</code> on Libera Chat</a 106 - >. 107 - </p> 108 76 <p id="login-msg" class="error w-full"></p> 109 77 </main> 110 78 </body>
+53
appview/pages/templates/user/signup.html
··· 1 + {{ define "user/signup" }} 2 + <!doctype html> 3 + <html lang="en" class="dark:bg-gray-900"> 4 + <head> 5 + <meta charset="UTF-8" /> 6 + <meta name="viewport" content="width=device-width, initial-scale=1.0" /> 7 + <meta property="og:title" content="signup · tangled" /> 8 + <meta property="og:url" content="https://tangled.sh/signup" /> 9 + <meta property="og:description" content="sign up for tangled" /> 10 + <script src="/static/htmx.min.js"></script> 11 + <link rel="stylesheet" href="/static/tw.css?{{ cssContentHash }}" type="text/css" /> 12 + <title>sign up &middot; tangled</title> 13 + </head> 14 + <body class="flex items-center justify-center min-h-screen"> 15 + <main class="max-w-md px-6 -mt-4"> 16 + <h1 class="text-center text-2xl font-semibold italic dark:text-white" >tangled</h1> 17 + <h2 class="text-center text-xl italic dark:text-white">tightly-knit social coding.</h2> 18 + <form 19 + class="mt-4 max-w-sm mx-auto" 20 + hx-post="/signup" 21 + hx-swap="none" 22 + hx-disabled-elt="#signup-button" 23 + > 24 + <div class="flex flex-col mt-2"> 25 + <label for="email">email</label> 26 + <input 27 + type="email" 28 + id="email" 29 + name="email" 30 + tabindex="4" 31 + required 32 + placeholder="jason@bourne.co" 33 + /> 34 + </div> 35 + <span class="text-sm text-gray-500 mt-1"> 36 + You will receive an email with an invite code. Enter your 37 + invite code, desired username, and password in the next 38 + page to complete your registration. 39 + </span> 40 + <button class="btn text-base w-full my-2 mt-6" type="submit" id="signup-button" tabindex="7" > 41 + <span>join now</span> 42 + </button> 43 + </form> 44 + <p class="text-sm text-gray-500"> 45 + Already have an account? <a href="/login" class="underline">Login to Tangled</a>. 46 + </p> 47 + 48 + <p id="signup-msg" class="error w-full"></p> 49 + </main> 50 + </body> 51 + </html> 52 + {{ end }} 53 +
+56 -49
appview/signup/signup.go
··· 104 104 105 105 func (s *Signup) Router() http.Handler { 106 106 r := chi.NewRouter() 107 + r.Get("/", s.signup) 107 108 r.Post("/", s.signup) 108 109 r.Get("/complete", s.complete) 109 110 r.Post("/complete", s.complete) ··· 113 112 } 114 113 115 114 func (s *Signup) signup(w http.ResponseWriter, r *http.Request) { 116 - if s.cf == nil { 117 - http.Error(w, "signup is disabled", http.StatusFailedDependency) 118 - } 119 - emailId := r.FormValue("email") 115 + switch r.Method { 116 + case http.MethodGet: 117 + s.pages.Signup(w) 118 + case http.MethodPost: 119 + if s.cf == nil { 120 + http.Error(w, "signup is disabled", http.StatusFailedDependency) 121 + } 122 + emailId := r.FormValue("email") 120 123 121 - if !email.IsValidEmail(emailId) { 122 - s.pages.Notice(w, "login-msg", "Invalid email address.") 123 - return 124 - } 124 + noticeId := "signup-msg" 125 + if !email.IsValidEmail(emailId) { 126 + s.pages.Notice(w, noticeId, "Invalid email address.") 127 + return 128 + } 125 129 126 - exists, err := db.CheckEmailExistsAtAll(s.db, emailId) 127 - if err != nil { 128 - s.l.Error("failed to check email existence", "error", err) 129 - s.pages.Notice(w, "login-msg", "Failed to complete signup. Try again later.") 130 - return 131 - } 132 - if exists { 133 - s.pages.Notice(w, "login-msg", "Email already exists.") 134 - return 135 - } 130 + exists, err := db.CheckEmailExistsAtAll(s.db, emailId) 131 + if err != nil { 132 + s.l.Error("failed to check email existence", "error", err) 133 + s.pages.Notice(w, noticeId, "Failed to complete signup. Try again later.") 134 + return 135 + } 136 + if exists { 137 + s.pages.Notice(w, noticeId, "Email already exists.") 138 + return 139 + } 136 140 137 - code, err := s.inviteCodeRequest() 138 - if err != nil { 139 - s.l.Error("failed to create invite code", "error", err) 140 - s.pages.Notice(w, "login-msg", "Failed to create invite code.") 141 - return 142 - } 141 + code, err := s.inviteCodeRequest() 142 + if err != nil { 143 + s.l.Error("failed to create invite code", "error", err) 144 + s.pages.Notice(w, noticeId, "Failed to create invite code.") 145 + return 146 + } 143 147 144 - em := email.Email{ 145 - APIKey: s.config.Resend.ApiKey, 146 - From: s.config.Resend.SentFrom, 147 - To: emailId, 148 - Subject: "Verify your Tangled account", 149 - Text: `Copy and paste this code below to verify your account on Tangled. 148 + em := email.Email{ 149 + APIKey: s.config.Resend.ApiKey, 150 + From: s.config.Resend.SentFrom, 151 + To: emailId, 152 + Subject: "Verify your Tangled account", 153 + Text: `Copy and paste this code below to verify your account on Tangled. 150 154 ` + code, 151 - Html: `<p>Copy and paste this code below to verify your account on Tangled.</p> 155 + Html: `<p>Copy and paste this code below to verify your account on Tangled.</p> 152 156 <p><code>` + code + `</code></p>`, 153 - } 157 + } 154 158 155 - err = email.SendEmail(em) 156 - if err != nil { 157 - s.l.Error("failed to send email", "error", err) 158 - s.pages.Notice(w, "login-msg", "Failed to send email.") 159 - return 160 - } 161 - err = db.AddInflightSignup(s.db, db.InflightSignup{ 162 - Email: emailId, 163 - InviteCode: code, 164 - }) 165 - if err != nil { 166 - s.l.Error("failed to add inflight signup", "error", err) 167 - s.pages.Notice(w, "login-msg", "Failed to complete sign up. Try again later.") 168 - return 169 - } 159 + err = email.SendEmail(em) 160 + if err != nil { 161 + s.l.Error("failed to send email", "error", err) 162 + s.pages.Notice(w, noticeId, "Failed to send email.") 163 + return 164 + } 165 + err = db.AddInflightSignup(s.db, db.InflightSignup{ 166 + Email: emailId, 167 + InviteCode: code, 168 + }) 169 + if err != nil { 170 + s.l.Error("failed to add inflight signup", "error", err) 171 + s.pages.Notice(w, noticeId, "Failed to complete sign up. Try again later.") 172 + return 173 + } 170 174 171 - s.pages.HxRedirect(w, "/signup/complete") 175 + s.pages.HxRedirect(w, "/signup/complete") 176 + } 172 177 } 173 178 174 179 func (s *Signup) complete(w http.ResponseWriter, r *http.Request) { 175 180 switch r.Method { 176 181 case http.MethodGet: 177 - s.pages.CompleteSignup(w, pages.SignupParams{}) 182 + s.pages.CompleteSignup(w) 178 183 case http.MethodPost: 179 184 username := r.FormValue("username") 180 185 password := r.FormValue("password")