Search, Paging, and "As of" Date #10
| @ -14,11 +14,11 @@ module private Helpers = | ||||
|   /// Central place to append sort criteria for prayer request queries | ||||
|   let reqSort sort (query : IQueryable<PrayerRequest>) = | ||||
|     match sort with | ||||
|     | "D" -> | ||||
|     | SortByDate -> | ||||
|         query.OrderByDescending(fun pr -> pr.updatedDate) | ||||
|           .ThenByDescending(fun pr -> pr.enteredDate) | ||||
|           .ThenBy(fun pr -> pr.requestor) | ||||
|     | _ -> | ||||
|     | SortByRequestor -> | ||||
|         query.OrderBy(fun pr -> pr.requestor) | ||||
|           .ThenByDescending(fun pr -> pr.updatedDate) | ||||
|           .ThenByDescending(fun pr -> pr.enteredDate) | ||||
|  | ||||
| @ -54,31 +54,65 @@ with | ||||
|     | "L" -> LongDate | ||||
|     | _ -> invalidArg "code" (sprintf "Unknown code %s" code) | ||||
|   /// Convert this DU case to a single-character string | ||||
|   member this.toCode () = | ||||
|   member this.code = | ||||
|     match this with | ||||
|     | NoDisplay -> "N" | ||||
|     | ShortDate -> "S" | ||||
|     | LongDate -> "L" | ||||
| 
 | ||||
| 
 | ||||
| /// How requests should be sorted | ||||
| type RequestSort = | ||||
|   /// Sort by date, then by requestor/subject | ||||
|   | SortByDate | ||||
|   /// Sort by requestor/subject, then by date | ||||
|   | SortByRequestor | ||||
| with | ||||
|   /// Convert to a DU case from a single-character string | ||||
|   static member fromCode code = | ||||
|     match code with | ||||
|     | "D" -> SortByDate | ||||
|     | "R" -> SortByRequestor | ||||
|     | _ -> invalidArg "code" (sprintf "Unknown code %s" code) | ||||
|   /// Convert this DU case to a single-character string | ||||
|   member this.code = | ||||
|     match this with | ||||
|     | SortByDate -> "D" | ||||
|     | SortByRequestor -> "R" | ||||
| 
 | ||||
| 
 | ||||
| module Converters = | ||||
|   open Microsoft.EntityFrameworkCore.Storage.ValueConversion | ||||
|   open Microsoft.FSharp.Linq.RuntimeHelpers | ||||
|   open System.Linq.Expressions | ||||
| 
 | ||||
|   let private fromDU = | ||||
|     <@ Func<AsOfDateDisplay, string>(fun (x : AsOfDateDisplay) -> x.toCode ()) @> | ||||
|   let private asOfFromDU = | ||||
|     <@ Func<AsOfDateDisplay, string>(fun (x : AsOfDateDisplay) -> x.code) @> | ||||
|     |> LeafExpressionConverter.QuotationToExpression | ||||
|     |> unbox<Expression<Func<AsOfDateDisplay, string>>> | ||||
| 
 | ||||
|   let private toDU = | ||||
|   let private asOfToDU = | ||||
|     <@ Func<string, AsOfDateDisplay>(AsOfDateDisplay.fromCode) @> | ||||
|     |> LeafExpressionConverter.QuotationToExpression | ||||
|     |> unbox<Expression<Func<string, AsOfDateDisplay>>> | ||||
|    | ||||
|   let private sortFromDU = | ||||
|     <@ Func<RequestSort, string>(fun (x : RequestSort) -> x.code) @> | ||||
|     |> LeafExpressionConverter.QuotationToExpression | ||||
|     |> unbox<Expression<Func<RequestSort, string>>> | ||||
| 
 | ||||
|   let private sortToDU = | ||||
|     <@ Func<string, RequestSort>(RequestSort.fromCode) @> | ||||
|     |> LeafExpressionConverter.QuotationToExpression | ||||
|     |> unbox<Expression<Func<string, RequestSort>>> | ||||
|    | ||||
|   /// Conversion between a string and an AsOfDateDisplay DU value | ||||
|   type AsOfDateDisplayConverter () = | ||||
|     inherit ValueConverter<AsOfDateDisplay, string> (fromDU, toDU) | ||||
|     inherit ValueConverter<AsOfDateDisplay, string> (asOfFromDU, asOfToDU) | ||||
| 
 | ||||
|   /// Conversion between a string and a RequestSort DU value | ||||
|   type RequestSortConverter () = | ||||
|     inherit ValueConverter<RequestSort, string> (sortFromDU, sortToDU) | ||||
| 
 | ||||
| 
 | ||||
| /// Statistics for churches | ||||
| @ -189,7 +223,7 @@ and [<CLIMutable; NoComparison; NoEquality>] ListPreferences = | ||||
|     /// The font size for the text on the prayer request list | ||||
|     textFontSize        : int | ||||
|     /// The order in which the prayer requests are sorted | ||||
|     requestSort         : string | ||||
|     requestSort         : RequestSort | ||||
|     /// The password used for "small group login" (view-only request list) | ||||
|     groupPassword       : string | ||||
|     /// The default e-mail type for this class | ||||
| @ -219,7 +253,7 @@ and [<CLIMutable; NoComparison; NoEquality>] ListPreferences = | ||||
|         lineColor           = "navy" | ||||
|         headingFontSize     = 16 | ||||
|         textFontSize        = 12 | ||||
|         requestSort         = "D" | ||||
|         requestSort         = SortByDate | ||||
|         groupPassword       = "" | ||||
|         defaultEmailType    = EmailType.Html | ||||
|         isPublic            = false | ||||
| @ -289,7 +323,7 @@ and [<CLIMutable; NoComparison; NoEquality>] ListPreferences = | ||||
|             .HasColumnName("RequestSort") | ||||
|             .IsRequired() | ||||
|             .HasMaxLength(1) | ||||
|             .HasDefaultValue "D" | ||||
|             .HasDefaultValue SortByDate | ||||
|           |> ignore | ||||
|           m.Property(fun e -> e.groupPassword) | ||||
|             .HasColumnName("GroupPassword") | ||||
| @ -323,6 +357,8 @@ and [<CLIMutable; NoComparison; NoEquality>] ListPreferences = | ||||
|             .HasDefaultValue NoDisplay | ||||
|           |> ignore) | ||||
|       |> ignore | ||||
|       mb.Model.FindEntityType(typeof<ListPreferences>).FindProperty("requestSort") | ||||
|         .SetValueConverter(Converters.RequestSortConverter ()) | ||||
|       mb.Model.FindEntityType(typeof<ListPreferences>).FindProperty("asOfDateDisplay") | ||||
|         .SetValueConverter(Converters.AsOfDateDisplayConverter ()) | ||||
| 
 | ||||
|  | ||||
| @ -5,6 +5,33 @@ open NodaTime.Testing | ||||
| open NodaTime | ||||
| open System | ||||
| 
 | ||||
| [<Tests>] | ||||
| let asOfDateDisplayTests = | ||||
|   testList "AsOfDateDisplay" [ | ||||
|     test "NoDisplay code is correct" { | ||||
|       Expect.equal NoDisplay.code "N" "The code for NoDisplay should have been \"N\"" | ||||
|       } | ||||
|     test "ShortDate code is correct" { | ||||
|       Expect.equal ShortDate.code "S" "The code for ShortDate should have been \"S\"" | ||||
|       } | ||||
|     test "LongDate code is correct" { | ||||
|       Expect.equal LongDate.code "L" "The code for LongDate should have been \"N\"" | ||||
|       } | ||||
|     test "fromCode N should return NoDisplay" { | ||||
|       Expect.equal (AsOfDateDisplay.fromCode "N") NoDisplay "\"N\" should have been converted to NoDisplay" | ||||
|       } | ||||
|     test "fromCode S should return ShortDate" { | ||||
|       Expect.equal (AsOfDateDisplay.fromCode "S") ShortDate "\"S\" should have been converted to ShortDate" | ||||
|       } | ||||
|     test "fromCode L should return LongDate" { | ||||
|       Expect.equal (AsOfDateDisplay.fromCode "L") LongDate "\"L\" should have been converted to LongDate" | ||||
|       } | ||||
|     test "fromCode X should raise" { | ||||
|       Expect.throws (fun () -> AsOfDateDisplay.fromCode "X" |> ignore) | ||||
|         "An unknown code should have raised an exception" | ||||
|       } | ||||
|     ] | ||||
| 
 | ||||
| [<Tests>] | ||||
| let churchTests = | ||||
|   testList "Church" [ | ||||
| @ -38,7 +65,7 @@ let listPreferencesTests = | ||||
|       Expect.equal mt.lineColor "navy" "The default heding line color should have been navy" | ||||
|       Expect.equal mt.headingFontSize 16 "The default heading font size should have been 16" | ||||
|       Expect.equal mt.textFontSize 12 "The default text font size should have been 12" | ||||
|       Expect.equal mt.requestSort "D" "The default request sort should have been D (date)" | ||||
|       Expect.equal mt.requestSort SortByDate "The default request sort should have been by date" | ||||
|       Expect.equal mt.groupPassword "" "The default group password should have been blank" | ||||
|       Expect.equal mt.defaultEmailType EmailType.Html "The default e-mail type should have been HTML" | ||||
|       Expect.isFalse mt.isPublic "The isPublic flag should not have been set" | ||||
| @ -130,6 +157,26 @@ let prayerRequestTests = | ||||
|       } | ||||
|     ] | ||||
| 
 | ||||
| [<Tests>] | ||||
| let requestSortTests = | ||||
|   testList "RequestSort" [ | ||||
|     test "SortByDate code is correct" { | ||||
|       Expect.equal SortByDate.code "D" "The code for SortByDate should have been \"D\"" | ||||
|       } | ||||
|     test "SortByRequestor code is correct" { | ||||
|       Expect.equal SortByRequestor.code "R" "The code for SortByRequestor should have been \"R\"" | ||||
|       } | ||||
|     test "fromCode D should return SortByDate" { | ||||
|       Expect.equal (RequestSort.fromCode "D") SortByDate "\"D\" should have been converted to SortByDate" | ||||
|       } | ||||
|     test "fromCode R should return SortByRequestor" { | ||||
|       Expect.equal (RequestSort.fromCode "R") SortByRequestor "\"R\" should have been converted to SortByRequestor" | ||||
|       } | ||||
|     test "fromCode Q should raise" { | ||||
|       Expect.throws (fun () -> RequestSort.fromCode "Q" |> ignore) "An unknown code should have raised an exception" | ||||
|       } | ||||
|     ] | ||||
| 
 | ||||
| [<Tests>] | ||||
| let smallGroupTests = | ||||
|   testList "SmallGroup" [ | ||||
|  | ||||
| @ -15,6 +15,18 @@ let countAll _ = true | ||||
| 
 | ||||
| module ReferenceListTests = | ||||
|    | ||||
|   [<Tests>] | ||||
|   let asOfDateListTests = | ||||
|     testList "ReferenceList.asOfDateList" [ | ||||
|       test "has all three options listed" { | ||||
|         let asOf = ReferenceList.asOfDateList _s | ||||
|         Expect.hasCountOf asOf 3u countAll "There should have been 3 as-of choices returned" | ||||
|         Expect.exists asOf (fun (x, _) -> x = NoDisplay.code) "The option for no display was not found" | ||||
|         Expect.exists asOf (fun (x, _) -> x = ShortDate.code) "The option for a short date was not found" | ||||
|         Expect.exists asOf (fun (x, _) -> x = LongDate.code)  "The option for a full date was not found" | ||||
|         } | ||||
|       ] | ||||
| 
 | ||||
|   [<Tests>] | ||||
|   let emailTypeListTests = | ||||
|     testList "ReferenceList.emailTypeList" [ | ||||
| @ -248,7 +260,7 @@ let editPreferencesTests = | ||||
|       Expect.equal edit.expireDays prefs.daysToExpire "The expiration days were not filled correctly" | ||||
|       Expect.equal edit.daysToKeepNew prefs.daysToKeepNew "The days to keep new were not filled correctly" | ||||
|       Expect.equal edit.longTermUpdateWeeks prefs.longTermUpdateWeeks "The weeks for update were not filled correctly" | ||||
|       Expect.equal edit.requestSort prefs.requestSort "The request sort was not filled correctly" | ||||
|       Expect.equal edit.requestSort prefs.requestSort.code "The request sort was not filled correctly" | ||||
|       Expect.equal edit.emailFromName prefs.emailFromName "The e-mail from name was not filled correctly" | ||||
|       Expect.equal edit.emailFromAddress prefs.emailFromAddress "The e-mail from address was not filled correctly" | ||||
|       Expect.equal edit.defaultEmailType prefs.defaultEmailType "The default e-mail type was not filled correctly" | ||||
| @ -572,7 +584,9 @@ let requestListTests = | ||||
|           let newList = | ||||
|             { reqList with | ||||
|                 listGroup = | ||||
|                   { reqList.listGroup with preferences = { reqList.listGroup.preferences with requestSort = "R" } } | ||||
|                   { reqList.listGroup with | ||||
|                       preferences = { reqList.listGroup.preferences with requestSort = SortByRequestor } | ||||
|                     } | ||||
|               } | ||||
|           let reqs = newList.requestsInCategory RequestType.Current | ||||
|           Expect.hasCountOf reqs 2u countAll "There should have been two requests" | ||||
|  | ||||
| @ -12,9 +12,9 @@ module ReferenceList = | ||||
| 
 | ||||
|   /// A localized list of the AsOfDateDisplay DU cases | ||||
|   let asOfDateList (s : IStringLocalizer) = | ||||
|     [ NoDisplay.toCode (), s.["Do not display the “as of” date"] | ||||
|       ShortDate.toCode (), s.["Display a short “as of” date"] | ||||
|       LongDate.toCode  (), s.["Display a full “as of” date"] | ||||
|     [ NoDisplay.code, s.["Do not display the “as of” date"] | ||||
|       ShortDate.code, s.["Display a short “as of” date"] | ||||
|       LongDate.code,  s.["Display a full “as of” date"] | ||||
|       ] | ||||
| 
 | ||||
|   /// A list of e-mail type options | ||||
| @ -289,7 +289,7 @@ with | ||||
|     { expireDays          = prefs.daysToExpire | ||||
|       daysToKeepNew       = prefs.daysToKeepNew | ||||
|       longTermUpdateWeeks = prefs.longTermUpdateWeeks | ||||
|       requestSort         = prefs.requestSort | ||||
|       requestSort         = prefs.requestSort.code | ||||
|       emailFromName       = prefs.emailFromName | ||||
|       emailFromAddress    = prefs.emailFromAddress | ||||
|       defaultEmailType    = prefs.defaultEmailType | ||||
| @ -303,7 +303,7 @@ with | ||||
|       timeZone            = prefs.timeZoneId | ||||
|       groupPassword       = Some prefs.groupPassword | ||||
|       pageSize            = prefs.pageSize | ||||
|       asOfDate            = prefs.asOfDateDisplay.toCode () | ||||
|       asOfDate            = prefs.asOfDateDisplay.code | ||||
|       listVisibility      = | ||||
|         match true with  | ||||
|         | _ when prefs.isPublic -> RequestVisibility.``public`` | ||||
| @ -322,7 +322,7 @@ with | ||||
|         daysToExpire        = this.expireDays | ||||
|         daysToKeepNew       = this.daysToKeepNew | ||||
|         longTermUpdateWeeks = this.longTermUpdateWeeks | ||||
|         requestSort         = this.requestSort | ||||
|         requestSort         = RequestSort.fromCode this.requestSort | ||||
|         emailFromName       = this.emailFromName | ||||
|         emailFromAddress    = this.emailFromAddress | ||||
|         defaultEmailType    = this.defaultEmailType | ||||
| @ -573,8 +573,8 @@ with | ||||
|       |> Seq.ofList | ||||
|       |> Seq.filter (fun req -> req.requestType = cat) | ||||
|     match this.listGroup.preferences.requestSort with | ||||
|     | "D" -> reqs |> Seq.sortByDescending (fun req -> req.updatedDate) | ||||
|     | _ -> reqs |> Seq.sortBy (fun req -> req.requestor) | ||||
|     | SortByDate -> reqs |> Seq.sortByDescending (fun req -> req.updatedDate) | ||||
|     | SortByRequestor -> reqs |> Seq.sortBy (fun req -> req.requestor) | ||||
|     |> List.ofSeq | ||||
|   /// Is this request new? | ||||
|   member this.isNew (req : PrayerRequest) = | ||||
|  | ||||
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user