diff --git a/conf/init.json b/conf/init.json
index 1a4892d..3c7c558 100644
--- a/conf/init.json
+++ b/conf/init.json
@@ -17,6 +17,11 @@
"name": "Userlist",
"to": "/userlist",
"icon": "fa-news"
+ },
+ {
+ "name": "Logout",
+ "to": "/logout",
+ "icon": "fa-lock"
}
]
}
\ No newline at end of file
diff --git a/package.json b/package.json
index b3b0a56..8d45c00 100644
--- a/package.json
+++ b/package.json
@@ -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"
},
diff --git a/src/components/logout.vue b/src/components/logout.vue
new file mode 100644
index 0000000..a1c3a8d
--- /dev/null
+++ b/src/components/logout.vue
@@ -0,0 +1,17 @@
+
+
+ Sie werden ausgeloggt....
+
+
+
+
diff --git a/src/components/my-table.vue b/src/components/my-table.vue
index 2a892fb..4ca4555 100644
--- a/src/components/my-table.vue
+++ b/src/components/my-table.vue
@@ -2,15 +2,19 @@
-
- {{ c.heading }} |
-
-
-
- {{ r[c.prop] }}
- {{ c.render(r) }}
- |
-
+
+
+ {{ c.heading }} |
+
+
+
+
+
+ {{ r[c.prop] }}
+ {{ c.render(r) }}
+ |
+
+
@@ -38,4 +42,18 @@ export default {
}
}
}
-
\ No newline at end of file
+
+
+
diff --git a/src/components/scroll-table.vue b/src/components/scroll-table.vue
index 471aad4..b70a4a5 100644
--- a/src/components/scroll-table.vue
+++ b/src/components/scroll-table.vue
@@ -1,8 +1,10 @@
@@ -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);
+ }
}
}
}
diff --git a/src/components/userlist.vue b/src/components/userlist.vue
index e83572e..cb9fc61 100644
--- a/src/components/userlist.vue
+++ b/src/components/userlist.vue
@@ -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;
diff --git a/src/main.js b/src/main.js
index 44a4132..b77a688 100644
--- a/src/main.js
+++ b/src/main.js
@@ -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 {
- 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);
- });
\ No newline at end of file
+ // 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);
+ });
\ No newline at end of file