+Vuex +ElementUI +Pug
- Log on now works, storing user profile in vuex state - Templates in Pug = awesome
This commit is contained in:
@@ -1,37 +1,17 @@
|
||||
<template>
|
||||
<div id="app">
|
||||
<navigation :auth="auth" />
|
||||
<div id="content" class="container">
|
||||
<router-view :auth="auth"></router-view>
|
||||
</div>
|
||||
<footer>
|
||||
<p class="text-right"><i>myPrayerJournal v0.8.0</i></p>
|
||||
</footer>
|
||||
</div>
|
||||
<template lang="pug">
|
||||
#app
|
||||
navigation
|
||||
#content.container
|
||||
router-view
|
||||
footer
|
||||
p.text-right: i myPrayerJournal v0.8.0
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import AuthService from './auth/AuthService'
|
||||
import Navigation from './components/Navigation.vue'
|
||||
|
||||
const auth = new AuthService()
|
||||
const { login, logout, authenticated, authNotifier } = auth
|
||||
|
||||
export default {
|
||||
name: 'app',
|
||||
data: function () {
|
||||
authNotifier.on('authChange', authState => {
|
||||
this.authenticated = authState.authenticated
|
||||
})
|
||||
return {
|
||||
auth,
|
||||
authenticated
|
||||
}
|
||||
},
|
||||
methods: {
|
||||
login,
|
||||
logout
|
||||
},
|
||||
components: {
|
||||
Navigation
|
||||
}
|
||||
|
||||
0
src/app/src/api/Api.js
Normal file
0
src/app/src/api/Api.js
Normal file
@@ -1,11 +1,9 @@
|
||||
import auth0 from 'auth0-js'
|
||||
import { AUTH_CONFIG } from './auth0-variables'
|
||||
import EventEmitter from 'EventEmitter'
|
||||
import router from './../router'
|
||||
|
||||
import * as types from '@/store/mutation-types'
|
||||
|
||||
export default class AuthService {
|
||||
authenticated = this.isAuthenticated()
|
||||
authNotifier = new EventEmitter()
|
||||
|
||||
constructor () {
|
||||
this.login = this.login.bind(this)
|
||||
@@ -20,24 +18,62 @@ export default class AuthService {
|
||||
redirectUri: AUTH_CONFIG.callbackUrl,
|
||||
audience: `https://${AUTH_CONFIG.domain}/userinfo`,
|
||||
responseType: 'token id_token',
|
||||
scope: 'openid'
|
||||
scope: 'openid profile email'
|
||||
})
|
||||
|
||||
login () {
|
||||
this.auth0.authorize()
|
||||
}
|
||||
|
||||
handleAuthentication () {
|
||||
this.auth0.parseHash((err, authResult) => {
|
||||
if (authResult && authResult.accessToken && authResult.idToken) {
|
||||
this.setSession(authResult)
|
||||
router.replace('/dashboard')
|
||||
} else if (err) {
|
||||
/**
|
||||
* Promisified parseHash function
|
||||
*/
|
||||
parseHash () {
|
||||
return new Promise((resolve, reject) => {
|
||||
this.auth0.parseHash((err, authResult) => {
|
||||
if (err) {
|
||||
reject(err)
|
||||
} else {
|
||||
resolve(authResult)
|
||||
}
|
||||
})
|
||||
})
|
||||
}
|
||||
|
||||
/**
|
||||
* Promisified userInfo function
|
||||
*
|
||||
* @param token The auth token from the login result
|
||||
*/
|
||||
userInfo (token) {
|
||||
return new Promise((resolve, reject) => {
|
||||
this.auth0.client.userInfo(token, (err, user) => {
|
||||
if (err) {
|
||||
reject(err)
|
||||
} else {
|
||||
resolve(user)
|
||||
}
|
||||
})
|
||||
})
|
||||
}
|
||||
|
||||
handleAuthentication (store, router) {
|
||||
this.parseHash()
|
||||
.then(authResult => {
|
||||
if (authResult && authResult.accessToken && authResult.idToken) {
|
||||
this.setSession(authResult)
|
||||
this.userInfo(authResult.accessToken)
|
||||
.then(user => {
|
||||
store.commit(types.USER_LOGGED_ON, user)
|
||||
router.replace('/dashboard')
|
||||
})
|
||||
}
|
||||
})
|
||||
.catch(err => {
|
||||
router.replace('/')
|
||||
console.log(err)
|
||||
alert(`Error: ${err.error}. Check the console for further details.`)
|
||||
}
|
||||
})
|
||||
})
|
||||
}
|
||||
|
||||
setSession (authResult) {
|
||||
@@ -48,17 +84,16 @@ export default class AuthService {
|
||||
localStorage.setItem('access_token', authResult.accessToken)
|
||||
localStorage.setItem('id_token', authResult.idToken)
|
||||
localStorage.setItem('expires_at', expiresAt)
|
||||
this.authNotifier.emit('authChange', { authenticated: true })
|
||||
}
|
||||
|
||||
logout () {
|
||||
logout (store, router) {
|
||||
// Clear access token and ID token from local storage
|
||||
localStorage.removeItem('access_token')
|
||||
localStorage.removeItem('id_token')
|
||||
localStorage.removeItem('expires_at')
|
||||
this.userProfile = null
|
||||
this.authNotifier.emit('authChange', false)
|
||||
localStorage.setItem('user_profile', JSON.stringify({}))
|
||||
// navigate to the home route
|
||||
store.commit(types.USER_LOGGED_OFF)
|
||||
router.replace('/')
|
||||
}
|
||||
|
||||
|
||||
@@ -1,21 +1,23 @@
|
||||
<template>
|
||||
<article>
|
||||
<page-title title="Your Dashboard" />
|
||||
<p>here you are! {{ JSON.stringify(this.user) }}</p>
|
||||
</article>
|
||||
<template lang="pug">
|
||||
article
|
||||
page-title(:title="title")
|
||||
p here you are!
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import { mapState } from 'vuex'
|
||||
import PageTitle from './PageTitle'
|
||||
|
||||
export default {
|
||||
name: 'dashboard',
|
||||
props: ['user'],
|
||||
data () {
|
||||
return {}
|
||||
},
|
||||
components: {
|
||||
PageTitle
|
||||
},
|
||||
computed: {
|
||||
title () {
|
||||
return `${this.user.given_name}'s Dashboard`
|
||||
},
|
||||
...mapState(['user'])
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
@@ -1,22 +1,15 @@
|
||||
<template>
|
||||
<article>
|
||||
<page-title title="Welcome!" hideOnPage="true" />
|
||||
<div class="row">
|
||||
<div class="col">
|
||||
<p> </p>
|
||||
<p>
|
||||
myPrayerJournal is a place where individuals can record their prayer requests, record that they prayed for
|
||||
them, update them as God moves in the situation, and record a final answer received on that request. It
|
||||
will also allow individuals to review their answered prayers.
|
||||
</p>
|
||||
<p>
|
||||
This site is currently in very limited alpha, as it is being developed with a core group of test users.
|
||||
If this is something in which you are interested, check back around mid-November 2017 for an update on the
|
||||
development progress.
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
</article>
|
||||
<template lang="pug">
|
||||
article
|
||||
page-title(title="Welcome!" hideOnPage="true")
|
||||
p
|
||||
p.
|
||||
myPrayerJournal is a place where individuals can record their prayer requests, record that they prayed for them,
|
||||
update them as God moves in the situation, and record a final answer received on that request. It will also
|
||||
allow individuals to review their answered prayers.
|
||||
p.
|
||||
This site is currently in very limited alpha, as it is being developed with a core group of test users. If
|
||||
this is something in which you are interested, check back around mid-November 2017 for an update on the
|
||||
development progress.
|
||||
</template>
|
||||
|
||||
<script>
|
||||
@@ -24,9 +17,6 @@ import PageTitle from './PageTitle.vue'
|
||||
|
||||
export default {
|
||||
name: 'home',
|
||||
data () {
|
||||
return {}
|
||||
},
|
||||
components: {
|
||||
PageTitle
|
||||
}
|
||||
|
||||
@@ -1,25 +1,41 @@
|
||||
<template>
|
||||
<b-navbar toggleable type="inverse" variant="inverse" fixed="top">
|
||||
<b-nav-toggle target="navCollapse"></b-nav-toggle>
|
||||
<b-link class="navbar-brand" :to="{ name: 'Home' }">
|
||||
<span style="font-weight:100;">my</span><span style="font-weight:600;">Prayer</span><span style="font-weight:700;">Journal</span>
|
||||
</b-link>
|
||||
<b-collapse is-nav id="navCollapse">
|
||||
<b-nav is-nav-bar>
|
||||
<b-nav-item v-if="auth.authenticated" :to="{ name: 'Dashboard' }">Dashboard</b-nav-item>
|
||||
<b-nav-item v-if="auth.authenticated" @click="auth.logout()">Log Off</b-nav-item>
|
||||
<b-nav-item v-if="!auth.authenticated" @click="auth.login()">Log On</b-nav-item>
|
||||
</b-nav>
|
||||
</b-collapse>
|
||||
</b-navbar>
|
||||
<template lang="pug">
|
||||
el-menu(theme="dark" mode="horizontal" class="mpj-top-nav" router=true)
|
||||
el-menu-item(index="/")
|
||||
span(style="font-weight:100;") my
|
||||
span(style="font-weight:600;") Prayer
|
||||
span(style="font-weight:700;") Journal
|
||||
el-menu-item(v-if="isAuthenticated" index="/dashboard") Dashboard
|
||||
el-menu-item(v-if="isAuthenticated" index="3"): a(@click.stop="logOff()") Log Off
|
||||
el-menu-item(v-if="!isAuthenticated" index="4"): a(@click.stop="logOn()") Log On
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import { mapState } from 'vuex'
|
||||
import AuthService from '@/auth/AuthService'
|
||||
|
||||
export default {
|
||||
name: 'navigation',
|
||||
props: ['auth'],
|
||||
data: function () {
|
||||
return { }
|
||||
}
|
||||
data () {
|
||||
return {
|
||||
auth0: new AuthService()
|
||||
}
|
||||
},
|
||||
methods: {
|
||||
logOn () {
|
||||
this.auth0.login()
|
||||
},
|
||||
logOff () {
|
||||
this.auth0.logout(this.$store, this.$router)
|
||||
}
|
||||
},
|
||||
computed: mapState(['isAuthenticated'])
|
||||
}
|
||||
</script>
|
||||
|
||||
<style scoped>
|
||||
.mpj-top-nav {
|
||||
position: fixed;
|
||||
top: 0px;
|
||||
width: 100%;
|
||||
}
|
||||
</style>
|
||||
|
||||
@@ -1,14 +1,11 @@
|
||||
<template>
|
||||
<h2 v-if="!hideOnPage" class="mpj-page-title" v-html="title"></h2>
|
||||
<template lang="pug">
|
||||
h2.mpj-page-title(v-if="!hideOnPage" v-html="title")
|
||||
</template>
|
||||
|
||||
<script>
|
||||
export default {
|
||||
name: 'page-title',
|
||||
props: ['title', 'hideOnPage'],
|
||||
data () {
|
||||
return {}
|
||||
},
|
||||
created () {
|
||||
document.title = `${this.title} « myPrayerJournal`
|
||||
},
|
||||
|
||||
@@ -3,12 +3,13 @@
|
||||
</template>
|
||||
|
||||
<script>
|
||||
export default {
|
||||
name: 'log-on',
|
||||
props: ['auth'],
|
||||
data () {
|
||||
this.auth.handleAuthentication()
|
||||
return {}
|
||||
}
|
||||
import AuthService from '@/auth/AuthService'
|
||||
|
||||
export default {
|
||||
name: 'log-on',
|
||||
data () {
|
||||
new AuthService().handleAuthentication(this.$store, this.$router)
|
||||
return {}
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
@@ -1,18 +1,22 @@
|
||||
// The Vue build version to load with the `import` command
|
||||
// (runtime-only or standalone) has been set in webpack.base.conf with an alias.
|
||||
import Vue from 'vue'
|
||||
import BootstrapVue from 'bootstrap-vue'
|
||||
import ElementUI from 'element-ui'
|
||||
import 'element-ui/lib/theme-default/index.css'
|
||||
|
||||
import App from './App'
|
||||
import router from './router'
|
||||
import store from './store'
|
||||
|
||||
Vue.config.productionTip = false
|
||||
|
||||
Vue.use(BootstrapVue)
|
||||
Vue.use(ElementUI)
|
||||
|
||||
/* eslint-disable no-new */
|
||||
new Vue({
|
||||
el: '#app',
|
||||
router,
|
||||
store,
|
||||
template: '<App/>',
|
||||
components: { App }
|
||||
})
|
||||
|
||||
31
src/app/src/store/index.js
Normal file
31
src/app/src/store/index.js
Normal file
@@ -0,0 +1,31 @@
|
||||
import Vue from 'vue'
|
||||
import Vuex from 'vuex'
|
||||
|
||||
import AuthService from '@/auth/AuthService'
|
||||
|
||||
import * as types from './mutation-types'
|
||||
|
||||
Vue.use(Vuex)
|
||||
|
||||
this.auth0 = new AuthService()
|
||||
|
||||
export default new Vuex.Store({
|
||||
state: {
|
||||
user: JSON.parse(localStorage.getItem('user_profile') || '{}'),
|
||||
isAuthenticated: this.auth0.isAuthenticated()
|
||||
},
|
||||
mutations: {
|
||||
[types.USER_LOGGED_ON] (state, user) {
|
||||
localStorage.setItem('user_profile', JSON.stringify(user))
|
||||
state.user = user
|
||||
state.isAuthenticated = true
|
||||
},
|
||||
[types.USER_LOGGED_OFF] (state) {
|
||||
state.user = {}
|
||||
state.isAuthenticated = false
|
||||
}
|
||||
},
|
||||
actions: {},
|
||||
getters: {},
|
||||
modules: {}
|
||||
})
|
||||
2
src/app/src/store/mutation-types.js
Normal file
2
src/app/src/store/mutation-types.js
Normal file
@@ -0,0 +1,2 @@
|
||||
export const USER_LOGGED_OFF = 'user-logged-out'
|
||||
export const USER_LOGGED_ON = 'user-logged-on'
|
||||
Reference in New Issue
Block a user