From 10ba1576ac9370017e33e19a00b0c8dfd99a1e1c Mon Sep 17 00:00:00 2001 From: AKP Date: Mon, 29 Jan 2024 23:51:55 +0000 Subject: [PATCH] Add pretty login/logout page --- internal/httpcore/endpoints_auth.go | 49 ++++---------------- internal/httpcore/htmlutil/skeleton.go | 63 +++++++++++++++++--------- 2 files changed, 50 insertions(+), 62 deletions(-) diff --git a/internal/httpcore/endpoints_auth.go b/internal/httpcore/endpoints_auth.go index 1b8272a..c0873b4 100644 --- a/internal/httpcore/endpoints_auth.go +++ b/internal/httpcore/endpoints_auth.go @@ -16,14 +16,12 @@ import ( ) func (endpoints) authLoginPage(ctx *fiber.Ctx) error { - titleLine := config.Get().Platform.SocietyName + " voting" - page := htmlutil.SkeletonPage(titleLine, - html.H1(g.Text(titleLine)), - html.P(g.Text("Please enter your details. Please note you must be a member to proceed.")), + page := htmlutil.SkeletonPage(config.Get().Platform.SocietyName + " voting", //g.If(requestProblem != "", // html.P(g.Textf("Error: %s", requestProblem), g.Attr("style", "color: red")), //), html.Script(g.Attr("src", "https://unpkg.com/htmx.org@1.9.10"), g.Attr("defer")), + html.H1(g.Attr("class", "h3 mb-3 fw-normal"), g.Text("Welcome!")), html.Div( g.Attr("hx-get", loginActionEndpoint), g.Attr("hx-trigger", "load"), @@ -114,9 +112,6 @@ func (endpoints) authLogin(ctx *fiber.Ctx) error { goto askNames } - fmt.Println(requestData.FirstName, guildMember.FirstName) - fmt.Println(requestData.LastName, guildMember.LastName) - if subtle.ConstantTimeCompare([]byte(requestData.FirstName), []byte(guildMember.FirstName)) == 0 || subtle.ConstantTimeCompare([]byte(requestData.LastName), []byte(guildMember.LastName)) == 0 { requestProblem = "Invalid name - please ensure that you are using the name the Guild of Students knows you as." @@ -190,13 +185,9 @@ askStudentID: g.Attr("style", "color: red;"), html.Em(g.Text(requestProblem+" If you're having trouble logging in, please speak to a member of committee.")), )), - html.H2(g.Text("What's your student ID?")), + htmlutil.SmallTitle("What's your student ID?"), htmlutil.FormInput("text", "studentid", "Your student ID", "Student ID"), - html.Br(), - html.Input( - g.Attr("type", "submit"), - g.Attr("value", "Next"), - ), + htmlutil.FormSubmitButton(), )) registeredAskPassword: @@ -205,14 +196,9 @@ registeredAskPassword: g.Attr("hx-post", loginActionEndpoint), g.Attr("hx-swap", "outerHTML"), g.Attr("hx-vals", string(requestDataJSON)), - html.H2(g.Text("Welcome back!")), html.P(g.Text("Please enter your password. If you've forgotten it, please speak to a member of committee.")), htmlutil.FormInput("password", "password", "", "Password"), - html.Br(), - html.Input( - g.Attr("type", "submit"), - g.Attr("value", "Next"), - ), + htmlutil.FormSubmitButton(), )) askNames: @@ -221,16 +207,10 @@ askNames: g.Attr("hx-post", loginActionEndpoint), g.Attr("hx-swap", "outerHTML"), g.Attr("hx-vals", string(requestDataJSON)), - html.H2(g.Text("Welcome!")), html.P(g.Text("In order to check that the student ID you entered is yours, please enter your name as the Guild of Students knows it.")), htmlutil.FormInput("text", "fname", "Your first name", "First name"), - html.Br(), htmlutil.FormInput("text", "lname", "Your last name", "Last name"), - html.Br(), - html.Input( - g.Attr("type", "submit"), - g.Attr("value", "Next"), - ), + htmlutil.FormSubmitButton(), )) askAuthCode: @@ -239,14 +219,9 @@ askAuthCode: g.Attr("hx-post", loginActionEndpoint), g.Attr("hx-swap", "outerHTML"), g.Attr("hx-vals", string(requestDataJSON)), - html.H2(g.Text("Welcome!")), html.P(g.Text("Please enter the authorisation code.")), - htmlutil.FormInput("text", "auth", "", "Authorisation code"), - html.Br(), - html.Input( - g.Attr("type", "submit"), - g.Attr("value", "Next"), - ), + htmlutil.FormInput("password", "auth", "", "Authorisation code"), + htmlutil.FormSubmitButton(), )) unregisteredAskPassword: @@ -259,16 +234,10 @@ unregisteredAskPassword: g.Attr("style", "color: red;"), html.Em(g.Text(requestProblem)), )), - html.H2(g.Text("Welcome!")), html.P(g.Text("Please choose a password.")), htmlutil.FormInput("password", "password", "", "Password"), - html.Br(), htmlutil.FormInput("password", "passwordconf", "", "Confirm password"), - html.Br(), - html.Input( - g.Attr("type", "submit"), - g.Attr("value", "Next"), - ), + htmlutil.FormSubmitButton(), )) } diff --git a/internal/httpcore/htmlutil/skeleton.go b/internal/httpcore/htmlutil/skeleton.go index 2272360..b33e844 100644 --- a/internal/httpcore/htmlutil/skeleton.go +++ b/internal/httpcore/htmlutil/skeleton.go @@ -10,26 +10,29 @@ import ( ) func SkeletonPage(title string, content ...g.Node) g.Node { - content = append(content, P(g.Attr("style", "color: grey; font-style: italic;"), - g.Text("Society Voting is open source software licensed under the BSD 2-Clause License. You can contribute "), - A(g.Attr("href", "https://github.com/CSSUoB/society-voting"), g.Text("here")), - g.Text("."), - )) - return HTML( Head( Meta(g.Attr("charset", "utf-8")), - Meta(g.Attr("name", "viewport"), g.Attr("content", "width=device-width, initial-scale=1.0")), + Meta(g.Attr("name", "viewport"), g.Attr("content", "width=device-width, initial-scale=1")), TitleEl(g.Text(title)), - StyleEl(g.Text(` -body { - font-family: sans-serif; - font-size: 1.1rem; - padding: 1em; -} -`)), + Link(g.Attr("rel", "stylesheet"), g.Attr("type", "text/css"), g.Attr("href", "https://cdn.jsdelivr.net/npm/bootstrap@5.3.2/dist/css/bootstrap.min.css")), + Link(g.Attr("rel", "icon"), g.Attr("href", "/favicon.svg"), g.Attr("type", "image/svg")), + StyleEl(g.Raw(`body,html{height:100%}.form-signin{max-width:330px;padding:1rem}.form-signin .form-floating:focus-within{z-index:2}`)), + ), + Body( + g.Attr("class", "d-flex align-items-center py-4 bg-body-tertiary"), + Main( + g.Attr("class", "form-signin w-100 m-auto"), + Img(g.Attr("src", "https://cssuob.github.io/resources/dinosaur/raster/tex_ballot.png"), g.Attr("style", "max-height: 72px; margin-bottom: 15px;")), + g.Group(content), + P( + g.Attr("class", "mt-3 mb-3 text-body-secondary"), + g.Text("Society Voting is open source software licensed under the BSD 2-Clause License. You can contribute "), + A(g.Attr("href", "https://github.com/CSSUoB/society-voting"), g.Text("here")), + g.Text("."), + ), + ), ), - Body(content...), ) } @@ -50,17 +53,33 @@ func SendFragment(ctx *fiber.Ctx, frag g.Node) error { func FormInput(inputType, name, placeholder, labelText string) g.Node { r := strconv.Itoa(rand.Intn(1000000)) - return g.Group([]g.Node{ - Label( - g.Text(labelText), - g.Attr("for", r), - g.Attr("style", "margin-right: 6px"), - ), + return Div( + g.Attr("class", "form-floating"), Input( g.Attr("type", inputType), g.Attr("placeholder", placeholder), g.Attr("name", name), g.Attr("id", r), + g.Attr("class", "form-control"), ), - }) + Label( + g.Text(labelText), + g.Attr("for", r), + ), + ) +} + +func SmallTitle(content string) g.Node { + return H2( + g.Attr("class", "h5 mb-3 fw-normal"), + g.Text(content), + ) } + +func FormSubmitButton() g.Node { + return Button( + g.Attr("class", "btn btn-primary w-100 py-2 mt-2"), + g.Attr("type", "submit"), + g.Text("Next"), + ) +} \ No newline at end of file