Feature parity achieved

The F#/Giraffe API backend now does everything the Go one did; now to finish request snoozing...
This commit is contained in:
Daniel J. Summers 2018-08-05 20:16:18 -05:00
parent 07226f8cd8
commit f6881afaa5
4 changed files with 23 additions and 27 deletions

View File

@ -37,8 +37,6 @@ module Entities =
status : string status : string
/// The text of the update, if applicable /// The text of the update, if applicable
text : string option text : string option
/// The request to which this history entry applies
request : Request
} }
with with
/// An empty history entry /// An empty history entry
@ -47,7 +45,6 @@ module Entities =
asOf = 0L asOf = 0L
status = "" status = ""
text = None text = None
request = Request.empty
} }
static member configureEF (mb : ModelBuilder) = static member configureEF (mb : ModelBuilder) =
@ -58,11 +55,7 @@ module Entities =
m.Property(fun e -> e.requestId).IsRequired () |> ignore m.Property(fun e -> e.requestId).IsRequired () |> ignore
m.Property(fun e -> e.asOf).IsRequired () |> ignore m.Property(fun e -> e.asOf).IsRequired () |> ignore
m.Property(fun e -> e.status).IsRequired() |> ignore m.Property(fun e -> e.status).IsRequired() |> ignore
m.Property(fun e -> e.text) |> ignore m.Property(fun e -> e.text) |> ignore)
m.HasOne(fun e -> e.request)
.WithMany(fun r -> r.history :> IEnumerable<History>)
.HasForeignKey(fun e -> e.requestId :> obj)
|> ignore)
|> ignore |> ignore
let typ = mb.Model.FindEntityType(typeof<History>) let typ = mb.Model.FindEntityType(typeof<History>)
let prop = typ.FindProperty("text") let prop = typ.FindProperty("text")
@ -76,8 +69,6 @@ module Entities =
asOf : int64 asOf : int64
/// The text of the notes /// The text of the notes
notes : string notes : string
/// The request to which this note applies
request : Request
} }
with with
/// An empty note /// An empty note
@ -85,7 +76,6 @@ module Entities =
{ requestId = "" { requestId = ""
asOf = 0L asOf = 0L
notes = "" notes = ""
request = Request.empty
} }
static member configureEF (mb : ModelBuilder) = static member configureEF (mb : ModelBuilder) =
@ -95,11 +85,7 @@ module Entities =
m.HasKey ("requestId", "asOf") |> ignore m.HasKey ("requestId", "asOf") |> ignore
m.Property(fun e -> e.requestId).IsRequired () |> ignore m.Property(fun e -> e.requestId).IsRequired () |> ignore
m.Property(fun e -> e.asOf).IsRequired () |> ignore m.Property(fun e -> e.asOf).IsRequired () |> ignore
m.Property(fun e -> e.notes).IsRequired () |> ignore m.Property(fun e -> e.notes).IsRequired () |> ignore)
m.HasOne(fun e -> e.request)
.WithMany(fun r -> r.notes :> IEnumerable<Note>)
.HasForeignKey(fun e -> e.requestId :> obj)
|> ignore)
|> ignore |> ignore
// Request is the identifying record for a prayer request. // Request is the identifying record for a prayer request.
@ -136,7 +122,15 @@ module Entities =
m.Property(fun e -> e.requestId).IsRequired () |> ignore m.Property(fun e -> e.requestId).IsRequired () |> ignore
m.Property(fun e -> e.enteredOn).IsRequired () |> ignore m.Property(fun e -> e.enteredOn).IsRequired () |> ignore
m.Property(fun e -> e.userId).IsRequired () |> ignore m.Property(fun e -> e.userId).IsRequired () |> ignore
m.Property(fun e -> e.snoozedUntil).IsRequired () |> ignore) m.Property(fun e -> e.snoozedUntil).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 |> ignore
/// 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
@ -230,7 +224,7 @@ type AppDbContext (opts : DbContextOptions<AppDbContext>) =
member this.JournalByUserId userId : JournalRequest seq = member this.JournalByUserId userId : JournalRequest seq =
upcast this.Journal upcast this.Journal
.Where(fun r -> r.userId = userId && r.lastStatus <> "Answered") .Where(fun r -> r.userId = userId && r.lastStatus <> "Answered")
.OrderByDescending(fun r -> r.asOf) .OrderBy(fun r -> r.asOf)
/// Retrieve a request by its ID and user ID /// Retrieve a request by its ID and user ID
member this.TryRequestById reqId userId : Task<Request option> = member this.TryRequestById reqId userId : Task<Request option> =

View File

@ -54,7 +54,7 @@ module private Helpers =
/// The "now" time in JavaScript /// The "now" time in JavaScript
let jsNow () = let jsNow () =
DateTime.Now.Subtract(DateTime (1970, 1, 1)).TotalSeconds |> int64 |> (*) 1000L DateTime.UtcNow.Subtract(DateTime (1970, 1, 1, 0, 0, 0)).TotalSeconds |> int64 |> (*) 1000L
/// Handler to return a 403 Not Authorized reponse /// Handler to return a 403 Not Authorized reponse
let notAuthorized : HttpHandler = let notAuthorized : HttpHandler =
@ -102,6 +102,7 @@ module Models =
until : int64 until : int64
} }
/// /api/journal URLs /// /api/journal URLs
module Journal = module Journal =
@ -206,7 +207,7 @@ module Request =
authorize authorize
>=> fun next ctx -> >=> fun next ctx ->
task { task {
let! req = (db ctx).TryRequestById reqId (userId ctx) let! req = (db ctx).TryJournalById reqId (userId ctx)
match req with match req with
| Some r -> return! json r next ctx | Some r -> return! json r next ctx
| None -> return! Error.notFound next ctx | None -> return! Error.notFound next ctx

View File

@ -10,6 +10,7 @@ article
b-table(small hover :fields='fields' :items='log') b-table(small hover :fields='fields' :items='log')
template(slot='action' scope='data'). template(slot='action' scope='data').
{{ data.item.status }} on #[span.text-nowrap {{ formatDate(data.item.asOf) }}] {{ data.item.status }} on #[span.text-nowrap {{ formatDate(data.item.asOf) }}]
template(slot='text' scope='data' v-if='data.item.text') {{ data.item.text.fields[0] }}
</template> </template>
<script> <script>
@ -44,12 +45,12 @@ export default {
}, },
lastText () { lastText () {
return this.request.history return this.request.history
.filter(hist => hist.text > '') .filter(hist => hist.text)
.sort(asOfDesc)[0].text .sort(asOfDesc)[0].text.fields[0]
}, },
log () { log () {
return (this.request.notes || []) return (this.request.notes || [])
.map(note => ({ asOf: note.asOf, text: note.notes, status: 'Notes' })) .map(note => ({ asOf: note.asOf, text: { case: 'Some', fields: [ note.notes ] }, status: 'Notes' }))
.concat(this.request.history) .concat(this.request.history)
.sort(asOfDesc) .sort(asOfDesc)
.slice(1) .slice(1)

View File

@ -2,8 +2,8 @@
b-list-group-item b-list-group-item
| {{ history.status }} | {{ history.status }}
| |
small.text-muted {{ asOf }} small.text-muted(:title='actualDate') {{ asOf }}
div(v-if='hasText').mpj-request-text {{ history.text }} div(v-if='history.text').mpj-request-text {{ history.text.fields[0] }}
</template> </template>
<script> <script>
@ -20,8 +20,8 @@ export default {
asOf () { asOf () {
return moment(this.history.asOf).fromNow() return moment(this.history.asOf).fromNow()
}, },
hasText () { actualDate () {
return this.history.text.length > 0 return moment(this.history.asOf).format('LLLL')
} }
} }
} }