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:
Daniel J. Summers 2019-07-30 23:56:34 -05:00
parent 87ce966ca1
commit c587d9772f
15 changed files with 179 additions and 310 deletions

View File

@ -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
}
*)

View File

@ -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
}

View File

@ -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
} }

View File

@ -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) =
@ -176,6 +176,6 @@ module Program =
[<EntryPoint>] [<EntryPoint>]
let main _ = let main _ =
let appRoot = Directory.GetCurrentDirectory () let appRoot = Directory.GetCurrentDirectory ()
use host = WebHostBuilder () |> (Configure.webHost appRoot [| "wwwroot" |] >> Configure.buildHost) use host = WebHostBuilder() |> (Configure.webHost appRoot [| "wwwroot" |] >> Configure.buildHost)
host.Run () host.Run ()
exitCode exitCode

View File

@ -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",

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.requestId' :key='request.Id'
: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.requestId' :key='req.Id'
: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.requestId' :key='req.Id'
:request='req' :request='req'
:toast='toast') :toast='toast')
p(v-else) Loading answered requests... p(v-else) Loading answered requests...

View File

@ -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'

View File

@ -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 () {

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.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)
} }
} }
} }

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.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 } })
} }
} }
} }

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.requestId' :key='req.Id'
: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.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)

View File

@ -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$/)