App functionality restored

time to implement MD components
This commit is contained in:
Daniel J. Summers 2019-08-20 21:41:49 -05:00
parent b5146f825a
commit 34c2148743
17 changed files with 122 additions and 103 deletions

View File

@ -142,7 +142,6 @@ module Models =
open FSharp.Control.Tasks.V2.ContextInsensitive open FSharp.Control.Tasks.V2.ContextInsensitive
/// /api/journal URLs /// /api/journal URLs
module Journal = module Journal =
@ -333,3 +332,36 @@ module Request =
return! setStatusCode 204 next ctx return! setStatusCode 204 next ctx
| None -> return! Error.notFound 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
open Giraffe.Serialization open Giraffe.Serialization
open Giraffe.TokenRouter
open Microsoft.AspNetCore.Authentication.JwtBearer open Microsoft.AspNetCore.Authentication.JwtBearer
open Microsoft.Extensions.DependencyInjection open Microsoft.Extensions.DependencyInjection
open MyPrayerJournal.Indexes open MyPrayerJournal.Indexes
@ -102,37 +101,6 @@ module Configure =
|> ignore |> ignore
bldr.ConfigureLogging logz 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 open System
/// Configure the web application /// Configure the web application
@ -148,7 +116,7 @@ module Configure =
| a -> | a ->
a.UseAuthentication() a.UseAuthentication()
.UseStaticFiles() .UseStaticFiles()
.UseGiraffe webApp .UseGiraffe Handlers.webApp
|> ignore) |> ignore)
bldr.Configure appConfig bldr.Configure appConfig

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

@ -3,7 +3,6 @@
// Vue packages and components // Vue packages and components
import Vue from 'vue' import Vue from 'vue'
import VueMaterial from 'vue-material' import VueMaterial from 'vue-material'
import VueProgressBar from 'vue-progressbar'
// myPrayerJournal components // myPrayerJournal components
import App from './App' import App from './App'
@ -20,17 +19,6 @@ import 'vue-material/dist/theme/default.css'
Vue.config.productionTip = false 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.use(VueMaterial)
Vue.component('date-from-now', DateFromNow) Vue.component('date-from-now', DateFromNow)
Vue.component('page-title', PageTitle) Vue.component('page-title', PageTitle)

View File

@ -76,34 +76,34 @@ export default new Vuex.Store({
}, },
actions: { actions: {
async [actions.ADD_REQUEST] ({ commit }, { progress, requestText, recurType, recurCount }) { async [actions.ADD_REQUEST] ({ commit }, { progress, requestText, recurType, recurCount }) {
progress.start() progress.$emit('show', 'indeterminate')
try { try {
const newRequest = await api.addRequest(requestText, recurType, recurCount) const newRequest = await api.addRequest(requestText, recurType, recurCount)
commit(mutations.REQUEST_ADDED, newRequest.data) commit(mutations.REQUEST_ADDED, newRequest.data)
progress.finish() progress.$emit('done')
} catch (err) { } catch (err) {
logError(err) logError(err)
progress.fail() progress.$emit('done')
} }
}, },
async [actions.LOAD_JOURNAL] ({ commit }, progress) { async [actions.LOAD_JOURNAL] ({ commit }, progress) {
commit(mutations.LOADED_JOURNAL, {}) commit(mutations.LOADED_JOURNAL, {})
progress.start() progress.$emit('show', 'query')
commit(mutations.LOADING_JOURNAL, true) commit(mutations.LOADING_JOURNAL, true)
api.setBearer(localStorage.getItem('id_token')) api.setBearer(localStorage.getItem('id_token'))
try { try {
const jrnl = await api.journal() const jrnl = await api.journal()
commit(mutations.LOADED_JOURNAL, jrnl.data) commit(mutations.LOADED_JOURNAL, jrnl.data)
progress.finish() progress.$emit('done')
} catch (err) { } catch (err) {
logError(err) logError(err)
progress.fail() progress.$emit('done')
} finally { } finally {
commit(mutations.LOADING_JOURNAL, false) commit(mutations.LOADING_JOURNAL, false)
} }
}, },
async [actions.UPDATE_REQUEST] ({ commit, state }, { progress, requestId, status, updateText, recurType, recurCount }) { async [actions.UPDATE_REQUEST] ({ commit, state }, { progress, requestId, status, updateText, recurType, recurCount }) {
progress.start() progress.$emit('show', 'indeterminate')
try { try {
let oldReq = (state.journal.filter(req => req.requestId === requestId) || [])[0] || {} let oldReq = (state.journal.filter(req => req.requestId === requestId) || [])[0] || {}
if (!(status === 'Prayed' && updateText === '')) { if (!(status === 'Prayed' && updateText === '')) {
@ -116,34 +116,34 @@ export default new Vuex.Store({
} }
const request = await api.getRequest(requestId) const request = await api.getRequest(requestId)
commit(mutations.REQUEST_UPDATED, request.data) commit(mutations.REQUEST_UPDATED, request.data)
progress.finish() progress.$emit('done')
} catch (err) { } catch (err) {
logError(err) logError(err)
progress.fail() progress.$emit('done')
} }
}, },
async [actions.SHOW_REQUEST_NOW] ({ commit }, { progress, requestId, showAfter }) { async [actions.SHOW_REQUEST_NOW] ({ commit }, { progress, requestId, showAfter }) {
progress.start() progress.$emit('show', 'indeterminate')
try { try {
await api.showRequest(requestId, showAfter) await api.showRequest(requestId, showAfter)
const request = await api.getRequest(requestId) const request = await api.getRequest(requestId)
commit(mutations.REQUEST_UPDATED, request.data) commit(mutations.REQUEST_UPDATED, request.data)
progress.finish() progress.$emit('done')
} catch (err) { } catch (err) {
logError(err) logError(err)
progress.fail() progress.$emit('done')
} }
}, },
async [actions.SNOOZE_REQUEST] ({ commit }, { progress, requestId, until }) { async [actions.SNOOZE_REQUEST] ({ commit }, { progress, requestId, until }) {
progress.start() progress.$emit('show', 'indeterminate')
try { try {
await api.snoozeRequest(requestId, until) await api.snoozeRequest(requestId, until)
const request = await api.getRequest(requestId) const request = await api.getRequest(requestId)
commit(mutations.REQUEST_UPDATED, request.data) commit(mutations.REQUEST_UPDATED, request.data)
progress.finish() progress.$emit('done')
} catch (err) { } catch (err) {
logError(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" resolved "https://registry.yarnpkg.com/vue-material/-/vue-material-1.0.0-beta-11.tgz#11baf0cdb22a35d35859c619099d6c3cb3cc2cc3"
integrity sha512-1+dIVkQafMIA/zNONb7OwGaTjAxaWk/JhUA2/FInQvbArxf1ToKB+yIdeSfzopQ1KICnBTAmk9E0Vdr5p4MWNA== 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: vue-router@^3.0.0:
version "3.1.2" version "3.1.2"
resolved "https://registry.yarnpkg.com/vue-router/-/vue-router-3.1.2.tgz#2e0904703545dabdd42b2b7a2e617f02f99a1969" resolved "https://registry.yarnpkg.com/vue-router/-/vue-router-3.1.2.tgz#2e0904703545dabdd42b2b7a2e617f02f99a1969"