changeset 539:924490b3395b

refac: Loginmask reworked The login is now more stable. The user gets better visual feedback for his actions.
author Thomas Junk <thomas.junk@intevation.de>
date Thu, 30 Aug 2018 12:39:09 +0200
parents 942a865986f6
children b2d1c82b3e27
files client/src/App.vue client/src/views/Login.vue
diffstat 2 files changed, 79 insertions(+), 126 deletions(-) [+]
line wrap: on
line diff
--- a/client/src/App.vue	Wed Aug 29 16:12:20 2018 +0200
+++ b/client/src/App.vue	Thu Aug 30 12:39:09 2018 +0200
@@ -7,6 +7,8 @@
 <style lang="scss">
 html {
   height: 100%;
+  width: 100%;
+  margin: 0 auto;
 }
 body {
   min-height: 100%;
@@ -20,14 +22,4 @@
   text-align: center;
   color: #2c3e50;
 }
-#nav {
-  padding: 30px;
-  a {
-    font-weight: bold;
-    color: #2c3e50;
-    &.router-link-exact-active {
-      color: #42b983;
-    }
-  }
-}
 </style>
--- a/client/src/views/Login.vue	Wed Aug 29 16:12:20 2018 +0200
+++ b/client/src/views/Login.vue	Thu Aug 30 12:39:09 2018 +0200
@@ -1,138 +1,81 @@
 (<template>
-  <div :class="loginStyle">
-    <div>
-      <div class="logogroup d-flex flex-row justify-content-center">
+  <div class="d-flex flex-column login shadow-lg">
+    <div class="loginmask">
+      <!-- logo section -->
+      <div class="d-flex flex-row justify-content-center mb-3">
         <div class="logo"><img src="../assets/logo.png"></div>
-        <div class="title"><h1>{{ appTitle }}</h1></div>
+        <div class="title">
+          <h1>{{ appTitle }}</h1>
+        </div>
       </div>
-    </div>
-    <div class="login-wrapper d-flex flex-row justify-content-center">
-      <form class="loginform form-signin" @submit.prevent="login">
-           <div id="alert" v-if="loginFailed" class="loginerrormessage alert alert-danger" role="alert">
-             <span class="loginerror"><translate>Login failed</translate></span>
-           </div>
-           <div id="alert" v-if="passwordJustResetted"
-                class="loginerrormessage alert alert-danger" role="alert">
-             <span class="loginerror"
-               ><translate>Password reset requested!</translate></span>
-           </div>
-        <div class="input-group mb-3 usernamegroup">
-          <input type="text" v-model="user" id="inputUsername" class="form-control" :placeholder="usernameLabel" required autofocus>
+      <!-- end logo section -->
+      <div id="alert" :style="errorMessageStyle" :class="errorMessageClass" role="alert">
+        <span>{{ errorMessage }}</span>
+      </div>
+      <form @submit.prevent="login">
+        <div class="input-group mb-3">
+          <input type="text" v-model="user" id="inputUsername" class="form-control shadow-sm" :placeholder="usernameLabel" required autofocus>
         </div>
-        <div class="input-group mb-3 passwordgroup">
-          <input :type="isPasswordVisible" v-model="password"
-            id="inputPassword" class="form-control"
-            :placeholder='passwordLabel'
-            :required='!showPasswordReset' :disabled='showPasswordReset'>
+        <div class="input-group mb-3">
+          <input :type="isPasswordVisible" v-model="password" id="inputPassword" class="form-control shadow-sm" :placeholder='passwordLabel' :required='!showPasswordReset' :disabled='showPasswordReset'>
           <div class="input-group-append">
-            <span class="input-group-text disabled" id="basic-addon2"
-              @click="showPassword"><i :class="eyeIcon"></i></span>
+            <span class="input-group-text disabled" id="basic-addon2" @click="showPassword">
+              <i :class="eyeIcon"></i>
+            </span>
           </div>
         </div>
-        <button class="submitbutton btn btn-primary btn-block"
-          :disabled="submitted || showPasswordReset" type="submit"
-          ><translate>Login</translate></button>
+        <button v-if="showPasswordReset==false" class="btn btn-primary btn-block shadow-sm" :disabled="submitted || showPasswordReset" type="submit">
+          <translate>Login</translate>
+        </button>
       </form>
-    </div>
 
-    <!-- password forgotten part -->
-    <div class="d-flex flex-row justify-content-center">
-      <form class="loginform form-signin">
+      <!-- password forgotten part -->
+      <form class="">
         <div v-if="showPasswordReset" class="passwordreset">
-          <!--
-          TODO text and action for password reset
-          <div class="input-group mb-3 usernamegroup">
-            <input type="text" v-model="usernameToReset" class="form-control" :placeholder="usernameLabel" required>
+          <button class="btn btn-block btn-info" type="button" @click="resetPassword">
+            <translate>Request password reset!</translate>
+          </button>
+          <div class="pull-right">
+            <a href="#" @click.prevent="togglePasswordReset">
+              <translate>back to login</translate>
+            </a>
           </div>
-          -->
-          <button class="btn btn-warning btn-block" type="button"
-            @click="resetPassword"
-            ><translate>Request password reset!</translate></button>
-            <div class="forgottenlink small">
-            <a href="#" @click.prevent="togglePasswordReset"
-               ><translate>back to login</translate></a></div>
+        </div>
+        <div v-else class="pull-right">
+          <a href="#" @click.prevent="togglePasswordReset">
+            <translate>Forgot password</translate>
+          </a>
         </div>
-        <div v-else class="forgottenlink small">
-            <a href="#" @click.prevent="togglePasswordReset"
-                ><translate>Forgot password</translate></a></div>
       </form>
+
+      <!-- bottom logo section -->
+      <div><img :src="secondaryLogo"></div>
     </div>
-
-    <!-- bottom logo section -->
-    <div class="secondary-logo d-flex flex-row justify-content-center"
-        ><img :src="secondaryLogo"></div>
   </div>
 </template>)
 
 <style lang="scss">
 @import "../assets/application.scss";
-$logincollapsed: 470px;
-$loginextended: 550px;
-
-.usernamegroup {
-  box-shadow: $basic-shadow-light !important;
-}
-.forgottenlink {
-  text-align: right;
-  margin-top: $small-offset;
-  margin-bottom: $small-offset;
-}
-#inputPassword {
-  border-right: none;
-}
-.input-group-text {
-  background-color: white !important;
-}
 
 .login {
-  width: 375px;
+  background-color: white;
+  min-width: 375px;
+  height: 500px;
   @extend %fully-centered;
-  padding-top: $offset;
-  padding-bottom: $offset;
-  box-shadow: $basic-shadow;
-}
-.logincollapsed {
-  height: $logincollapsed;
 }
 
-.loginextended {
-  height: $loginextended;
-}
-.loginerror {
-  white-space: pre;
-}
-.loginerrormessage {
-  box-shadow: $basic-shadow-light !important;
-}
-.loginform {
-  width: 300px;
-}
-.logogroup {
-  margin-top: $offset;
-  margin-bottom: $offset;
+.loginmask {
+  margin-left: $large-offset;
+  margin-right: $large-offset;
+  margin-top: $large-offset;
 }
-.passwordreset {
-  margin-top: $offset;
-  margin-bottom: $offset;
-}
-.mail-icon {
-  width: $iconwidth;
-}
-.passwordgroup {
-  box-shadow: $basic-shadow-light !important;
+
+.logo {
+  margin-right: $offset;
 }
-.password-icon {
-  position: relative;
-  top: 10px;
-  font-size: $iconsize;
-  line-height: $iconLineHeight;
-  width: $iconwidth;
-}
-.submitbutton {
-  box-shadow: $basic-shadow-light !important;
-}
-.title {
-  margin-left: $offset;
+
+.alert {
+  padding: 0.5rem;
 }
 </style>
 
@@ -155,6 +98,12 @@
     };
   },
   computed: {
+    errorMessage() {
+      if (this.loginFailed) return this.$gettext("Login failed");
+      if (this.passwordJustResetted)
+        return this.$gettext("Password reset requested!");
+      return "&npsp;";
+    },
     passwordLabel() {
       return this.$gettext("Enter passphrase");
     },
@@ -171,14 +120,25 @@
         "fa-eye-slash": this.readablePassword
       };
     },
-    loginStyle() {
-      return {
-        login: true,
-        logincollapsed: !this.loginFailed,
-        loginextended: this.loginFailed,
-        "bg-white": true,
-        rounded: true
+    errorMessageStyle() {
+      if (this.loginFailed || this.passwordJustResetted) {
+        return "visibility:visible";
+      }
+      return "visibility:hidden";
+    },
+    errorMessageClass() {
+      let result = {
+        "mb-3": true,
+        errormessage: true,
+        alert: true
       };
+      if (this.loginFailed) {
+        result["alert-danger"] = true;
+      }
+      if (this.passwordJustResetted) {
+        result["alert-info"] = true;
+      }
+      return result;
     },
     ...mapGetters("application", ["appTitle", "secondaryLogo"])
   },
@@ -207,6 +167,7 @@
     togglePasswordReset() {
       this.passwordJustResetted = false;
       this.showPasswordReset = !this.showPasswordReset;
+      this.loginFailed = false;
     },
     resetPassword() {
       if (this.user) {