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:
Daniel J. Summers
2017-07-29 16:28:27 -05:00
parent 632f06ac5f
commit 338f11d1ab
31 changed files with 12054 additions and 60 deletions

73
src/app/src/App.vue Normal file
View 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>

View 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
}
}

View 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>

View File

@@ -0,0 +1,34 @@
<template>
<article>
<page-title title="Welcome!" hideOnPage="true" />
<div class="row">
<div class="col">
<p>&nbsp;</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.&nbsp; 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.&nbsp;
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>

View 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>

View 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>

View 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
View 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 }
})

View 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 }
]
})