- Removed fixi library (not a good fit)
This commit is contained in:
		
							parent
							
								
									2e5a1426f6
								
							
						
					
					
						commit
						c9ccfe8b68
					
				| @ -68,6 +68,10 @@ module Json = | ||||
|         opts | ||||
| 
 | ||||
| 
 | ||||
| module private Helpers = | ||||
|     let instant (it: Instant) = | ||||
|         it.ToString() | ||||
| 
 | ||||
| open BitBadger.Documents | ||||
| open BitBadger.Documents.Sqlite | ||||
| 
 | ||||
| @ -120,19 +124,19 @@ module SmallGroups = | ||||
| 
 | ||||
|     /// Query to retrieve data for a small group info instance | ||||
|     let private infoQuery = | ||||
|         $"SELECT g.data->>'id' AS id, g.data->>'groupName' AS groupName, c.data->>'churchName' AS churchName, | ||||
|         $"SELECT g.data->>'id' AS id, g.data->>'name' AS groupName, c.data->>'name' AS churchName, | ||||
|                  g.data->'preferences'->>'timeZoneId' AS timeZoneId, g.data->'preferences'->>'isPublic' AS isPublic | ||||
|             FROM {Table.Group} g | ||||
|                  INNER JOIN {Table.Church} c ON c.data->>'id' = g.data->>'churchId'" | ||||
| 
 | ||||
|     /// Query to retrieve data for a small group select list item | ||||
|     let private itemQuery = | ||||
|         $"SELECT g.data->>'groupName' AS groupName, g.data->>'id' AS id, c.data->>'churchName' AS churchName | ||||
|         $"SELECT g.data->>'name' AS groupName, g.data->>'id' AS id, c.data->>'name' AS churchName | ||||
|             FROM {Table.Group} g | ||||
|                  INNER JOIN {Table.Church} c ON c.data->>'id' = g.data->>'churchId'" | ||||
| 
 | ||||
|     /// The ORDER BY clause for select list item queries | ||||
|     let private itemOrderBy = "ORDER BY c.data->>'churchName', g.data->>'groupName'" | ||||
|     let private itemOrderBy = "ORDER BY c.data->>'name', g.data->>'name'" | ||||
| 
 | ||||
|     /// Map a row to a Small Group list item | ||||
|     let private toSmallGroupItem (rdr: SqliteDataReader) = | ||||
| @ -142,13 +146,13 @@ module SmallGroups = | ||||
|     /// Get the group IDs for the given church | ||||
|     let internal groupIdsByChurch (churchId: ChurchId) = | ||||
|         backgroundTask { | ||||
|             let! groups = Find.byFields<SmallGroup> Table.Group All [ Field.Equal "churchId" churchId ] | ||||
|             let! groups = Find.byFields<SmallGroup> Table.Group All [ Field.Equal "churchId" (string churchId) ] | ||||
|             return groups |> List.map _.Id | ||||
|         } | ||||
| 
 | ||||
|     /// Count the number of small groups for a church | ||||
|     let countByChurch (churchId: ChurchId) = | ||||
|         Count.byFields Table.Group All [ Field.Equal "churchId" churchId ] | ||||
|         Count.byFields Table.Group All [ Field.Equal "churchId" (string churchId) ] | ||||
| 
 | ||||
|     /// Delete a small group by its ID | ||||
|     let deleteById (groupId: SmallGroupId) = | ||||
| @ -156,20 +160,21 @@ module SmallGroups = | ||||
|             use conn = Configuration.dbConn () | ||||
|             use! txn = conn.BeginTransactionAsync() | ||||
| 
 | ||||
|             let! users = Find.byFields<User> Table.User All [ Field.InArray "smallGroups" Table.User [ groupId ] ] | ||||
|             let! users = | ||||
|                 Find.byFields<User> Table.User All [ Field.InArray "smallGroups" Table.User [ (string groupId) ] ] | ||||
| 
 | ||||
|             for user in users do | ||||
|                 do! Patch.byId Table.User user.Id {| SmallGroups = user.SmallGroups |> List.except [ groupId ] |} | ||||
| 
 | ||||
|             do! conn.deleteByFields Table.Request All [ Field.Equal "smallGroupId" groupId ] | ||||
|             do! conn.deleteById Table.Group groupId | ||||
|             do! conn.deleteByFields Table.Request All [ Field.Equal "smallGroupId" (string groupId) ] | ||||
|             do! conn.deleteById Table.Group (string groupId) | ||||
| 
 | ||||
|             do! txn.CommitAsync() | ||||
|         } | ||||
| 
 | ||||
|     /// Get information for all small groups | ||||
|     let infoForAll () = | ||||
|         Custom.list $"{infoQuery} ORDER BY g.data->>'groupName'" [] SmallGroupInfo.FromReader | ||||
|         Custom.list $"{infoQuery} ORDER BY g.data->>'name'" [] SmallGroupInfo.FromReader | ||||
| 
 | ||||
|     /// Get a list of small group IDs along with a description that includes the church name | ||||
|     let listAll () = | ||||
| @ -197,14 +202,14 @@ module SmallGroups = | ||||
|         Find.firstByFields<SmallGroup> | ||||
|             Table.Group | ||||
|             All | ||||
|             [ Field.Equal "id" groupId; Field.Equal "preferences.groupPassword" password ] | ||||
|             [ Field.Equal "id" (string groupId); Field.Equal "preferences.groupPassword" password ] | ||||
| 
 | ||||
|     /// Save a small group | ||||
|     let save group = save<SmallGroup> Table.Group group | ||||
| 
 | ||||
|     /// Save a small group's list preferences | ||||
|     let savePreferences (groupId: SmallGroupId) (pref: ListPreferences) = | ||||
|         Patch.byId Table.Group groupId {| Preferences = pref |} | ||||
|         Patch.byId Table.Group (string groupId) {| Preferences = pref |} | ||||
| 
 | ||||
|     /// Get a small group by its ID (including list preferences) | ||||
|     let tryById groupId = | ||||
| @ -223,17 +228,18 @@ module Churches = | ||||
|             use conn = Configuration.dbConn () | ||||
|             use! txn = conn.BeginTransactionAsync() | ||||
| 
 | ||||
|             let! groupIds = SmallGroups.groupIdsByChurch churchId | ||||
|             let! groupIds   = SmallGroups.groupIdsByChurch churchId | ||||
|             let  gIdStrings = groupIds |> List.map string | ||||
| 
 | ||||
|             do! Delete.byFields Table.Request All [ Field.In "smallGroupId" groupIds ] | ||||
|             do! Delete.byFields Table.Request All [ Field.In "smallGroupId" gIdStrings ] | ||||
| 
 | ||||
|             let! users = Find.byFields<User> Table.User All [ Field.InArray "smallGroups" Table.User groupIds ] | ||||
|             let! users = Find.byFields<User> Table.User All [ Field.InArray "smallGroups" Table.User gIdStrings ] | ||||
| 
 | ||||
|             for user in users do | ||||
|                 do! Patch.byId Table.User user.Id {| SmallGroups = user.SmallGroups |> List.except groupIds |} | ||||
|                 do! Patch.byId Table.User (string user.Id) {| SmallGroups = user.SmallGroups |> List.except groupIds |} | ||||
| 
 | ||||
|             do! Delete.byFields Table.Group All [ Field.Equal "churchId" churchId ] | ||||
|             do! Delete.byId Table.Church churchId | ||||
|             do! Delete.byFields Table.Group All [ Field.Equal "churchId" (string churchId) ] | ||||
|             do! Delete.byId Table.Church (string churchId) | ||||
|             do! txn.CommitAsync() | ||||
|         } | ||||
| 
 | ||||
| @ -250,17 +256,17 @@ module Members = | ||||
| 
 | ||||
|     /// Count members for the given small group | ||||
|     let countByGroup (groupId: SmallGroupId) = | ||||
|         Count.byFields Table.Member All [ Field.Equal "smallGroupId" groupId ] | ||||
|         Count.byFields Table.Member All [ Field.Equal "smallGroupId" (string groupId) ] | ||||
| 
 | ||||
|     /// Delete a small group member by its ID | ||||
|     let deleteById (memberId: MemberId) = Delete.byId Table.Member memberId | ||||
|     let deleteById (memberId: MemberId) = Delete.byId Table.Member (string memberId) | ||||
| 
 | ||||
|     /// Retrieve all members for a given small group | ||||
|     let forGroup (groupId: SmallGroupId) = | ||||
|         Find.byFieldsOrdered<Member> | ||||
|             Table.Member | ||||
|             All | ||||
|             [ Field.Equal "smallGroupId" groupId ] | ||||
|             [ Field.Equal "smallGroupId" (string groupId) ] | ||||
|             [ Field.Named "memberName" ] | ||||
| 
 | ||||
|     /// Save a small group member | ||||
| @ -312,15 +318,15 @@ module PrayerRequests = | ||||
|     let countByChurch churchId = | ||||
|         backgroundTask { | ||||
|             let! groupIds = SmallGroups.groupIdsByChurch churchId | ||||
|             return! Count.byFields Table.Request All [ Field.In "smallGroupId" groupIds ] | ||||
|             return! Count.byFields Table.Request All [ Field.In "smallGroupId" (List.map string groupIds) ] | ||||
|         } | ||||
| 
 | ||||
|     /// Count the number of prayer requests for a small group | ||||
|     let countByGroup (groupId: SmallGroupId) = | ||||
|         Count.byFields Table.Request All [ Field.Equal "smallGroupId" groupId ] | ||||
|         Count.byFields Table.Request All [ Field.Equal "smallGroupId" (string groupId) ] | ||||
| 
 | ||||
|     /// Delete a prayer request by its ID | ||||
|     let deleteById (reqId: PrayerRequestId) = Delete.byId Table.Request reqId | ||||
|     let deleteById (reqId: PrayerRequestId) = Delete.byId Table.Request (string reqId) | ||||
| 
 | ||||
|     /// Get all (or active) requests for a small group as of now or the specified date | ||||
|     let forGroup (opts: PrayerRequestOptions) = | ||||
| @ -332,11 +338,11 @@ module PrayerRequests = | ||||
|                     (theDate.AtStartOfDayInZone(opts.SmallGroup.TimeZone) | ||||
|                          - Duration.FromDays opts.SmallGroup.Preferences.DaysToExpire) | ||||
|                         .ToInstant() | ||||
|                 $"""AND (   data->>'updatedDate'  > :updatedDate | ||||
|                          OR data->>'expiration'   = :expManual | ||||
|                          OR data->>'requestType' IN (:typLongTerm, :typExpecting)) | ||||
|                 $"""AND (   date(data->>'updatedDate')  > date(:updatedDate) | ||||
|                          OR data->>'expiration'         = :expManual | ||||
|                          OR data->>'requestType'       IN (:typLongTerm, :typExpecting)) | ||||
|                     AND data->>'expiration' <> :expForced""", | ||||
|                 [ SqliteParameter(":updatedDate", expDate) | ||||
|                 [ SqliteParameter(":updatedDate", string expDate) | ||||
|                   SqliteParameter(":expManual", string Manual) | ||||
|                   SqliteParameter(":typLongTerm", string LongTermRequest) | ||||
|                   SqliteParameter(":typExpecting", string Expecting) | ||||
| @ -346,8 +352,9 @@ module PrayerRequests = | ||||
| 
 | ||||
|         Custom.list | ||||
|             $"SELECT data FROM {Table.Request} | ||||
|                WHERE data->>'smallGroupId = :groupId {sql} | ||||
|                ORDER BY {orderBy opts.SmallGroup.Preferences.RequestSort} | ||||
|                WHERE data->>'smallGroupId' = :groupId | ||||
|                  {sql} | ||||
|                {orderBy opts.SmallGroup.Preferences.RequestSort} | ||||
|                {paginate opts.PageNumber opts.SmallGroup.Preferences.PageSize}" | ||||
|             (SqliteParameter(":groupId", string opts.SmallGroup.Id) :: parameters) | ||||
|             fromData<PrayerRequest> | ||||
| @ -357,18 +364,20 @@ module PrayerRequests = | ||||
| 
 | ||||
|     /// Search prayer requests for the given term | ||||
|     let searchForGroup group searchTerm pageNbr = | ||||
|         let pct = "%" | ||||
|         Custom.list | ||||
|             $"SELECT data FROM {Table.Request} | ||||
|                WHERE data->>'smallGroupId' = :groupId | ||||
|                  AND data->>'requestText' LIKE :search | ||||
|                   UNION | ||||
|               SELECT data FROM {Table.Request} | ||||
|                WHERE data->>'smallGroupId' = :groupId | ||||
|                  AND COALESCE(data->>'requestor', '') LIKE :search | ||||
|               ORDER BY {orderBy group.Preferences.RequestSort} | ||||
|             $"WITH results AS ( | ||||
|                 SELECT data FROM {Table.Request} | ||||
|                  WHERE data->>'smallGroupId' = :groupId | ||||
|                    AND data->>'text' LIKE :search | ||||
|               UNION | ||||
|                 SELECT data FROM {Table.Request} | ||||
|                  WHERE data->>'smallGroupId' = :groupId | ||||
|                    AND COALESCE(data->>'requestor', '') LIKE :search) | ||||
|               SELECT data FROM results | ||||
|               {orderBy group.Preferences.RequestSort} | ||||
|               {paginate pageNbr group.Preferences.PageSize}" | ||||
|             [ SqliteParameter(":groupId", string group.Id) | ||||
|               SqliteParameter(":search", $"%%%s{searchTerm}%%") ] | ||||
|             [ SqliteParameter(":groupId", string group.Id); SqliteParameter(":search", $"{pct}%s{searchTerm}{pct}") ] | ||||
|             fromData<PrayerRequest> | ||||
| 
 | ||||
|     /// Retrieve a prayer request by its ID | ||||
| @ -380,11 +389,11 @@ module PrayerRequests = | ||||
|         if withTime then | ||||
|             Patch.byId | ||||
|                 Table.Request | ||||
|                 req.Id | ||||
|                 (string req.Id) | ||||
|                 {| UpdatedDate = req.UpdatedDate | ||||
|                    Expiration = req.Expiration |} | ||||
|         else | ||||
|             Patch.byId Table.Request req.Id {| Expiration = req.Expiration |} | ||||
|             Patch.byId Table.Request (string req.Id) {| Expiration = req.Expiration |} | ||||
| 
 | ||||
| 
 | ||||
| /// Functions to manipulate users | ||||
| @ -398,22 +407,22 @@ module Users = | ||||
|     let countByChurch churchId = | ||||
|         backgroundTask { | ||||
|             let! groupIds = SmallGroups.groupIdsByChurch churchId | ||||
|             return! Count.byFields Table.User All [ Field.InArray "smallGroups" Table.User groupIds ] | ||||
|             return! Count.byFields Table.User All [ Field.InArray "smallGroups" Table.User (List.map string groupIds) ] | ||||
|         } | ||||
| 
 | ||||
|     /// Count the number of users for a small group | ||||
|     let countByGroup (groupId: SmallGroupId) = | ||||
|         Count.byFields Table.User All [ Field.InArray "smallGroups" Table.User [ groupId ] ] | ||||
|         Count.byFields Table.User All [ Field.InArray "smallGroups" Table.User [ (string groupId) ] ] | ||||
| 
 | ||||
|     /// Delete a user by its database ID | ||||
|     let deleteById (userId: UserId) = Delete.byId Table.User userId | ||||
|     let deleteById (userId: UserId) = Delete.byId Table.User (string userId) | ||||
| 
 | ||||
|     /// Get a list of users authorized to administer the given small group | ||||
|     let listByGroupId (groupId: SmallGroupId) = | ||||
|         Find.byFieldsOrdered<User> | ||||
|             Table.User | ||||
|             All | ||||
|             [ Field.InArray "smallGroups" Table.User [ groupId ] ] | ||||
|             [ Field.InArray "smallGroups" Table.User [ (string groupId) ] ] | ||||
|             [ Field.Named "lastName"; Field.Named "firstName" ] | ||||
| 
 | ||||
|     /// Save a user's information | ||||
| @ -425,7 +434,7 @@ module Users = | ||||
|             Table.User | ||||
|             All | ||||
|             [ Field.Equal "email" email | ||||
|               Field.InArray "smallGroups" Table.User [ groupId ] ] | ||||
|               Field.InArray "smallGroups" Table.User [ (string groupId) ] ] | ||||
| 
 | ||||
|     /// Find a user by their database ID | ||||
|     let tryById userId = | ||||
| @ -433,12 +442,12 @@ module Users = | ||||
| 
 | ||||
|     /// Update a user's last seen date/time | ||||
|     let updateLastSeen (userId: UserId) (now: Instant) = | ||||
|         Patch.byId Table.User userId {| LastSeen = now |} | ||||
|         Patch.byId Table.User (string userId) {| LastSeen = now |} | ||||
| 
 | ||||
|     /// Update a user's password hash | ||||
|     let updatePassword (user: User) = | ||||
|         Patch.byId Table.User user.Id {| PasswordHash = user.PasswordHash |} | ||||
|         Patch.byId Table.User (string user.Id) {| PasswordHash = user.PasswordHash |} | ||||
| 
 | ||||
|     /// Update a user's authorized small groups | ||||
|     let updateSmallGroups (userId: UserId) (groupIds: SmallGroupId list) = | ||||
|         Patch.byId Table.User userId {| SmallGroups = groupIds |} | ||||
|         Patch.byId Table.User (string userId) {| SmallGroups = groupIds |} | ||||
|  | ||||
| @ -87,6 +87,7 @@ module Configure = | ||||
|         let cachePath = defaultArg (Option.ofObj (cfg.GetConnectionString "SessionDB")) "./data/session.db" | ||||
|         let _ = svc.AddSqliteCache(fun o -> o.CachePath <- cachePath) | ||||
|         let _ = svc.AddSession() | ||||
|         let _ = svc.AddLogging() | ||||
|         let _ = svc.AddAntiforgery() | ||||
|         let _ = svc.AddRouting() | ||||
|         let _ = svc.AddSingleton<IClock> SystemClock.Instance | ||||
| @ -219,8 +220,8 @@ module Configure = | ||||
|     open Microsoft.Extensions.Options | ||||
| 
 | ||||
|     /// Configure the application | ||||
|     let app (app: IApplicationBuilder) = | ||||
|         let env = app.ApplicationServices.GetRequiredService<IWebHostEnvironment>() | ||||
|     let app (app: WebApplication) = | ||||
|         let env = app.Services.GetRequiredService<IWebHostEnvironment>() | ||||
| 
 | ||||
|         if env.IsDevelopment() then | ||||
|             app.UseDeveloperExceptionPage() | ||||
| @ -232,24 +233,20 @@ module Configure = | ||||
|         let _ = app.UseCanonicalDomains() | ||||
|         let _ = app.UseStatusCodePagesWithReExecute "/error/{0}" | ||||
|         let _ = app.UseStaticFiles() | ||||
| 
 | ||||
|         let _ = | ||||
|             app.UseCookiePolicy(CookiePolicyOptions(MinimumSameSitePolicy = SameSiteMode.Strict)) | ||||
| 
 | ||||
|         let _ = app.UseCookiePolicy(CookiePolicyOptions(MinimumSameSitePolicy = SameSiteMode.Strict)) | ||||
|         let _ = app.UseMiddleware<RequestStartMiddleware>() | ||||
|         let _ = app.UseRouting() | ||||
|         let _ = app.UseSession() | ||||
| 
 | ||||
|         let _ = | ||||
|             app.UseRequestLocalization(app.ApplicationServices.GetService<IOptions<RequestLocalizationOptions>>().Value) | ||||
| 
 | ||||
|         let _ = app.UseRequestLocalization(app.Services.GetService<IOptions<RequestLocalizationOptions>>().Value) | ||||
|         let _ = app.UseAuthentication() | ||||
|         let _ = app.UseAuthorization() | ||||
|         let _ = app.UseEndpoints(fun e -> e.MapGiraffeEndpoints routes) | ||||
| 
 | ||||
|         app.ApplicationServices.GetRequiredService<IStringLocalizerFactory>() | ||||
|         app.Services.GetRequiredService<IStringLocalizerFactory>() | ||||
|         |> Views.I18N.setUpFactories | ||||
| 
 | ||||
| open Microsoft.Extensions.DependencyInjection | ||||
| open Microsoft.Extensions.Logging | ||||
| 
 | ||||
| /// The web application | ||||
| module App = | ||||
| @ -258,22 +255,32 @@ module App = | ||||
| 
 | ||||
|     [<EntryPoint>] | ||||
|     let main args = | ||||
|         let contentRoot = Directory.GetCurrentDirectory() | ||||
| 
 | ||||
|         let app = | ||||
|             WebHostBuilder() | ||||
|                 .UseContentRoot(contentRoot) | ||||
|         let contentRoot = Directory.GetCurrentDirectory() | ||||
|         let builder = | ||||
|             WebApplication.CreateBuilder( | ||||
|                 WebApplicationOptions( | ||||
|                     Args = args, | ||||
|                     ApplicationName = "PrayerTracker", | ||||
|                     ContentRootPath = contentRoot, | ||||
|                     WebRootPath = Path.Combine(contentRoot, "wwwroot"))) | ||||
|         let _ = | ||||
|             builder.WebHost | ||||
|                 .ConfigureAppConfiguration(Configure.configuration) | ||||
|                 .UseKestrel(Configure.kestrel) | ||||
|                 .UseWebRoot(Path.Combine(contentRoot, "wwwroot")) | ||||
|                 .ConfigureKestrel(Configure.kestrel) | ||||
|                 .ConfigureServices(Configure.services) | ||||
|                 .ConfigureLogging(Configure.logging) | ||||
|                 .Configure(System.Action<IApplicationBuilder> Configure.app) | ||||
|                 .Build() | ||||
| 
 | ||||
|         if args.Length > 0 then | ||||
|             printfn $"Unrecognized option {args[0]}" | ||||
|         else | ||||
|             app.Run() | ||||
|         use app = builder.Build() | ||||
| 
 | ||||
|         Configure.app app | ||||
| 
 | ||||
|         let fac = app.Services.GetRequiredService<ILoggerFactory>() | ||||
|         let log = fac.CreateLogger "PrayerTracker" | ||||
|         log.LogInformation "Application Started" | ||||
| 
 | ||||
|         app.Run() | ||||
| 
 | ||||
|         log.LogInformation "Application Shutting Down" | ||||
| 
 | ||||
|         0 | ||||
|  | ||||
| @ -13,11 +13,11 @@ let toSelectList<'T> valFunc textFunc withDefault emptyText (items: 'T seq) = | ||||
|           SelectListItem($"""— %A{s[emptyText]} —""", "") | ||||
|       | _ -> () | ||||
|       yield! items |> Seq.map (fun x -> SelectListItem(textFunc x, valFunc x)) ] | ||||
|    | ||||
| 
 | ||||
| /// Create a select list from an enumeration | ||||
| let toSelectListWithEmpty<'T> valFunc textFunc emptyText (items: 'T seq) = | ||||
|     toSelectList valFunc textFunc true emptyText items | ||||
|      | ||||
| 
 | ||||
| /// Create a select list from an enumeration | ||||
| let toSelectListWithDefault<'T> valFunc textFunc (items: 'T seq) = | ||||
|     toSelectList valFunc textFunc true "Select" items | ||||
| @ -117,7 +117,7 @@ let addInfo ctx msg = | ||||
| /// Add an informational HTML message to the session | ||||
| let addHtmlInfo ctx msg = | ||||
|     addUserMessage ctx { UserMessage.info with Text = htmlString msg } | ||||
|    | ||||
| 
 | ||||
| /// Add a warning message to the session | ||||
| let addWarning ctx msg = | ||||
|     addUserMessage ctx { UserMessage.warning with Text = htmlLocString msg } | ||||
|  | ||||
| @ -182,13 +182,6 @@ let toHtmlIds it = | ||||
| let renderHtmlNode = RenderView.AsString.htmlNode | ||||
| 
 | ||||
| 
 | ||||
| open Giraffe.Fixi | ||||
| 
 | ||||
| /// Create a page link that will make the request with fixi | ||||
| let pageLink href attrs content = | ||||
|     a (List.append [ _href href; _fxGet; _fxAction href; _fxTarget "#pt-body" ] attrs) content | ||||
| 
 | ||||
| 
 | ||||
| open Microsoft.AspNetCore.Html | ||||
| 
 | ||||
| /// Render an HTML node, then return the value as an HTML string | ||||
| @ -224,6 +217,10 @@ module TimeZones = | ||||
| 
 | ||||
| open Giraffe.ViewEngine.Htmx | ||||
| 
 | ||||
| /// Create a page link that will make the request with fixi | ||||
| let pageLink href attrs content = | ||||
|     a (List.append [ _href href; _hxGet href ] attrs) content | ||||
| 
 | ||||
| /// Known htmx targets | ||||
| module Target = | ||||
| 
 | ||||
|  | ||||
| @ -12,7 +12,7 @@ let langCode () = if CultureInfo.CurrentCulture.Name.StartsWith "es" then "es" e | ||||
| 
 | ||||
| /// Navigation items | ||||
| module Navigation = | ||||
|    | ||||
| 
 | ||||
|     /// Top navigation bar | ||||
|     let top m = | ||||
|         let s          = I18N.localizer.Force() | ||||
| @ -103,7 +103,7 @@ module Navigation = | ||||
|             section [ _class "pt-title-bar-center"; _ariaLabel "Empty center space in top menu" ] [] | ||||
|             section [ _class "pt-title-bar-right"; _roleToolBar; _ariaLabel "Right side of top menu" ] [ | ||||
|                 ul [] rightLinks ] ] | ||||
|      | ||||
| 
 | ||||
|     /// Identity bar (below top nav) | ||||
|     let identity m = | ||||
|         let s = I18N.localizer.Force() | ||||
| @ -111,7 +111,7 @@ module Navigation = | ||||
|             div [] [ | ||||
|                 span [ _title s["Language"].Value ] [ icon "record_voice_over"; space ] | ||||
|                 match langCode () with | ||||
|                 | "es" ->  | ||||
|                 | "es" -> | ||||
|                     strong [] [ locStr s["Spanish"] ] | ||||
|                     rawText "     " | ||||
|                     pageLink "/language/en" [] [ locStr s["Change to English"] ] | ||||
| @ -142,14 +142,14 @@ module Navigation = | ||||
| 
 | ||||
| /// Content layouts | ||||
| module Content = | ||||
|    | ||||
| 
 | ||||
|     /// Content layout that tops at 60rem | ||||
|     let standard = div [ _class "pt-content" ] | ||||
| 
 | ||||
|     /// Content layout that uses the full width of the browser window | ||||
|     let wide = div [ _class "pt-content pt-full-width" ] | ||||
| 
 | ||||
|    | ||||
| 
 | ||||
| /// Separator for parts of the title | ||||
| let private titleSep = rawText " « " | ||||
| 
 | ||||
| @ -274,14 +274,14 @@ let private partialHead pgTitle = | ||||
| let private pageLayout viewInfo pgTitle content = | ||||
|     body [] [ | ||||
|         Navigation.top viewInfo | ||||
|         div [ _id "pt-body" ] (contentSection viewInfo pgTitle content) | ||||
|         div [ _id "pt-body"; Target.content ] (contentSection viewInfo pgTitle content) | ||||
|         match viewInfo.Layout with | ||||
|         | FullPage -> | ||||
|             script [ _src "/js/ckeditor/ckeditor.js" ] [] | ||||
|             script [ _src "/_/fixi-0.5.7.js" ] [] | ||||
|             Htmx.Script.minified | ||||
|             script [ _src "/_/app.js" ] [] | ||||
|         | _ -> () ] | ||||
|      | ||||
| 
 | ||||
| /// The standard layout(s) for PrayerTracker | ||||
| let standard viewInfo pageTitle content = | ||||
|     let s       = I18N.localizer.Force() | ||||
| @ -328,7 +328,7 @@ let help pageTitle isHome content = | ||||
|                     div [] [ | ||||
|                         locStr s["Language"]; rawText ": " | ||||
|                         match langCode () with | ||||
|                         | "es" ->  | ||||
|                         | "es" -> | ||||
|                             locStr s["Spanish"]; rawText " • " | ||||
|                             a [ _href "/language/en" ] [ locStr s["Change to English"] ] | ||||
|                         | _ -> | ||||
| @ -348,4 +348,3 @@ let help pageTitle isHome content = | ||||
|                             p [ _class "pt-center-text" ] [ | ||||
|                                 a [ _href "/help"; _title s["Help Index"].Value ] [ | ||||
|                                     rawText "« "; locStr s["Back to Help Index"] ] ] ] ] ] ] ] | ||||
|      | ||||
| @ -15,7 +15,6 @@ | ||||
|   </ItemGroup> | ||||
| 
 | ||||
|   <ItemGroup> | ||||
|     <PackageReference Include="Giraffe.Fixi" Version="0.5.7" /> | ||||
|     <PackageReference Include="Giraffe.ViewEngine" Version="1.4.0" /> | ||||
|     <PackageReference Include="Giraffe.ViewEngine.Htmx" Version="2.0.4" /> | ||||
|     <PackageReference Include="MailKit" Version="4.10.0" /> | ||||
|  | ||||
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user