~jan0sch/smederee
Showing details for patch 53bc774bbbb7d4e650bd85ebbf04e5162113b639.
diff -rN -u old-smederee/modules/hub/src/main/resources/assets/css/main.css new-smederee/modules/hub/src/main/resources/assets/css/main.css --- old-smederee/modules/hub/src/main/resources/assets/css/main.css 2025-02-03 05:05:52.387339381 +0000 +++ new-smederee/modules/hub/src/main/resources/assets/css/main.css 2025-02-03 05:05:52.391339387 +0000 @@ -1,31 +1,87 @@ main { - margin-left: 1em; - margin-right: 1em; + margin-left: 1em; + margin-right: 1em; } -.button-success, -.button-error, -.button-warning, -.button-secondary { - color: white; +.pure-button { + background-color: #1f8dd6; + color: white; + padding: 0.5em 2em; + border-radius: 5px; } -.button-success { - background: rgb(28, 184, 65); - /* this is a green */ +a.pure-button-primary { + background: white; + color: #1f8dd6; + border-radius: 5px; + font-size: 120%; } -.button-error { - background: rgb(202, 60, 60); - /* this is a maroon */ +.home-menu { + padding: 0.5em; + text-align: center; + box-shadow: 0 1px 1px rgba(0,0,0, 0.10); +} +.home-menu { + background: #2d3e50; +} + +.home-menu .pure-menu-heading { + color: white; + font-weight: 400; + font-size: 120%; } -.button-warning { - background: rgb(223, 117, 20); - /* this is an orange */ +.home-menu .pure-menu-selected a { + color: white; } -.button-secondary { - background: rgb(66, 184, 221); - /* this is a light blue */ +.home-menu a { + color: #6FBEF3; +} +.home-menu li a:hover, +.home-menu li a:focus { + background: none; + border: none; + color: #AECFE5; +} + +@media (min-width: 48em) { + + /* We increase the body font size */ + body { + font-size: 16px; + } + + /* We can align the menu header to the left, but float the + menu items to the right. */ + .home-menu { + text-align: left; + } + .home-menu ul { + float: right; + } + + /* We increase the height of the splash-container */ + /* .splash-container { + height: 500px; + }*/ + + /* We decrease the width of the .splash, since we have more width + to work with */ + .splash { + width: 50%; + height: 50%; + } + + .splash-head { + font-size: 250%; + } + + + /* We remove the border-separator assigned to .l-box-lrg */ + .l-box-lrg { + border: none; + } + } diff -rN -u old-smederee/modules/hub/src/main/resources/messages_en.properties new-smederee/modules/hub/src/main/resources/messages_en.properties --- old-smederee/modules/hub/src/main/resources/messages_en.properties 2025-02-03 05:05:52.387339381 +0000 +++ new-smederee/modules/hub/src/main/resources/messages_en.properties 2025-02-03 05:05:52.391339387 +0000 @@ -13,6 +13,11 @@ errors.forbidden.title = 403 - Forbidden # Forms +form.login.button.submit=Login +form.login.password=Password +form.login.password.placeholder=Please enter your password here. +form.login.username=Username +form.login.username.placeholder=Please enter your username. form.signup.button.submit=Sign up for an account form.signup.email=Email address form.signup.email.help=Please enter your email address. @@ -29,6 +34,7 @@ global.imprint=Imprint global.login=Login global.logout=Logout +global.navbar.top.logo=Smederee global.privacy=Privacy Policy global.signup=Sign Up global.terms.of.use=Terms of Use diff -rN -u old-smederee/modules/hub/src/main/scala/de/smederee/hub/AuthenticationRoutes.scala new-smederee/modules/hub/src/main/scala/de/smederee/hub/AuthenticationRoutes.scala --- old-smederee/modules/hub/src/main/scala/de/smederee/hub/AuthenticationRoutes.scala 2025-02-03 05:05:52.387339381 +0000 +++ new-smederee/modules/hub/src/main/scala/de/smederee/hub/AuthenticationRoutes.scala 2025-02-03 05:05:52.391339387 +0000 @@ -147,7 +147,7 @@ } private val parseLoginFormForLoggedInUsers: AuthedRoutes[Account, F] = AuthedRoutes.of { - case ar @ GET -> Root / "login" as _ => + case ar @ POST -> Root / "login" as _ => SeeOther.apply(Location(Uri(path = Uri.Path.Root))) // Redirect already logged in users. } diff -rN -u old-smederee/modules/hub/src/main/scala/de/smederee/hub/HubServer.scala new-smederee/modules/hub/src/main/scala/de/smederee/hub/HubServer.scala --- old-smederee/modules/hub/src/main/scala/de/smederee/hub/HubServer.scala 2025-02-03 05:05:52.387339381 +0000 +++ new-smederee/modules/hub/src/main/scala/de/smederee/hub/HubServer.scala 2025-02-03 05:05:52.391339387 +0000 @@ -80,7 +80,7 @@ signUpRoutes = new SignupRoutes[IO](configuration.service.signup, signUpRepo) landingPages = new LandingPageRoutes[IO]() protectedRoutesWithFallThrough = authenticationWithFallThrough( - authenticationRoutes.protectedRoutes <+> landingPages.protectedRoutes + authenticationRoutes.protectedRoutes <+> signUpRoutes.protectedRoutes <+> landingPages.protectedRoutes ) globalRoutes = Router( Constants.assetsPath.path.toAbsolute.toString -> assetsRoutes, diff -rN -u old-smederee/modules/hub/src/main/scala/de/smederee/hub/SignupRoutes.scala new-smederee/modules/hub/src/main/scala/de/smederee/hub/SignupRoutes.scala --- old-smederee/modules/hub/src/main/scala/de/smederee/hub/SignupRoutes.scala 2025-02-03 05:05:52.387339381 +0000 +++ new-smederee/modules/hub/src/main/scala/de/smederee/hub/SignupRoutes.scala 2025-02-03 05:05:52.391339387 +0000 @@ -22,6 +22,7 @@ import org.http4s.FormDataDecoder._ import org.http4s._ import org.http4s.dsl.Http4sDsl +import org.http4s.headers.Location import org.http4s.implicits._ import org.http4s.twirl.TwirlInstances._ import org.slf4j.LoggerFactory @@ -117,6 +118,11 @@ } } + private val parseSignUpFormForLoggedInUsers: AuthedRoutes[Account, F] = AuthedRoutes.of { + case ar @ POST -> Root / "signup" as _ => + SeeOther.apply(Location(Uri(path = Uri.Path.Root))) // Redirect already logged in users. + } + // Render the signup form. private val showSignUpForm = HttpRoutes.of[F] { case request @ GET -> Root / "signup" => for { @@ -125,5 +131,12 @@ } yield resp } + private val showSignUpFormForLoggedInUsers: AuthedRoutes[Account, F] = AuthedRoutes.of { + case ar @ GET -> Root / "signup" as _ => + SeeOther.apply(Location(Uri(path = Uri.Path.Root))) // Redirect already logged in users. + } + + val protectedRoutes = showSignUpFormForLoggedInUsers <+> parseSignUpFormForLoggedInUsers + val routes = showSignUpForm <+> parseSignUpForm } diff -rN -u old-smederee/modules/hub/src/main/twirl/de/smederee/hub/views/index.scala.html new-smederee/modules/hub/src/main/twirl/de/smederee/hub/views/index.scala.html --- old-smederee/modules/hub/src/main/twirl/de/smederee/hub/views/index.scala.html 2025-02-03 05:05:52.387339381 +0000 +++ new-smederee/modules/hub/src/main/twirl/de/smederee/hub/views/index.scala.html 2025-02-03 05:05:52.391339387 +0000 @@ -17,12 +17,11 @@ @customHeaders </head> <body> - <navbar class="header"> - <div class="home-menu pure-menu pure-menu-horizontal pure-menu-fixed"> - <a class="pure-menu-heading" href="">@Messages("landingpage.index.menu.heading")</a> + <navbar class="header navbar" id="navbar-top"> + <nav class="home-menu pure-menu pure-menu-horizontal pure-menu-fixed"> + <a class="logo pure-menu-heading" href="@pathPrefix/">@Messages("global.navbar.top.logo")</a> <ul class="pure-menu-list"> - <li class="pure-menu-item pure-menu-selected"><a href="#" class="pure-menu-link">Home</a></li> @if(user.nonEmpty) { <li class="pure-menu-item"> <form action="/logout" method="POST" accept-charset="UTF-8" class="inline"> @@ -35,7 +34,7 @@ <li class="pure-menu-item"><a href="/signup" class="pure-menu-link">@Messages("global.signup")</a></li> } </ul> - </div> + </nav> </navbar> <div class="splash-container"> @@ -73,7 +72,7 @@ <div class="ribbon l-box-lrg pure-g"> <div class="l-box-lrg is-center pure-u-1 pure-u-md-1-2 pure-u-lg-2-5"> - <img width="300" alt="File Icons" class="pure-img-responsive" src="@pathPrefix/assets/img/malcolm-lightbody-gPRvTP0sZ2M-unsplash.jpg"> + <img width="300" alt="A smithy in which a smith is working on an anvil." class="pure-img-responsive" src="@pathPrefix/assets/img/malcolm-lightbody-gPRvTP0sZ2M-unsplash.jpg"> </div> <div class="pure-u-1 pure-u-md-1-2 pure-u-lg-3-5"> <h2 class="content-head content-head-ribbon">@Messages("landingpage.index.ribbon.title")</h2> @@ -88,7 +87,7 @@ <div class="l-box-lrg pure-u-1 pure-u-md-2-5"> <div class="signup-form"> <form action="@createFullPath(pathPrefix)(actionSignup)" class="pure-form pure-form-stacked" method="POST" accept-charset="UTF-8" class="pure-form pure-form-aligned" autocomplete="on"> - <fieldset id="signup-data"> + <fieldset id="signup-data" @{user.map(_ => "disabled")}> <div class="pure-control-group"> <label for="@{fieldName}">@Messages("form.signup.username")</label> <input class="pure-input-1-2" id="@{fieldName}" name="@{fieldName}" placeholder="@Messages("form.signup.username.placeholder")" maxlength="31" required="" type="text" value="" autocomplete="username"> @@ -103,7 +102,7 @@ </div> @csrfToken(csrf) <div class="pure-controls"> - <button type="submit" class="pure-button button-success">@Messages("form.signup.button.submit")</button> + <button type="submit" class="pure-button" @{user.map(_ => "disabled")}>@Messages("form.signup.button.submit")</button> </div> </fieldset> </form> diff -rN -u old-smederee/modules/hub/src/main/twirl/de/smederee/hub/views/login.scala.html new-smederee/modules/hub/src/main/twirl/de/smederee/hub/views/login.scala.html --- old-smederee/modules/hub/src/main/twirl/de/smederee/hub/views/login.scala.html 2025-02-03 05:05:52.387339381 +0000 +++ new-smederee/modules/hub/src/main/twirl/de/smederee/hub/views/login.scala.html 2025-02-03 05:05:52.391339387 +0000 @@ -2,37 +2,43 @@ @(lang: LanguageCode = LanguageCode("en"), pathPrefix: Option[Uri] = None)(action: Uri, csrf: Option[CsrfToken] = None, title: Option[String] = None)(formData: Map[String, String] = Map.empty, formErrors: FormErrors = FormErrors.empty) @main(lang, pathPrefix)()(csrf, title) { - <div class="pure-u-1-1 pure-u-md-1-1 login"> - <div class="form-errors"> - @formErrors.get(fieldGlobal).map { es => +@defining(lang.toLocale) { implicit locale => +<div class="content"> + <div class="pure-g"> + <div class="pure-u-1-1 pure-u-md-1-1 login"> + <div class="form-errors"> + @formErrors.get(fieldGlobal).map { es => @for(error <- es) { - <p class="alert alert-danger"> - <span class="glyphicon glyphicon-exclamation-sign" aria-hidden="true"></span> - <span class="sr-only">Fehler:</span> - @error - </p> + <p class="alert alert-danger"> + <span class="glyphicon glyphicon-exclamation-sign" aria-hidden="true"></span> + <span class="sr-only">Fehler:</span> + @error + </p> } - } - </div> - <div class="login-form"> - <form action="@createFullPath(pathPrefix)(action)" method="POST" accept-charset="UTF-8" class="pure-form pure-form-aligned"> - <fieldset id="login-data"> - <div class="pure-control-group"> - <label for="@{fieldName}">Username</label> - <input class="pure-input-1-2" id="@{fieldName}" name="@{fieldName}" placeholder="Please enter your username." maxlength="31" required="" type="text" value="@{formData.get(fieldName)}"> - @renderFormErrors(fieldName, formErrors) - </div> - <div class="pure-control-group"> - <label for="@{fieldPassword}">Password</label> - <input class="pure-input-1-2" id="@{fieldPassword}" name="@{fieldPassword}" placeholder="Please enter your password here." maxlength="128" required="" type="password" value=""> - @renderFormErrors(fieldPassword, formErrors) - </div> - @csrfToken(csrf) - <div class="pure-controls"> - <button type="submit" class="pure-button button-success">Login</button> - </div> - </fieldset> - </form> + } + </div> + <div class="login-form"> + <form action="@createFullPath(pathPrefix)(action)" method="POST" accept-charset="UTF-8" class="pure-form pure-form-aligned" autocomplete="on"> + <fieldset id="login-data"> + <div class="pure-control-group"> + <label for="@{fieldName}">@Messages("form.login.username")</label> + <input class="pure-input-1-2" id="@{fieldName}" name="@{fieldName}" placeholder="@Messages("form.login.username.placeholder")" maxlength="31" required="" type="text" value="@{formData.get(fieldName)}" autocomplete="username"> + @renderFormErrors(fieldName, formErrors) + </div> + <div class="pure-control-group"> + <label for="@{fieldPassword}">@Messages("form.login.password")</label> + <input class="pure-input-1-2" id="@{fieldPassword}" name="@{fieldPassword}" placeholder="@Messages("form.login.password.placeholder")" maxlength="128" required="" type="password" value="" autocomplete="password"> + @renderFormErrors(fieldPassword, formErrors) + </div> + @csrfToken(csrf) + <div class="pure-controls"> + <button type="submit" class="pure-button">@Messages("form.login.button.submit")</button> + </div> + </fieldset> + </form> + </div> </div> </div> +</div> +} } diff -rN -u old-smederee/modules/hub/src/main/twirl/de/smederee/hub/views/main.scala.html new-smederee/modules/hub/src/main/twirl/de/smederee/hub/views/main.scala.html --- old-smederee/modules/hub/src/main/twirl/de/smederee/hub/views/main.scala.html 2025-02-03 05:05:52.387339381 +0000 +++ new-smederee/modules/hub/src/main/twirl/de/smederee/hub/views/main.scala.html 2025-02-03 05:05:52.391339387 +0000 @@ -1,4 +1,5 @@ @(lang: LanguageCode = LanguageCode("en"), pathPrefix: Option[Uri] = None, tags: MetaTags = MetaTags.empty)(customFooters: Html = Html(""), customHeaders: Html = Html(""))(csrf: Option[CsrfToken] = None, title: Option[String] = None, user: Option[Account] = None)(content: Html) +@defining(lang.toLocale) { implicit locale => <!DOCTYPE html> <html lang="@lang"> <head> @@ -12,8 +13,11 @@ @customHeaders </head> <body> - <navbar class="navbar" id="navbar-top">@navbar(lang, pathPrefix)(csrf, user)</navbar> - <main class="pure-g">@content</main> - <footer class="footer">@customFooters</footer> + <navbar class="header navbar" id="navbar-top">@navbar(lang, pathPrefix)(csrf, user)</navbar> + <main class="content-wrapper"> + @content + <footer class="footer">@customFooters</footer> + </main> </body> </html> +} diff -rN -u old-smederee/modules/hub/src/main/twirl/de/smederee/hub/views/navbar.scala.html new-smederee/modules/hub/src/main/twirl/de/smederee/hub/views/navbar.scala.html --- old-smederee/modules/hub/src/main/twirl/de/smederee/hub/views/navbar.scala.html 2025-02-03 05:05:52.391339387 +0000 +++ new-smederee/modules/hub/src/main/twirl/de/smederee/hub/views/navbar.scala.html 2025-02-03 05:05:52.391339387 +0000 @@ -1,17 +1,20 @@ @(lang: LanguageCode, pathPrefix: Option[Uri])(csrf: Option[CsrfToken] = None, user: Option[Account] = None) -<nav class="home-menu pure-menu pure-menu-horizontal pure-menu-fixed"> - <a class="logo pure-menu-heading" href="#">Smederee</a> +@defining(lang.toLocale) { implicit locale => +<nav class="home-menu pure-menu pure-menu-horizontal"> + <a class="logo pure-menu-heading" href="@pathPrefix/">@Messages("global.navbar.top.logo")</a> + <ul class="pure-menu-list"> - <li class=""><a class="pure-menu-link" href="#">...</a></li> - @if(user.nonEmpty) { - <li class="pure-menu-item"> - <form action="/logout" method="POST" accept-charset="UTF-8" class="inline"> - @csrfToken(csrf) - <button class="pure-menu-link" type="submit">Logout</button> - </form> - </li> - } else { - <li class="pure-menu-item"><a class="btn right" href="">Login</a></li> - } + @if(user.nonEmpty) { + <li class="pure-menu-item"> + <form action="/logout" method="POST" accept-charset="UTF-8" class="inline"> + @csrfToken(csrf) + <button class="pure-menu-link" type="submit">@Messages("global.logout")</button> + </form> + </li> + } else { + <li class="pure-menu-item"><a href="/login" class="pure-menu-link">@Messages("global.login")</a></li> + <li class="pure-menu-item"><a href="/signup" class="pure-menu-link">@Messages("global.signup")</a></li> + } </ul> </nav> +} diff -rN -u old-smederee/modules/hub/src/main/twirl/de/smederee/hub/views/signup.scala.html new-smederee/modules/hub/src/main/twirl/de/smederee/hub/views/signup.scala.html --- old-smederee/modules/hub/src/main/twirl/de/smederee/hub/views/signup.scala.html 2025-02-03 05:05:52.391339387 +0000 +++ new-smederee/modules/hub/src/main/twirl/de/smederee/hub/views/signup.scala.html 2025-02-03 05:05:52.391339387 +0000 @@ -2,45 +2,51 @@ @(lang: LanguageCode = LanguageCode("en"), pathPrefix: Option[Uri] = None)(action: Uri, csrf: Option[CsrfToken] = None, title: Option[String] = None)(formData: Map[String, String] = Map.empty, formErrors: FormErrors = FormErrors.empty) @main(lang, pathPrefix)()(csrf, title) { - <div class="pure-u-1-1 pure-u-md-1-1 signup"> - <div class="form-errors"> - @formErrors.get(fieldGlobal).map { es => - @for(error <- es) { - <p class="alert alert-danger"> - <span class="glyphicon glyphicon-exclamation-sign" aria-hidden="true"></span> - <span class="sr-only">Fehler:</span> - @error - </p> - } - } - </div> - <div class="signup-form"> - <form action="@createFullPath(pathPrefix)(action)" method="POST" accept-charset="UTF-8" class="pure-form pure-form-aligned" autocomplete="on"> - <fieldset id="signup-data"> - <div class="pure-control-group"> - <label for="@{fieldName}">Username</label> - <input class="pure-input-1-2" id="@{fieldName}" name="@{fieldName}" placeholder="Please choose your username." maxlength="31" required="" type="text" value="@{formData.get(fieldName)}" autocomplete="username"> - <small class="pure-form-message" id="@{fieldName}.help">A username is required because it will be used to group your projects and other stuff. It must be between 2 and 31 characters long and contain only lowercase alphanumeric characters and start with a character (letter).</small> - @renderFormErrors(fieldName, formErrors) - </div> - <div class="pure-control-group"> - <label for="@{fieldEmail}">Email address</label> - <input class="pure-input-1-2" id="@{fieldEmail}" name="@{fieldEmail}" placeholder="some@@somewhere.org" maxlength="128" required="" type="email" value="@{formData.get(fieldEmail)}" autocomplete="email"> - <small class="pure-form-message" id="@{fieldEmail}.help">Please enter your email address.</small> - @renderFormErrors(fieldEmail, formErrors) - </div> - <div class="pure-control-group"> - <label for="@{fieldPassword}">Password</label> - <input class="pure-input-1-2" id="@{fieldPassword}" name="@{fieldPassword}" placeholder="Please choose a secure password!" maxlength="128" required="" type="password" value="" autocomplete="new-password"> - <small class="pure-form-message" id="@{fieldPassword}.help">Your password must be at least 12 characters long.</small> - @renderFormErrors(fieldPassword, formErrors) - </div> - @csrfToken(csrf) - <div class="pure-controls"> - <button type="submit" class="pure-button button-success">Sign up for an account</button> - </div> - </fieldset> - </form> +@defining(lang.toLocale) { implicit locale => + <div class="content"> + <div class="pure-g"> + <div class="pure-u-1-1 pure-u-md-1-1 signup"> + <div class="form-errors"> + @formErrors.get(fieldGlobal).map { es => + @for(error <- es) { + <p class="alert alert-danger"> + <span class="glyphicon glyphicon-exclamation-sign" aria-hidden="true"></span> + <span class="sr-only">Fehler:</span> + @error + </p> + } + } + </div> + <div class="signup-form"> + <form action="@createFullPath(pathPrefix)(action)" method="POST" accept-charset="UTF-8" class="pure-form pure-form-aligned" autocomplete="on"> + <fieldset id="signup-data"> + <div class="pure-control-group"> + <label for="@{fieldName}">Username</label> + <input class="pure-input-1-2" id="@{fieldName}" name="@{fieldName}" placeholder="Please choose your username." maxlength="31" required="" type="text" value="@{formData.get(fieldName)}" autocomplete="username"> + <small class="pure-form-message" id="@{fieldName}.help">A username is required because it will be used to group your projects and other stuff. It must be between 2 and 31 characters long and contain only lowercase alphanumeric characters and start with a character (letter).</small> + @renderFormErrors(fieldName, formErrors) + </div> + <div class="pure-control-group"> + <label for="@{fieldEmail}">Email address</label> + <input class="pure-input-1-2" id="@{fieldEmail}" name="@{fieldEmail}" placeholder="some@@somewhere.org" maxlength="128" required="" type="email" value="@{formData.get(fieldEmail)}" autocomplete="email"> + <small class="pure-form-message" id="@{fieldEmail}.help">Please enter your email address.</small> + @renderFormErrors(fieldEmail, formErrors) + </div> + <div class="pure-control-group"> + <label for="@{fieldPassword}">Password</label> + <input class="pure-input-1-2" id="@{fieldPassword}" name="@{fieldPassword}" placeholder="Please choose a secure password!" maxlength="128" required="" type="password" value="" autocomplete="new-password"> + <small class="pure-form-message" id="@{fieldPassword}.help">Your password must be at least 12 characters long.</small> + @renderFormErrors(fieldPassword, formErrors) + </div> + @csrfToken(csrf) + <div class="pure-controls"> + <button type="submit" class="pure-button">@Messages("form.signup.button.submit")</button> + </div> + </fieldset> + </form> + </div> + </div> </div> </div> } +}