changeset 6:7c1bde663c8e vue-cli

current frontend
author Thomas Junk <thomas.junk@intevation.de>
date Thu, 14 Jun 2018 13:33:26 +0200
parents 1597506a2241
children e4bc7e0465b3
files .env.sample package.json src/lib/http.js src/router.js src/stores/application.js src/stores/language.js src/stores/user.js src/views/Login.vue src/views/Main.vue yarn.lock
diffstat 10 files changed, 89 insertions(+), 26 deletions(-) [+]
line wrap: on
line diff
--- a/.env.sample	Wed Jun 13 10:57:57 2018 +0200
+++ b/.env.sample	Thu Jun 14 13:33:26 2018 +0200
@@ -1,1 +1,2 @@
 VUE_APP_TITLE="Waterway Monitoring system"
+VUE_API_URL="/api/"
--- a/package.json	Wed Jun 13 10:57:57 2018 +0200
+++ b/package.json	Thu Jun 14 13:33:26 2018 +0200
@@ -9,6 +9,7 @@
     "test:unit": "vue-cli-service test:unit"
   },
   "dependencies": {
+    "axios": "^0.18.0",
     "bootstrap": "^4.1.1",
     "vue": "^2.5.16",
     "vue-router": "^3.0.1",
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/lib/http.js	Thu Jun 14 13:33:26 2018 +0200
@@ -0,0 +1,8 @@
+import axios from "axios";
+
+export const HTTP = axios.create({
+  baseURL: process.env.VUE_APP_API_URL || "/api"
+  /* headers: {
+    Authorization: 'Bearer {token}'
+  }*/
+});
--- a/src/router.js	Wed Jun 13 10:57:57 2018 +0200
+++ b/src/router.js	Thu Jun 14 13:33:26 2018 +0200
@@ -1,7 +1,7 @@
 import Vue from "vue";
 import Router from "vue-router";
 import Login from "./views/Login.vue";
-import UserClient from "./views/UserClient.vue";
+import Main from "./views/Main.vue";
 import store from "./store";
 
 Vue.use(Router);
@@ -9,14 +9,14 @@
 const router = new Router({
   routes: [
     {
-      path: "/",
+      path: "/login",
       name: "login",
       component: Login
     },
     {
-      path: "/client",
-      name: "userclient",
-      component: UserClient,
+      path: "/",
+      name: "main",
+      component: Main,
       meta: {
         requiresAuth: true
       }
@@ -32,7 +32,7 @@
   const requiresAuth = to.matched.some(record => record.meta.requiresAuth);
   const currentUser = store.getters["user/authenticated"];
   if (requiresAuth && !currentUser) {
-    next("/");
+    next("/login");
   } else if (requiresAuth && currentUser) {
     next();
   } else {
--- a/src/stores/application.js	Wed Jun 13 10:57:57 2018 +0200
+++ b/src/stores/application.js	Thu Jun 14 13:33:26 2018 +0200
@@ -1,14 +1,25 @@
 const Application = {
   namespaced: true,
   state: {
-    appTitle: process.env.VUE_APP_TITLE
+    appTitle: process.env.VUE_APP_TITLE,
+    loginFailed: false
   },
   getters: {
     appTitle: state => {
       return state.appTitle;
+    },
+    loginFailed: state => {
+      return state.loginFailed;
     }
   },
-  mutations: {},
+  mutations: {
+    loginError(state) {
+      state.loginFailed = true;
+    },
+    loginSuccess(state) {
+      state.loginFailed = false;
+    }
+  },
   actions: {}
 };
 
--- a/src/stores/language.js	Wed Jun 13 10:57:57 2018 +0200
+++ b/src/stores/language.js	Thu Jun 14 13:33:26 2018 +0200
@@ -4,7 +4,8 @@
     signinHeader: "Please sign in",
     emailLabel: "Email address",
     passwordLabel: "Password",
-    loginButtonLabel: "Login"
+    loginButtonLabel: "Login",
+    loginAttemptFailed: "Login Failed"
   },
   getters: {
     signinHeader: state => {
@@ -16,6 +17,9 @@
     passwordLabel: state => {
       return state.passwordLabel;
     },
+    loginAttemptFailed: state => {
+      return state.loginAttemptFailed;
+    },
     loginButtonLabel: state => {
       return state.loginButtonLabel;
     }
--- a/src/stores/user.js	Wed Jun 13 10:57:57 2018 +0200
+++ b/src/stores/user.js	Thu Jun 14 13:33:26 2018 +0200
@@ -1,28 +1,39 @@
+import { HTTP } from "../lib/http";
+
 const User = {
   namespaced: true,
   state: {
-    authenticated: false,
-    authStatus: "error"
+    authenticated: false
   },
   getters: {
     authenticated: state => {
       return state.authenticated;
-    },
-    authStatus: state => {
-      return state.authStatus;
     }
   },
   mutations: {
-    auth_success: state => {
+    auth_success: (state, token) => {
       state.authenticated = true;
+      sessionStorage.setItem("token", token);
+    },
+    auth_failure: state => {
+      state.authenticated = false;
+      sessionStorage.removeItem("token");
     }
   },
   actions: {
-    auth({ commit }, user) {
-      const { username, password } = user;
-      if (username === "admin" && password === "secret") {
-        commit("auth_success");
-      }
+    login({ commit }, user) {
+      return new Promise((resolve, reject) => {
+        HTTP.post("/token", user)
+          .then(response => {
+            let token = response.data;
+            commit("auth_success", token);
+            resolve(response);
+          })
+          .catch(error => {
+            commit("auth_failure");
+            reject(error);
+          });
+      });
     }
   }
 };
--- a/src/views/Login.vue	Wed Jun 13 10:57:57 2018 +0200
+++ b/src/views/Login.vue	Thu Jun 14 13:33:26 2018 +0200
@@ -9,11 +9,14 @@
     <div class="login-wrapper border border-light d-flex flex-row justify-content-center">
       <form class="form-signin" @submit.prevent="login">
         <h2 class="form-signin-heading">{{ signinHeader }}</h2>
+        <div v-if="loginFailed" class="alert alert-danger" role="alert">
+          {{ loginAttemptFailed }}
+        </div>
         <label for="inputEmail" class="sr-only">{{ emailLabel }}</label>
         <input type="text" v-model="username" id="inputEmail" class="form-control" :placeholder="emailLabel" required autofocus>
         <label for="inputPassword" class="sr-only">{{ passwordLabel }}</label>
         <input type="password" v-model="password" id="inputPassword" class="form-control" :placeholder="passwordLabel" required>
-        <button class="btn btn-lg btn-primary btn-block" type="submit">{{ loginButtonLabel }}</button>
+        <button class="btn btn-lg btn-primary btn-block" :disabled="submitted" type="submit">{{ loginButtonLabel }}</button>
       </form>
     </div>
   </div>
@@ -33,22 +36,34 @@
   data() {
     return {
       username: "",
-      password: ""
+      password: "",
+      submitted: false
     };
   },
   computed: {
-    ...mapGetters("application", ["appTitle"]),
+    ...mapGetters("application", ["appTitle", "loginFailed"]),
     ...mapGetters("i18n", [
       "signinHeader",
       "emailLabel",
       "passwordLabel",
-      "loginButtonLabel"
+      "loginButtonLabel",
+      "loginAttemptFailed"
     ])
   },
   methods: {
     login() {
+      this.submitted = true;
       const { username, password } = this;
-      this.$store.dispatch("user/auth", { username, password });
+      this.$store
+        .dispatch("user/login", { username, password })
+        .then(() => {
+          this.$store.commit("application/loginSuccess");
+          this.$router.push("/");
+        })
+        .catch(() => {
+          this.$store.commit("application/loginError");
+          this.submitted = false;
+        });
     }
   }
 };
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/views/Main.vue	Thu Jun 14 13:33:26 2018 +0200
@@ -0,0 +1,5 @@
+<template>
+  <div class="main">
+    <h1>Guarded!</h1>
+  </div>
+</template>
--- a/yarn.lock	Wed Jun 13 10:57:57 2018 +0200
+++ b/yarn.lock	Thu Jun 14 13:33:26 2018 +0200
@@ -1362,6 +1362,13 @@
   version "1.7.0"
   resolved "https://registry.yarnpkg.com/aws4/-/aws4-1.7.0.tgz#d4d0e9b9dbfca77bf08eeb0a8a471550fe39e289"
 
+axios@^0.18.0:
+  version "0.18.0"
+  resolved "https://registry.yarnpkg.com/axios/-/axios-0.18.0.tgz#32d53e4851efdc0a11993b6cd000789d70c05102"
+  dependencies:
+    follow-redirects "^1.3.0"
+    is-buffer "^1.1.5"
+
 babel-code-frame@^6.22.0, babel-code-frame@^6.26.0:
   version "6.26.0"
   resolved "https://registry.yarnpkg.com/babel-code-frame/-/babel-code-frame-6.26.0.tgz#63fd43f7dc1e3bb7ce35947db8fe369a3f58c74b"
@@ -3436,7 +3443,7 @@
     inherits "^2.0.1"
     readable-stream "^2.0.4"
 
-follow-redirects@^1.0.0:
+follow-redirects@^1.0.0, follow-redirects@^1.3.0:
   version "1.5.0"
   resolved "https://registry.yarnpkg.com/follow-redirects/-/follow-redirects-1.5.0.tgz#234f49cf770b7f35b40e790f636ceba0c3a0ab77"
   dependencies: