logout handling

This commit is contained in:
Sebastian Frank 2017-08-25 12:25:19 +02:00
parent 2ef22fd197
commit cd7a727f0f
No known key found for this signature in database
GPG Key ID: DC2BC5C506EBF6F3
7 changed files with 173 additions and 72 deletions

View File

@ -17,6 +17,11 @@
"name": "Userlist",
"to": "/userlist",
"icon": "fa-news"
},
{
"name": "Logout",
"to": "/logout",
"icon": "fa-lock"
}
]
}

View File

@ -5,7 +5,7 @@
"description": "JS UI for Basispanel Server Management",
"main": "index.js",
"scripts": {
"serve": "WEBPACK_ENV=dev webpack-dev-server --inline --hot --open",
"serve": "WEBPACK_ENV=dev webpack-dev-server --inline --hot --host 0.0.0.0",
"dev": "WEBPACK_ENV=dev webpack --progress --colors --watch",
"build": "WEBPACK_ENV=production webpack --colors"
},

17
src/components/logout.vue Normal file
View File

@ -0,0 +1,17 @@
<template>
<div>
Sie werden ausgeloggt....
</div>
</template>
<script>
export default {
name: 'logout',
created() {
this.$store.commit('clearLogin');
setTimeout(() => {
this.$router.replace('/login');
}, 2000);
}
}
</script>

View File

@ -2,15 +2,19 @@
<div class="My-Table">
<table>
<tr>
<th v-for="(c, i) in columns" :key="i">{{ c.heading }}</th>
</tr>
<tr v-for="(r, ri) in rows" :key="ri">
<td v-for="(c, ci) in columns" :key="ci">
<span v-if="c.prop">{{ r[c.prop] }}</span>
<span v-else-if="c.render">{{ c.render(r) }}</span>
</td>
</tr>
<thead>
<tr>
<th v-for="(c, i) in columns" :key="i">{{ c.heading }}</th>
</tr>
</thead>
<tbody is="transition-group" name="list">
<tr v-for="(r, ri) in rows" :key="ri">
<td v-for="(c, ci) in columns" :key="ci + 'c'">
<span v-if="c.prop">{{ r[c.prop] }}</span>
<span v-else-if="c.render">{{ c.render(r) }}</span>
</td>
</tr>
</tbody>
</table>
</div>
@ -38,4 +42,18 @@ export default {
}
}
}
</script>
</script>
<style>
.list-item {
display: inline-block;
margin-right: 10px;
}
.list-enter-active, .list-leave-active {
transition: all 1s;
}
.list-enter, .list-leave-to /* .list-leave-active below version 2.1.8 */ {
opacity: 0;
transform: translateY(30px);
}
</style>

View File

@ -1,8 +1,10 @@
<template>
<div class="Scroll-Table">
<my-table :columns="columns" :rows="rows"></my-table>
<div v-show="hasMore" v-if="!loading" v-observe-visibility="visibilityChanged">...</div>
<div v-if="loading">loading...</div>
<div v-if="loadingDelayed">loading...</div>
<div style="padding-left: 30%; padding-bottom: 100px;">
<span v-show="hasMore" v-if="!loadingDelayed" v-observe-visibility="visibilityChanged">...</span>
</div>
</div>
</template>
@ -56,15 +58,28 @@ export default {
watch: {
newRows(rows) {
rows.forEach(row => {
this.rows.push(row)
this.rowsToPush.push(row);
});
this.currentOffset += rows.length;
this.pushRows(); // for transition
},
loading(l) {
if (!l) {
// delay after loading for visibility observer
setTimeout(() => {
this.loadingDelayed = false;
}, 200);
} else {
this.loadingDelayed = true;
}
}
},
data() {
return {
rows: [ ],
currentOffset: this.offset
rowsToPush: [ ],
currentOffset: this.offset,
loadingDelayed: false
}
},
methods: {
@ -73,6 +88,15 @@ export default {
// infinite scrolling
this.handler(this.currentOffset, this.limit);
}
},
pushRows() {
let row = this.rowsToPush.shift();
if (row) {
this.rows.push(row);
setTimeout(() => {
this.pushRows();
}, 50);
}
}
}
}

View File

@ -49,9 +49,7 @@ export default {
.then(rows => {
this.hasMore = (rows.length >= limit);
this.newRows = rows;
setTimeout(() => {
this.loading = false;
}, 200); // for oberserver
this.loading = false;
})
.catch(error => {
this.loading = false;

View File

@ -7,6 +7,7 @@ import JwtDecode from 'jwt-decode';
import App from './app.vue';
import Dashboard from './components/dashboard.vue';
import LoginForm from './components/forms/login.vue';
import Logout from './components/logout.vue';
import Userlist from './components/userlist.vue';
Vue.use(VueRouter);
@ -25,6 +26,10 @@ const routes = [
{
path: '/userlist',
component: Userlist
},
{
path: '/logout',
component: Logout
}
];
@ -36,35 +41,41 @@ const store = new Vuex.Store({
state: {
api: {},
navigation: [],
login: {},
authToken: '',
jwt: {},
credentials: {}
persist: {
login: {},
authToken: '',
jwt: {},
credentials: {}
}
},
mutations: {
setAPI(state, payload) {
state.api = payload;
},
setNavigation(state, payload) {
for (var i=0; i<payload.length; i++) {
for (var i = 0; i < payload.length; i++) {
state.navigation.push(payload[i]); // = payload;
}
},
setCredentials(state, payload) {
state.credentials = {
state.persist.credentials = {
username: payload.username,
password: payload.password
}
};
objectToPersist(state.persist, 'persistantStore');
},
setLogin(state, payload) {
state.login = payload.User;
state.authToken = payload.AuthToken;
state.jwt = JwtDecode(payload.AuthToken);
state.persist.login = payload.User;
state.persist.authToken = payload.AuthToken;
state.persist.jwt = JwtDecode(payload.AuthToken);
objectToPersist(state.persist, 'persistantStore');
},
clearLogin() {
state.login = {};
state.authToken = '';
state.jwt = {};
clearLogin(state) {
state.persist.login = {};
state.persist.authToken = '';
state.persist.jwt = {};
state.persist.credentials = {};
objectToPersist(state.persist, 'persistantStore');
}
},
actions: {
@ -78,25 +89,25 @@ const store = new Vuex.Store({
params: payload.params,
data: payload.data,
headers: {
'X-Auth-Token': context.state.authToken
'X-Auth-Token': context.state.persist.authToken
}
})
.then(response => {
console.log(response);
resolve(response.data);
console.log(response);
resolve(response.data);
})
.catch(error => {
console.dir(error);
reject(error);
console.dir(error);
reject(error);
})
});
};
if (payload.endpoint != 'login') {
// no jwt check for login call
// empty username = not logged in
if (!context.state.credentials.username) {
if (!context.state.persist.credentials.username) {
return new Promise((resolve, reject) => {
// show login page
router.push('/login');
@ -105,7 +116,7 @@ const store = new Vuex.Store({
}
let now = Math.round(Date.now() / 1000);
if ( context.state.jwt.exp < (now + 300) ) {
if (context.state.persist.jwt.exp < (now + 300)) {
// too old jwt, logout
return new Promise((resolve, reject) => {
context.commit('clearLogin');
@ -114,11 +125,11 @@ const store = new Vuex.Store({
});
}
if ( (context.state.jwt.exp - 60) < now ) {
if ((context.state.persist.jwt.exp - 60) < now) {
// jwt near expire, get new one
console.log("getting new jwt");
return context.dispatch('login', context.state.credentials)
return context.dispatch('login', context.state.persist.credentials)
.then(() => {
console.log("LOOOGIIIINNN");
return doRequest();
@ -144,43 +155,71 @@ const store = new Vuex.Store({
resolve(data.User);
})
.catch(error => {
if (error.response && error.response.data && error.response.data.error) {
reject(error.response.data.error);
} else {
reject([]);
}
if (error.response && error.response.data && error.response.data.error) {
reject(error.response.data.error);
} else {
reject([]);
}
});
});
}
}
});
function objectToPersist(obj, key) {
try {
const serialized = JSON.stringify(obj);
localStorage.setItem(key ? key : 'persistant', serialized);
} catch (error) {
console.error(error);
}
};
function persistToObject(key) {
try {
const serialized = localStorage.getItem(key ? key : 'persistant');
if (serialized === null) {
return undefined;
}
return JSON.parse(serialized);
} catch (error) {
console.log(error);
return undefined;
}
}
// get store persist part from localStorage
let persist = persistToObject('persistantStore');
if (persist) {
store.state.persist = persist;
}
// load init
Axios.get('conf/init.json')
.then(results => {
// set navigation
if ( !Array.isArray(results.data.navigation) ) {
alert('invalid data in: ' + this.src);
return;
}
store.commit("setNavigation", results.data.navigation);
.then(results => {
// set navigation
if (!Array.isArray(results.data.navigation)) {
alert('invalid data in init.json');
return;
}
store.commit("setNavigation", results.data.navigation);
// set api config in store
store.commit("setAPI", results.data.api);
// set api config in store
store.commit("setAPI", results.data.api);
// load app, when init finishs
new Vue({
el: '#vue-app',
components: {
App
},
data: {
navItems: store.state.navigation
},
router,
store
});
})
.catch(error => {
alert('error loading: ' + error.message);
});
// load app, when init finishs
new Vue({
el: '#vue-app',
components: {
App
},
data: {
navItems: store.state.navigation
},
router,
store
});
})
.catch(error => {
alert('error loading: ' + error.message);
});