]
let requestListTests =
- testList "RequestList" [
- let withRequestList f () =
- { requests = [
- { PrayerRequest.empty with
- requestType = CurrentRequest
- requestor = Some "Zeb"
- text = "zyx"
- updatedDate = DateTime.Today
- }
- { PrayerRequest.empty with
- requestType = CurrentRequest
- requestor = Some "Aaron"
- text = "abc"
- updatedDate = DateTime.Today - TimeSpan.FromDays 9.
- }
- { PrayerRequest.empty with
- requestType = PraiseReport
- text = "nmo"
- updatedDate = DateTime.Today
+ testList "RequestList" [
+ let withRequestList f () =
+ { Requests = [
+ { PrayerRequest.empty with
+ requestType = CurrentRequest
+ requestor = Some "Zeb"
+ text = "zyx"
+ updatedDate = DateTime.Today
+ }
+ { PrayerRequest.empty with
+ requestType = CurrentRequest
+ requestor = Some "Aaron"
+ text = "abc"
+ updatedDate = DateTime.Today - TimeSpan.FromDays 9.
+ }
+ { PrayerRequest.empty with
+ requestType = PraiseReport
+ text = "nmo"
+ updatedDate = DateTime.Today
+ }
+ ]
+ Date = DateTime.Today
+ SmallGroup = SmallGroup.empty
+ ShowHeader = false
+ Recipients = []
+ CanEmail = false
}
+ |> f
+ yield! testFixture withRequestList [
+ "AsHtml succeeds without header or as-of date",
+ fun reqList ->
+ let htmlList = { reqList with SmallGroup = { reqList.SmallGroup with name = "Test HTML Group" } }
+ let html = htmlList.AsHtml _s
+ Expect.equal -1 (html.IndexOf "Test HTML Group")
+ "The small group name should not have existed (no header)"
+ let curReqHeading =
+ [ """"""
+ ""
+ """"""
+ " Current Requests |
"
+ ]
+ |> String.concat ""
+ Expect.stringContains html curReqHeading """Heading for category "Current Requests" not found"""
+ let curReqHtml =
+ [ ""
+ """- """
+ "Zeb — zyx
"
+ """- """
+ "Aaron — abc
"
+ ]
+ |> String.concat ""
+ Expect.stringContains html curReqHtml """Expected HTML for "Current Requests" requests not found"""
+ let praiseHeading =
+ [ """"""
+ ""
+ """"""
+ " Praise Reports |
"
+ ]
+ |> String.concat ""
+ Expect.stringContains html praiseHeading """Heading for category "Praise Reports" not found"""
+ let praiseHtml =
+ [ ""
+ ]
+ |> String.concat ""
+ Expect.stringContains html praiseHtml """Expected HTML for "Praise Reports" requests not found"""
+ "AsHtml succeeds with header",
+ fun reqList ->
+ let htmlList =
+ { reqList with
+ SmallGroup = { reqList.SmallGroup with name = "Test HTML Group" }
+ ShowHeader = true
+ }
+ let html = htmlList.AsHtml _s
+ let lstHeading =
+ [ """"""
+ """Prayer Requests
"""
+ """Test HTML Group
"""
+ htmlList.Date.ToString "MMMM d, yyyy"
+ "
"
+ ]
+ |> String.concat ""
+ Expect.stringContains html lstHeading "Expected HTML for the list heading not found"
+ // spot check; without header test tests this exhaustively
+ Expect.stringContains html "Zeb — zyx" "Expected requests not found"
+ "AsHtml succeeds with short as-of date",
+ fun reqList ->
+ let htmlList =
+ { reqList with
+ SmallGroup =
+ { reqList.SmallGroup with
+ preferences = { reqList.SmallGroup.preferences with asOfDateDisplay = ShortDate }
+ }
+ }
+ let html = htmlList.AsHtml _s
+ let expected =
+ htmlList.Requests[0].updatedDate.ToShortDateString ()
+ |> sprintf """Zeb — zyx (as of %s)"""
+ // spot check; if one request has it, they all should
+ Expect.stringContains html expected "Expected short as-of date not found"
+ "AsHtml succeeds with long as-of date",
+ fun reqList ->
+ let htmlList =
+ { reqList with
+ SmallGroup =
+ { reqList.SmallGroup with
+ preferences = { reqList.SmallGroup.preferences with asOfDateDisplay = LongDate }
+ }
+ }
+ let html = htmlList.AsHtml _s
+ let expected =
+ htmlList.Requests[0].updatedDate.ToLongDateString ()
+ |> sprintf """Zeb — zyx (as of %s)"""
+ // spot check; if one request has it, they all should
+ Expect.stringContains html expected "Expected long as-of date not found"
+ "AsText succeeds with no as-of date",
+ fun reqList ->
+ let textList = { reqList with SmallGroup = { reqList.SmallGroup with name = "Test Group" } }
+ let text = textList.AsText _s
+ 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 ((textList.Date.ToString "MMMM d, yyyy") + "\n \n") "List date not found"
+ Expect.stringContains text "--------------------\n CURRENT REQUESTS\n--------------------\n"
+ """Heading for category "Current Requests" not found"""
+ Expect.stringContains text " + Zeb - zyx\n" "First request not found"
+ Expect.stringContains text " - Aaron - abc\n \n"
+ "Second request not found; should have been end of category"
+ Expect.stringContains text "------------------\n PRAISE REPORTS\n------------------\n"
+ """Heading for category "Praise Reports" not found"""
+ Expect.stringContains text " + nmo\n \n" "Last request not found"
+ "AsText succeeds with short as-of date",
+ fun reqList ->
+ let textList =
+ { reqList with
+ SmallGroup =
+ { reqList.SmallGroup with
+ preferences = { reqList.SmallGroup.preferences with asOfDateDisplay = ShortDate }
+ }
+ }
+ let text = textList.AsText _s
+ let expected =
+ textList.Requests[0].updatedDate.ToShortDateString ()
+ |> sprintf " + Zeb - zyx (as of %s)"
+ // spot check; if one request has it, they all should
+ Expect.stringContains text expected "Expected short as-of date not found"
+ "AsText succeeds with long as-of date",
+ fun reqList ->
+ let textList =
+ { reqList with
+ SmallGroup =
+ { reqList.SmallGroup with
+ preferences = { reqList.SmallGroup.preferences with asOfDateDisplay = LongDate }
+ }
+ }
+ let text = textList.AsText _s
+ let expected =
+ textList.Requests[0].updatedDate.ToLongDateString ()
+ |> sprintf " + Zeb - zyx (as of %s)"
+ // spot check; if one request has it, they all should
+ Expect.stringContains text expected "Expected long as-of date not found"
+ "IsNew succeeds for both old and new requests",
+ fun reqList ->
+ let allReqs = reqList.RequestsByType _s
+ let _, _, reqs = allReqs |> List.find (fun (typ, _, _) -> typ = CurrentRequest)
+ Expect.hasCountOf reqs 2u countAll "There should have been two requests"
+ Expect.isTrue (reqList.IsNew (List.head reqs)) "The first request should have been new"
+ Expect.isFalse (reqList.IsNew (List.last reqs)) "The second request should not have been new"
+ "RequestsByType succeeds",
+ fun reqList ->
+ let allReqs = reqList.RequestsByType _s
+ Expect.hasLength allReqs 2 "There should have been two types of request groupings"
+ let maybeCurrent = allReqs |> List.tryFind (fun (typ, _, _) -> typ = CurrentRequest)
+ Expect.isSome maybeCurrent "There should have been current requests"
+ let _, _, reqs = Option.get maybeCurrent
+ Expect.hasCountOf reqs 2u countAll "There should have been two requests"
+ let first = List.head reqs
+ Expect.equal first.text "zyx" "The requests should be sorted by updated date descending"
+ Expect.isTrue (allReqs |> List.exists (fun (typ, _, _) -> typ = PraiseReport))
+ "There should have been praise reports"
+ Expect.isFalse (allReqs |> List.exists (fun (typ, _, _) -> typ = Announcement))
+ "There should not have been announcements"
+ "RequestsByType succeeds and sorts by requestor",
+ fun reqList ->
+ let newList =
+ { reqList with
+ SmallGroup =
+ { reqList.SmallGroup with
+ preferences = { reqList.SmallGroup.preferences with requestSort = SortByRequestor }
+ }
+ }
+ let allReqs = newList.RequestsByType _s
+ let _, _, reqs = allReqs |> List.find (fun (typ, _, _) -> typ = CurrentRequest)
+ Expect.hasCountOf reqs 2u countAll "There should have been two requests"
+ let first = List.head reqs
+ Expect.equal first.text "abc" "The requests should be sorted by requestor"
]
- date = DateTime.Today
- listGroup = SmallGroup.empty
- showHeader = false
- recipients = []
- canEmail = false
- }
- |> f
- yield! testFixture withRequestList [
- "asHtml succeeds without header or as-of date",
- fun reqList ->
- let htmlList = { reqList with listGroup = { reqList.listGroup with name = "Test HTML Group" } }
- let html = htmlList.asHtml _s
- Expect.equal -1 (html.IndexOf "Test HTML Group") "The small group name should not have existed (no header)"
- let curReqHeading =
- [ ""
- ""
- ""
- " Current Requests |
"
- ]
- |> String.concat ""
- Expect.stringContains html curReqHeading "Heading for category \"Current Requests\" not found"
- let curReqHtml =
- [ ""
- "- "
- "Zeb — zyx
"
- "- "
- "Aaron — abc
"
- ]
- |> String.concat ""
- Expect.stringContains html curReqHtml "Expected HTML for \"Current Requests\" requests not found"
- let praiseHeading =
- [ ""
- ""
- ""
- " Praise Reports |
"
- ]
- |> String.concat ""
- Expect.stringContains html praiseHeading "Heading for category \"Praise Reports\" not found"
- let praiseHtml =
- [ ""
- ]
- |> String.concat ""
- Expect.stringContains html praiseHtml "Expected HTML for \"Praise Reports\" requests not found"
- "asHtml succeeds with header",
- fun reqList ->
- let htmlList =
- { reqList with
- listGroup = { reqList.listGroup with name = "Test HTML Group" }
- showHeader = true
- }
- let html = htmlList.asHtml _s
- let lstHeading =
- [ ""
- "Prayer Requests
"
- "Test HTML Group
"
- htmlList.date.ToString "MMMM d, yyyy"
- "
"
- ]
- |> String.concat ""
- Expect.stringContains html lstHeading "Expected HTML for the list heading not found"
- // spot check; without header test tests this exhaustively
- Expect.stringContains html "Zeb — zyx" "Expected requests not found"
- "asHtml succeeds with short as-of date",
- fun reqList ->
- let htmlList =
- { reqList with
- listGroup =
- { reqList.listGroup with
- preferences = { reqList.listGroup.preferences with asOfDateDisplay = ShortDate }
- }
- }
- let html = htmlList.asHtml _s
- let expected =
- htmlList.requests.[0].updatedDate.ToShortDateString ()
- |> sprintf "Zeb — zyx (as of %s)"
- // spot check; if one request has it, they all should
- Expect.stringContains html expected "Expected short as-of date not found"
- "asHtml succeeds with long as-of date",
- fun reqList ->
- let htmlList =
- { reqList with
- listGroup =
- { reqList.listGroup with
- preferences = { reqList.listGroup.preferences with asOfDateDisplay = LongDate }
- }
- }
- let html = htmlList.asHtml _s
- let expected =
- htmlList.requests.[0].updatedDate.ToLongDateString ()
- |> sprintf "Zeb — zyx (as of %s)"
- // spot check; if one request has it, they all should
- Expect.stringContains html expected "Expected long as-of date not found"
- "asText succeeds with no as-of date",
- fun reqList ->
- let textList = { reqList with listGroup = { reqList.listGroup with name = "Test Group" } }
- let text = textList.asText _s
- Expect.stringContains text (textList.listGroup.name + "\n") "Small group name 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 "--------------------\n CURRENT REQUESTS\n--------------------\n"
- "Heading for category \"Current Requests\" not found"
- Expect.stringContains text " + Zeb - zyx\n" "First request not found"
- Expect.stringContains text " - Aaron - abc\n \n" "Second request not found; should have been end of category"
- Expect.stringContains text "------------------\n PRAISE REPORTS\n------------------\n"
- "Heading for category \"Praise Reports\" not found"
- Expect.stringContains text " + nmo\n \n" "Last request not found"
- "asText succeeds with short as-of date",
- fun reqList ->
- let textList =
- { reqList with
- listGroup =
- { reqList.listGroup with
- preferences = { reqList.listGroup.preferences with asOfDateDisplay = ShortDate }
- }
- }
- let text = textList.asText _s
- let expected =
- textList.requests.[0].updatedDate.ToShortDateString ()
- |> sprintf " + Zeb - zyx (as of %s)"
- // spot check; if one request has it, they all should
- Expect.stringContains text expected "Expected short as-of date not found"
- "asText succeeds with long as-of date",
- fun reqList ->
- let textList =
- { reqList with
- listGroup =
- { reqList.listGroup with
- preferences = { reqList.listGroup.preferences with asOfDateDisplay = LongDate }
- }
- }
- let text = textList.asText _s
- let expected =
- textList.requests.[0].updatedDate.ToLongDateString ()
- |> sprintf " + Zeb - zyx (as of %s)"
- // spot check; if one request has it, they all should
- Expect.stringContains text expected "Expected long as-of date not found"
- "isNew succeeds for both old and new requests",
- fun reqList ->
- let reqs = reqList.requestsInCategory CurrentRequest
- Expect.hasCountOf reqs 2u countAll "There should have been two requests"
- Expect.isTrue (reqList.isNew (List.head reqs)) "The first request should have been new"
- Expect.isFalse (reqList.isNew (List.last reqs)) "The second request should not have been new"
- "requestsInCategory succeeds when requests exist",
- fun reqList ->
- let reqs = reqList.requestsInCategory CurrentRequest
- Expect.hasCountOf reqs 2u countAll "There should have been two requests"
- let first = List.head reqs
- Expect.equal first.text "zyx" "The requests should be sorted by updated date descending"
- "requestsInCategory succeeds when requests do not exist",
- fun reqList ->
- Expect.isEmpty (reqList.requestsInCategory Announcement) "There should have been no \"Announcement\" requests"
- "requestsInCategory succeeds and sorts by requestor",
- fun reqList ->
- let newList =
- { reqList with
- listGroup =
- { reqList.listGroup with
- preferences = { reqList.listGroup.preferences with requestSort = SortByRequestor }
- }
- }
- let reqs = newList.requestsInCategory CurrentRequest
- Expect.hasCountOf reqs 2u countAll "There should have been two requests"
- let first = List.head reqs
- Expect.equal first.text "abc" "The requests should be sorted by requestor"
- ]
]
[]
let userLogOnTests =
- testList "UserLogOn" [
- test "empty is as expected" {
- let mt = UserLogOn.empty
- Expect.equal mt.emailAddress "" "The e-mail address should be blank"
- Expect.equal mt.password "" "The password should be blank"
- Expect.equal mt.smallGroupId Guid.Empty "The small group ID should be an empty GUID"
- Expect.isNone mt.rememberMe "Remember Me should be None"
- Expect.isNone mt.redirectUrl "Redirect URL should be None"
- }
+ testList "UserLogOn" [
+ test "empty is as expected" {
+ let mt = UserLogOn.empty
+ Expect.equal mt.Email "" "The e-mail address should be blank"
+ Expect.equal mt.Password "" "The password should be blank"
+ Expect.equal mt.SmallGroupId Guid.Empty "The small group ID should be an empty GUID"
+ Expect.isNone mt.RememberMe "Remember Me should be None"
+ Expect.isNone mt.RedirectUrl "Redirect URL should be None"
+ }
]
[]
let userMessageTests =
- testList "UserMessage" [
- test "Error is constructed properly" {
- let msg = UserMessage.error
- Expect.equal msg.level "ERROR" "Incorrect message level"
- Expect.equal msg.text HtmlString.Empty "Text should have been blank"
- Expect.isNone msg.description "Description should have been None"
- }
- test "Warning is constructed properly" {
- let msg = UserMessage.warning
- Expect.equal msg.level "WARNING" "Incorrect message level"
- Expect.equal msg.text HtmlString.Empty "Text should have been blank"
- Expect.isNone msg.description "Description should have been None"
- }
- test "Info is constructed properly" {
- let msg = UserMessage.info
- Expect.equal msg.level "Info" "Incorrect message level"
- Expect.equal msg.text HtmlString.Empty "Text should have been blank"
- Expect.isNone msg.description "Description should have been None"
- }
+ testList "UserMessage" [
+ test "Error is constructed properly" {
+ let msg = UserMessage.error
+ Expect.equal msg.Level Error "Incorrect message level"
+ Expect.equal msg.Text HtmlString.Empty "Text should have been blank"
+ Expect.isNone msg.Description "Description should have been None"
+ }
+ test "Warning is constructed properly" {
+ let msg = UserMessage.warning
+ Expect.equal msg.Level Warning "Incorrect message level"
+ Expect.equal msg.Text HtmlString.Empty "Text should have been blank"
+ Expect.isNone msg.Description "Description should have been None"
+ }
+ test "Info is constructed properly" {
+ let msg = UserMessage.info
+ Expect.equal msg.Level Info "Incorrect message level"
+ Expect.equal msg.Text HtmlString.Empty "Text should have been blank"
+ Expect.isNone msg.Description "Description should have been None"
+ }
]
diff --git a/src/PrayerTracker.UI/Church.fs b/src/PrayerTracker.UI/Church.fs
index a235f7f..28ec25c 100644
--- a/src/PrayerTracker.UI/Church.fs
+++ b/src/PrayerTracker.UI/Church.fs
@@ -6,45 +6,50 @@ open PrayerTracker.ViewModels
/// View for the church edit page
let edit (m : EditChurch) ctx vi =
- let pageTitle = match m.isNew () with true -> "Add a New Church" | false -> "Edit Church"
+ let pageTitle = match m.IsNew with true -> "Add a New Church" | false -> "Edit Church"
let s = I18N.localizer.Force ()
[ form [ _action "/web/church/save"; _method "post"; _class "pt-center-columns" ] [
style [ _scoped ] [
rawText "#name { width: 20rem; } #city { width: 10rem; } #st { width: 3rem; } #interfaceAddress { width: 30rem; }"
]
csrfToken ctx
- input [ _type "hidden"; _name "churchId"; _value (flatGuid m.churchId) ]
+ input [ _type "hidden"; _name (nameof m.ChurchId); _value (flatGuid m.ChurchId) ]
div [ _class "pt-field-row" ] [
div [ _class "pt-field" ] [
label [ _for "name" ] [ locStr s["Church Name"] ]
- input [ _type "text"; _name "name"; _id "name"; _required; _autofocus; _value m.name ]
+ input [ _type "text"; _name (nameof m.Name); _id "name"; _required; _autofocus; _value m.Name ]
]
div [ _class "pt-field" ] [
label [ _for "City"] [ locStr s["City"] ]
- input [ _type "text"; _name "city"; _id "city"; _required; _value m.city ]
+ input [ _type "text"; _name (nameof m.City); _id "city"; _required; _value m.City ]
]
div [ _class "pt-field" ] [
- label [ _for "ST" ] [ locStr s["State"] ]
- input [ _type "text"; _name "st"; _id "st"; _required; _minlength "2"; _maxlength "2"; _value m.st ]
+ label [ _for "state" ] [ locStr s["State or Province"] ]
+ input [ _type "text"
+ _name (nameof m.State)
+ _id "state"
+ _required
+ _minlength "2"; _maxlength "2"
+ _value m.State ]
]
]
div [ _class "pt-field-row" ] [
div [ _class "pt-checkbox-field" ] [
input [ _type "checkbox"
- _name "hasInterface"
+ _name (nameof m.HasInterface)
_id "hasInterface"
_value "True"
- match m.hasInterface with Some x when x -> _checked | _ -> () ]
+ if defaultArg m.HasInterface false then _checked ]
label [ _for "hasInterface" ] [ locStr s["Has an interface with Virtual Prayer Room"] ]
]
]
div [ _class "pt-field-row pt-fadeable"; _id "divInterfaceAddress" ] [
div [ _class "pt-field" ] [
label [ _for "interfaceAddress" ] [ locStr s["VPR Interface URL"] ]
- input
- [ _type "url"; _name "interfaceAddress"; _id "interfaceAddress";
- _value (match m.interfaceAddress with Some ia -> ia | None -> "")
- ]
+ input [ _type "url"
+ _name (nameof m.InterfaceAddress)
+ _id "interfaceAddress";
+ _value (defaultArg m.InterfaceAddress "") ]
]
]
div [ _class "pt-field-row" ] [ submit [] "save" s["Save Church"] ]
diff --git a/src/PrayerTracker.UI/Home.fs b/src/PrayerTracker.UI/Home.fs
index 06abe48..654eed5 100644
--- a/src/PrayerTracker.UI/Home.fs
+++ b/src/PrayerTracker.UI/Home.fs
@@ -37,7 +37,7 @@ let error code vi =
_alt $"""%A{s["PrayerTracker"]} %A{s["from Bit Badger Solutions"]}"""
_title $"""%A{s["PrayerTracker"]} %A{s["from Bit Badger Solutions"]}"""
_style "vertical-align:text-bottom;" ]
- str vi.version
+ str vi.Version
]
]
|> div []
diff --git a/src/PrayerTracker.UI/Layout.fs b/src/PrayerTracker.UI/Layout.fs
index cc3ae4b..38e178d 100644
--- a/src/PrayerTracker.UI/Layout.fs
+++ b/src/PrayerTracker.UI/Layout.fs
@@ -20,7 +20,7 @@ module Navigation =
let s = I18N.localizer.Force ()
let menuSpacer = rawText " "
let leftLinks = [
- match m.user with
+ match m.User with
| Some u ->
li [ _class "dropdown" ] [
a [ _class "dropbtn"; _role "button"; _aria "label" s["Requests"].Value; _title s["Requests"].Value ]
@@ -56,7 +56,7 @@ module Navigation =
]
]
| None ->
- match m.group with
+ match m.Group with
| Some _ ->
li [] [
a [ _href "/web/prayer-requests/view"
@@ -91,9 +91,9 @@ module Navigation =
]
]
let rightLinks =
- match m.group with
+ match m.Group with
| Some _ -> [
- match m.user with
+ match m.User with
| Some _ ->
li [] [
a [ _href "/web/user/password"
@@ -137,9 +137,9 @@ module Navigation =
rawText " • "
a [ _href "/web/language/es" ] [ locStr s["Cambie a Español"] ]
]
- match m.group with
+ match m.Group with
| Some g ->[
- match m.user with
+ match m.User with
| Some u ->
span [ _class "u" ] [ locStr s["Currently Logged On"] ]
rawText " "
@@ -151,7 +151,7 @@ module Navigation =
rawText " "
icon "group"
space
- match m.user with
+ match m.User with
| Some _ -> a [ _href "/web/small-group" ] [ strong [] [ str g.name ] ]
| None -> strong [] [ str g.name ]
rawText " "
@@ -190,9 +190,9 @@ let private htmlHead m pageTitle =
meta [ _charset "UTF-8" ]
title [] [ locStr pageTitle; titleSep; locStr s["PrayerTracker"] ]
yield! commonHead
- for cssFile in m.style do
+ for cssFile in m.Style do
link [ _rel "stylesheet"; _href $"/css/{cssFile}.css"; _type "text/css" ]
- for jsFile in m.script do
+ for jsFile in m.Script do
script [ _src $"/js/{jsFile}.js" ] []
]
@@ -207,25 +207,25 @@ let private helpLink link =
/// Render the page title, and optionally a help link
let private renderPageTitle m pageTitle =
h2 [ _id "pt-page-title" ] [
- match m.helpLink with Some link -> Help.fullLink (langCode ()) link |> helpLink | None -> ()
+ match m.HelpLink with Some link -> Help.fullLink (langCode ()) link |> helpLink | None -> ()
locStr pageTitle
]
/// Render the messages that may need to be displayed to the user
let private messages m =
let s = I18N.localizer.Force ()
- m.messages
+ m.Messages
|> List.map (fun msg ->
- table [ _class $"pt-msg {msg.level.ToLower ()}" ] [
+ table [ _class $"pt-msg {MessageLevel.toCssClass msg.Level}" ] [
tr [] [
td [] [
- match msg.level with
- | "Info" -> ()
+ match msg.Level with
+ | Info -> ()
| lvl ->
- strong [] [ locStr s[lvl] ]
+ strong [] [ locStr s[MessageLevel.toString lvl] ]
rawText " » "
- rawText msg.text.Value
- match msg.description with
+ rawText msg.Text.Value
+ match msg.Description with
| Some desc ->
br []
div [ _class "description" ] [ rawText desc.Value ]
@@ -238,7 +238,7 @@ let private messages m =
let private htmlFooter m =
let s = I18N.localizer.Force ()
let imgText = sprintf "%O %O" s["PrayerTracker"] s["from Bit Badger Solutions"]
- let resultTime = TimeSpan(DateTime.Now.Ticks - m.requestStart).TotalSeconds
+ let resultTime = TimeSpan(DateTime.Now.Ticks - m.RequestStart).TotalSeconds
footer [] [
div [ _id "pt-legal" ] [
a [ _href "/web/legal/privacy-policy" ] [ locStr s["Privacy Policy"] ]
@@ -255,7 +255,7 @@ let private htmlFooter m =
div [ _id "pt-footer" ] [
a [ _href "/web/"; _style "line-height:28px;" ]
[ img [ _src $"""/img/%O{s["footer_en"]}.png"""; _alt imgText; _title imgText ] ]
- str m.version
+ str m.Version
space
i [ _title s["This page loaded in {0:N3} seconds", resultTime].Value; _class "material-icons md-18" ]
[ str "schedule" ]
diff --git a/src/PrayerTracker.UI/PrayerRequest.fs b/src/PrayerTracker.UI/PrayerRequest.fs
index 3cca333..3efe208 100644
--- a/src/PrayerTracker.UI/PrayerRequest.fs
+++ b/src/PrayerTracker.UI/PrayerRequest.fs
@@ -13,35 +13,35 @@ open PrayerTracker.ViewModels
/// View for the prayer request edit page
let edit (m : EditRequest) today ctx vi =
let s = I18N.localizer.Force ()
- let pageTitle = if m.isNew () then "Add a New Request" else "Edit Request"
+ let pageTitle = if m.IsNew then "Add a New Request" else "Edit Request"
[ form [ _action "/web/prayer-request/save"; _method "post"; _class "pt-center-columns" ] [
csrfToken ctx
- input [ _type "hidden"; _name "requestId"; _value (flatGuid m.requestId) ]
+ input [ _type "hidden"; _name (nameof m.RequestId); _value (flatGuid m.RequestId) ]
div [ _class "pt-field-row" ] [
div [ _class "pt-field" ] [
- label [ _for "requestType" ] [ locStr s["Request Type"] ]
+ label [ _for (nameof m.RequestType) ] [ locStr s["Request Type"] ]
ReferenceList.requestTypeList s
|> Seq.ofList
|> Seq.map (fun (typ, desc) -> typ.code, desc.Value)
- |> selectList "requestType" m.requestType [ _required; _autofocus ]
+ |> selectList (nameof m.RequestType) m.RequestType [ _required; _autofocus ]
]
div [ _class "pt-field" ] [
label [ _for "requestor" ] [ locStr s["Requestor / Subject"] ]
input [ _type "text"
- _name "requestor"
+ _name (nameof m.Requestor)
_id "requestor"
- _value (match m.requestor with Some x -> x | None -> "") ]
+ _value (defaultArg m.Requestor "") ]
]
- if m.isNew () then
+ if m.IsNew then
div [ _class "pt-field" ] [
label [ _for "enteredDate" ] [ locStr s["Date"] ]
- input [ _type "date"; _name "enteredDate"; _id "enteredDate"; _placeholder today ]
+ input [ _type "date"; _name (nameof m.EnteredDate); _id "enteredDate"; _placeholder today ]
]
else
div [ _class "pt-field" ] [
div [ _class "pt-checkbox-field" ] [
br []
- input [ _type "checkbox"; _name "skipDateUpdate"; _id "skipDateUpdate"; _value "True" ]
+ input [ _type "checkbox"; _name (nameof m.SkipDateUpdate); _id "skipDateUpdate"; _value "True" ]
label [ _for "skipDateUpdate" ] [ locStr s["Check to not update the date"] ]
br []
small [] [ em [] [ str (s["Typo Corrections"].Value.ToLower ()); rawText ", etc." ] ]
@@ -51,11 +51,11 @@ let edit (m : EditRequest) today ctx vi =
div [ _class "pt-field-row" ] [
div [ _class "pt-field" ] [
label [] [ locStr s["Expiration"] ]
- ReferenceList.expirationList s ((m.isNew >> not) ())
+ ReferenceList.expirationList s (not m.IsNew)
|> List.map (fun exp ->
let radioId = $"expiration_{fst exp}"
span [ _class "text-nowrap" ] [
- radio "expiration" radioId (fst exp) m.expiration
+ radio (nameof m.Expiration) radioId (fst exp) m.Expiration
label [ _for radioId ] [ locStr (snd exp) ]
rawText " "
])
@@ -65,7 +65,7 @@ let edit (m : EditRequest) today ctx vi =
div [ _class "pt-field-row" ] [
div [ _class "pt-field pt-editor" ] [
label [ _for "text" ] [ locStr s["Request"] ]
- textarea [ _name "text"; _id "text" ] [ str m.text ]
+ textarea [ _name (nameof m.Text); _id "text" ] [ str m.Text ]
]
]
div [ _class "pt-field-row" ] [ submit [] "save" s["Save Request"] ]
@@ -78,9 +78,9 @@ let edit (m : EditRequest) today ctx vi =
/// View for the request e-mail results page
let email m vi =
let s = I18N.localizer.Force ()
- let pageTitle = $"""{s["Prayer Requests"].Value} • {m.listGroup.name}"""
- let prefs = m.listGroup.preferences
- let addresses = String.Join (", ", m.recipients |> List.map (fun mbr -> $"{mbr.memberName} <{mbr.email}>"))
+ let pageTitle = $"""{s["Prayer Requests"].Value} • {m.SmallGroup.name}"""
+ let prefs = m.SmallGroup.preferences
+ let addresses = m.Recipients |> List.map (fun mbr -> $"{mbr.memberName} <{mbr.email}>") |> String.concat ", "
[ p [ _style $"font-family:{prefs.listFonts};font-size:%i{prefs.textFontSize}pt;" ] [
locStr s["The request list was sent to the following people, via individual e-mails"]
rawText ":"
@@ -88,11 +88,11 @@ let email m vi =
small [] [ str addresses ]
]
span [ _class "pt-email-heading" ] [ locStr s["HTML Format"]; rawText ":" ]
- div [ _class "pt-email-canvas" ] [ rawText (m.asHtml s) ]
+ div [ _class "pt-email-canvas" ] [ rawText (m.AsHtml s) ]
br []
br []
span [ _class "pt-email-heading" ] [ locStr s["Plain-Text Format"]; rawText ":" ]
- div [ _class "pt-email-canvas" ] [ pre [] [ str (m.asText s) ] ]
+ div [ _class "pt-email-canvas" ] [ pre [] [ str (m.AsText s) ] ]
]
|> Layout.Content.standard
|> Layout.standard vi pageTitle
@@ -101,7 +101,7 @@ let email m vi =
/// View for a small group's public prayer request list
let list (m : RequestList) vi =
[ br []
- I18N.localizer.Force () |> (m.asHtml >> rawText)
+ I18N.localizer.Force () |> (m.AsHtml >> rawText)
]
|> Layout.Content.standard
|> Layout.standard vi "View Request List"
@@ -154,24 +154,24 @@ let lists (groups : SmallGroup list) vi =
/// View for the prayer request maintenance page
-let maintain m (ctx : HttpContext) vi =
- let s = I18N.localizer.Force ()
- let l = I18N.forView "Requests/Maintain"
- use sw = new StringWriter ()
- let raw = rawLocText sw
- let now = m.smallGroup.localDateNow (ctx.GetService ())
- let typs = ReferenceList.requestTypeList s |> Map.ofList
+let maintain (m : MaintainRequests) (ctx : HttpContext) vi =
+ let s = I18N.localizer.Force ()
+ let l = I18N.forView "Requests/Maintain"
+ use sw = new StringWriter ()
+ let raw = rawLocText sw
+ let now = m.SmallGroup.localDateNow (ctx.GetService ())
+ let types = ReferenceList.requestTypeList s |> Map.ofList
let updReq (req : PrayerRequest) =
- if req.updateRequired now m.smallGroup.preferences.daysToExpire m.smallGroup.preferences.longTermUpdateWeeks then
+ if req.updateRequired now m.SmallGroup.preferences.daysToExpire m.SmallGroup.preferences.longTermUpdateWeeks then
"pt-request-update"
else ""
|> _class
let reqExp (req : PrayerRequest) =
- _class (if req.isExpired now m.smallGroup.preferences.daysToExpire then "pt-request-expired" else "")
+ _class (if req.isExpired now m.SmallGroup.preferences.daysToExpire then "pt-request-expired" else "")
/// Iterate the sequence once, before we render, so we can get the count of it at the top of the table
let requests =
- m.requests
- |> Seq.map (fun req ->
+ m.Requests
+ |> List.map (fun req ->
let reqId = flatGuid req.prayerRequestId
let reqText = htmlToPlainText req.text
let delAction = $"/web/prayer-request/{reqId}/delete"
@@ -187,7 +187,7 @@ let maintain m (ctx : HttpContext) vi =
td [] [
a [ _href $"/web/prayer-request/{reqId}/edit"; _title l["Edit This Prayer Request"].Value ]
[ icon "edit" ]
- if req.isExpired now m.smallGroup.preferences.daysToExpire then
+ if req.isExpired now m.SmallGroup.preferences.daysToExpire then
a [ _href $"/web/prayer-request/{reqId}/restore"
_title l["Restore This Inactive Request"].Value ]
[ icon "visibility" ]
@@ -202,7 +202,7 @@ let maintain m (ctx : HttpContext) vi =
td [ updReq req ] [
str (req.updatedDate.ToString(s["MMMM d, yyyy"].Value, Globalization.CultureInfo.CurrentUICulture))
]
- td [] [ locStr typs[req.requestType] ]
+ td [] [ locStr types[req.requestType] ]
td [ reqExp req ] [ str (match req.requestor with Some r -> r | None -> " ") ]
td [] [
match reqText.Length with
@@ -218,7 +218,7 @@ let maintain m (ctx : HttpContext) vi =
rawText " "
a [ _href "/web/prayer-requests/view"; _title s["View Prayer Request List"].Value ]
[ icon "list"; rawText " "; locStr s["View Prayer Request List"] ]
- match m.searchTerm with
+ match m.SearchTerm with
| Some _ ->
rawText " "
a [ _href "/web/prayer-requests"; _title l["Clear Search Criteria"].Value ]
@@ -229,7 +229,7 @@ let maintain m (ctx : HttpContext) vi =
input [ _type "text"
_name "search"
_placeholder l["Search requests..."].Value
- _value (defaultArg m.searchTerm "")
+ _value (defaultArg m.SearchTerm "")
]
space
submit [] "search" s["Search"]
@@ -253,54 +253,52 @@ let maintain m (ctx : HttpContext) vi =
]
div [ _class "pt-center-text" ] [
br []
- match m.onlyActive with
+ match m.OnlyActive with
| Some true ->
raw l["Inactive requests are currently not shown"]
br []
a [ _href "/web/prayer-requests/inactive" ] [ raw l["Show Inactive Requests"] ]
| _ ->
- match Option.isSome m.onlyActive with
- | true ->
+ if defaultArg m.OnlyActive false then
raw l["Inactive requests are currently shown"]
br []
a [ _href "/web/prayer-requests" ] [ raw l["Do Not Show Inactive Requests"] ]
br []
br []
- | false -> ()
- let srch = [ match m.searchTerm with Some s -> "search", s | None -> () ]
- let pg = defaultArg m.pageNbr 1
- let url =
- match m.onlyActive with Some true | None -> "" | _ -> "/inactive" |> sprintf "/web/prayer-requests%s"
+ let search = [ match m.SearchTerm with Some s -> "search", s | None -> () ]
+ let pg = defaultArg m.PageNbr 1
+ let url =
+ match m.OnlyActive with Some true | None -> "" | _ -> "/inactive" |> sprintf "/web/prayer-requests%s"
match pg with
| 1 -> ()
| _ ->
// button (_type "submit" :: attrs) [ icon ico; rawText " "; locStr text ]
- let withPage = match pg with 2 -> srch | _ -> ("page", string (pg - 1)) :: srch
+ let withPage = match pg with 2 -> search | _ -> ("page", string (pg - 1)) :: search
a [ _href (makeUrl url withPage) ]
[ icon "keyboard_arrow_left"; space; raw l["Previous Page"] ]
rawText " "
- match requests.Length = m.smallGroup.preferences.pageSize with
+ match requests.Length = m.SmallGroup.preferences.pageSize with
| true ->
- a [ _href (makeUrl url (("page", string (pg + 1)) :: srch)) ]
+ a [ _href (makeUrl url (("page", string (pg + 1)) :: search)) ]
[ raw l["Next Page"]; space; icon "keyboard_arrow_right" ]
| false -> ()
]
form [ _id "DeleteForm"; _action ""; _method "post" ] [ csrfToken ctx ]
]
|> Layout.Content.wide
- |> Layout.standard vi (match m.searchTerm with Some _ -> "Search Results" | None -> "Maintain Requests")
+ |> Layout.standard vi (match m.SearchTerm with Some _ -> "Search Results" | None -> "Maintain Requests")
/// View for the printable prayer request list
let print m version =
let s = I18N.localizer.Force ()
- let pageTitle = $"""{s["Prayer Requests"].Value} • {m.listGroup.name}"""
+ let pageTitle = $"""{s["Prayer Requests"].Value} • {m.SmallGroup.name}"""
let imgAlt = $"""{s["PrayerTracker"].Value} {s["from Bit Badger Solutions"].Value}"""
article [] [
- rawText (m.asHtml s)
+ rawText (m.AsHtml s)
br []
hr []
- div [ _style $"font-size:70%%;font-family:{m.listGroup.preferences.listFonts};" ] [
+ div [ _style $"font-size:70%%;font-family:{m.SmallGroup.preferences.listFonts};" ] [
img [ _src $"""/img/{s["footer_en"].Value}.png"""
_style "vertical-align:text-bottom;"
_alt imgAlt
@@ -315,21 +313,21 @@ let print m version =
/// View for the prayer request list
let view m vi =
let s = I18N.localizer.Force ()
- let pageTitle = $"""{s["Prayer Requests"].Value} • {m.listGroup.name}"""
+ let pageTitle = $"""{s["Prayer Requests"].Value} • {m.SmallGroup.name}"""
let spacer = rawText " "
- let dtString = m.date.ToString "yyyy-MM-dd"
+ let dtString = m.Date.ToString "yyyy-MM-dd"
[ div [ _class "pt-center-text" ] [
br []
a [ _class "pt-icon-link"
_href $"/web/prayer-requests/print/{dtString}"
_title s["View Printable"].Value
] [ icon "print"; rawText " "; locStr s["View Printable"] ]
- if m.canEmail then
+ if m.CanEmail then
spacer
- if m.date.DayOfWeek <> DayOfWeek.Sunday then
+ if m.Date.DayOfWeek <> DayOfWeek.Sunday then
let rec findSunday (date : DateTime) =
if date.DayOfWeek = DayOfWeek.Sunday then date else findSunday (date.AddDays 1.)
- let sunday = findSunday m.date
+ let sunday = findSunday m.Date
a [ _class "pt-icon-link"
_href $"""/web/prayer-requests/view/{sunday.ToString "yyyy-MM-dd"}"""
_title s["List for Next Sunday"].Value ] [
@@ -349,7 +347,7 @@ let view m vi =
]
]
br []
- rawText (m.asHtml s)
+ rawText (m.AsHtml s)
]
|> Layout.Content.standard
|> Layout.standard vi pageTitle
diff --git a/src/PrayerTracker.UI/PrayerTracker.UI.fsproj b/src/PrayerTracker.UI/PrayerTracker.UI.fsproj
index 4253ebc..47d5a02 100644
--- a/src/PrayerTracker.UI/PrayerTracker.UI.fsproj
+++ b/src/PrayerTracker.UI/PrayerTracker.UI.fsproj
@@ -18,14 +18,15 @@