#1: draft of user page using Vuex

This commit is contained in:
Davide Alberani 2017-01-15 22:35:54 +01:00
parent d87e555dea
commit 0684f927b4
5 changed files with 143 additions and 36 deletions

View file

@ -22,7 +22,8 @@
"vue-material": "^0.6.3", "vue-material": "^0.6.3",
"vue-resource": "^1.0.3", "vue-resource": "^1.0.3",
"vue-router": "^2.1.1", "vue-router": "^2.1.1",
"vuejs-datepicker": "^0.4.27" "vuejs-datepicker": "^0.4.27",
"vuex": "^2.1.1"
}, },
"devDependencies": { "devDependencies": {
"autoprefixer": "^6.4.0", "autoprefixer": "^6.4.0",

View file

@ -1,11 +1,20 @@
<template> <template>
<md-toolbar id="toolbar" class="md-dense"> <md-toolbar id="toolbar" class="md-dense">
<span v-if="currentPath == 'user'">
<md-button class="md-icon-button" @click="goBack()">
<md-icon>backspace</md-icon>&nbsp;
</md-button>
</span>
<span v-else class="button-spacer">&nbsp;</span>
<h2 id="toolbar-title" class="md-title">ibt2</h2> <h2 id="toolbar-title" class="md-title">ibt2</h2>
<span v-if="loggedInUser.username"> <span v-if="loggedInUser.username">
<span id="logged-in"> <md-button id="logged-in-icon" class="md-icon-button" @click="toUserPage()">
Logged in: <router-link :to="userUrl">{{ loggedInUser.username }}</router-link> <md-icon>person_pin</md-icon>
</md-button>
<span id="logged-in" class="md-subheading">
<router-link :to="userUrl" class="username-link">{{ loggedInUser.username }}</router-link>
</span> </span>
<md-button class="md-icon-button" @click="logout()"> <md-button id="logout-icon" class="md-icon-button" @click="logout()">
<md-icon>exit_to_app</md-icon> <md-icon>exit_to_app</md-icon>
</md-button> </md-button>
</span> </span>
@ -15,11 +24,16 @@
</md-button> </md-button>
<span v-show="showLoginForm" id="login-form"> <span v-show="showLoginForm" id="login-form">
<md-input-container id="username-input" class="login-input" md-inline> <md-input-container id="username-input" class="login-input" md-inline>
<md-input ref="usernameInput" @keyup.enter.native="focusToPassword()" v-model="username" placeholder="username" md-inline />&nbsp; <md-input ref="usernameInput" @keyup.enter.native="focusToPassword()" v-model="username" placeholder="username" md-inline />
</md-input-container> </md-input-container>&nbsp;
<md-input-container id="password-input" class="login-input" md-inline> <span id="password-block">
<md-input ref="passwordInput" @keyup.enter.native="login()" v-model="password" placeholder="password" type="password" md-line /> <md-input-container id="password-input" class="login-input" md-inline>
</md-input-container> <md-input ref="passwordInput" @keyup.enter.native="login()" v-model="password" placeholder="password" type="password" md-line />
</md-input-container>
<md-button id="login-button" class="md-icon-button" @click="login()">
<md-icon>play_circle_outline</md-icon>
</md-button>
</span>
</span> </span>
</span> </span>
</md-toolbar> </md-toolbar>
@ -31,8 +45,7 @@ export default {
return { return {
username: '', username: '',
password: '', password: '',
showLoginForm: false, showLoginForm: false
loggedInUser: {username: ''}
} }
}, },
@ -43,10 +56,19 @@ export default {
return ''; return '';
} }
return '/user/' + this.loggedInUser._id; return '/user/' + this.loggedInUser._id;
},
loggedInUser() {
return this.$store.state.loggedInUser;
},
currentPath() {
return this.$route.name;
} }
}, },
beforeCreate: function() { beforeCreate: function() {
this.usersUrl = this.$resource('users');
this.currentUserUrl = this.$resource('users/current'); this.currentUserUrl = this.$resource('users/current');
this.loginUrl = this.$resource('login'); this.loginUrl = this.$resource('login');
this.logoutUrl = this.$resource('logout'); this.logoutUrl = this.$resource('logout');
@ -57,6 +79,14 @@ export default {
}, },
methods: { methods: {
goBack() {
this.$router.back();
},
toUserPage() {
this.$router.push(this.userUrl);
},
focusToLoginForm() { focusToLoginForm() {
this.showLoginForm = true; this.showLoginForm = true;
var that = this; var that = this;
@ -68,10 +98,13 @@ export default {
}, },
login() { login() {
this.loginUrl.save({username: this.username, password: this.password}).then((response) => { var user_data = {username: this.username, password: this.password};
this.loginUrl.save(user_data).then((response) => {
return response.json(); return response.json();
}, (response) => { }, (response) => {
alert('login: failed to get resource'); if (response.status == 401) {
this.createUser(user_data);
}
}).then((data) => { }).then((data) => {
this.showLoginForm = false; this.showLoginForm = false;
this.getUserInfo(); this.getUserInfo();
@ -84,28 +117,42 @@ export default {
}, (response) => { }, (response) => {
alert('logout: failed to get resource'); alert('logout: failed to get resource');
}).then((json) => { }).then((json) => {
this.loggedInUser = {}; this.$store.commit('clearLoggedInUser');
}); });
}, },
createUser(user_data) {
user_data.username = user_data.username || {};
user_data.username = user_data.username || this.username;
user_data.password = user_data.password || this.password;
this.usersUrl.save(user_data).then((response) => {
return response.json();
}, (response) => {
alert('createUser: failed to get resource');
}).then((json) => {
this.showLoginForm = false;
this.getUserInfo();
});
},
getUserInfo(callback) { getUserInfo(callback) {
this.currentUserUrl.get().then((response) => { this.currentUserUrl.get().then((response) => {
return response.json(); return response.json();
}, (response) => { }, (response) => {
alert('getUserInfo: failed to get resource'); alert('getUserInfo: failed to get resource');
}).then((data) => { }).then((data) => {
this.loggedInUser = data || {}; data = data || {};
this.$store.commit('setLoggedInUser', data);
if (callback) { if (callback) {
callback(this.loggedInUser); callback(data);
} }
}); });
} }
} }
} }
</script> </script>
<style> <style>
#toolbar-title { #toolbar-title {
flex: 1; flex: 1;
} }
@ -117,23 +164,53 @@ export default {
padding-left: 4px; padding-left: 4px;
min-height: 24px; min-height: 24px;
line-height: 0px; line-height: 0px;
margin-right: 20px;
background-color: white; background-color: white;
} }
#username-input { #username-input {
display: inline; display: inline;
float: left; float: left;
margin-right: 20px;
} }
#password-input { #password-input {
display: inline;
float: left;
}
#password-block {
display: inline; display: inline;
float: right; float: right;
} }
#login-button {
height: 32px;
}
#logged-in-icon {
margin-right: 0px;
padding-right: 0px;
color: #f6f72f !important;
}
#logged-in { #logged-in {
position: relative; position: relative;
top: 10px; top: 10px;
} }
#logout-icon {
margin-left: 0px;
padding-left: 0px;
}
.username-link {
font-weight: bold;
color: #f6f72f !important;
}
.button-spacer {
width: 52px;
}
</style> </style>

View file

@ -1,6 +1,6 @@
<template> <template>
<div id="user"> <div id="user">
User User {{loggedInUser}}
</div> </div>
</template> </template>
<script> <script>
@ -11,6 +11,15 @@ export default {
} }
}, },
computed: {
count() {
return this.$store.state.count;
},
loggedInUser() {
return this.$store.state.loggedInUser;
}
},
beforeCreate: function() { beforeCreate: function() {
this.userUrl = this.$resource('users'); this.userUrl = this.$resource('users');
}, },
@ -19,18 +28,6 @@ export default {
}, },
methods: { methods: {
getUserInfo(callback) {
this.currentUserUrl.get().then((response) => {
return response.json();
}, (response) => {
alert('getUserInfo: failed to get resource');
}).then((data) => {
this.loggedInUser = data || {};
if (callback) {
callback(this.loggedInUser);
}
});
}
}, },
components: { components: {

View file

@ -1,6 +1,7 @@
// The Vue build version to load with the `import` command // The Vue build version to load with the `import` command
// (runtime-only or standalone) has been set in webpack.base.conf with an alias. // (runtime-only or standalone) has been set in webpack.base.conf with an alias.
import Vue from 'vue'; import Vue from 'vue';
import Vuex from 'vuex';
import VueRouter from 'vue-router'; import VueRouter from 'vue-router';
import VueResource from 'vue-resource'; import VueResource from 'vue-resource';
import VueMaterial from 'vue-material'; import VueMaterial from 'vue-material';
@ -8,25 +9,41 @@ import 'vue-material/dist/vue-material.css';
import 'roboto-fontface/css/roboto/roboto-fontface.css'; import 'roboto-fontface/css/roboto/roboto-fontface.css';
import 'material-design-icons/iconfont/material-icons.css'; import 'material-design-icons/iconfont/material-icons.css';
import jQuery from 'jquery'; import jQuery from 'jquery';
import store_data from './store.js';
import App from './App'; import App from './App';
import User from './User'; import User from './User';
import Toolbar from './Toolbar'; import Toolbar from './Toolbar';
Vue.use(Vuex);
Vue.use(VueRouter); Vue.use(VueRouter);
Vue.use(VueResource); Vue.use(VueResource);
Vue.use(VueMaterial); Vue.use(VueMaterial);
var routes = [ var routes = [
{path: '/', component: App}, {path: '/', name: 'root', component: App},
{path: '/day/', component: App}, {path: '/day/', name: 'days', component: App},
{path: '/day/:day', component: App}, {path: '/day/:day', name: 'day', component: App},
{path: '/user/:user', component: User} {path: '/user/:user', name: 'user', component: User}
]; ];
const store = new Vuex.Store(store_data);
const router = new VueRouter({routes}); const router = new VueRouter({routes});
const store2 = new Vuex.Store({
state: {
count: 0
},
mutations: {
increment (state) {
state.count++;
}
}
});
var vue = new Vue({ var vue = new Vue({
el: '#app', el: '#app',
store: store,
template: '<div id="app"><Toolbar /><router-view class="view"></router-view></div>', template: '<div id="app"><Toolbar /><router-view class="view"></router-view></div>',
router: router, router: router,
components: { App, Toolbar, User } components: { App, Toolbar, User }

15
src/store.js Normal file
View file

@ -0,0 +1,15 @@
export default {
state: {
loggedInUser: {username: ''}
},
mutations: {
clearLoggedInUser(state, user) {
state.loggedInUser = {username: ''};
},
setLoggedInUser(state, user) {
state.loggedInUser = user;
}
}
};