myPrayerJournal v2 #27

Merged
danieljsummers merged 27 commits from version-2 into master 2019-09-03 00:01:26 +00:00
17 changed files with 122 additions and 103 deletions
Showing only changes of commit 34c2148743 - Show all commits

View File

@ -142,7 +142,6 @@ module Models =
open FSharp.Control.Tasks.V2.ContextInsensitive
/// /api/journal URLs
module Journal =
@ -333,3 +332,36 @@ module Request =
return! setStatusCode 204 next ctx
| None -> return! Error.notFound next ctx
}
open Giraffe.TokenRouter
/// The routes for myPrayerJournal
let webApp : HttpHandler =
router Error.notFound [
route "/" Vue.app
subRoute "/api/" [
GET [
route "journal" Journal.journal
subRoute "request" [
route "s/answered" Request.answered
routef "/%s/full" Request.getFull
routef "/%s/notes" Request.getNotes
routef "/%s" Request.get
]
]
PATCH [
subRoute "request" [
routef "/%s/recurrence" Request.updateRecurrence
routef "/%s/show" Request.show
routef "/%s/snooze" Request.snooze
]
]
POST [
subRoute "request" [
route "" Request.add
routef "/%s/history" Request.addHistory
routef "/%s/note" Request.addNote
]
]
]
]

View File

@ -37,7 +37,6 @@ module Configure =
open Giraffe
open Giraffe.Serialization
open Giraffe.TokenRouter
open Microsoft.AspNetCore.Authentication.JwtBearer
open Microsoft.Extensions.DependencyInjection
open MyPrayerJournal.Indexes
@ -102,37 +101,6 @@ module Configure =
|> ignore
bldr.ConfigureLogging logz
/// Routes for the available URLs within myPrayerJournal
let webApp =
router Handlers.Error.notFound [
route "/" Handlers.Vue.app
subRoute "/api/" [
GET [
route "journal" Handlers.Journal.journal
subRoute "request" [
route "s/answered" Handlers.Request.answered
routef "/%s/full" Handlers.Request.getFull
routef "/%s/notes" Handlers.Request.getNotes
routef "/%s" Handlers.Request.get
]
]
PATCH [
subRoute "request" [
routef "/%s/recurrence" Handlers.Request.updateRecurrence
routef "/%s/show" Handlers.Request.show
routef "/%s/snooze" Handlers.Request.snooze
]
]
POST [
subRoute "request" [
route "" Handlers.Request.add
routef "/%s/history" Handlers.Request.addHistory
routef "/%s/note" Handlers.Request.addNote
]
]
]
]
open System
/// Configure the web application
@ -148,7 +116,7 @@ module Configure =
| a ->
a.UseAuthentication()
.UseStaticFiles()
.UseGiraffe webApp
.UseGiraffe Handlers.webApp
|> ignore)
bldr.Configure appConfig

View File

@ -18,7 +18,6 @@
"moment": "^2.18.1",
"vue": "^2.5.15",
"vue-material": "^1.0.0-beta-11",
"vue-progressbar": "^0.7.3",
"vue-router": "^3.0.0",
"vuex": "^3.0.1"
},

View File

@ -10,8 +10,9 @@
span(style='font-weight:700;') Journal
navigation
md-app-content
md-progress-bar(v-if='progress.visible'
:md-mode='progress.mode')
router-view
vue-progress-bar
md-snackbar(:md-active.sync='snackbar.visible'
md-position='center'
:md-duration='snackbar.interval'
@ -43,8 +44,13 @@ export default {
},
data () {
return {
messageEvents: new Vue(),
progress: {
events: new Vue(),
visible: false,
mode: 'query'
},
snackbar: {
events: new Vue(),
visible: false,
message: '',
interval: 4000
@ -52,13 +58,12 @@ export default {
}
},
mounted () {
this.messageEvents.$on('info', this.showInfo)
this.messageEvents.$on('error', this.showError)
this.progress.events.$on('show', this.showProgress)
this.progress.events.$on('done', this.hideProgress)
this.snackbar.events.$on('info', this.showInfo)
this.snackbar.events.$on('error', this.showError)
},
computed: {
messages () {
return this.messageEvents
},
version () {
return version.endsWith('.0')
? version.endsWith('.0.0')
@ -79,11 +84,19 @@ export default {
showError (message) {
this.snackbar.interval = Infinity
this.showSnackbar(message)
},
showProgress (mode) {
this.progress.mode = mode
this.progress.visible = true
},
hideProgress () {
this.progress.visible = false
}
},
provide () {
return {
messages: this.messageEvents
messages: this.snackbar.events,
progress: this.progress.events
}
}
}
@ -281,4 +294,7 @@ a:hover {
.material-icons {
vertical-align: middle;
}
.md-progress-bar {
margin: 24px;
}
</style>

View File

@ -32,7 +32,10 @@ import actions from '@/store/action-types'
export default {
name: 'journal',
inject: ['messages'],
inject: [
'messages',
'progress'
],
components: {
NotesEdit,
RequestCard,
@ -53,7 +56,7 @@ export default {
...mapState(['user', 'journal', 'isLoadingJournal'])
},
async created () {
await this.$store.dispatch(actions.LOAD_JOURNAL, this.$Progress)
await this.$store.dispatch(actions.LOAD_JOURNAL, this.progress)
this.messages.$emit('info', `Loaded ${this.journal.length} prayer requests`)
},
provide () {

View File

@ -21,6 +21,7 @@ import actions from '@/store/action-types'
export default {
name: 'active-requests',
inject: ['progress'],
components: {
RequestListItem
},
@ -41,7 +42,7 @@ export default {
async ensureJournal () {
if (!Array.isArray(this.journal)) {
this.loaded = false
await this.$store.dispatch(actions.LOAD_JOURNAL, this.$Progress)
await this.$store.dispatch(actions.LOAD_JOURNAL, this.progress)
}
this.requests = this.journal
.sort((a, b) => a.showAfter - b.showAfter)

View File

@ -19,7 +19,10 @@ import RequestListItem from '@/components/request/RequestListItem'
export default {
name: 'answered-requests',
inject: ['messages'],
inject: [
'messages',
'progress'
],
components: {
RequestListItem
},
@ -30,15 +33,15 @@ export default {
}
},
async mounted () {
this.$Progress.start()
this.progress.$emit('show', 'query')
try {
const reqs = await api.getAnsweredRequests()
this.requests = reqs.data
this.$Progress.finish()
this.progress.$emit('done')
} catch (err) {
console.error(err)
this.messages.$emit('error', 'Error loading requests; check console for details')
this.$Progress.fail()
this.progress.$emit('done')
} finally {
this.loaded = true
}

View File

@ -77,7 +77,10 @@ import actions from '@/store/action-types'
export default {
name: 'edit-request',
inject: ['messages'],
inject: [
'messages',
'progress'
],
props: {
id: {
type: String,
@ -162,7 +165,7 @@ export default {
async saveRequest () {
if (this.isNew) {
await this.$store.dispatch(actions.ADD_REQUEST, {
progress: this.$Progress,
progress: this.progress,
requestText: this.form.requestText,
recurType: this.form.recur.typ === 'Immediate' ? 'Immediate' : this.form.recur.other,
recurCount: this.form.recur.typ === 'Immediate' ? 0 : Number.parseInt(this.form.recur.count)
@ -170,7 +173,7 @@ export default {
this.messages.$emit('info', 'New prayer request added')
} else {
await this.$store.dispatch(actions.UPDATE_REQUEST, {
progress: this.$Progress,
progress: this.progress,
requestId: this.form.requestId,
updateText: this.form.requestText,
status: this.form.status,

View File

@ -31,6 +31,7 @@ const asOfDesc = (a, b) => b.asOf - a.asOf
export default {
name: 'full-request',
inject: ['progress'],
props: {
id: {
type: String,
@ -72,14 +73,14 @@ export default {
}
},
async mounted () {
this.$Progress.start()
this.progress.$emit('show', 'indeterminate')
try {
const req = await api.getFullRequest(this.id)
this.request = req.data
this.$Progress.finish()
this.progress.$emit('done')
} catch (e) {
console.log(e)
this.$Progress.fail()
this.progress.$emit('done')
}
},
methods: {

View File

@ -38,8 +38,9 @@ import api from '@/api'
export default {
name: 'notes-edit',
inject: [
'journalEvents',
'messages',
'journalEvents'
'progress'
],
data () {
return {
@ -72,14 +73,14 @@ export default {
this.notesVisible = false
},
async loadNotes () {
this.$Progress.start()
this.progress.$emit('show', 'indeterminate')
try {
const notes = await api.getNotes(this.form.requestId)
this.priorNotes = notes.data
this.$Progress.finish()
this.progress.$emit('done')
} catch (e) {
console.error(e)
this.$Progress.fail()
this.progress.$emit('done')
} finally {
this.priorNotesLoaded = true
}
@ -89,15 +90,15 @@ export default {
this.notesVisible = true
},
async saveNotes () {
this.$Progress.start()
this.progress.$emit('show', 'indeterminate')
try {
await api.addNote(this.form.requestId, this.form.notes)
this.$Progress.finish()
this.progress.$emit('done')
this.messages.$emit('info', 'Added notes')
this.closeDialog()
} catch (e) {
console.error(e)
this.$Progress.fail()
this.progress.$emit('done')
}
},
trimText () {

View File

@ -35,7 +35,10 @@ import actions from '@/store/action-types'
export default {
name: 'request-list-item',
inject: ['messages'],
inject: [
'messages',
'progress'
],
props: {
request: { required: true }
},
@ -59,7 +62,7 @@ export default {
methods: {
async cancelSnooze () {
await this.$store.dispatch(actions.SNOOZE_REQUEST, {
progress: this.$Progress,
progress: this.progress,
requestId: this.request.requestId,
until: 0
})
@ -71,7 +74,7 @@ export default {
},
async showNow () {
await this.$store.dispatch(actions.SHOW_REQUEST_NOW, {
progress: this.$Progress,
progress: this.progress,
requestId: this.request.requestId,
showAfter: Date.now()
})

View File

@ -26,7 +26,11 @@ import actions from '@/store/action-types'
export default {
name: 'snooze-request',
inject: ['messages'],
inject: [
'journalEvents',
'messages',
'progress'
],
props: {
events: { required: true }
},
@ -40,7 +44,7 @@ export default {
}
},
created () {
this.events.$on('snooze', this.openDialog)
this.journalEvents.$on('snooze', this.openDialog)
},
computed: {
isValid () {
@ -59,7 +63,7 @@ export default {
},
async snoozeRequest () {
await this.$store.dispatch(actions.SNOOZE_REQUEST, {
progress: this.$Progress,
progress: this.progress,
requestId: this.form.requestId,
until: Date.parse(this.form.snoozedUntil)
})

View File

@ -21,6 +21,7 @@ import RequestListItem from '@/components/request/RequestListItem'
export default {
name: 'snoozed-requests',
inject: ['progress'],
components: {
RequestListItem
},
@ -40,7 +41,7 @@ export default {
async ensureJournal () {
if (!Array.isArray(this.journal)) {
this.loaded = false
await this.$store.dispatch(actions.LOAD_JOURNAL, this.$Progress)
await this.$store.dispatch(actions.LOAD_JOURNAL, this.progress)
}
this.requests = this.journal
.filter(req => req.snoozedUntil > Date.now())

View File

@ -11,8 +11,9 @@ import AuthService from '@/auth/AuthService'
export default {
name: 'log-on',
inject: ['progress'],
created () {
this.$Progress.start()
this.progress.$emit('show', 'indeterminate')
new AuthService().handleAuthentication(this.$store, this.$router)
// Auth service redirects to dashboard, which restarts the progress bar
}

View File

@ -3,7 +3,6 @@
// Vue packages and components
import Vue from 'vue'
import VueMaterial from 'vue-material'
import VueProgressBar from 'vue-progressbar'
// myPrayerJournal components
import App from './App'
@ -20,17 +19,6 @@ import 'vue-material/dist/theme/default.css'
Vue.config.productionTip = false
Vue.use(VueProgressBar, {
color: 'yellow',
failedColor: 'red',
height: '5px',
transition: {
speed: '0.2s',
opacity: '0.6s',
termination: 1000
}
})
Vue.use(VueMaterial)
Vue.component('date-from-now', DateFromNow)
Vue.component('page-title', PageTitle)

View File

@ -76,34 +76,34 @@ export default new Vuex.Store({
},
actions: {
async [actions.ADD_REQUEST] ({ commit }, { progress, requestText, recurType, recurCount }) {
progress.start()
progress.$emit('show', 'indeterminate')
try {
const newRequest = await api.addRequest(requestText, recurType, recurCount)
commit(mutations.REQUEST_ADDED, newRequest.data)
progress.finish()
progress.$emit('done')
} catch (err) {
logError(err)
progress.fail()
progress.$emit('done')
}
},
async [actions.LOAD_JOURNAL] ({ commit }, progress) {
commit(mutations.LOADED_JOURNAL, {})
progress.start()
progress.$emit('show', 'query')
commit(mutations.LOADING_JOURNAL, true)
api.setBearer(localStorage.getItem('id_token'))
try {
const jrnl = await api.journal()
commit(mutations.LOADED_JOURNAL, jrnl.data)
progress.finish()
progress.$emit('done')
} catch (err) {
logError(err)
progress.fail()
progress.$emit('done')
} finally {
commit(mutations.LOADING_JOURNAL, false)
}
},
async [actions.UPDATE_REQUEST] ({ commit, state }, { progress, requestId, status, updateText, recurType, recurCount }) {
progress.start()
progress.$emit('show', 'indeterminate')
try {
let oldReq = (state.journal.filter(req => req.requestId === requestId) || [])[0] || {}
if (!(status === 'Prayed' && updateText === '')) {
@ -116,34 +116,34 @@ export default new Vuex.Store({
}
const request = await api.getRequest(requestId)
commit(mutations.REQUEST_UPDATED, request.data)
progress.finish()
progress.$emit('done')
} catch (err) {
logError(err)
progress.fail()
progress.$emit('done')
}
},
async [actions.SHOW_REQUEST_NOW] ({ commit }, { progress, requestId, showAfter }) {
progress.start()
progress.$emit('show', 'indeterminate')
try {
await api.showRequest(requestId, showAfter)
const request = await api.getRequest(requestId)
commit(mutations.REQUEST_UPDATED, request.data)
progress.finish()
progress.$emit('done')
} catch (err) {
logError(err)
progress.fail()
progress.$emit('done')
}
},
async [actions.SNOOZE_REQUEST] ({ commit }, { progress, requestId, until }) {
progress.start()
progress.$emit('show', 'indeterminate')
try {
await api.snoozeRequest(requestId, until)
const request = await api.getRequest(requestId)
commit(mutations.REQUEST_UPDATED, request.data)
progress.finish()
progress.$emit('done')
} catch (err) {
logError(err)
progress.fail()
progress.$emit('done')
}
}
},

View File

@ -8307,11 +8307,6 @@ vue-material@^1.0.0-beta-11:
resolved "https://registry.yarnpkg.com/vue-material/-/vue-material-1.0.0-beta-11.tgz#11baf0cdb22a35d35859c619099d6c3cb3cc2cc3"
integrity sha512-1+dIVkQafMIA/zNONb7OwGaTjAxaWk/JhUA2/FInQvbArxf1ToKB+yIdeSfzopQ1KICnBTAmk9E0Vdr5p4MWNA==
vue-progressbar@^0.7.3:
version "0.7.5"
resolved "https://registry.yarnpkg.com/vue-progressbar/-/vue-progressbar-0.7.5.tgz#414730892252b1e45582d4979dec93038e007f79"
integrity sha512-VeNG/inMsFbvdCTS7lJ1gjDAKSUZdqkhW9gS1tb0we1rqFKxR+BCEiVUgw5C84vODKb14M2GWHTw0WVdpoVg6g==
vue-router@^3.0.0:
version "3.1.2"
resolved "https://registry.yarnpkg.com/vue-router/-/vue-router-3.1.2.tgz#2e0904703545dabdd42b2b7a2e617f02f99a1969"