A lot is working...
...but a lot is not. The JSON for the journal is not including the Id field; I suspect the majority of the problems reside with that issue.
This commit is contained in:
parent
87ce966ca1
commit
c587d9772f
@ -63,6 +63,7 @@ module Indexes =
|
|||||||
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,
|
||||||
|
lastStatus = req.history.OrderByDescending(hist => hist.asOf).First().status,
|
||||||
snoozedUntil = req.snoozedUntil,
|
snoozedUntil = req.snoozedUntil,
|
||||||
showAfter = req.showAfter,
|
showAfter = req.showAfter,
|
||||||
recurType = req.recurType,
|
recurType = req.recurType,
|
||||||
@ -72,6 +73,7 @@ module Indexes =
|
|||||||
this.Fields <-
|
this.Fields <-
|
||||||
[ "text", 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)
|
||||||
]
|
]
|
||||||
|> dict
|
|> dict
|
||||||
|> Dictionary<string, IndexFieldOptions>
|
|> Dictionary<string, IndexFieldOptions>
|
||||||
@ -105,67 +107,87 @@ module Extensions =
|
|||||||
r.Values.["Item"] <- item
|
r.Values.["Item"] <- item
|
||||||
PatchCommandData (docId, null, r, null)
|
PatchCommandData (docId, null, r, null)
|
||||||
|
|
||||||
// Extensions for the RavenDB session type
|
|
||||||
type IAsyncDocumentSession with
|
/// All data manipulations within myPrayerJournal
|
||||||
|
module Data =
|
||||||
|
|
||||||
|
open Indexes
|
||||||
|
open Raven.Client.Documents.Session
|
||||||
|
|
||||||
/// Add a history entry
|
/// Add a history entry
|
||||||
member this.AddHistory (reqId : RequestId) (hist : History) =
|
let addHistory reqId (hist : History) (sess : IAsyncDocumentSession) =
|
||||||
listPush "history" (RequestId.toString reqId) hist
|
sess.Advanced.Patch<Request, History> (
|
||||||
|> this.Advanced.Defer
|
RequestId.toString reqId,
|
||||||
|
(fun r -> r.history :> IEnumerable<History>),
|
||||||
|
fun (h : JavaScriptArray<History>) -> h.Add (hist) :> obj)
|
||||||
|
|
||||||
/// Add a note
|
/// Add a note
|
||||||
member this.AddNote (reqId : RequestId) (note : Note) =
|
let addNote reqId (note : Note) (sess : IAsyncDocumentSession) =
|
||||||
listPush "notes" (RequestId.toString reqId) note
|
sess.Advanced.Patch<Request, Note> (
|
||||||
|> this.Advanced.Defer
|
RequestId.toString reqId,
|
||||||
|
(fun r -> r.notes :> IEnumerable<Note>),
|
||||||
|
fun (h : JavaScriptArray<Note>) -> h.Add (note) :> obj)
|
||||||
|
|
||||||
/// Add a request
|
/// Add a request
|
||||||
member this.AddRequest req =
|
let addRequest req (sess : IAsyncDocumentSession) =
|
||||||
this.StoreAsync (req, req.Id)
|
sess.StoreAsync (req, req.Id)
|
||||||
|
|
||||||
/// Retrieve all answered requests for the given user
|
/// Retrieve all answered requests for the given user
|
||||||
// TODO: not right
|
let answeredRequests userId (sess : IAsyncDocumentSession) =
|
||||||
member this.AnsweredRequests (userId : UserId) =
|
sess.Query<JournalRequest, Requests_AsJournal>()
|
||||||
sprintf "%s where userId = '%s' and lastStatus = 'Answered' order by asOf as long desc"
|
.Where(fun r -> r.userId = userId && r.lastStatus = "Answered")
|
||||||
(fromIndex typeof<Requests_AsJournal>) (UserId.toString userId)
|
.OrderByDescending(fun r -> r.asOf)
|
||||||
|> this.Advanced.AsyncRawQuery<JournalRequest>
|
.ProjectInto<JournalRequest>()
|
||||||
|
.ToListAsync()
|
||||||
|
|
||||||
/// Retrieve the user's current journal
|
/// Retrieve the user's current journal
|
||||||
// TODO: probably not right either
|
let journalByUserId userId (sess : IAsyncDocumentSession) =
|
||||||
member this.JournalByUserId (userId : UserId) =
|
|
||||||
sprintf "%s where userId = '%s' and lastStatus <> 'Answered' order by showAfter as long"
|
|
||||||
(fromIndex typeof<Requests_AsJournal>) (UserId.toString userId)
|
|
||||||
|> this.Advanced.AsyncRawQuery<JournalRequest>
|
|
||||||
|
|
||||||
/// Retrieve a request, including its history and notes, by its ID and user ID
|
|
||||||
member this.TryFullRequestById (reqId : RequestId) userId =
|
|
||||||
task {
|
task {
|
||||||
let! req = RequestId.toString reqId |> this.LoadAsync
|
let! jrnl =
|
||||||
match Option.fromObject req with
|
sess.Query<JournalRequest, Requests_AsJournal>()
|
||||||
| Some r when r.userId = userId -> return Some r
|
.Where(fun r -> r.userId = userId && r.lastStatus <> "Answered")
|
||||||
| _ -> return None
|
.OrderBy(fun r -> r.asOf)
|
||||||
|
.ProjectInto<JournalRequest>()
|
||||||
|
.ToListAsync()
|
||||||
|
return
|
||||||
|
jrnl
|
||||||
|
|> List.ofSeq
|
||||||
|
|> List.map (fun r -> r.history <- []; r.notes <- []; r)
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Retrieve a request by its ID and user ID (without notes and history)
|
/// Save changes in the current document session
|
||||||
member this.TryRequestById reqId userId =
|
let saveChanges (sess : IAsyncDocumentSession) =
|
||||||
|
sess.SaveChangesAsync ()
|
||||||
|
|
||||||
|
/// Retrieve a request, including its history and notes, by its ID and user ID
|
||||||
|
let tryFullRequestById reqId userId (sess : IAsyncDocumentSession) =
|
||||||
task {
|
task {
|
||||||
match! this.TryFullRequestById reqId userId with
|
let! req = RequestId.toString reqId |> sess.LoadAsync
|
||||||
|
return match Option.fromObject req with Some r when r.userId = userId -> Some r | _ -> None
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/// Retrieve a request by its ID and user ID (without notes and history)
|
||||||
|
let tryRequestById reqId userId (sess : IAsyncDocumentSession) =
|
||||||
|
task {
|
||||||
|
match! tryFullRequestById reqId userId sess with
|
||||||
| Some r -> return Some { r with history = []; notes = [] }
|
| Some r -> return Some { r with history = []; notes = [] }
|
||||||
| _ -> return None
|
| _ -> return None
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Retrieve notes for a request by its ID and user ID
|
/// Retrieve notes for a request by its ID and user ID
|
||||||
member this.NotesById reqId userId =
|
let notesById reqId userId (sess : IAsyncDocumentSession) =
|
||||||
task {
|
task {
|
||||||
match! this.TryRequestById reqId userId with
|
match! tryFullRequestById reqId userId sess with
|
||||||
| Some req -> return req.notes
|
| Some req -> return req.notes
|
||||||
| None -> return []
|
| None -> return []
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Retrieve a journal request by its ID and user ID
|
/// Retrieve a journal request by its ID and user ID
|
||||||
member this.TryJournalById (reqId : RequestId) userId =
|
let tryJournalById reqId userId (sess : IAsyncDocumentSession) =
|
||||||
task {
|
task {
|
||||||
let! req =
|
let! req =
|
||||||
this.Query<Request, Requests_AsJournal>()
|
sess.Query<Request, Requests_AsJournal>()
|
||||||
.Where(fun x -> x.Id = (RequestId.toString reqId) && x.userId = userId)
|
.Where(fun x -> x.Id = (RequestId.toString reqId) && x.userId = userId)
|
||||||
.ProjectInto<JournalRequest>()
|
.ProjectInto<JournalRequest>()
|
||||||
.FirstOrDefaultAsync ()
|
.FirstOrDefaultAsync ()
|
||||||
@ -173,176 +195,15 @@ module Extensions =
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// Update the recurrence for a request
|
/// Update the recurrence for a request
|
||||||
member this.UpdateRecurrence (reqId : RequestId) (recurType : Recurrence) (recurCount : int16) =
|
let updateRecurrence reqId recurType recurCount (sess : IAsyncDocumentSession) =
|
||||||
let r = PatchRequest()
|
sess.Advanced.Patch<Request, Recurrence> (RequestId.toString reqId, (fun r -> r.recurType), recurType)
|
||||||
r.Script <- "this.recurType = args.Type; this.recurCount = args.Count"
|
sess.Advanced.Patch<Request, int16> (RequestId.toString reqId, (fun r -> r.recurCount), recurCount)
|
||||||
r.Values.["Type"] <- string recurType
|
|
||||||
r.Values.["Count"] <- recurCount
|
|
||||||
PatchCommandData (RequestId.toString reqId, null, r, null) |> this.Advanced.Defer
|
|
||||||
|
|
||||||
/// Update the "show after" timestamp for a request
|
|
||||||
member this.UpdateShowAfter (reqId : RequestId) (showAfter : Ticks) =
|
|
||||||
fieldUpdate "showAfter" (RequestId.toString reqId) (Ticks.toLong showAfter)
|
|
||||||
|> this.Advanced.Defer
|
|
||||||
|
|
||||||
/// Update a snoozed request
|
/// Update a snoozed request
|
||||||
member this.UpdateSnoozed (reqId : RequestId) (until : Ticks) =
|
let updateSnoozed reqId until (sess : IAsyncDocumentSession) =
|
||||||
let r = PatchRequest()
|
sess.Advanced.Patch<Request, Ticks> (RequestId.toString reqId, (fun r -> r.snoozedUntil), until)
|
||||||
r.Script <- "this.snoozedUntil = args.Item; this.showAfter = args.Item"
|
sess.Advanced.Patch<Request, Ticks> (RequestId.toString reqId, (fun r -> r.showAfter), until)
|
||||||
r.Values.["Item"] <- Ticks.toLong until
|
|
||||||
PatchCommandData (RequestId.toString reqId, null, r, null) |> this.Advanced.Defer
|
|
||||||
|
|
||||||
|
/// Update the "show after" timestamp for a request
|
||||||
|
let updateShowAfter reqId showAfter (sess : IAsyncDocumentSession) =
|
||||||
(*
|
sess.Advanced.Patch<Request, Ticks> (RequestId.toString reqId, (fun r -> r.showAfter), showAfter)
|
||||||
/// Entity Framework configuration for myPrayerJournal
|
|
||||||
module internal EFConfig =
|
|
||||||
|
|
||||||
open FSharp.EFCore.OptionConverter
|
|
||||||
open System.Collections.Generic
|
|
||||||
|
|
||||||
/// Configure EF properties for all entity types
|
|
||||||
let configure (mb : ModelBuilder) =
|
|
||||||
mb.Entity<History> (
|
|
||||||
fun m ->
|
|
||||||
m.ToTable "history" |> ignore
|
|
||||||
m.HasKey ("requestId", "asOf") |> ignore
|
|
||||||
m.Property(fun e -> e.requestId).IsRequired () |> ignore
|
|
||||||
m.Property(fun e -> e.asOf).IsRequired () |> ignore
|
|
||||||
m.Property(fun e -> e.status).IsRequired() |> ignore
|
|
||||||
m.Property(fun e -> e.text) |> ignore)
|
|
||||||
|> ignore
|
|
||||||
mb.Model.FindEntityType(typeof<History>).FindProperty("text").SetValueConverter (OptionConverter<string> ())
|
|
||||||
|
|
||||||
mb.Entity<Note> (
|
|
||||||
fun m ->
|
|
||||||
m.ToTable "note" |> ignore
|
|
||||||
m.HasKey ("requestId", "asOf") |> ignore
|
|
||||||
m.Property(fun e -> e.requestId).IsRequired () |> ignore
|
|
||||||
m.Property(fun e -> e.asOf).IsRequired () |> ignore
|
|
||||||
m.Property(fun e -> e.notes).IsRequired () |> ignore)
|
|
||||||
|> ignore
|
|
||||||
|
|
||||||
mb.Entity<Request> (
|
|
||||||
fun m ->
|
|
||||||
m.ToTable "request" |> ignore
|
|
||||||
m.HasKey(fun e -> e.requestId :> obj) |> ignore
|
|
||||||
m.Property(fun e -> e.requestId).IsRequired () |> ignore
|
|
||||||
m.Property(fun e -> e.enteredOn).IsRequired () |> ignore
|
|
||||||
m.Property(fun e -> e.userId).IsRequired () |> ignore
|
|
||||||
m.Property(fun e -> e.snoozedUntil).IsRequired () |> ignore
|
|
||||||
m.Property(fun e -> e.showAfter).IsRequired () |> ignore
|
|
||||||
m.Property(fun e -> e.recurType).IsRequired() |> ignore
|
|
||||||
m.Property(fun e -> e.recurCount).IsRequired() |> ignore
|
|
||||||
m.HasMany(fun e -> e.history :> IEnumerable<History>)
|
|
||||||
.WithOne()
|
|
||||||
.HasForeignKey(fun e -> e.requestId :> obj)
|
|
||||||
|> ignore
|
|
||||||
m.HasMany(fun e -> e.notes :> IEnumerable<Note>)
|
|
||||||
.WithOne()
|
|
||||||
.HasForeignKey(fun e -> e.requestId :> obj)
|
|
||||||
|> ignore)
|
|
||||||
|> ignore
|
|
||||||
|
|
||||||
mb.Query<JournalRequest> (
|
|
||||||
fun m ->
|
|
||||||
m.ToView "journal" |> ignore
|
|
||||||
m.Ignore(fun e -> e.history :> obj) |> ignore
|
|
||||||
m.Ignore(fun e -> e.notes :> obj) |> ignore)
|
|
||||||
|> ignore
|
|
||||||
|
|
||||||
|
|
||||||
open System.Linq
|
|
||||||
|
|
||||||
/// Data context
|
|
||||||
type AppDbContext (opts : DbContextOptions<AppDbContext>) =
|
|
||||||
inherit DbContext (opts)
|
|
||||||
|
|
||||||
[<DefaultValue>]
|
|
||||||
val mutable private history : DbSet<History>
|
|
||||||
[<DefaultValue>]
|
|
||||||
val mutable private notes : DbSet<Note>
|
|
||||||
[<DefaultValue>]
|
|
||||||
val mutable private requests : DbSet<Request>
|
|
||||||
[<DefaultValue>]
|
|
||||||
val mutable private journal : DbQuery<JournalRequest>
|
|
||||||
|
|
||||||
member this.History
|
|
||||||
with get () = this.history
|
|
||||||
and set v = this.history <- v
|
|
||||||
member this.Notes
|
|
||||||
with get () = this.notes
|
|
||||||
and set v = this.notes <- v
|
|
||||||
member this.Requests
|
|
||||||
with get () = this.requests
|
|
||||||
and set v = this.requests <- v
|
|
||||||
member this.Journal
|
|
||||||
with get () = this.journal
|
|
||||||
and set v = this.journal <- v
|
|
||||||
|
|
||||||
override __.OnModelCreating (mb : ModelBuilder) =
|
|
||||||
base.OnModelCreating mb
|
|
||||||
EFConfig.configure mb
|
|
||||||
|
|
||||||
/// Register a disconnected entity with the context, having the given state
|
|
||||||
member private this.RegisterAs<'TEntity when 'TEntity : not struct> state e =
|
|
||||||
this.Entry<'TEntity>(e).State <- state
|
|
||||||
|
|
||||||
/// Add an entity instance to the context
|
|
||||||
member this.AddEntry e =
|
|
||||||
this.RegisterAs EntityState.Added e
|
|
||||||
|
|
||||||
/// Update the entity instance's values
|
|
||||||
member this.UpdateEntry e =
|
|
||||||
this.RegisterAs EntityState.Modified e
|
|
||||||
|
|
||||||
/// Retrieve all answered requests for the given user
|
|
||||||
member this.AnsweredRequests userId : JournalRequest seq =
|
|
||||||
upcast this.Journal
|
|
||||||
.Where(fun r -> r.userId = userId && r.lastStatus = "Answered")
|
|
||||||
.OrderByDescending(fun r -> r.asOf)
|
|
||||||
|
|
||||||
/// Retrieve the user's current journal
|
|
||||||
member this.JournalByUserId userId : JournalRequest seq =
|
|
||||||
upcast this.Journal
|
|
||||||
.Where(fun r -> r.userId = userId && r.lastStatus <> "Answered")
|
|
||||||
.OrderBy(fun r -> r.showAfter)
|
|
||||||
|
|
||||||
/// Retrieve a request by its ID and user ID
|
|
||||||
member this.TryRequestById reqId userId =
|
|
||||||
task {
|
|
||||||
let! req = this.Requests.AsNoTracking().FirstOrDefaultAsync(fun r -> r.requestId = reqId && r.userId = userId)
|
|
||||||
return Option.fromObject req
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Retrieve notes for a request by its ID and user ID
|
|
||||||
member this.NotesById reqId userId =
|
|
||||||
task {
|
|
||||||
match! this.TryRequestById reqId userId with
|
|
||||||
| Some _ -> return this.Notes.AsNoTracking().Where(fun n -> n.requestId = reqId) |> List.ofSeq
|
|
||||||
| None -> return []
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Retrieve a journal request by its ID and user ID
|
|
||||||
member this.TryJournalById reqId userId =
|
|
||||||
task {
|
|
||||||
let! req = this.Journal.FirstOrDefaultAsync(fun r -> r.requestId = reqId && r.userId = userId)
|
|
||||||
return Option.fromObject req
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Retrieve a request, including its history and notes, by its ID and user ID
|
|
||||||
member this.TryFullRequestById requestId userId =
|
|
||||||
task {
|
|
||||||
match! this.TryJournalById requestId userId with
|
|
||||||
| Some req ->
|
|
||||||
let! fullReq =
|
|
||||||
this.Requests.AsNoTracking()
|
|
||||||
.Include(fun r -> r.history)
|
|
||||||
.Include(fun r -> r.notes)
|
|
||||||
.FirstOrDefaultAsync(fun r -> r.requestId = requestId && r.userId = userId)
|
|
||||||
match Option.fromObject fullReq with
|
|
||||||
| Some _ -> return Some { req with history = List.ofSeq fullReq.history; notes = List.ofSeq fullReq.notes }
|
|
||||||
| None -> return None
|
|
||||||
| None -> return None
|
|
||||||
}
|
|
||||||
*)
|
|
||||||
|
@ -155,29 +155,29 @@ with
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// JournalRequest is the form of a prayer request returned for the request journal display. It also contains
|
/// JournalRequest is the form of a prayer request returned for the request journal display. It also contains
|
||||||
/// properties that may be filled for history and notes
|
/// properties that may be filled for history and notes.
|
||||||
[<CLIMutable; NoComparison; NoEquality>]
|
// RavenDB doesn't like the "@"-suffixed properties from record types in a ProjectInto clause
|
||||||
type JournalRequest =
|
[<NoComparison; NoEquality>]
|
||||||
{ /// The ID of the request
|
type JournalRequest () =
|
||||||
requestId : RequestId
|
/// The ID of the request
|
||||||
|
[<DefaultValue>] val mutable requestId : RequestId
|
||||||
/// The ID of the user to whom the request belongs
|
/// The ID of the user to whom the request belongs
|
||||||
userId : UserId
|
[<DefaultValue>] val mutable userId : UserId
|
||||||
/// The current text of the request
|
/// The current text of the request
|
||||||
text : string
|
[<DefaultValue>] val mutable text : string
|
||||||
/// The last time action was taken on the request
|
/// The last time action was taken on the request
|
||||||
asOf : Ticks
|
[<DefaultValue>] val mutable asOf : Ticks
|
||||||
/// The last status for the request
|
/// The last status for the request
|
||||||
lastStatus : string
|
[<DefaultValue>] val mutable lastStatus : string
|
||||||
/// The time that this request should reappear in the user's journal
|
/// The time that this request should reappear in the user's journal
|
||||||
snoozedUntil : Ticks
|
[<DefaultValue>] val mutable snoozedUntil : Ticks
|
||||||
/// The time after which this request should reappear in the user's journal by configured recurrence
|
/// The time after which this request should reappear in the user's journal by configured recurrence
|
||||||
showAfter : Ticks
|
[<DefaultValue>] val mutable showAfter : Ticks
|
||||||
/// The type of recurrence for this request
|
/// The type of recurrence for this request
|
||||||
recurType : Recurrence
|
[<DefaultValue>] val mutable recurType : Recurrence
|
||||||
/// How many of the recurrence intervals should occur between appearances in the journal
|
/// How many of the recurrence intervals should occur between appearances in the journal
|
||||||
recurCount : int16
|
[<DefaultValue>] val mutable recurCount : int16
|
||||||
/// History entries for the request
|
/// History entries for the request
|
||||||
history : History list
|
[<DefaultValue>] val mutable history : History list
|
||||||
/// Note entries for the request
|
/// Note entries for the request
|
||||||
notes : Note list
|
[<DefaultValue>] val mutable notes : Note list
|
||||||
}
|
|
||||||
|
@ -144,7 +144,8 @@ module Journal =
|
|||||||
>=> fun next ctx ->
|
>=> fun next ctx ->
|
||||||
task {
|
task {
|
||||||
use sess = session ctx
|
use sess = session ctx
|
||||||
let! jrnl = ((userId >> sess.JournalByUserId) ctx).ToListAsync ()
|
let usrId = userId ctx
|
||||||
|
let! jrnl = Data.journalByUserId usrId sess
|
||||||
return! json jrnl next ctx
|
return! json jrnl next ctx
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -164,7 +165,7 @@ module Request =
|
|||||||
let reqId = (Cuid.Generate >> toReqId) ()
|
let reqId = (Cuid.Generate >> toReqId) ()
|
||||||
let usrId = userId ctx
|
let usrId = userId ctx
|
||||||
let now = jsNow ()
|
let now = jsNow ()
|
||||||
do! sess.AddRequest
|
do! Data.addRequest
|
||||||
{ Request.empty with
|
{ Request.empty with
|
||||||
Id = RequestId.toString reqId
|
Id = RequestId.toString reqId
|
||||||
userId = usrId
|
userId = usrId
|
||||||
@ -173,15 +174,14 @@ module Request =
|
|||||||
recurType = Recurrence.fromString r.recurType
|
recurType = Recurrence.fromString r.recurType
|
||||||
recurCount = r.recurCount
|
recurCount = r.recurCount
|
||||||
history = [
|
history = [
|
||||||
{ History.empty with
|
{ asOf = now
|
||||||
asOf = now
|
|
||||||
status = Created
|
status = Created
|
||||||
text = Some r.requestText
|
text = Some r.requestText
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
}
|
} sess
|
||||||
do! sess.SaveChangesAsync ()
|
do! Data.saveChanges sess
|
||||||
match! sess.TryJournalById reqId usrId with
|
match! Data.tryJournalById reqId usrId sess with
|
||||||
| Some req -> return! (setStatusCode 201 >=> json req) next ctx
|
| Some req -> return! (setStatusCode 201 >=> json req) next ctx
|
||||||
| None -> return! Error.notFound next ctx
|
| None -> return! Error.notFound next ctx
|
||||||
}
|
}
|
||||||
@ -192,24 +192,24 @@ module Request =
|
|||||||
>=> fun next ctx ->
|
>=> fun next ctx ->
|
||||||
task {
|
task {
|
||||||
use sess = session ctx
|
use sess = session ctx
|
||||||
|
let usrId = userId ctx
|
||||||
let reqId = toReqId requestId
|
let reqId = toReqId requestId
|
||||||
match! sess.TryRequestById reqId (userId ctx) with
|
match! Data.tryRequestById reqId usrId sess with
|
||||||
| Some req ->
|
| Some req ->
|
||||||
let! hist = ctx.BindJsonAsync<Models.HistoryEntry> ()
|
let! hist = ctx.BindJsonAsync<Models.HistoryEntry> ()
|
||||||
let now = jsNow ()
|
let now = jsNow ()
|
||||||
let act = RequestAction.fromString hist.status
|
let act = RequestAction.fromString hist.status
|
||||||
{ History.empty with
|
Data.addHistory reqId
|
||||||
asOf = now
|
{ asOf = now
|
||||||
status = act
|
status = act
|
||||||
text = match hist.updateText with null | "" -> None | x -> Some x
|
text = match hist.updateText with null | "" -> None | x -> Some x
|
||||||
}
|
} sess
|
||||||
|> sess.AddHistory reqId
|
|
||||||
match act with
|
match act with
|
||||||
| Prayed ->
|
| Prayed ->
|
||||||
(Ticks.toLong now) + (Recurrence.duration req.recurType * int64 req.recurCount)
|
let nextShow = (Ticks.toLong now) + (Recurrence.duration req.recurType * int64 req.recurCount)
|
||||||
|> (Ticks >> sess.UpdateShowAfter reqId)
|
Data.updateShowAfter reqId (Ticks nextShow) sess
|
||||||
| _ -> ()
|
| _ -> ()
|
||||||
do! sess.SaveChangesAsync ()
|
do! Data.saveChanges sess
|
||||||
return! created next ctx
|
return! created next ctx
|
||||||
| None -> return! Error.notFound next ctx
|
| None -> return! Error.notFound next ctx
|
||||||
}
|
}
|
||||||
@ -220,12 +220,13 @@ module Request =
|
|||||||
>=> fun next ctx ->
|
>=> fun next ctx ->
|
||||||
task {
|
task {
|
||||||
use sess = session ctx
|
use sess = session ctx
|
||||||
|
let usrId = userId ctx
|
||||||
let reqId = toReqId requestId
|
let reqId = toReqId requestId
|
||||||
match! sess.TryRequestById reqId (userId ctx) with
|
match! Data.tryRequestById reqId usrId sess with
|
||||||
| Some _ ->
|
| Some _ ->
|
||||||
let! notes = ctx.BindJsonAsync<Models.NoteEntry> ()
|
let! notes = ctx.BindJsonAsync<Models.NoteEntry> ()
|
||||||
sess.AddNote reqId { asOf = jsNow (); notes = notes.notes }
|
Data.addNote reqId { asOf = jsNow (); notes = notes.notes } sess
|
||||||
do! sess.SaveChangesAsync ()
|
do! Data.saveChanges sess
|
||||||
return! created next ctx
|
return! created next ctx
|
||||||
| None -> return! Error.notFound next ctx
|
| None -> return! Error.notFound next ctx
|
||||||
}
|
}
|
||||||
@ -236,7 +237,8 @@ module Request =
|
|||||||
>=> fun next ctx ->
|
>=> fun next ctx ->
|
||||||
task {
|
task {
|
||||||
use sess = session ctx
|
use sess = session ctx
|
||||||
let! reqs = ((userId >> sess.AnsweredRequests) ctx).ToListAsync ()
|
let usrId = userId ctx
|
||||||
|
let! reqs = Data.answeredRequests usrId sess
|
||||||
return! json reqs next ctx
|
return! json reqs next ctx
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -246,7 +248,8 @@ module Request =
|
|||||||
>=> fun next ctx ->
|
>=> fun next ctx ->
|
||||||
task {
|
task {
|
||||||
use sess = session ctx
|
use sess = session ctx
|
||||||
match! sess.TryJournalById (toReqId requestId) (userId ctx) with
|
let usrId = userId ctx
|
||||||
|
match! Data.tryJournalById (toReqId requestId) usrId sess with
|
||||||
| Some req -> return! json req next ctx
|
| Some req -> return! json req next ctx
|
||||||
| None -> return! Error.notFound next ctx
|
| None -> return! Error.notFound next ctx
|
||||||
}
|
}
|
||||||
@ -257,7 +260,8 @@ module Request =
|
|||||||
>=> fun next ctx ->
|
>=> fun next ctx ->
|
||||||
task {
|
task {
|
||||||
use sess = session ctx
|
use sess = session ctx
|
||||||
match! sess.TryFullRequestById (toReqId requestId) (userId ctx) with
|
let usrId = userId ctx
|
||||||
|
match! Data.tryFullRequestById (toReqId requestId) usrId sess with
|
||||||
| Some req -> return! json req next ctx
|
| Some req -> return! json req next ctx
|
||||||
| None -> return! Error.notFound next ctx
|
| None -> return! Error.notFound next ctx
|
||||||
}
|
}
|
||||||
@ -268,7 +272,8 @@ module Request =
|
|||||||
>=> fun next ctx ->
|
>=> fun next ctx ->
|
||||||
task {
|
task {
|
||||||
use sess = session ctx
|
use sess = session ctx
|
||||||
let! notes = sess.NotesById (toReqId requestId) (userId ctx)
|
let usrId = userId ctx
|
||||||
|
let! notes = Data.notesById (toReqId requestId) usrId sess
|
||||||
return! json notes next ctx
|
return! json notes next ctx
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -278,12 +283,13 @@ module Request =
|
|||||||
>=> fun next ctx ->
|
>=> fun next ctx ->
|
||||||
task {
|
task {
|
||||||
use sess = session ctx
|
use sess = session ctx
|
||||||
|
let usrId = userId ctx
|
||||||
let reqId = toReqId requestId
|
let reqId = toReqId requestId
|
||||||
match! sess.TryRequestById reqId (userId ctx) with
|
match! Data.tryRequestById reqId usrId sess with
|
||||||
| Some _ ->
|
| Some _ ->
|
||||||
let! show = ctx.BindJsonAsync<Models.Show> ()
|
let! show = ctx.BindJsonAsync<Models.Show> ()
|
||||||
sess.UpdateShowAfter reqId (Ticks show.showAfter)
|
Data.updateShowAfter reqId (Ticks show.showAfter) sess
|
||||||
do! sess.SaveChangesAsync ()
|
do! Data.saveChanges sess
|
||||||
return! setStatusCode 204 next ctx
|
return! setStatusCode 204 next ctx
|
||||||
| None -> return! Error.notFound next ctx
|
| None -> return! Error.notFound next ctx
|
||||||
}
|
}
|
||||||
@ -294,12 +300,13 @@ module Request =
|
|||||||
>=> fun next ctx ->
|
>=> fun next ctx ->
|
||||||
task {
|
task {
|
||||||
use sess = session ctx
|
use sess = session ctx
|
||||||
|
let usrId = userId ctx
|
||||||
let reqId = toReqId requestId
|
let reqId = toReqId requestId
|
||||||
match! sess.TryRequestById reqId (userId ctx) with
|
match! Data.tryRequestById reqId usrId sess with
|
||||||
| Some _ ->
|
| Some _ ->
|
||||||
let! until = ctx.BindJsonAsync<Models.SnoozeUntil> ()
|
let! until = ctx.BindJsonAsync<Models.SnoozeUntil> ()
|
||||||
sess.UpdateSnoozed reqId (Ticks until.until)
|
Data.updateSnoozed reqId (Ticks until.until) sess
|
||||||
do! sess.SaveChangesAsync ()
|
do! Data.saveChanges sess
|
||||||
return! setStatusCode 204 next ctx
|
return! setStatusCode 204 next ctx
|
||||||
| None -> return! Error.notFound next ctx
|
| None -> return! Error.notFound next ctx
|
||||||
}
|
}
|
||||||
@ -310,12 +317,13 @@ module Request =
|
|||||||
>=> fun next ctx ->
|
>=> fun next ctx ->
|
||||||
task {
|
task {
|
||||||
use sess = session ctx
|
use sess = session ctx
|
||||||
|
let usrId = userId ctx
|
||||||
let reqId = toReqId requestId
|
let reqId = toReqId requestId
|
||||||
match! sess.TryRequestById reqId (userId ctx) with
|
match! Data.tryRequestById reqId usrId sess with
|
||||||
| Some _ ->
|
| Some _ ->
|
||||||
let! recur = ctx.BindJsonAsync<Models.Recurrence> ()
|
let! recur = ctx.BindJsonAsync<Models.Recurrence> ()
|
||||||
sess.UpdateRecurrence reqId (Recurrence.fromString recur.recurType) recur.recurCount
|
Data.updateRecurrence reqId (Recurrence.fromString recur.recurType) recur.recurCount sess
|
||||||
do! sess.SaveChangesAsync ()
|
do! Data.saveChanges sess
|
||||||
return! setStatusCode 204 next ctx
|
return! setStatusCode 204 next ctx
|
||||||
| None -> return! Error.notFound next ctx
|
| None -> return! Error.notFound next ctx
|
||||||
}
|
}
|
||||||
|
@ -27,9 +27,9 @@ module Configure =
|
|||||||
|
|
||||||
/// Configure Kestrel from appsettings.json
|
/// Configure Kestrel from appsettings.json
|
||||||
let kestrel (bldr : IWebHostBuilder) =
|
let kestrel (bldr : IWebHostBuilder) =
|
||||||
let kestrel (ctx : WebHostBuilderContext) (opts : KestrelServerOptions) =
|
let kestrelOpts (ctx : WebHostBuilderContext) (opts : KestrelServerOptions) =
|
||||||
(ctx.Configuration.GetSection >> opts.Configure >> ignore) "Kestrel"
|
(ctx.Configuration.GetSection >> opts.Configure >> ignore) "Kestrel"
|
||||||
bldr.ConfigureKestrel kestrel
|
bldr.UseKestrel().ConfigureKestrel kestrelOpts
|
||||||
|
|
||||||
/// Configure the web root directory
|
/// Configure the web root directory
|
||||||
let webRoot pathSegments (bldr : IWebHostBuilder) =
|
let webRoot pathSegments (bldr : IWebHostBuilder) =
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
{
|
{
|
||||||
"name": "my-prayer-journal",
|
"name": "my-prayer-journal",
|
||||||
"version": "1.2.2",
|
"version": "2.0.0",
|
||||||
"description": "myPrayerJournal - Front End",
|
"description": "myPrayerJournal - Front End",
|
||||||
"author": "Daniel J. Summers <daniel@bitbadger.solutions>",
|
"author": "Daniel J. Summers <daniel@bitbadger.solutions>",
|
||||||
"private": true,
|
"private": true,
|
||||||
@ -8,9 +8,9 @@
|
|||||||
"serve": "vue-cli-service serve",
|
"serve": "vue-cli-service serve",
|
||||||
"build": "vue-cli-service build --modern",
|
"build": "vue-cli-service build --modern",
|
||||||
"lint": "vue-cli-service lint",
|
"lint": "vue-cli-service lint",
|
||||||
"apistart": "cd ../api/MyPrayerJournal.Api && dotnet run",
|
"apistart": "cd ../MyPrayerJournal.Api && dotnet run",
|
||||||
"vue": "vue-cli-service build --modern && cd ../api/MyPrayerJournal.Api && dotnet run",
|
"vue": "vue-cli-service build --modern && cd ../MyPrayerJournal.Api && dotnet run",
|
||||||
"publish": "vue-cli-service build --modern && cd ../api/MyPrayerJournal.Api && dotnet publish -c Release"
|
"publish": "vue-cli-service build --modern && cd ../MyPrayerJournal.Api && dotnet publish -c Release"
|
||||||
},
|
},
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"auth0-js": "^9.7.3",
|
"auth0-js": "^9.7.3",
|
||||||
|
@ -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.requestId'
|
:key='request.Id'
|
||||||
:request='request'
|
:request='request'
|
||||||
:events='eventBus'
|
:events='eventBus'
|
||||||
:toast='toast')
|
:toast='toast')
|
||||||
|
@ -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.requestId'
|
:key='req.Id'
|
||||||
:request='req'
|
:request='req'
|
||||||
:toast='toast')
|
:toast='toast')
|
||||||
p(v-else) Loading journal...
|
p(v-else) Loading journal...
|
||||||
|
@ -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 “Answered”, it will appear here
|
No answered requests found; once you have marked one as “Answered”, it will appear here
|
||||||
request-list-item(v-for='req in requests'
|
request-list-item(v-for='req in requests'
|
||||||
:key='req.requestId'
|
:key='req.Id'
|
||||||
:request='req'
|
:request='req'
|
||||||
:toast='toast')
|
:toast='toast')
|
||||||
p(v-else) Loading answered requests...
|
p(v-else) Loading answered requests...
|
||||||
|
@ -134,7 +134,7 @@ 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.requestId === this.id)[0]
|
const req = this.journal.filter(r => r.Id === 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'
|
||||||
|
@ -85,7 +85,7 @@ export default {
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
openDialog (request) {
|
openDialog (request) {
|
||||||
this.form.requestId = request.requestId
|
this.form.requestId = request.Id
|
||||||
this.notesVisible = true
|
this.notesVisible = true
|
||||||
},
|
},
|
||||||
async saveNotes () {
|
async saveNotes () {
|
||||||
|
@ -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.requestId,
|
requestId: this.request.Id,
|
||||||
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.requestId } })
|
this.$router.push({ name: 'EditRequest', params: { id: this.request.Id } })
|
||||||
},
|
},
|
||||||
showNotes () {
|
showNotes () {
|
||||||
this.events.$emit('notes', this.request)
|
this.events.$emit('notes', this.request)
|
||||||
},
|
},
|
||||||
snooze () {
|
snooze () {
|
||||||
this.events.$emit('snooze', this.request.requestId)
|
this.events.$emit('snooze', this.request.Id)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -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.requestId,
|
requestId: this.request.Id,
|
||||||
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.requestId } })
|
this.$router.push({ name: 'EditRequest', params: { id: this.request.Id } })
|
||||||
},
|
},
|
||||||
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.Id,
|
||||||
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.requestId } })
|
this.$router.push({ name: 'FullRequest', params: { id: this.request.Id } })
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -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.requestId'
|
:key='req.Id'
|
||||||
:request='req'
|
:request='req'
|
||||||
:toast='toast')
|
:toast='toast')
|
||||||
p(v-else) Loading journal...
|
p(v-else) Loading journal...
|
||||||
|
@ -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.requestId !== request.requestId)
|
let jrnl = state.journal.filter(it => it.Id !== request.Id)
|
||||||
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.requestId === requestId) || [])[0] || {}
|
let oldReq = (state.journal.filter(req => req.Id === 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)
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
const webpack = require('webpack')
|
const webpack = require('webpack')
|
||||||
module.exports = {
|
module.exports = {
|
||||||
outputDir: '../api/MyPrayerJournal.Api/wwwroot',
|
outputDir: '../MyPrayerJournal.Api/wwwroot',
|
||||||
configureWebpack: {
|
configureWebpack: {
|
||||||
plugins: [
|
plugins: [
|
||||||
new webpack.IgnorePlugin(/^\.\/locale$/, /moment$/)
|
new webpack.IgnorePlugin(/^\.\/locale$/, /moment$/)
|
||||||
|
Loading…
Reference in New Issue
Block a user