API/app working nicely with RavenDB

time to v2 the app...
This commit is contained in:
Daniel J. Summers 2019-07-31 19:13:36 -05:00
parent c587d9772f
commit d0456ab886
15 changed files with 89 additions and 121 deletions

View File

@ -1,17 +1,14 @@
namespace MyPrayerJournal namespace MyPrayerJournal
open FSharp.Control.Tasks.V2.ContextInsensitive
open Microsoft.FSharpLu
open Newtonsoft.Json
open Raven.Client.Documents
open Raven.Client.Documents.Indexes
open Raven.Client.Documents.Linq
open System open System
open System.Collections.Generic open System.Collections.Generic
/// JSON converters for various DUs /// JSON converters for various DUs
module Converters = module Converters =
open Microsoft.FSharpLu.Json
open Newtonsoft.Json
/// JSON converter for request IDs /// JSON converter for request IDs
type RequestIdJsonConverter () = type RequestIdJsonConverter () =
inherit JsonConverter<RequestId> () inherit JsonConverter<RequestId> ()
@ -36,30 +33,28 @@ module Converters =
override __.ReadJson(reader: JsonReader, _ : Type, _ : Ticks, _ : bool, _ : JsonSerializer) = override __.ReadJson(reader: JsonReader, _ : Type, _ : Ticks, _ : bool, _ : JsonSerializer) =
(string >> int64 >> Ticks) reader.Value (string >> int64 >> Ticks) reader.Value
/// A sequence of all custom converters for myPrayerJournal /// A sequence of all custom converters needed for myPrayerJournal
let all : JsonConverter seq = let all : JsonConverter seq =
seq { seq {
yield RequestIdJsonConverter () yield RequestIdJsonConverter ()
yield UserIdJsonConverter () yield UserIdJsonConverter ()
yield TicksJsonConverter () yield TicksJsonConverter ()
yield CompactUnionJsonConverter true
} }
/// RavenDB index declarations /// RavenDB index declarations
module Indexes = module Indexes =
/// Index requests by user ID open Raven.Client.Documents.Indexes
type Requests_ByUserId () as this =
inherit AbstractJavaScriptIndexCreationTask ()
do
this.Maps <- HashSet<string> [ "docs.Requests.Select(req => new { userId = req.userId })" ]
/// Index requests for a journal view /// Index requests for a journal view
type Requests_AsJournal () as this = type Requests_AsJournal () as this =
inherit AbstractJavaScriptIndexCreationTask () inherit AbstractJavaScriptIndexCreationTask ()
do do
this.Maps <- HashSet<string> [ this.Maps <- HashSet<string> [
"docs.Requests.Select(req => new { """docs.Requests.Select(req => new {
requestId = req.Id, requestId = req.Id.Replace("Requests/", ""),
userId = req.userId, userId = req.userId,
text = req.history.Where(hist => hist.text != null).OrderByDescending(hist => hist.asOf).First().text, text = req.history.Where(hist => hist.text != null).OrderByDescending(hist => hist.asOf).First().text,
asOf = req.history.OrderByDescending(hist => hist.asOf).First().asOf, asOf = req.history.OrderByDescending(hist => hist.asOf).First().asOf,
@ -68,10 +63,11 @@ module Indexes =
showAfter = req.showAfter, showAfter = req.showAfter,
recurType = req.recurType, recurType = req.recurType,
recurCount = req.recurCount recurCount = req.recurCount
})" })"""
] ]
this.Fields <- this.Fields <-
[ "text", IndexFieldOptions (Storage = Nullable FieldStorage.Yes) [ "requestId", IndexFieldOptions (Storage = Nullable FieldStorage.Yes)
"text", IndexFieldOptions (Storage = Nullable FieldStorage.Yes)
"asOf", IndexFieldOptions (Storage = Nullable FieldStorage.Yes) "asOf", IndexFieldOptions (Storage = Nullable FieldStorage.Yes)
"lastStatus", IndexFieldOptions (Storage = Nullable FieldStorage.Yes) "lastStatus", IndexFieldOptions (Storage = Nullable FieldStorage.Yes)
] ]
@ -79,39 +75,14 @@ module Indexes =
|> Dictionary<string, IndexFieldOptions> |> Dictionary<string, IndexFieldOptions>
/// Extensions on the IAsyncDocumentSession interface to support our data manipulation needs
[<AutoOpen>]
module Extensions =
open Indexes
open Raven.Client.Documents.Commands.Batches
open Raven.Client.Documents.Operations
open Raven.Client.Documents.Session
/// Format an RQL query by a strongly-typed index
let fromIndex (typ : Type) =
typ.Name.Replace ("_", "/") |> sprintf "from index '%s'"
/// Utility method to create a patch request to push an item on the end of a list
let listPush<'T> listName docId (item : 'T) =
let r = PatchRequest()
r.Script <- sprintf "this.%s.push(args.Item)" listName
r.Values.["Item"] <- item
PatchCommandData (docId, null, r, null)
/// Utility method to create a patch to update a single field
// TODO: think we need to include quotes if it's a string
let fieldUpdate<'T> fieldName docId (item : 'T) =
let r = PatchRequest()
r.Script <- sprintf "this.%s = args.Item" fieldName
r.Values.["Item"] <- item
PatchCommandData (docId, null, r, null)
/// All data manipulations within myPrayerJournal /// All data manipulations within myPrayerJournal
module Data = module Data =
open FSharp.Control.Tasks.V2.ContextInsensitive
open Indexes open Indexes
open Microsoft.FSharpLu
open Raven.Client.Documents
open Raven.Client.Documents.Linq
open Raven.Client.Documents.Session open Raven.Client.Documents.Session
/// Add a history entry /// Add a history entry
@ -134,11 +105,15 @@ module Data =
/// Retrieve all answered requests for the given user /// Retrieve all answered requests for the given user
let answeredRequests userId (sess : IAsyncDocumentSession) = let answeredRequests userId (sess : IAsyncDocumentSession) =
sess.Query<JournalRequest, Requests_AsJournal>() task {
.Where(fun r -> r.userId = userId && r.lastStatus = "Answered") let! reqs =
.OrderByDescending(fun r -> r.asOf) sess.Query<JournalRequest, Requests_AsJournal>()
.ProjectInto<JournalRequest>() .Where(fun r -> r.userId = userId && r.lastStatus = "Answered")
.ToListAsync() .OrderByDescending(fun r -> r.asOf)
.ProjectInto<JournalRequest>()
.ToListAsync ()
return List.ofSeq reqs
}
/// Retrieve the user's current journal /// Retrieve the user's current journal
let journalByUserId userId (sess : IAsyncDocumentSession) = let journalByUserId userId (sess : IAsyncDocumentSession) =

View File

@ -43,21 +43,13 @@ type Recurrence =
| Days | Days
| Weeks | Weeks
module Recurrence = module Recurrence =
/// The string reprsentation used in the database and the web app
// TODO/FIXME: will this be true in v2? it's not in the database...
let toString x =
match x with
| Immediate -> "immediate"
| Hours -> "hours"
| Days -> "days"
| Weeks -> "weeks"
/// Create a recurrence value from a string /// Create a recurrence value from a string
let fromString x = let fromString x =
match x with match x with
| "immediate" -> Immediate | "Immediate" -> Immediate
| "hours" -> Hours | "Hours" -> Hours
| "days" -> Days | "Days" -> Days
| "weeks" -> Weeks | "Weeks" -> Weeks
| _ -> invalidOp (sprintf "%s is not a valid recurrence" x) | _ -> invalidOp (sprintf "%s is not a valid recurrence" x)
/// The duration of the recurrence /// The duration of the recurrence
let duration x = let duration x =
@ -159,8 +151,8 @@ with
// RavenDB doesn't like the "@"-suffixed properties from record types in a ProjectInto clause // RavenDB doesn't like the "@"-suffixed properties from record types in a ProjectInto clause
[<NoComparison; NoEquality>] [<NoComparison; NoEquality>]
type JournalRequest () = type JournalRequest () =
/// The ID of the request /// The ID of the request (just the CUID part)
[<DefaultValue>] val mutable requestId : RequestId [<DefaultValue>] val mutable requestId : string
/// The ID of the user to whom the request belongs /// The ID of the user to whom the request belongs
[<DefaultValue>] val mutable userId : UserId [<DefaultValue>] val mutable userId : UserId
/// The current text of the request /// The current text of the request

View File

@ -1,6 +1,6 @@
/// HTTP handlers for the myPrayerJournal API /// HTTP handlers for the myPrayerJournal API
[<RequireQualifiedAccess>] [<RequireQualifiedAccess>]
module MyPrayerJournal.Api.Handlers module MyPrayerJournal.Handlers
open FSharp.Control.Tasks.V2.ContextInsensitive open FSharp.Control.Tasks.V2.ContextInsensitive
open Giraffe open Giraffe
@ -46,7 +46,9 @@ module private Helpers =
/// Create a RavenDB session /// Create a RavenDB session
let session (ctx : HttpContext) = let session (ctx : HttpContext) =
ctx.GetService<IDocumentStore>().OpenAsyncSession () let sess = ctx.GetService<IDocumentStore>().OpenAsyncSession ()
sess.Advanced.WaitForIndexesAfterSaveChanges ()
sess
/// Get the user's "sub" claim /// Get the user's "sub" claim
let user (ctx : HttpContext) = let user (ctx : HttpContext) =

View File

@ -2,7 +2,7 @@
<PropertyGroup> <PropertyGroup>
<TargetFramework>netcoreapp2.2</TargetFramework> <TargetFramework>netcoreapp2.2</TargetFramework>
<Version>1.2.2.0</Version> <Version>2.0.0.0</Version>
</PropertyGroup> </PropertyGroup>
<ItemGroup> <ItemGroup>

View File

@ -1,4 +1,4 @@
namespace MyPrayerJournal.Api module MyPrayerJournal.Api
open Microsoft.AspNetCore.Builder open Microsoft.AspNetCore.Builder
open Microsoft.AspNetCore.Hosting open Microsoft.AspNetCore.Hosting
@ -40,10 +40,10 @@ module Configure =
open Giraffe.TokenRouter open Giraffe.TokenRouter
open Microsoft.AspNetCore.Authentication.JwtBearer open Microsoft.AspNetCore.Authentication.JwtBearer
open Microsoft.Extensions.DependencyInjection open Microsoft.Extensions.DependencyInjection
open Microsoft.FSharpLu.Json
open MyPrayerJournal open MyPrayerJournal
open MyPrayerJournal.Indexes open MyPrayerJournal.Indexes
open Newtonsoft.Json open Newtonsoft.Json
open Newtonsoft.Json.Serialization
open Raven.Client.Documents open Raven.Client.Documents
open Raven.Client.Documents.Indexes open Raven.Client.Documents.Indexes
open System.Security.Cryptography.X509Certificates open System.Security.Cryptography.X509Certificates
@ -51,19 +51,14 @@ module Configure =
/// Configure dependency injection /// Configure dependency injection
let services (bldr : IWebHostBuilder) = let services (bldr : IWebHostBuilder) =
let svcs (sc : IServiceCollection) = let svcs (sc : IServiceCollection) =
/// A set of JSON converters used for both Giraffe's request serialization and RavenDB's storage
let jsonConverters : JsonConverter seq =
seq {
yield! Converters.all
yield CompactUnionJsonConverter true
}
/// Custom settings for the JSON serializer (uses compact representation for options and DUs) /// Custom settings for the JSON serializer (uses compact representation for options and DUs)
let jsonSettings = let jsonSettings =
let x = NewtonsoftJsonSerializer.DefaultSettings let x = NewtonsoftJsonSerializer.DefaultSettings
jsonConverters |> List.ofSeq |> List.iter x.Converters.Add Converters.all |> List.ofSeq |> List.iter x.Converters.Add
x.NullValueHandling <- NullValueHandling.Ignore x.NullValueHandling <- NullValueHandling.Ignore
x.MissingMemberHandling <- MissingMemberHandling.Error x.MissingMemberHandling <- MissingMemberHandling.Error
x.Formatting <- Formatting.Indented x.Formatting <- Formatting.Indented
x.ContractResolver <- DefaultContractResolver ()
x x
use sp = sc.BuildServiceProvider () use sp = sc.BuildServiceProvider ()
@ -87,10 +82,12 @@ module Configure =
let store = new DocumentStore () let store = new DocumentStore ()
store.Urls <- [| config.["URL"] |] store.Urls <- [| config.["URL"] |]
store.Database <- config.["Database"] store.Database <- config.["Database"]
// store.Certificate <- new X509Certificate2 (config.["Certificate"], config.["Password"]) match isNull config.["Certificate"] with
store.Conventions.CustomizeJsonSerializer <- fun x -> jsonConverters |> List.ofSeq |> List.iter x.Converters.Add | true -> ()
| false -> store.Certificate <- new X509Certificate2 (config.["Certificate"], config.["Password"])
store.Conventions.CustomizeJsonSerializer <- fun x -> Converters.all |> List.ofSeq |> List.iter x.Converters.Add
store.Initialize () |> (sc.AddSingleton >> ignore) store.Initialize () |> (sc.AddSingleton >> ignore)
IndexCreation.CreateIndexes (typeof<Requests_ByUserId>.Assembly, store) IndexCreation.CreateIndexes (typeof<Requests_AsJournal>.Assembly, store)
bldr.ConfigureServices svcs bldr.ConfigureServices svcs
open Microsoft.Extensions.Logging open Microsoft.Extensions.Logging
@ -169,13 +166,11 @@ module Configure =
/// Build the web host from the given configuration /// Build the web host from the given configuration
let buildHost (bldr : IWebHostBuilder) = bldr.Build () let buildHost (bldr : IWebHostBuilder) = bldr.Build ()
module Program = let exitCode = 0
let exitCode = 0 [<EntryPoint>]
let main _ =
[<EntryPoint>] let appRoot = Directory.GetCurrentDirectory ()
let main _ = use host = WebHostBuilder() |> (Configure.webHost appRoot [| "wwwroot" |] >> Configure.buildHost)
let appRoot = Directory.GetCurrentDirectory () host.Run ()
use host = WebHostBuilder() |> (Configure.webHost appRoot [| "wwwroot" |] >> Configure.buildHost) exitCode
host.Run ()
exitCode

View File

@ -39,7 +39,11 @@ export default {
return this.$refs.toast return this.$refs.toast
}, },
version () { version () {
return version.endsWith('.0') ? version.substr(0, version.length - 2) : version return version.endsWith('.0')
? version.endsWith('.0.0')
? version.substr(0, version.length - 4)
: version.substr(0, version.length - 2)
: version
} }
} }
} }

View File

@ -10,7 +10,7 @@ article.mpj-main-content-wide(role='main')
br br
.mpj-journal(v-if='journal.length > 0') .mpj-journal(v-if='journal.length > 0')
request-card(v-for='request in journal' request-card(v-for='request in journal'
:key='request.Id' :key='request.requestId'
:request='request' :request='request'
:events='eventBus' :events='eventBus'
:toast='toast') :toast='toast')

View File

@ -5,7 +5,7 @@ article.mpj-main-content(role='main')
p.mpj-text-center(v-if='requests.length === 0'): em. p.mpj-text-center(v-if='requests.length === 0'): em.
No active requests found; return to #[router-link(:to='{ name: "Journal" } ') your journal] No active requests found; return to #[router-link(:to='{ name: "Journal" } ') your journal]
request-list-item(v-for='req in requests' request-list-item(v-for='req in requests'
:key='req.Id' :key='req.requestId'
:request='req' :request='req'
:toast='toast') :toast='toast')
p(v-else) Loading journal... p(v-else) Loading journal...

View File

@ -5,7 +5,7 @@ article.mpj-main-content(role='main')
p.text-center(v-if='requests.length === 0'): em. p.text-center(v-if='requests.length === 0'): em.
No answered requests found; once you have marked one as &ldquo;Answered&rdquo;, it will appear here No answered requests found; once you have marked one as &ldquo;Answered&rdquo;, it will appear here
request-list-item(v-for='req in requests' request-list-item(v-for='req in requests'
:key='req.Id' :key='req.requestId'
:request='req' :request='req'
:toast='toast') :toast='toast')
p(v-else) Loading answered requests... p(v-else) Loading answered requests...

View File

@ -42,7 +42,7 @@ article.mpj-main-content(role='main')
input(v-model='form.recur.typ' input(v-model='form.recur.typ'
type='radio' type='radio'
name='recur' name='recur'
value='immediate') value='Immediate')
| Immediately | Immediately
| &nbsp; &nbsp; | &nbsp; &nbsp;
label.normal label.normal
@ -56,9 +56,9 @@ article.mpj-main-content(role='main')
:disabled='!showRecurrence').mpj-recur-count :disabled='!showRecurrence').mpj-recur-count
select(v-model='form.recur.other' select(v-model='form.recur.other'
:disabled='!showRecurrence').mpj-recur-type :disabled='!showRecurrence').mpj-recur-type
option(value='hours') hours option(value='Hours') hours
option(value='days') days option(value='Days') days
option(value='weeks') weeks option(value='Weeks') weeks
.mpj-text-right .mpj-text-right
button(:disabled='!isValidRecurrence' button(:disabled='!isValidRecurrence'
@click.stop='saveRequest()').primary. @click.stop='saveRequest()').primary.
@ -92,7 +92,7 @@ export default {
requestText: '', requestText: '',
status: 'Updated', status: 'Updated',
recur: { recur: {
typ: 'immediate', typ: 'Immediate',
other: '', other: '',
count: '' count: ''
} }
@ -101,16 +101,16 @@ export default {
}, },
computed: { computed: {
isValidRecurrence () { isValidRecurrence () {
if (this.form.recur.typ === 'immediate') return true if (this.form.recur.typ === 'Immediate') return true
const count = Number.parseInt(this.form.recur.count) const count = Number.parseInt(this.form.recur.count)
if (isNaN(count) || this.form.recur.other === '') return false if (isNaN(count) || this.form.recur.other === '') return false
if (this.form.recur.other === 'hours' && count > (365 * 24)) return false if (this.form.recur.other === 'Hours' && count > (365 * 24)) return false
if (this.form.recur.other === 'days' && count > 365) return false if (this.form.recur.other === 'Days' && count > 365) return false
if (this.form.recur.other === 'weeks' && count > 52) return false if (this.form.recur.other === 'Weeks' && count > 52) return false
return true return true
}, },
showRecurrence () { showRecurrence () {
return this.form.recur.typ !== 'immediate' return this.form.recur.typ !== 'Immediate'
}, },
toast () { toast () {
return this.$parent.$refs.toast return this.$parent.$refs.toast
@ -125,7 +125,7 @@ export default {
this.form.requestId = '' this.form.requestId = ''
this.form.requestText = '' this.form.requestText = ''
this.form.status = 'Created' this.form.status = 'Created'
this.form.recur.typ = 'immediate' this.form.recur.typ = 'Immediate'
this.form.recur.other = '' this.form.recur.other = ''
this.form.recur.count = '' this.form.recur.count = ''
} else { } else {
@ -134,12 +134,12 @@ export default {
if (this.journal.length === 0) { if (this.journal.length === 0) {
await this.$store.dispatch(actions.LOAD_JOURNAL, this.$Progress) await this.$store.dispatch(actions.LOAD_JOURNAL, this.$Progress)
} }
const req = this.journal.filter(r => r.Id === this.id)[0] const req = this.journal.filter(r => r.requestId === this.id)[0]
this.form.requestId = this.id this.form.requestId = this.id
this.form.requestText = req.text this.form.requestText = req.text
this.form.status = 'Updated' this.form.status = 'Updated'
if (req.recurType === 'immediate') { if (req.recurType === 'Immediate') {
this.form.recur.typ = 'immediate' this.form.recur.typ = 'Immediate'
this.form.recur.other = '' this.form.recur.other = ''
this.form.recur.count = '' this.form.recur.count = ''
} else { } else {
@ -166,8 +166,8 @@ export default {
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)
}) })
this.toast.showToast('New prayer request added', { theme: 'success' }) this.toast.showToast('New prayer request added', { theme: 'success' })
} else { } else {
@ -176,8 +176,8 @@ export default {
requestId: this.form.requestId, requestId: this.form.requestId,
updateText: this.form.requestText, updateText: this.form.requestText,
status: this.form.status, status: this.form.status,
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)
}) })
if (this.form.status === 'Answered') { if (this.form.status === 'Answered') {
this.toast.showToast('Request updated and removed from active journal', { theme: 'success' }) this.toast.showToast('Request updated and removed from active journal', { theme: 'success' })

View File

@ -85,7 +85,7 @@ export default {
} }
}, },
openDialog (request) { openDialog (request) {
this.form.requestId = request.Id this.form.requestId = request.requestId
this.notesVisible = true this.notesVisible = true
}, },
async saveNotes () { async saveNotes () {

View File

@ -36,20 +36,20 @@ export default {
async markPrayed () { async markPrayed () {
await this.$store.dispatch(actions.UPDATE_REQUEST, { await this.$store.dispatch(actions.UPDATE_REQUEST, {
progress: this.$Progress, progress: this.$Progress,
requestId: this.request.Id, requestId: this.request.requestId,
status: 'Prayed', status: 'Prayed',
updateText: '' updateText: ''
}) })
this.toast.showToast('Request marked as prayed', { theme: 'success' }) this.toast.showToast('Request marked as prayed', { theme: 'success' })
}, },
showEdit () { showEdit () {
this.$router.push({ name: 'EditRequest', params: { id: this.request.Id } }) this.$router.push({ name: 'EditRequest', params: { id: this.request.requestId } })
}, },
showNotes () { showNotes () {
this.events.$emit('notes', this.request) this.events.$emit('notes', this.request)
}, },
snooze () { snooze () {
this.events.$emit('snooze', this.request.Id) this.events.$emit('snooze', this.request.requestId)
} }
} }
} }

View File

@ -60,26 +60,26 @@ export default {
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.Id, requestId: this.request.requestId,
until: 0 until: 0
}) })
this.toast.showToast('Request un-snoozed', { theme: 'success' }) this.toast.showToast('Request un-snoozed', { theme: 'success' })
this.$parent.$emit('requestUnsnoozed') this.$parent.$emit('requestUnsnoozed')
}, },
editRequest () { editRequest () {
this.$router.push({ name: 'EditRequest', params: { id: this.request.Id } }) this.$router.push({ name: 'EditRequest', params: { id: this.request.requestId } })
}, },
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.Id, requestId: this.request.requestId,
showAfter: Date.now() showAfter: Date.now()
}) })
this.toast.showToast('Recurrence skipped; request now shows in journal', { theme: 'success' }) this.toast.showToast('Recurrence skipped; request now shows in journal', { theme: 'success' })
this.$parent.$emit('requestNowShown') this.$parent.$emit('requestNowShown')
}, },
viewFull () { viewFull () {
this.$router.push({ name: 'FullRequest', params: { id: this.request.Id } }) this.$router.push({ name: 'FullRequest', params: { id: this.request.requestId } })
} }
} }
} }

View File

@ -5,7 +5,7 @@ article.mpj-main-content(role='main')
p.mpj-text-center(v-if='requests.length === 0'): em. p.mpj-text-center(v-if='requests.length === 0'): em.
No snoozed requests found; return to #[router-link(:to='{ name: "Journal" } ') your journal] No snoozed requests found; return to #[router-link(:to='{ name: "Journal" } ') your journal]
request-list-item(v-for='req in requests' request-list-item(v-for='req in requests'
:key='req.Id' :key='req.requestId'
:request='req' :request='req'
:toast='toast') :toast='toast')
p(v-else) Loading journal... p(v-else) Loading journal...

View File

@ -56,7 +56,7 @@ export default new Vuex.Store({
state.journal.push(newRequest) state.journal.push(newRequest)
}, },
[mutations.REQUEST_UPDATED] (state, request) { [mutations.REQUEST_UPDATED] (state, request) {
let jrnl = state.journal.filter(it => it.Id !== request.Id) let jrnl = state.journal.filter(it => it.requestId !== request.requestId)
if (request.lastStatus !== 'Answered') jrnl.push(request) if (request.lastStatus !== 'Answered') jrnl.push(request)
state.journal = jrnl state.journal = jrnl
}, },
@ -103,7 +103,7 @@ export default new Vuex.Store({
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.start()
try { try {
let oldReq = (state.journal.filter(req => req.Id === requestId) || [])[0] || {} let oldReq = (state.journal.filter(req => req.requestId === requestId) || [])[0] || {}
if (!(status === 'Prayed' && updateText === '')) { if (!(status === 'Prayed' && updateText === '')) {
if (status !== 'Answered' && (oldReq.recurType !== recurType || oldReq.recurCount !== recurCount)) { if (status !== 'Answered' && (oldReq.recurType !== recurType || oldReq.recurCount !== recurCount)) {
await api.updateRecurrence(requestId, recurType, recurCount) await api.updateRecurrence(requestId, recurType, recurCount)