Version 8 #43
|
@ -952,7 +952,8 @@ module PrayerRequest =
|
||||||
| Automatic, Expecting -> false
|
| Automatic, Expecting -> false
|
||||||
| Automatic, _ ->
|
| Automatic, _ ->
|
||||||
// Automatic expiration
|
// Automatic expiration
|
||||||
asOf.PlusDays -group.Preferences.DaysToExpire > req.UpdatedDate.InZone(SmallGroup.timeZone group).Date
|
Period.Between(req.UpdatedDate.InZone(SmallGroup.timeZone group).Date, asOf, PeriodUnits.Days).Days
|
||||||
|
>= group.Preferences.DaysToExpire
|
||||||
|
|
||||||
/// Is an update required for this long-term request?
|
/// Is an update required for this long-term request?
|
||||||
let updateRequired asOf group req =
|
let updateRequired asOf group req =
|
||||||
|
|
|
@ -143,6 +143,8 @@ let memberTests =
|
||||||
|
|
||||||
[<Tests>]
|
[<Tests>]
|
||||||
let prayerRequestTests =
|
let prayerRequestTests =
|
||||||
|
let instantNow = SystemClock.Instance.GetCurrentInstant
|
||||||
|
let localDateNow () = (instantNow ()).InUtc().Date
|
||||||
testList "PrayerRequest" [
|
testList "PrayerRequest" [
|
||||||
test "empty is as expected" {
|
test "empty is as expected" {
|
||||||
let mt = PrayerRequest.empty
|
let mt = PrayerRequest.empty
|
||||||
|
@ -150,8 +152,8 @@ let prayerRequestTests =
|
||||||
Expect.equal mt.RequestType CurrentRequest "The request type should have been Current"
|
Expect.equal mt.RequestType CurrentRequest "The request type should have been Current"
|
||||||
Expect.equal mt.UserId.Value Guid.Empty "The user ID should have been an empty GUID"
|
Expect.equal mt.UserId.Value Guid.Empty "The user ID should have been an empty GUID"
|
||||||
Expect.equal mt.SmallGroupId.Value Guid.Empty "The small group ID should have been an empty GUID"
|
Expect.equal mt.SmallGroupId.Value Guid.Empty "The small group ID should have been an empty GUID"
|
||||||
Expect.equal mt.EnteredDate DateTime.MinValue "The entered date should have been the minimum"
|
Expect.equal mt.EnteredDate Instant.MinValue "The entered date should have been the minimum"
|
||||||
Expect.equal mt.UpdatedDate DateTime.MinValue "The updated date should have been the minimum"
|
Expect.equal mt.UpdatedDate Instant.MinValue "The updated date should have been the minimum"
|
||||||
Expect.isNone mt.Requestor "The requestor should not exist"
|
Expect.isNone mt.Requestor "The requestor should not exist"
|
||||||
Expect.equal mt.Text "" "The request text should have been blank"
|
Expect.equal mt.Text "" "The request text should have been blank"
|
||||||
Expect.isFalse mt.NotifyChaplain "The notify chaplain flag should not have been set"
|
Expect.isFalse mt.NotifyChaplain "The notify chaplain flag should not have been set"
|
||||||
|
@ -159,62 +161,60 @@ let prayerRequestTests =
|
||||||
Expect.equal mt.User.Id.Value Guid.Empty "The user should have been an empty one"
|
Expect.equal mt.User.Id.Value Guid.Empty "The user should have been an empty one"
|
||||||
Expect.equal mt.SmallGroup.Id.Value Guid.Empty "The small group should have been an empty one"
|
Expect.equal mt.SmallGroup.Id.Value Guid.Empty "The small group should have been an empty one"
|
||||||
}
|
}
|
||||||
test "IsExpired always returns false for expecting requests" {
|
test "isExpired always returns false for expecting requests" {
|
||||||
let req = { PrayerRequest.empty with RequestType = Expecting }
|
PrayerRequest.isExpired (localDateNow ()) SmallGroup.empty
|
||||||
Expect.isFalse (req.IsExpired DateTime.Now 0) "An expecting request should never be considered expired"
|
{ PrayerRequest.empty with RequestType = Expecting }
|
||||||
|
|> Flip.Expect.isFalse "An expecting request should never be considered expired"
|
||||||
}
|
}
|
||||||
test "IsExpired always returns false for manually-expired requests" {
|
test "isExpired always returns false for manually-expired requests" {
|
||||||
let req = { PrayerRequest.empty with UpdatedDate = DateTime.Now.AddMonths -1; Expiration = Manual }
|
PrayerRequest.isExpired (localDateNow ()) SmallGroup.empty
|
||||||
Expect.isFalse (req.IsExpired DateTime.Now 4) "A never-expired request should never be considered expired"
|
{ PrayerRequest.empty with UpdatedDate = (instantNow ()) - Duration.FromDays 1; Expiration = Manual }
|
||||||
|
|> Flip.Expect.isFalse "A never-expired request should never be considered expired"
|
||||||
}
|
}
|
||||||
test "IsExpired always returns false for long term/recurring requests" {
|
test "isExpired always returns false for long term/recurring requests" {
|
||||||
let req = { PrayerRequest.empty with RequestType = LongTermRequest }
|
PrayerRequest.isExpired (localDateNow ()) SmallGroup.empty
|
||||||
Expect.isFalse (req.IsExpired DateTime.Now 0)
|
{ PrayerRequest.empty with RequestType = LongTermRequest }
|
||||||
"A recurring/long-term request should never be considered expired"
|
|> Flip.Expect.isFalse "A recurring/long-term request should never be considered expired"
|
||||||
}
|
}
|
||||||
test "IsExpired always returns true for force-expired requests" {
|
test "isExpired always returns true for force-expired requests" {
|
||||||
let req = { PrayerRequest.empty with UpdatedDate = DateTime.Now; Expiration = Forced }
|
PrayerRequest.isExpired (localDateNow ()) SmallGroup.empty
|
||||||
Expect.isTrue (req.IsExpired DateTime.Now 5) "A force-expired request should always be considered expired"
|
{ PrayerRequest.empty with UpdatedDate = (instantNow ()); Expiration = Forced }
|
||||||
|
|> Flip.Expect.isTrue "A force-expired request should always be considered expired"
|
||||||
}
|
}
|
||||||
test "IsExpired returns false for non-expired requests" {
|
test "isExpired returns false for non-expired requests" {
|
||||||
let now = DateTime.Now
|
let now = instantNow ()
|
||||||
let req = { PrayerRequest.empty with UpdatedDate = now.AddDays -5. }
|
PrayerRequest.isExpired (now.InUtc().Date) SmallGroup.empty
|
||||||
Expect.isFalse (req.IsExpired now 7) "A request updated 5 days ago should not be considered expired"
|
{ PrayerRequest.empty with UpdatedDate = now - Duration.FromDays 5 }
|
||||||
|
|> Flip.Expect.isFalse "A request updated 5 days ago should not be considered expired"
|
||||||
}
|
}
|
||||||
test "IsExpired returns true for expired requests" {
|
test "isExpired returns true for expired requests" {
|
||||||
let now = DateTime.Now
|
let now = instantNow ()
|
||||||
let req = { PrayerRequest.empty with UpdatedDate = now.AddDays -8. }
|
PrayerRequest.isExpired (now.InUtc().Date) SmallGroup.empty
|
||||||
Expect.isTrue (req.IsExpired now 7) "A request updated 8 days ago should be considered expired"
|
{ PrayerRequest.empty with UpdatedDate = now - Duration.FromDays 15 }
|
||||||
|
|> Flip.Expect.isTrue "A request updated 15 days ago should be considered expired"
|
||||||
}
|
}
|
||||||
test "IsExpired returns true for same-day expired requests" {
|
test "isExpired returns true for same-day expired requests" {
|
||||||
let now = DateTime.Now
|
let now = instantNow ()
|
||||||
let req = { PrayerRequest.empty with UpdatedDate = now.Date.AddDays(-7.).AddSeconds -1. }
|
PrayerRequest.isExpired (now.InUtc().Date) SmallGroup.empty
|
||||||
Expect.isTrue (req.IsExpired now 7)
|
{ PrayerRequest.empty with UpdatedDate = now - (Duration.FromDays 14) - (Duration.FromSeconds 1L) }
|
||||||
"A request entered a second before midnight should be considered expired"
|
|> Flip.Expect.isTrue "A request entered a second before midnight should be considered expired"
|
||||||
}
|
}
|
||||||
test "UpdateRequired returns false for expired requests" {
|
test "updateRequired returns false for expired requests" {
|
||||||
let req = { PrayerRequest.empty with Expiration = Forced }
|
PrayerRequest.updateRequired (localDateNow ()) SmallGroup.empty
|
||||||
Expect.isFalse (req.UpdateRequired DateTime.Now 7 4) "An expired request should not require an update"
|
{ PrayerRequest.empty with Expiration = Forced }
|
||||||
|
|> Flip.Expect.isFalse "An expired request should not require an update"
|
||||||
}
|
}
|
||||||
test "UpdateRequired returns false when an update is not required for an active request" {
|
test "updateRequired returns false when an update is not required for an active request" {
|
||||||
let now = DateTime.Now
|
let now = instantNow ()
|
||||||
let req =
|
PrayerRequest.updateRequired (localDateNow ()) SmallGroup.empty
|
||||||
{ PrayerRequest.empty with
|
{ PrayerRequest.empty with RequestType = LongTermRequest; UpdatedDate = now - Duration.FromDays 14 }
|
||||||
RequestType = LongTermRequest
|
|> Flip.Expect.isFalse "An active request updated 14 days ago should not require an update until 28 days"
|
||||||
UpdatedDate = now.AddDays -14.
|
|
||||||
}
|
|
||||||
Expect.isFalse (req.UpdateRequired now 7 4)
|
|
||||||
"An active request updated 14 days ago should not require an update until 28 days"
|
|
||||||
}
|
}
|
||||||
test "UpdateRequired returns true when an update is required for an active request" {
|
test "UpdateRequired returns true when an update is required for an active request" {
|
||||||
let now = DateTime.Now
|
let now = instantNow ()
|
||||||
let req =
|
PrayerRequest.updateRequired (localDateNow ()) SmallGroup.empty
|
||||||
{ PrayerRequest.empty with
|
{ PrayerRequest.empty with RequestType = LongTermRequest; UpdatedDate = now - Duration.FromDays 34 }
|
||||||
RequestType = LongTermRequest
|
|> Flip.Expect.isTrue "An active request updated 34 days ago should require an update (past 28 days)"
|
||||||
UpdatedDate = now.AddDays -34.
|
|
||||||
}
|
|
||||||
Expect.isTrue (req.UpdateRequired now 7 4)
|
|
||||||
"An active request updated 34 days ago should require an update (past 28 days)"
|
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
|
|
||||||
|
@ -288,9 +288,9 @@ let requestSortTests =
|
||||||
[<Tests>]
|
[<Tests>]
|
||||||
let smallGroupTests =
|
let smallGroupTests =
|
||||||
testList "SmallGroup" [
|
testList "SmallGroup" [
|
||||||
let now = DateTime (2017, 5, 12, 12, 15, 0, DateTimeKind.Utc)
|
let now = Instant.FromDateTimeUtc (DateTime (2017, 5, 12, 12, 15, 0, DateTimeKind.Utc))
|
||||||
let withFakeClock f () =
|
let withFakeClock f () =
|
||||||
FakeClock (Instant.FromDateTimeUtc now) |> f
|
FakeClock now |> f
|
||||||
yield test "empty is as expected" {
|
yield test "empty is as expected" {
|
||||||
let mt = SmallGroup.empty
|
let mt = SmallGroup.empty
|
||||||
Expect.equal mt.Id.Value Guid.Empty "The small group ID should have been an empty GUID"
|
Expect.equal mt.Id.Value Guid.Empty "The small group ID should have been an empty GUID"
|
||||||
|
@ -311,10 +311,12 @@ let smallGroupTests =
|
||||||
{ SmallGroup.empty with
|
{ SmallGroup.empty with
|
||||||
Preferences = { ListPreferences.empty with TimeZoneId = TimeZoneId "Europe/Berlin" }
|
Preferences = { ListPreferences.empty with TimeZoneId = TimeZoneId "Europe/Berlin" }
|
||||||
}
|
}
|
||||||
Expect.isGreaterThan (grp.LocalTimeNow clock) now "UTC to Europe/Berlin should have added hours"
|
let tz = DateTimeZoneProviders.Tzdb["Europe/Berlin"]
|
||||||
|
Expect.isGreaterThan (SmallGroup.localTimeNow clock grp) (now.InUtc().LocalDateTime)
|
||||||
|
"UTC to Europe/Berlin should have added hours"
|
||||||
"LocalTimeNow adjusts the time behind UTC",
|
"LocalTimeNow adjusts the time behind UTC",
|
||||||
fun clock ->
|
fun clock ->
|
||||||
Expect.isLessThan (SmallGroup.empty.LocalTimeNow clock) now
|
Expect.isLessThan (SmallGroup.localTimeNow clock SmallGroup.empty) (now.InUtc().LocalDateTime)
|
||||||
"UTC to America/Denver should have subtracted hours"
|
"UTC to America/Denver should have subtracted hours"
|
||||||
"LocalTimeNow returns UTC when the time zone is invalid",
|
"LocalTimeNow returns UTC when the time zone is invalid",
|
||||||
fun clock ->
|
fun clock ->
|
||||||
|
@ -322,16 +324,17 @@ let smallGroupTests =
|
||||||
{ SmallGroup.empty with
|
{ SmallGroup.empty with
|
||||||
Preferences = { ListPreferences.empty with TimeZoneId = TimeZoneId "garbage" }
|
Preferences = { ListPreferences.empty with TimeZoneId = TimeZoneId "garbage" }
|
||||||
}
|
}
|
||||||
Expect.equal (grp.LocalTimeNow clock) now "UTC should have been returned for an invalid time zone"
|
Expect.equal (SmallGroup.localTimeNow clock grp) (now.InUtc().LocalDateTime)
|
||||||
|
"UTC should have been returned for an invalid time zone"
|
||||||
]
|
]
|
||||||
yield test "LocalTimeNow fails when clock is not passed" {
|
yield test "localTimeNow fails when clock is not passed" {
|
||||||
Expect.throws (fun () -> (SmallGroup.empty.LocalTimeNow >> ignore) null)
|
Expect.throws (fun () -> (SmallGroup.localTimeNow null SmallGroup.empty |> ignore))
|
||||||
"Should have raised an exception for null clock"
|
"Should have raised an exception for null clock"
|
||||||
}
|
}
|
||||||
yield test "LocalDateNow returns the date portion" {
|
yield test "LocalDateNow returns the date portion" {
|
||||||
let now' = DateTime (2017, 5, 12, 1, 15, 0, DateTimeKind.Utc)
|
let clock = FakeClock (Instant.FromDateTimeUtc (DateTime (2017, 5, 12, 1, 15, 0, DateTimeKind.Utc)))
|
||||||
let clock = FakeClock (Instant.FromDateTimeUtc now')
|
Expect.isLessThan (SmallGroup.localDateNow clock SmallGroup.empty) (now.InUtc().Date)
|
||||||
Expect.isLessThan (SmallGroup.empty.LocalDateNow clock) now.Date "The date should have been a day earlier"
|
"The date should have been a day earlier"
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
|
|
||||||
|
|
|
@ -3,6 +3,7 @@
|
||||||
open System
|
open System
|
||||||
open Expecto
|
open Expecto
|
||||||
open Microsoft.AspNetCore.Html
|
open Microsoft.AspNetCore.Html
|
||||||
|
open NodaTime
|
||||||
open PrayerTracker.Entities
|
open PrayerTracker.Entities
|
||||||
open PrayerTracker.Tests.TestLocalization
|
open PrayerTracker.Tests.TestLocalization
|
||||||
open PrayerTracker.Utils
|
open PrayerTracker.Utils
|
||||||
|
@ -121,7 +122,7 @@ let appViewInfoTests =
|
||||||
Expect.isNone vi.HelpLink "The help link should have been set to none"
|
Expect.isNone vi.HelpLink "The help link should have been set to none"
|
||||||
Expect.isEmpty vi.Messages "There should have been no messages set"
|
Expect.isEmpty vi.Messages "There should have been no messages set"
|
||||||
Expect.equal vi.Version "" "The version should have been blank"
|
Expect.equal vi.Version "" "The version should have been blank"
|
||||||
Expect.isGreaterThan vi.RequestStart DateTime.MinValue.Ticks "The request start time should have been set"
|
Expect.equal vi.RequestStart Instant.MinValue "The request start time should have been the minimum value"
|
||||||
Expect.isNone vi.User "There should not have been a user"
|
Expect.isNone vi.User "There should not have been a user"
|
||||||
Expect.isNone vi.Group "There should not have been a small group"
|
Expect.isNone vi.Group "There should not have been a small group"
|
||||||
}
|
}
|
||||||
|
@ -497,26 +498,27 @@ let messageLevelTests =
|
||||||
let requestListTests =
|
let requestListTests =
|
||||||
testList "RequestList" [
|
testList "RequestList" [
|
||||||
let withRequestList f () =
|
let withRequestList f () =
|
||||||
|
let today = SystemClock.Instance.GetCurrentInstant ()
|
||||||
{ Requests = [
|
{ Requests = [
|
||||||
{ PrayerRequest.empty with
|
{ PrayerRequest.empty with
|
||||||
RequestType = CurrentRequest
|
RequestType = CurrentRequest
|
||||||
Requestor = Some "Zeb"
|
Requestor = Some "Zeb"
|
||||||
Text = "zyx"
|
Text = "zyx"
|
||||||
UpdatedDate = DateTime.Today
|
UpdatedDate = today
|
||||||
}
|
}
|
||||||
{ PrayerRequest.empty with
|
{ PrayerRequest.empty with
|
||||||
RequestType = CurrentRequest
|
RequestType = CurrentRequest
|
||||||
Requestor = Some "Aaron"
|
Requestor = Some "Aaron"
|
||||||
Text = "abc"
|
Text = "abc"
|
||||||
UpdatedDate = DateTime.Today - TimeSpan.FromDays 9.
|
UpdatedDate = today - Duration.FromDays 9
|
||||||
}
|
}
|
||||||
{ PrayerRequest.empty with
|
{ PrayerRequest.empty with
|
||||||
RequestType = PraiseReport
|
RequestType = PraiseReport
|
||||||
Text = "nmo"
|
Text = "nmo"
|
||||||
UpdatedDate = DateTime.Today
|
UpdatedDate = today
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
Date = DateTime.Today
|
Date = today.InUtc().Date
|
||||||
SmallGroup = SmallGroup.empty
|
SmallGroup = SmallGroup.empty
|
||||||
ShowHeader = false
|
ShowHeader = false
|
||||||
Recipients = []
|
Recipients = []
|
||||||
|
@ -574,7 +576,7 @@ let requestListTests =
|
||||||
[ """<div style="text-align:center;font-family:Century Gothic,Tahoma,Luxi Sans,sans-serif">"""
|
[ """<div style="text-align:center;font-family:Century Gothic,Tahoma,Luxi Sans,sans-serif">"""
|
||||||
"""<span style="font-size:16pt;"><strong>Prayer Requests</strong></span><br>"""
|
"""<span style="font-size:16pt;"><strong>Prayer Requests</strong></span><br>"""
|
||||||
"""<span style="font-size:12pt;"><strong>Test HTML Group</strong><br>"""
|
"""<span style="font-size:12pt;"><strong>Test HTML Group</strong><br>"""
|
||||||
htmlList.Date.ToString "MMMM d, yyyy"
|
htmlList.Date.ToString ("MMMM d, yyyy", null)
|
||||||
"</span></div><br>"
|
"</span></div><br>"
|
||||||
]
|
]
|
||||||
|> String.concat ""
|
|> String.concat ""
|
||||||
|
@ -592,7 +594,7 @@ let requestListTests =
|
||||||
}
|
}
|
||||||
let html = htmlList.AsHtml _s
|
let html = htmlList.AsHtml _s
|
||||||
let expected =
|
let expected =
|
||||||
htmlList.Requests[0].UpdatedDate.ToShortDateString ()
|
htmlList.Requests[0].UpdatedDate.InUtc().Date.ToString ("d", null)
|
||||||
|> sprintf """<strong>Zeb</strong> — zyx<i style="font-size:9.60pt"> (as of %s)</i>"""
|
|> sprintf """<strong>Zeb</strong> — zyx<i style="font-size:9.60pt"> (as of %s)</i>"""
|
||||||
// spot check; if one request has it, they all should
|
// spot check; if one request has it, they all should
|
||||||
Expect.stringContains html expected "Expected short as-of date not found"
|
Expect.stringContains html expected "Expected short as-of date not found"
|
||||||
|
@ -607,7 +609,7 @@ let requestListTests =
|
||||||
}
|
}
|
||||||
let html = htmlList.AsHtml _s
|
let html = htmlList.AsHtml _s
|
||||||
let expected =
|
let expected =
|
||||||
htmlList.Requests[0].UpdatedDate.ToLongDateString ()
|
htmlList.Requests[0].UpdatedDate.InUtc().Date.ToString ("D", null)
|
||||||
|> sprintf """<strong>Zeb</strong> — zyx<i style="font-size:9.60pt"> (as of %s)</i>"""
|
|> sprintf """<strong>Zeb</strong> — zyx<i style="font-size:9.60pt"> (as of %s)</i>"""
|
||||||
// spot check; if one request has it, they all should
|
// spot check; if one request has it, they all should
|
||||||
Expect.stringContains html expected "Expected long as-of date not found"
|
Expect.stringContains html expected "Expected long as-of date not found"
|
||||||
|
@ -617,7 +619,8 @@ let requestListTests =
|
||||||
let text = textList.AsText _s
|
let text = textList.AsText _s
|
||||||
Expect.stringContains text $"{textList.SmallGroup.Name}\n" "Small group name not found"
|
Expect.stringContains text $"{textList.SmallGroup.Name}\n" "Small group name not found"
|
||||||
Expect.stringContains text "Prayer Requests\n" "List heading not found"
|
Expect.stringContains text "Prayer Requests\n" "List heading not found"
|
||||||
Expect.stringContains text ((textList.Date.ToString "MMMM d, yyyy") + "\n \n") "List date not found"
|
Expect.stringContains text ((textList.Date.ToString ("MMMM d, yyyy", null)) + "\n \n")
|
||||||
|
"List date not found"
|
||||||
Expect.stringContains text "--------------------\n CURRENT REQUESTS\n--------------------\n"
|
Expect.stringContains text "--------------------\n CURRENT REQUESTS\n--------------------\n"
|
||||||
"""Heading for category "Current Requests" not found"""
|
"""Heading for category "Current Requests" not found"""
|
||||||
Expect.stringContains text " + Zeb - zyx\n" "First request not found"
|
Expect.stringContains text " + Zeb - zyx\n" "First request not found"
|
||||||
|
@ -637,7 +640,7 @@ let requestListTests =
|
||||||
}
|
}
|
||||||
let text = textList.AsText _s
|
let text = textList.AsText _s
|
||||||
let expected =
|
let expected =
|
||||||
textList.Requests[0].UpdatedDate.ToShortDateString ()
|
textList.Requests[0].UpdatedDate.InUtc().Date.ToString ("d", null)
|
||||||
|> sprintf " + Zeb - zyx (as of %s)"
|
|> sprintf " + Zeb - zyx (as of %s)"
|
||||||
// spot check; if one request has it, they all should
|
// spot check; if one request has it, they all should
|
||||||
Expect.stringContains text expected "Expected short as-of date not found"
|
Expect.stringContains text expected "Expected short as-of date not found"
|
||||||
|
@ -652,7 +655,7 @@ let requestListTests =
|
||||||
}
|
}
|
||||||
let text = textList.AsText _s
|
let text = textList.AsText _s
|
||||||
let expected =
|
let expected =
|
||||||
textList.Requests[0].UpdatedDate.ToLongDateString ()
|
textList.Requests[0].UpdatedDate.InUtc().Date.ToString ("D", null)
|
||||||
|> sprintf " + Zeb - zyx (as of %s)"
|
|> sprintf " + Zeb - zyx (as of %s)"
|
||||||
// spot check; if one request has it, they all should
|
// spot check; if one request has it, they all should
|
||||||
Expect.stringContains text expected "Expected long as-of date not found"
|
Expect.stringContains text expected "Expected long as-of date not found"
|
||||||
|
|
|
@ -38,15 +38,13 @@ let edit (model : EditRequest) today ctx viewInfo =
|
||||||
inputField "date" (nameof model.EnteredDate) "" [ _placeholder today ]
|
inputField "date" (nameof model.EnteredDate) "" [ _placeholder today ]
|
||||||
]
|
]
|
||||||
else
|
else
|
||||||
// TODO: do these need to be nested like this?
|
|
||||||
div [ _inputField ] [
|
div [ _inputField ] [
|
||||||
div [ _checkboxField ] [
|
|
||||||
br []
|
br []
|
||||||
|
div [ _checkboxField ] [
|
||||||
inputField "checkbox" (nameof model.SkipDateUpdate) "True" []
|
inputField "checkbox" (nameof model.SkipDateUpdate) "True" []
|
||||||
label [ _for (nameof model.SkipDateUpdate) ] [ locStr s["Check to not update the date"] ]
|
label [ _for (nameof model.SkipDateUpdate) ] [ locStr s["Check to not update the date"] ]
|
||||||
br []
|
|
||||||
small [] [ em [] [ str (s["Typo Corrections"].Value.ToLower ()); rawText ", etc." ] ]
|
|
||||||
]
|
]
|
||||||
|
small [] [ em [] [ str (s["Typo Corrections"].Value.ToLower ()); rawText ", etc." ] ]
|
||||||
]
|
]
|
||||||
]
|
]
|
||||||
div [ _fieldRow ] [
|
div [ _fieldRow ] [
|
||||||
|
@ -57,7 +55,7 @@ let edit (model : EditRequest) today ctx viewInfo =
|
||||||
let radioId = String.concat "_" [ nameof model.Expiration; fst exp ]
|
let radioId = String.concat "_" [ nameof model.Expiration; fst exp ]
|
||||||
span [ _class "text-nowrap" ] [
|
span [ _class "text-nowrap" ] [
|
||||||
radio (nameof model.Expiration) radioId (fst exp) model.Expiration
|
radio (nameof model.Expiration) radioId (fst exp) model.Expiration
|
||||||
label [ _for radioId ] [ locStr (snd exp) ]
|
label [ _for radioId ] [ space; locStr (snd exp) ]
|
||||||
rawText " "
|
rawText " "
|
||||||
])
|
])
|
||||||
|> div [ _class "pt-center-text" ]
|
|> div [ _class "pt-center-text" ]
|
||||||
|
|
|
@ -768,7 +768,7 @@ with
|
||||||
/// Is this request new?
|
/// Is this request new?
|
||||||
member this.IsNew (req : PrayerRequest) =
|
member this.IsNew (req : PrayerRequest) =
|
||||||
let reqDate = req.UpdatedDate.InZone(SmallGroup.timeZone this.SmallGroup).Date
|
let reqDate = req.UpdatedDate.InZone(SmallGroup.timeZone this.SmallGroup).Date
|
||||||
Period.Between(this.Date, reqDate, PeriodUnits.Days).Days <= this.SmallGroup.Preferences.DaysToKeepNew
|
Period.Between(reqDate, this.Date, PeriodUnits.Days).Days <= this.SmallGroup.Preferences.DaysToKeepNew
|
||||||
|
|
||||||
/// Generate this list as HTML
|
/// Generate this list as HTML
|
||||||
member this.AsHtml (s : IStringLocalizer) =
|
member this.AsHtml (s : IStringLocalizer) =
|
||||||
|
@ -797,6 +797,7 @@ with
|
||||||
]
|
]
|
||||||
]
|
]
|
||||||
]
|
]
|
||||||
|
let tz = SmallGroup.timeZone this.SmallGroup
|
||||||
reqs
|
reqs
|
||||||
|> List.map (fun req ->
|
|> List.map (fun req ->
|
||||||
let bullet = if this.IsNew req then "circle" else "disc"
|
let bullet = if this.IsNew req then "circle" else "disc"
|
||||||
|
@ -804,7 +805,7 @@ with
|
||||||
match req.Requestor with
|
match req.Requestor with
|
||||||
| Some r when r <> "" ->
|
| Some r when r <> "" ->
|
||||||
strong [] [ str r ]
|
strong [] [ str r ]
|
||||||
rawText " — "
|
rawText " – "
|
||||||
| Some _ -> ()
|
| Some _ -> ()
|
||||||
| None -> ()
|
| None -> ()
|
||||||
rawText req.Text
|
rawText req.Text
|
||||||
|
@ -814,8 +815,8 @@ with
|
||||||
| LongDate ->
|
| LongDate ->
|
||||||
let dt =
|
let dt =
|
||||||
match p.AsOfDateDisplay with
|
match p.AsOfDateDisplay with
|
||||||
| ShortDate -> req.UpdatedDate.ToString ("d", null)
|
| ShortDate -> req.UpdatedDate.InZone(tz).Date.ToString ("d", null)
|
||||||
| LongDate -> req.UpdatedDate.ToString ("D", null)
|
| LongDate -> req.UpdatedDate.InZone(tz).Date.ToString ("D", null)
|
||||||
| _ -> ""
|
| _ -> ""
|
||||||
i [ _style $"font-size:%.2f{asOfSize}pt" ] [
|
i [ _style $"font-size:%.2f{asOfSize}pt" ] [
|
||||||
rawText " ("; str s["as of"].Value; str " "; str dt; rawText ")"
|
rawText " ("; str s["as of"].Value; str " "; str dt; rawText ")"
|
||||||
|
@ -828,6 +829,7 @@ with
|
||||||
|
|
||||||
/// Generate this list as plain text
|
/// Generate this list as plain text
|
||||||
member this.AsText (s : IStringLocalizer) =
|
member this.AsText (s : IStringLocalizer) =
|
||||||
|
let tz = SmallGroup.timeZone this.SmallGroup
|
||||||
seq {
|
seq {
|
||||||
this.SmallGroup.Name
|
this.SmallGroup.Name
|
||||||
s["Prayer Requests"].Value
|
s["Prayer Requests"].Value
|
||||||
|
@ -846,8 +848,8 @@ with
|
||||||
| _ ->
|
| _ ->
|
||||||
let dt =
|
let dt =
|
||||||
match this.SmallGroup.Preferences.AsOfDateDisplay with
|
match this.SmallGroup.Preferences.AsOfDateDisplay with
|
||||||
| ShortDate -> req.UpdatedDate.ToString ("d", null)
|
| ShortDate -> req.UpdatedDate.InZone(tz).Date.ToString ("d", null)
|
||||||
| LongDate -> req.UpdatedDate.ToString ("D", null)
|
| LongDate -> req.UpdatedDate.InZone(tz).Date.ToString ("D", null)
|
||||||
| _ -> ""
|
| _ -> ""
|
||||||
$""" ({s["as of"].Value} {dt})"""
|
$""" ({s["as of"].Value} {dt})"""
|
||||||
|> sprintf " %s %s%s%s" bullet requestor (htmlToPlainText req.Text)
|
|> sprintf " %s %s%s%s" bullet requestor (htmlToPlainText req.Text)
|
||||||
|
|
|
@ -4,19 +4,26 @@ module PrayerTracker.Extensions
|
||||||
open Microsoft.AspNetCore.Http
|
open Microsoft.AspNetCore.Http
|
||||||
open Microsoft.FSharpLu
|
open Microsoft.FSharpLu
|
||||||
open Newtonsoft.Json
|
open Newtonsoft.Json
|
||||||
|
open NodaTime
|
||||||
|
open NodaTime.Serialization.JsonNet
|
||||||
open PrayerTracker.Entities
|
open PrayerTracker.Entities
|
||||||
open PrayerTracker.ViewModels
|
open PrayerTracker.ViewModels
|
||||||
|
|
||||||
|
/// JSON.NET serializer settings for NodaTime
|
||||||
|
let private jsonSettings = JsonSerializerSettings().ConfigureForNodaTime DateTimeZoneProviders.Tzdb
|
||||||
|
|
||||||
/// Extensions on the .NET session object
|
/// Extensions on the .NET session object
|
||||||
type ISession with
|
type ISession with
|
||||||
|
|
||||||
/// Set an object in the session
|
/// Set an object in the session
|
||||||
member this.SetObject key value =
|
member this.SetObject key value =
|
||||||
this.SetString (key, JsonConvert.SerializeObject value)
|
this.SetString (key, JsonConvert.SerializeObject (value, jsonSettings))
|
||||||
|
|
||||||
/// Get an object from the session
|
/// Get an object from the session
|
||||||
member this.GetObject<'T> key =
|
member this.GetObject<'T> key =
|
||||||
match this.GetString key with null -> Unchecked.defaultof<'T> | v -> JsonConvert.DeserializeObject<'T> v
|
match this.GetString key with
|
||||||
|
| null -> Unchecked.defaultof<'T>
|
||||||
|
| v -> JsonConvert.DeserializeObject<'T> (v, jsonSettings)
|
||||||
|
|
||||||
/// The currently logged on small group
|
/// The currently logged on small group
|
||||||
member this.CurrentGroup
|
member this.CurrentGroup
|
||||||
|
@ -63,7 +70,6 @@ type ClaimsPrincipal with
|
||||||
|
|
||||||
|
|
||||||
open Giraffe
|
open Giraffe
|
||||||
open NodaTime
|
|
||||||
open PrayerTracker
|
open PrayerTracker
|
||||||
|
|
||||||
/// Extensions on the ASP.NET Core HTTP context
|
/// Extensions on the ASP.NET Core HTTP context
|
||||||
|
|
|
@ -27,6 +27,7 @@
|
||||||
<PackageReference Include="Giraffe" Version="6.0.0" />
|
<PackageReference Include="Giraffe" Version="6.0.0" />
|
||||||
<PackageReference Include="Giraffe.Htmx" Version="1.8.0" />
|
<PackageReference Include="Giraffe.Htmx" Version="1.8.0" />
|
||||||
<PackageReference Include="NeoSmart.Caching.Sqlite" Version="6.0.1" />
|
<PackageReference Include="NeoSmart.Caching.Sqlite" Version="6.0.1" />
|
||||||
|
<PackageReference Include="NodaTime.Serialization.JsonNet" Version="3.0.0" />
|
||||||
<PackageReference Include="Npgsql.EntityFrameworkCore.PostgreSQL" Version="6.0.6" />
|
<PackageReference Include="Npgsql.EntityFrameworkCore.PostgreSQL" Version="6.0.6" />
|
||||||
<PackageReference Update="FSharp.Core" Version="6.0.5" />
|
<PackageReference Update="FSharp.Core" Version="6.0.5" />
|
||||||
<PackageReference Include="Npgsql.EntityFrameworkCore.PostgreSQL.NodaTime" Version="6.0.6" />
|
<PackageReference Include="Npgsql.EntityFrameworkCore.PostgreSQL.NodaTime" Version="6.0.6" />
|
||||||
|
|
|
@ -238,6 +238,7 @@ footer a:hover {
|
||||||
flex-flow: row wrap;
|
flex-flow: row wrap;
|
||||||
align-items: center;
|
align-items: center;
|
||||||
justify-content: center;
|
justify-content: center;
|
||||||
|
gap: 2rem;
|
||||||
}
|
}
|
||||||
.pt-field {
|
.pt-field {
|
||||||
display: flex;
|
display: flex;
|
||||||
|
@ -255,9 +256,6 @@ footer a:hover {
|
||||||
text-transform: uppercase;
|
text-transform: uppercase;
|
||||||
color: #777;
|
color: #777;
|
||||||
}
|
}
|
||||||
.pt-field ~ .pt-field {
|
|
||||||
margin-left: 3rem;
|
|
||||||
}
|
|
||||||
.pt-center-text {
|
.pt-center-text {
|
||||||
text-align: center;
|
text-align: center;
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue
Block a user