Vue it is
I know, the 18th front-end change; I have a feeling there won't be a 19th.
This commit is contained in:
73
src/app/src/App.vue
Normal file
73
src/app/src/App.vue
Normal file
@@ -0,0 +1,73 @@
|
||||
<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>
|
||||
|
||||
<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
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
<style>
|
||||
@import url('../node_modules/bootstrap/dist/css/bootstrap.css');
|
||||
@import url('../node_modules/bootstrap-vue/dist/bootstrap-vue.css');
|
||||
|
||||
body {
|
||||
padding-top: 60px;
|
||||
}
|
||||
footer {
|
||||
border-top: solid 1px lightgray;
|
||||
margin-top: 1rem;
|
||||
padding: 0 1rem;
|
||||
|
||||
}
|
||||
.material-icons.md-18 {
|
||||
font-size: 18px;
|
||||
}
|
||||
.material-icons.md-24 {
|
||||
font-size: 24px;
|
||||
}
|
||||
.material-icons.md-36 {
|
||||
font-size: 36px;
|
||||
}
|
||||
.material-icons.md-48 {
|
||||
font-size: 48px;
|
||||
}
|
||||
.material-icons {
|
||||
vertical-align: middle;
|
||||
}
|
||||
.mpj-page-title {
|
||||
border-bottom: solid 1px lightgray;
|
||||
margin-bottom: 20px;
|
||||
}
|
||||
</style>
|
||||
70
src/app/src/auth/AuthService.js
Normal file
70
src/app/src/auth/AuthService.js
Normal file
@@ -0,0 +1,70 @@
|
||||
import auth0 from 'auth0-js'
|
||||
import { AUTH_CONFIG } from './auth0-variables'
|
||||
import EventEmitter from 'EventEmitter'
|
||||
import router from './../router'
|
||||
|
||||
export default class AuthService {
|
||||
authenticated = this.isAuthenticated()
|
||||
authNotifier = new EventEmitter()
|
||||
|
||||
constructor () {
|
||||
this.login = this.login.bind(this)
|
||||
this.setSession = this.setSession.bind(this)
|
||||
this.logout = this.logout.bind(this)
|
||||
this.isAuthenticated = this.isAuthenticated.bind(this)
|
||||
}
|
||||
|
||||
auth0 = new auth0.WebAuth({
|
||||
domain: AUTH_CONFIG.domain,
|
||||
clientID: AUTH_CONFIG.clientId,
|
||||
redirectUri: AUTH_CONFIG.callbackUrl,
|
||||
audience: `https://${AUTH_CONFIG.domain}/userinfo`,
|
||||
responseType: 'token id_token',
|
||||
scope: 'openid'
|
||||
})
|
||||
|
||||
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) {
|
||||
router.replace('/')
|
||||
console.log(err)
|
||||
alert(`Error: ${err.error}. Check the console for further details.`)
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
setSession (authResult) {
|
||||
// Set the time that the access token will expire at
|
||||
let expiresAt = JSON.stringify(
|
||||
authResult.expiresIn * 1000 + new Date().getTime()
|
||||
)
|
||||
localStorage.setItem('access_token', authResult.accessToken)
|
||||
localStorage.setItem('id_token', authResult.idToken)
|
||||
localStorage.setItem('expires_at', expiresAt)
|
||||
this.authNotifier.emit('authChange', { authenticated: true })
|
||||
}
|
||||
|
||||
logout () {
|
||||
// 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)
|
||||
// navigate to the home route
|
||||
router.replace('/')
|
||||
}
|
||||
|
||||
isAuthenticated () {
|
||||
// Check whether the current time is past the access token's expiry time
|
||||
let expiresAt = JSON.parse(localStorage.getItem('expires_at'))
|
||||
return new Date().getTime() < expiresAt
|
||||
}
|
||||
}
|
||||
21
src/app/src/components/Dashboard.vue
Normal file
21
src/app/src/components/Dashboard.vue
Normal file
@@ -0,0 +1,21 @@
|
||||
<template>
|
||||
<article>
|
||||
<page-title title="Your Dashboard" />
|
||||
<p>here you are! {{ JSON.stringify(this.user) }}</p>
|
||||
</article>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import PageTitle from './PageTitle'
|
||||
|
||||
export default {
|
||||
name: 'dashboard',
|
||||
props: ['user'],
|
||||
data () {
|
||||
return {}
|
||||
},
|
||||
components: {
|
||||
PageTitle
|
||||
}
|
||||
}
|
||||
</script>
|
||||
34
src/app/src/components/Home.vue
Normal file
34
src/app/src/components/Home.vue
Normal file
@@ -0,0 +1,34 @@
|
||||
<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>
|
||||
|
||||
<script>
|
||||
import PageTitle from './PageTitle.vue'
|
||||
|
||||
export default {
|
||||
name: 'home',
|
||||
data () {
|
||||
return {}
|
||||
},
|
||||
components: {
|
||||
PageTitle
|
||||
}
|
||||
}
|
||||
</script>
|
||||
25
src/app/src/components/Navigation.vue
Normal file
25
src/app/src/components/Navigation.vue
Normal file
@@ -0,0 +1,25 @@
|
||||
<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>
|
||||
|
||||
<script>
|
||||
export default {
|
||||
name: 'navigation',
|
||||
props: ['auth'],
|
||||
data: function () {
|
||||
return { }
|
||||
}
|
||||
}
|
||||
</script>
|
||||
21
src/app/src/components/PageTitle.vue
Normal file
21
src/app/src/components/PageTitle.vue
Normal file
@@ -0,0 +1,21 @@
|
||||
<template>
|
||||
<h2 v-if="!hideOnPage" class="mpj-page-title" v-html="title"></h2>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
export default {
|
||||
name: 'page-title',
|
||||
props: ['title', 'hideOnPage'],
|
||||
data () {
|
||||
return {}
|
||||
},
|
||||
created () {
|
||||
document.title = `${this.title} « myPrayerJournal`
|
||||
},
|
||||
watch: {
|
||||
title () {
|
||||
document.title = `${this.title} « myPrayerJournal`
|
||||
}
|
||||
}
|
||||
}
|
||||
</script>
|
||||
14
src/app/src/components/user/LogOn.vue
Normal file
14
src/app/src/components/user/LogOn.vue
Normal file
@@ -0,0 +1,14 @@
|
||||
<template>
|
||||
<p>hang tight...</p>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
export default {
|
||||
name: 'log-on',
|
||||
props: ['auth'],
|
||||
data () {
|
||||
this.auth.handleAuthentication()
|
||||
return {}
|
||||
}
|
||||
}
|
||||
</script>
|
||||
18
src/app/src/main.js
Normal file
18
src/app/src/main.js
Normal file
@@ -0,0 +1,18 @@
|
||||
// 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 App from './App'
|
||||
import router from './router'
|
||||
|
||||
Vue.config.productionTip = false
|
||||
|
||||
Vue.use(BootstrapVue)
|
||||
|
||||
/* eslint-disable no-new */
|
||||
new Vue({
|
||||
el: '#app',
|
||||
router,
|
||||
template: '<App/>',
|
||||
components: { App }
|
||||
})
|
||||
17
src/app/src/router/index.js
Normal file
17
src/app/src/router/index.js
Normal file
@@ -0,0 +1,17 @@
|
||||
import Vue from 'vue'
|
||||
import Router from 'vue-router'
|
||||
|
||||
import Dashboard from '@/components/Dashboard'
|
||||
import Home from '@/components/Home'
|
||||
import LogOn from '@/components/user/LogOn'
|
||||
|
||||
Vue.use(Router)
|
||||
|
||||
export default new Router({
|
||||
mode: 'history',
|
||||
routes: [
|
||||
{ path: '/', name: 'Home', component: Home },
|
||||
{ path: '/dashboard', name: 'Dashboard', component: Dashboard },
|
||||
{ path: '/user/log-on', name: 'LogOn', component: LogOn }
|
||||
]
|
||||
})
|
||||
Reference in New Issue
Block a user