From 2c34650cebe6ba11f3ff3cdcdab9cbe5ebba1ab8 Mon Sep 17 00:00:00 2001 From: "Daniel J. Summers" Date: Sat, 18 Aug 2018 19:32:48 -0500 Subject: [PATCH] Completed recurrence work (#16) Requests can now: - be entered with recurrence - be updated with recurrence - manually skip recurrence period Also did an app-wide clean-up to ensure that everything is done the same way in all places --- src/api/MyPrayerJournal.Api/Data.fs | 2 +- src/api/MyPrayerJournal.Api/Handlers.fs | 54 +++++++++- src/api/MyPrayerJournal.Api/Program.fs | 16 ++- src/app/src/App.vue | 14 ++- src/app/src/api/index.js | 38 +++++-- .../components/{ => common}/Navigation.vue | 0 .../src/components/request/ActiveRequests.vue | 3 +- .../src/components/request/EditRequest.vue | 74 ++++++++----- .../src/components/request/FullRequest.vue | 5 +- src/app/src/components/request/NewRequest.vue | 100 ------------------ src/app/src/components/request/NotesEdit.vue | 18 ++-- .../src/components/request/RequestCard.vue | 4 +- .../components/request/RequestListItem.vue | 36 +++++-- .../src/components/request/SnoozeRequest.vue | 10 +- src/app/src/components/user/LogOn.vue | 2 +- src/app/src/router/index.js | 7 ++ src/app/src/store/action-types.js | 2 + src/app/src/store/index.js | 26 ++++- 18 files changed, 228 insertions(+), 183 deletions(-) rename src/app/src/components/{ => common}/Navigation.vue (100%) delete mode 100644 src/app/src/components/request/NewRequest.vue diff --git a/src/api/MyPrayerJournal.Api/Data.fs b/src/api/MyPrayerJournal.Api/Data.fs index ab9fdc8..3a2d948 100644 --- a/src/api/MyPrayerJournal.Api/Data.fs +++ b/src/api/MyPrayerJournal.Api/Data.fs @@ -245,7 +245,7 @@ type AppDbContext (opts : DbContextOptions) = .OrderBy(fun r -> r.asOf) /// Retrieve a request by its ID and user ID - member this.TryRequestById reqId userId : Task = + member this.TryRequestById reqId userId = task { let! req = this.Requests.AsNoTracking().FirstOrDefaultAsync(fun r -> r.requestId = reqId && r.userId = userId) return toOption req diff --git a/src/api/MyPrayerJournal.Api/Handlers.fs b/src/api/MyPrayerJournal.Api/Handlers.fs index be7dc8e..2991d81 100644 --- a/src/api/MyPrayerJournal.Api/Handlers.fs +++ b/src/api/MyPrayerJournal.Api/Handlers.fs @@ -95,6 +95,15 @@ module Models = notes : string } + /// Recurrence update + [] + type Recurrence = + { /// The recurrence type + recurType : string + /// The recurrence cound + recurCount : int16 + } + /// A prayer request [] type Request = @@ -103,9 +112,16 @@ module Models = /// The recurrence type recurType : string /// The recurrence count - recurCount : int16 option + recurCount : int16 } + /// Reset the "showAfter" property on a request + [] + type Show = + { /// The time after which the request should appear + showAfter : int64 + } + /// The time until which a request should not appear in the journal [] type SnoozeUntil = @@ -156,7 +172,7 @@ module Request = enteredOn = now showAfter = now recurType = r.recurType - recurCount = defaultArg r.recurCount 0s + recurCount = r.recurCount } |> db.AddEntry { History.empty with @@ -255,7 +271,23 @@ module Request = return! json notes next ctx } - /// POST /api/request/[req-id]/snooze + /// PATCH /api/request/[req-id]/show + let show reqId : HttpHandler = + authorize + >=> fun next ctx -> + task { + let db = db ctx + match! db.TryRequestById reqId (userId ctx) with + | Some req -> + let! show = ctx.BindJsonAsync () + { req with showAfter = show.showAfter } + |> db.UpdateEntry + let! _ = db.SaveChangesAsync () + return! setStatusCode 204 next ctx + | None -> return! Error.notFound next ctx + } + + /// PATCH /api/request/[req-id]/snooze let snooze reqId : HttpHandler = authorize >=> fun next ctx -> @@ -270,3 +302,19 @@ module Request = return! setStatusCode 204 next ctx | None -> return! Error.notFound next ctx } + + /// PATCH /api/request/[req-id]/recurrence + let updateRecurrence reqId : HttpHandler = + authorize + >=> fun next ctx -> + task { + let db = db ctx + match! db.TryRequestById reqId (userId ctx) with + | Some req -> + let! recur = ctx.BindJsonAsync () + { req with recurType = recur.recurType; recurCount = recur.recurCount } + |> db.UpdateEntry + let! _ = db.SaveChangesAsync () + return! setStatusCode 204 next ctx + | None -> return! Error.notFound next ctx + } diff --git a/src/api/MyPrayerJournal.Api/Program.fs b/src/api/MyPrayerJournal.Api/Program.fs index 73f0884..2e21bd3 100644 --- a/src/api/MyPrayerJournal.Api/Program.fs +++ b/src/api/MyPrayerJournal.Api/Program.fs @@ -58,10 +58,17 @@ module Configure = 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 + 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 [ @@ -69,7 +76,6 @@ module Configure = route "" Handlers.Request.add routef "/%s/history" Handlers.Request.addHistory routef "/%s/note" Handlers.Request.addNote - routef "/%s/snooze" Handlers.Request.snooze ] ] ] diff --git a/src/app/src/App.vue b/src/app/src/App.vue index a034b44..a7e6f02 100644 --- a/src/app/src/App.vue +++ b/src/app/src/App.vue @@ -19,7 +19,7 @@ - diff --git a/src/app/src/components/request/FullRequest.vue b/src/app/src/components/request/FullRequest.vue index 55db339..480a724 100644 --- a/src/app/src/components/request/FullRequest.vue +++ b/src/app/src/components/request/FullRequest.vue @@ -55,11 +55,12 @@ export default { .sort(asOfDesc)[0].text.fields[0] }, log () { - return (this.request.notes || []) + const allHistory = (this.request.notes || []) .map(note => ({ asOf: note.asOf, text: { case: 'Some', fields: [ note.notes ] }, status: 'Notes' })) .concat(this.request.history) .sort(asOfDesc) - .slice(1) + // Skip the first entry for answered requests; that info is already displayed + return this.isAnswered ? allHistory.slice(1) : allHistory }, openDays () { const asOf = this.isAnswered ? this.answered : Date.now() diff --git a/src/app/src/components/request/NewRequest.vue b/src/app/src/components/request/NewRequest.vue deleted file mode 100644 index 98a0cfb..0000000 --- a/src/app/src/components/request/NewRequest.vue +++ /dev/null @@ -1,100 +0,0 @@ - - - diff --git a/src/app/src/components/request/NotesEdit.vue b/src/app/src/components/request/NotesEdit.vue index 278e0fa..85c28e1 100644 --- a/src/app/src/components/request/NotesEdit.vue +++ b/src/app/src/components/request/NotesEdit.vue @@ -3,11 +3,12 @@ .mpj-modal-content.mpj-narrow header.mpj-bg h5 Add Notes to Prayer Request - label(for='notes') Notes - br - textarea#notes(v-model='form.notes' - :rows='10' - @blur='trimText()') + label + | Notes + br + textarea(v-model='form.notes' + :rows='10' + @blur='trimText()').mpj-full-width .mpj-text-right button(@click='saveNotes()').primary. #[md-icon(icon='save')] Save @@ -75,7 +76,6 @@ export default { try { const notes = await api.getNotes(this.form.requestId) this.priorNotes = notes.data - console.log(this.priorNotes) this.$Progress.finish() } catch (e) { console.error(e) @@ -85,7 +85,6 @@ export default { } }, openDialog (request) { - console.log('Received openDialog event') this.form.requestId = request.requestId this.notesVisible = true }, @@ -108,10 +107,7 @@ export default { } -