Version 3.4 #78
@ -5,7 +5,7 @@ RUN dotnet restore
|
|||||||
|
|
||||||
COPY ./MyPrayerJournal ./
|
COPY ./MyPrayerJournal ./
|
||||||
RUN dotnet publish -c Release -r linux-x64
|
RUN dotnet publish -c Release -r linux-x64
|
||||||
RUN rm bin/Release/net8.0/linux-x64/publish/appsettings.*.json
|
RUN rm bin/Release/net8.0/linux-x64/publish/appsettings.*.json || true
|
||||||
|
|
||||||
FROM mcr.microsoft.com/dotnet/aspnet:8.0-alpine as final
|
FROM mcr.microsoft.com/dotnet/aspnet:8.0-alpine as final
|
||||||
WORKDIR /app
|
WORKDIR /app
|
||||||
|
@ -278,13 +278,16 @@ module Components =
|
|||||||
requireUser >=> renderComponent [ RequestId.ofString requestId |> Views.Journal.snooze ]
|
requireUser >=> renderComponent [ RequestId.ofString requestId |> Views.Journal.snooze ]
|
||||||
|
|
||||||
|
|
||||||
/// / URL
|
/// / URL and documentation
|
||||||
module Home =
|
module Home =
|
||||||
|
|
||||||
// GET /
|
// GET /
|
||||||
let home : HttpHandler =
|
let home : HttpHandler =
|
||||||
partialStatic "Welcome!" Views.Layout.home
|
partialStatic "Welcome!" Views.Layout.home
|
||||||
|
|
||||||
|
// GET /docs
|
||||||
|
let docs : HttpHandler =
|
||||||
|
partialStatic "Documentation" Views.Docs.index
|
||||||
|
|
||||||
/// /journal URL
|
/// /journal URL
|
||||||
module Journal =
|
module Journal =
|
||||||
@ -296,7 +299,7 @@ module Journal =
|
|||||||
|> Seq.tryFind (fun c -> c.Type = ClaimTypes.GivenName)
|
|> Seq.tryFind (fun c -> c.Type = ClaimTypes.GivenName)
|
||||||
|> Option.map (_.Value)
|
|> Option.map (_.Value)
|
||||||
|> Option.defaultValue "Your"
|
|> Option.defaultValue "Your"
|
||||||
let title = usr |> match usr with "Your" -> sprintf "%s" | _ -> sprintf "%s's"
|
let title = usr |> match usr with "Your" -> sprintf "%s" | _ -> sprintf "%s’s"
|
||||||
return! partial $"{title} Prayer Journal" (Views.Journal.journal usr) next ctx
|
return! partial $"{title} Prayer Journal" (Views.Journal.journal usr) next ctx
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -530,6 +533,7 @@ let routes = [
|
|||||||
routef "request/%s/snooze" Components.snooze
|
routef "request/%s/snooze" Components.snooze
|
||||||
]
|
]
|
||||||
]
|
]
|
||||||
|
GET_HEAD [ route "/docs" Home.docs ]
|
||||||
GET_HEAD [ route "/journal" Journal.journal ]
|
GET_HEAD [ route "/journal" Journal.journal ]
|
||||||
subRoute "/legal/" [
|
subRoute "/legal/" [
|
||||||
GET_HEAD [
|
GET_HEAD [
|
||||||
|
@ -16,6 +16,7 @@
|
|||||||
<Compile Include="Views/Layout.fs" />
|
<Compile Include="Views/Layout.fs" />
|
||||||
<Compile Include="Views/Legal.fs" />
|
<Compile Include="Views/Legal.fs" />
|
||||||
<Compile Include="Views/Request.fs" />
|
<Compile Include="Views/Request.fs" />
|
||||||
|
<Compile Include="Views\Docs.fs" />
|
||||||
<Compile Include="Handlers.fs" />
|
<Compile Include="Handlers.fs" />
|
||||||
<Compile Include="Program.fs" />
|
<Compile Include="Program.fs" />
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
|
184
src/MyPrayerJournal/Views/Docs.fs
Normal file
184
src/MyPrayerJournal/Views/Docs.fs
Normal file
@ -0,0 +1,184 @@
|
|||||||
|
module MyPrayerJournal.Views.Docs
|
||||||
|
|
||||||
|
open Giraffe.ViewEngine
|
||||||
|
|
||||||
|
/// The "About myPrayerJournal" section
|
||||||
|
let private about = [
|
||||||
|
h3 [ _class "mb-3 mt-4" ] [ rawText "About myPrayerJournal" ]
|
||||||
|
p [] [
|
||||||
|
rawText "Journaling has a long history; it helps people remember what happened, and the act of writing helps "
|
||||||
|
rawText "people think about what happened and process it. A prayer journal is not a new concept; it helps you "
|
||||||
|
rawText "keep track of the requests for which you've prayed, you can use it to pray over things repeatedly, "
|
||||||
|
rawText "and you can write the result when the answer comes "; em [] [ rawText "(or it was “no”)" ]
|
||||||
|
rawText "."
|
||||||
|
]
|
||||||
|
p [] [
|
||||||
|
rawText "myPrayerJournal was borne of out of a personal desire "
|
||||||
|
a [ _href "https://daniel.summershome.org"; _target "_blank"; _rel "noopener" ] [ rawText "Daniel" ]
|
||||||
|
rawText " had to have something that would help him with his prayer life. When it’s time to pray, "
|
||||||
|
rawText "it’s not really time to use an app, so the design goal here is to keep it simple and "
|
||||||
|
rawText "unobtrusive. It will also help eliminate some of the downsides to a paper prayer journal, like not "
|
||||||
|
rawText "remembering whether you’ve prayed for a request, or running out of room to write another update "
|
||||||
|
rawText "on one."
|
||||||
|
]
|
||||||
|
]
|
||||||
|
|
||||||
|
/// The "Signing Up" section
|
||||||
|
let private signUp = [
|
||||||
|
h3 [ _class "mb-3 mt-4" ] [ rawText "Signing Up" ]
|
||||||
|
p [] [
|
||||||
|
rawText "myPrayerJournal uses login services using Google or Microsoft accounts. The only information the "
|
||||||
|
rawText "application stores in its database is your user Id token it receives from these services, so there "
|
||||||
|
rawText "are no permissions you should have to accept from these provider other than establishing that you can "
|
||||||
|
rawText "log on with that account. Because of this, you’ll want to pick the same one each time; the "
|
||||||
|
rawText "tokens between the two accounts are different, even if you use the same e-mail address to log on to "
|
||||||
|
rawText "both."
|
||||||
|
]
|
||||||
|
]
|
||||||
|
|
||||||
|
/// The "Your Prayer Journal" section
|
||||||
|
let private yourJournal = [
|
||||||
|
h3 [ _class "mb-3 mt-4" ] [ rawText "Your Prayer Journal" ]
|
||||||
|
p [] [
|
||||||
|
rawText "Your current requests will be presented in columns (usually three, but it could be more or less, "
|
||||||
|
rawText "depending on the size of your screen or device). Each request is in its own card, and the buttons at "
|
||||||
|
rawText "the top of each card apply to that request. The last line of each request also tells you how long it "
|
||||||
|
rawText "has been since anything has been done on that request. Any time you see something like “a few "
|
||||||
|
rawText "minutes ago,” you can hover over that to see the actual date/time the action was taken."
|
||||||
|
]
|
||||||
|
]
|
||||||
|
|
||||||
|
/// The "Adding a Request" section
|
||||||
|
let private addRequest = [
|
||||||
|
h3 [ _class "mb-3 mt-4" ] [ rawText "Adding a Request" ]
|
||||||
|
p [] [
|
||||||
|
rawText "To add a request, click the “Add a New Request” button at the top of your journal. Then, "
|
||||||
|
rawText "enter the text of the request as you see fit; there is no right or wrong way, and you are the only "
|
||||||
|
rawText "person who will see the text you enter. When you save the request, it will go to the bottom of the "
|
||||||
|
rawText "list of requests."
|
||||||
|
]
|
||||||
|
]
|
||||||
|
|
||||||
|
/// The "Setting Request Recurrence" section
|
||||||
|
let private setRecurrence = [
|
||||||
|
h3 [ _class "mb-3 mt-4" ] [ rawText "Setting Request Recurrence" ]
|
||||||
|
p [] [
|
||||||
|
rawText "When you add or update a request, you can choose whether requests go to the bottom of the journal "
|
||||||
|
rawText "once they have been marked “Prayed” or whether they will reappear after a delay. You can "
|
||||||
|
rawText "set recurrence in terms of hours, days, or weeks, but it cannot be longer than 365 days. If you "
|
||||||
|
rawText "decide you want a request to reappear sooner, you can skip the current delay; click the "
|
||||||
|
rawText "“Active” menu link, find the request in the list (likely near the bottom), and click the "
|
||||||
|
rawText "“Show Now” button."
|
||||||
|
]
|
||||||
|
]
|
||||||
|
|
||||||
|
/// The "Praying for Requests" section
|
||||||
|
let private praying = [
|
||||||
|
h3 [ _class "mb-3 mt-4" ] [ rawText "Praying for Requests" ]
|
||||||
|
p [] [
|
||||||
|
rawText "The first button for each request has a checkmark icon; clicking this button will mark the request as "
|
||||||
|
rawText "“Prayed” and move it to the bottom of the list (or off, if you’ve set a recurrence "
|
||||||
|
rawText "period for the request). This allows you, if you’re praying through your requests, to start at "
|
||||||
|
rawText "the top left (with the request that it’s been the longest since you’ve prayed) and click "
|
||||||
|
rawText "the button as you pray; when the request move below or away, the next-least-recently-prayed request "
|
||||||
|
rawText "will take the top spot."
|
||||||
|
]
|
||||||
|
]
|
||||||
|
|
||||||
|
/// The "Editing Requests" section
|
||||||
|
let private editing = [
|
||||||
|
h3 [ _class "mb-3 mt-4" ] [ rawText "Editing Requests" ]
|
||||||
|
p [] [
|
||||||
|
rawText "The second button for each request has a pencil icon. This allows you to edit the text of the "
|
||||||
|
rawText "request, pretty much the same way you entered it; it starts with the current text, and you can add to "
|
||||||
|
rawText "it, modify it, or completely replace it. By default, updates will go in with an “Updated” "
|
||||||
|
rawText "status; you have the option to also mark this update as “Prayed” or "
|
||||||
|
rawText "“Answered”. Answered requests will drop off the journal list."
|
||||||
|
]
|
||||||
|
]
|
||||||
|
|
||||||
|
/// The "Adding Notes" section
|
||||||
|
let private addNotes = [
|
||||||
|
h3 [ _class "mb-3 mt-4" ] [ rawText "Adding Notes" ]
|
||||||
|
p [] [
|
||||||
|
rawText "The third button for each request has an icon that looks like a speech bubble with lines on it; this "
|
||||||
|
rawText "lets you record notes about the request. If there is something you want to record that doesn’t "
|
||||||
|
rawText "change the text of the request, this is the place to do it. For example, you may be praying for a "
|
||||||
|
rawText "long-term health issue, and that person tells you that their status is the same; or, you may want to "
|
||||||
|
rawText "record something God said to you while you were praying for that request."
|
||||||
|
]
|
||||||
|
]
|
||||||
|
|
||||||
|
/// The "Snoozing Requests" section
|
||||||
|
let private snoozing = [
|
||||||
|
h3 [ _class "mb-3 mt-4" ] [ rawText "Snoozing Requests" ]
|
||||||
|
p [] [
|
||||||
|
rawText "There may be a time where a request does not need to appear. The fourth button, with the clock icon, "
|
||||||
|
rawText "allows you to snooze requests until the day you specify. Additionally, if you have any snoozed "
|
||||||
|
rawText "requests, a “Snoozed” menu item will appear next to the “Journal” one; this "
|
||||||
|
rawText "page allows you to see what requests are snoozed, and return them to your journal by canceling the "
|
||||||
|
rawText "snooze."
|
||||||
|
]
|
||||||
|
]
|
||||||
|
|
||||||
|
/// The "Viewing a Request and Its History" section
|
||||||
|
let private viewing = [
|
||||||
|
h3 [ _class "mb-3 mt-4" ] [ rawText "Viewing a Request and Its History" ]
|
||||||
|
p [] [
|
||||||
|
rawText "myPrayerJournal tracks all of the actions related to a request; from the “Active” and "
|
||||||
|
rawText "“Answered” menu links (and “Snoozed”, if it’s showing), there is a "
|
||||||
|
rawText "“View Full Request” button. That page will show the current text of the request; how many "
|
||||||
|
rawText "times it has been marked as prayed; how long it has been an active request; and a log of all updates, "
|
||||||
|
rawText "prayers, and notes you have recorded. That log is listed from most recent to least recent; if you "
|
||||||
|
rawText "want to read it chronologically, press the “End” key on your keyboard and read it from "
|
||||||
|
rawText "the bottom up."
|
||||||
|
]
|
||||||
|
p [] [
|
||||||
|
rawText "The “Active” link will show all requests that have not yet been marked answered, "
|
||||||
|
rawText "including snoozed and recurring requests. If requests are snoozed, or in a recurrence period off the "
|
||||||
|
rawText "journal, there will be a button where you can return the request to the list (either “Cancel "
|
||||||
|
rawText "Snooze” or “Show Now”). The “Answered” link shows all requests that "
|
||||||
|
rawText "have been marked answered. The “Snoozed” link only shows snoozed requests."
|
||||||
|
]
|
||||||
|
]
|
||||||
|
|
||||||
|
/// The "Final Notes" section
|
||||||
|
let private finalNotes = [
|
||||||
|
h3 [ _class "mb-3 mt-4" ] [ rawText "Final Notes" ]
|
||||||
|
ul [] [
|
||||||
|
li [] [
|
||||||
|
rawText "If you encounter errors, please "
|
||||||
|
a [ _href "https://git.bitbadger.solutions/bit-badger/myPrayerJournal/issues"; _target "_blank" ] [
|
||||||
|
rawText "file an issue"
|
||||||
|
]; rawText " (or "
|
||||||
|
a [ _href "mailto:daniel@bitbadger.solutions?subject=myPrayerJournal+Issue" ] [ rawText "e-mail Daniel" ]
|
||||||
|
rawText " if you do not have an account on that server) with as much detail as possible. You can also "
|
||||||
|
rawText "provide suggestions, or browse the list of currently open issues."
|
||||||
|
]
|
||||||
|
li [] [
|
||||||
|
rawText "Prayer requests and their history are securely backed up nightly along with other Bit Badger "
|
||||||
|
rawText "Solutions data."
|
||||||
|
]
|
||||||
|
li [] [
|
||||||
|
rawText "Prayer changes things - most of all, the one doing the praying. I pray that this tool enables you "
|
||||||
|
rawText "to deepen and strengthen your prayer life."
|
||||||
|
]
|
||||||
|
]
|
||||||
|
]
|
||||||
|
|
||||||
|
/// The documentation page
|
||||||
|
let index =
|
||||||
|
article [ _class "container mt-3" ] [
|
||||||
|
h2 [ _class "mb-3" ] [ rawText "Documentation" ]
|
||||||
|
yield! about
|
||||||
|
yield! signUp
|
||||||
|
yield! yourJournal
|
||||||
|
yield! addRequest
|
||||||
|
yield! setRecurrence
|
||||||
|
yield! praying
|
||||||
|
yield! editing
|
||||||
|
yield! addNotes
|
||||||
|
yield! snoozing
|
||||||
|
yield! viewing
|
||||||
|
yield! finalNotes
|
||||||
|
]
|
@ -6,48 +6,44 @@ open Giraffe.ViewEngine.Accessibility
|
|||||||
|
|
||||||
/// The data needed to render a page-level view
|
/// The data needed to render a page-level view
|
||||||
type PageRenderContext =
|
type PageRenderContext =
|
||||||
{ /// Whether the user is authenticated
|
{ /// Whether the user is authenticated
|
||||||
IsAuthenticated : bool
|
IsAuthenticated: bool
|
||||||
|
|
||||||
/// Whether the user has snoozed requests
|
/// Whether the user has snoozed requests
|
||||||
HasSnoozed : bool
|
HasSnoozed: bool
|
||||||
|
|
||||||
/// The current URL
|
/// The current URL
|
||||||
CurrentUrl : string
|
CurrentUrl: string
|
||||||
|
|
||||||
/// The title for the page to be rendered
|
/// The title for the page to be rendered
|
||||||
PageTitle : string
|
PageTitle: string
|
||||||
|
|
||||||
/// The content of the page
|
/// The content of the page
|
||||||
Content : XmlNode
|
Content: XmlNode }
|
||||||
}
|
|
||||||
|
|
||||||
/// The home page
|
/// The home page
|
||||||
let home =
|
let home =
|
||||||
article [ _class "container mt-3" ] [
|
article [ _class "container mt-3" ]
|
||||||
p [] [ rawText " " ]
|
[ p [] [ rawText " " ]
|
||||||
p [] [
|
p []
|
||||||
str "myPrayerJournal is a place where individuals can record their prayer requests, record that they "
|
[ str "myPrayerJournal is a place where individuals can record their prayer requests, record that they "
|
||||||
str "prayed for them, update them as God moves in the situation, and record a final answer received on "
|
str "prayed for them, update them as God moves in the situation, and record a final answer received on "
|
||||||
str "that request. It also allows individuals to review their answered prayers."
|
str "that request. It also allows individuals to review their answered prayers." ]
|
||||||
]
|
p []
|
||||||
p [] [
|
[ str "This site is open and available to the general public. To get started, simply click the "
|
||||||
str "This site is open and available to the general public. To get started, simply click the "
|
rawText "“Log On” link above, and log on with either a Microsoft or Google account. You can "
|
||||||
rawText "“Log On” link above, and log on with either a Microsoft or Google account. You can "
|
rawText "also learn more about the site at the “Docs” link, also above." ] ]
|
||||||
rawText "also learn more about the site at the “Docs” link, also above."
|
|
||||||
]
|
|
||||||
]
|
|
||||||
|
|
||||||
/// The default navigation bar, which will load the items on page load, and whenever a refresh event occurs
|
/// The default navigation bar, which will load the items on page load, and whenever a refresh event occurs
|
||||||
let private navBar ctx =
|
let private navBar ctx =
|
||||||
nav [ _class "navbar navbar-dark"; _roleNavigation ] [
|
nav [ _class "navbar navbar-dark"; _roleNavigation ]
|
||||||
div [ _class "container-fluid" ] [
|
[ div [ _class "container-fluid" ]
|
||||||
pageLink "/" [ _class "navbar-brand" ] [
|
[ pageLink
|
||||||
span [ _class "m" ] [ str "my" ]
|
"/" [ _class "navbar-brand" ]
|
||||||
span [ _class "p" ] [ str "Prayer" ]
|
[ span [ _class "m" ] [ str "my" ]
|
||||||
span [ _class "j" ] [ str "Journal" ]
|
span [ _class "p" ] [ str "Prayer" ]
|
||||||
]
|
span [ _class "j" ] [ str "Journal" ] ]
|
||||||
seq {
|
seq {
|
||||||
let navLink (matchUrl : string) =
|
let navLink (matchUrl : string) =
|
||||||
match ctx.CurrentUrl.StartsWith matchUrl with true -> [ _class "is-active-route" ] | false -> []
|
match ctx.CurrentUrl.StartsWith matchUrl with true -> [ _class "is-active-route" ] | false -> []
|
||||||
|> pageLink matchUrl
|
|> pageLink matchUrl
|
||||||
@ -58,91 +54,72 @@ let private navBar ctx =
|
|||||||
li [ _class "nav-item" ] [ navLink "/requests/answered" [ str "Answered" ] ]
|
li [ _class "nav-item" ] [ navLink "/requests/answered" [ str "Answered" ] ]
|
||||||
li [ _class "nav-item" ] [ a [ _href "/user/log-off" ] [ str "Log Off" ] ]
|
li [ _class "nav-item" ] [ a [ _href "/user/log-off" ] [ str "Log Off" ] ]
|
||||||
else li [ _class "nav-item"] [ a [ _href "/user/log-on" ] [ str "Log On" ] ]
|
else li [ _class "nav-item"] [ a [ _href "/user/log-on" ] [ str "Log On" ] ]
|
||||||
li [ _class "nav-item" ] [
|
li [ _class "nav-item" ] [ navLink "/docs" [ str "Docs" ] ]
|
||||||
a [ _href "https://docs.prayerjournal.me"; _target "_blank"; _rel "noopener" ] [ str "Docs" ]
|
}
|
||||||
]
|
|> List.ofSeq
|
||||||
}
|
|> ul [ _class "navbar-nav me-auto d-flex flex-row" ] ] ]
|
||||||
|> List.ofSeq
|
|
||||||
|> ul [ _class "navbar-nav me-auto d-flex flex-row" ]
|
|
||||||
]
|
|
||||||
]
|
|
||||||
|
|
||||||
/// The title tag with the application name appended
|
/// The title tag with the application name appended
|
||||||
let titleTag ctx =
|
let titleTag ctx =
|
||||||
title [] [ str ctx.PageTitle; rawText " « myPrayerJournal" ]
|
title [] [ rawText ctx.PageTitle; rawText " « myPrayerJournal" ]
|
||||||
|
|
||||||
/// The HTML `head` element
|
/// The HTML `head` element
|
||||||
let htmlHead ctx =
|
let htmlHead ctx =
|
||||||
head [ _lang "en" ] [
|
head [ _lang "en" ]
|
||||||
meta [ _name "viewport"; _content "width=device-width, initial-scale=1" ]
|
[ meta [ _name "viewport"; _content "width=device-width, initial-scale=1" ]
|
||||||
meta [ _name "description"; _content "Online prayer journal - free w/Google or Microsoft account" ]
|
meta [ _name "description"; _content "Online prayer journal - free w/Google or Microsoft account" ]
|
||||||
titleTag ctx
|
titleTag ctx
|
||||||
link [ _href "https://cdn.jsdelivr.net/npm/bootstrap@5.3.2/dist/css/bootstrap.min.css"
|
link [ _href "https://cdn.jsdelivr.net/npm/bootstrap@5.3.2/dist/css/bootstrap.min.css"
|
||||||
_rel "stylesheet"
|
_rel "stylesheet"
|
||||||
_integrity "sha384-T3c6CoIi6uLrA9TneNEoa7RxnatzjcDSCmG1MXxSR1GAsXEV/Dwwykc2MPK8M2HN"
|
_integrity "sha384-T3c6CoIi6uLrA9TneNEoa7RxnatzjcDSCmG1MXxSR1GAsXEV/Dwwykc2MPK8M2HN"
|
||||||
_crossorigin "anonymous" ]
|
_crossorigin "anonymous" ]
|
||||||
link [ _href "https://fonts.googleapis.com/icon?family=Material+Icons"; _rel "stylesheet" ]
|
link [ _href "https://fonts.googleapis.com/icon?family=Material+Icons"; _rel "stylesheet" ]
|
||||||
link [ _href "/style/style.css"; _rel "stylesheet" ]
|
link [ _href "/style/style.css"; _rel "stylesheet" ] ]
|
||||||
]
|
|
||||||
|
|
||||||
/// Element used to display toasts
|
/// Element used to display toasts
|
||||||
let toaster =
|
let toaster =
|
||||||
div [ _ariaLive "polite"; _ariaAtomic "true"; _id "toastHost" ] [
|
div [ _ariaLive "polite"; _ariaAtomic "true"; _id "toastHost" ]
|
||||||
div [ _class "toast-container position-absolute p-3 bottom-0 end-0"; _id "toasts" ] []
|
[ div [ _class "toast-container position-absolute p-3 bottom-0 end-0"; _id "toasts" ] [] ]
|
||||||
]
|
|
||||||
|
|
||||||
/// The page's `footer` element
|
/// The page's `footer` element
|
||||||
let htmlFoot =
|
let htmlFoot =
|
||||||
footer [ _class "container-fluid" ] [
|
footer [ _class "container-fluid" ]
|
||||||
p [ _class "text-muted text-end" ] [
|
[ p [ _class "text-muted text-end" ]
|
||||||
str $"myPrayerJournal {version}"
|
[ str $"myPrayerJournal {version}"
|
||||||
br []
|
br []
|
||||||
em [] [
|
em []
|
||||||
small [] [
|
[ small []
|
||||||
pageLink "/legal/privacy-policy" [] [ str "Privacy Policy" ]
|
[ pageLink "/legal/privacy-policy" [] [ str "Privacy Policy" ]
|
||||||
rawText " • "
|
rawText " • "
|
||||||
pageLink "/legal/terms-of-service" [] [ str "Terms of Service" ]
|
pageLink "/legal/terms-of-service" [] [ str "Terms of Service" ]
|
||||||
rawText " • "
|
rawText " • "
|
||||||
a [ _href "https://github.com/bit-badger/myprayerjournal"; _target "_blank"; _rel "noopener" ] [
|
a [ _href "https://git.bitbadger.solutions/bit-badger/myPrayerJournal"
|
||||||
str "Developed"
|
_target "_blank"
|
||||||
]
|
_rel "noopener" ] [ str "Developed" ]
|
||||||
str " and hosted by "
|
str " and hosted by "
|
||||||
a [ _href "https://bitbadger.solutions"; _target "_blank"; _rel "noopener" ] [
|
a [ _href "https://bitbadger.solutions"; _target "_blank"; _rel "noopener" ]
|
||||||
str "Bit Badger Solutions"
|
[ str "Bit Badger Solutions" ] ] ] ]
|
||||||
]
|
Htmx.Script.minified
|
||||||
]
|
script [] [ rawText "if (!htmx) document.write('<script src=\"/script/htmx.min.js\"><\/script>')" ]
|
||||||
]
|
script [ _async
|
||||||
]
|
_src "https://cdn.jsdelivr.net/npm/bootstrap@5.3.2/dist/js/bootstrap.bundle.min.js"
|
||||||
Htmx.Script.minified
|
_integrity "sha384-C6RzsynM9kWDrMNeT87bh95OGNyZPhcTNXj1NW7RuBCsyN/o0jlpcV8Qyq46cDfL"
|
||||||
script [] [
|
_crossorigin "anonymous" ] []
|
||||||
rawText "if (!htmx) document.write('<script src=\"/script/htmx.min.js\"><\/script>')"
|
script []
|
||||||
]
|
[ rawText "setTimeout(function () { "
|
||||||
script [ _async
|
rawText "if (!bootstrap) document.write('<script src=\"/script/bootstrap.bundle.min.js\"><\/script>') "
|
||||||
_src "https://cdn.jsdelivr.net/npm/bootstrap@5.3.2/dist/js/bootstrap.bundle.min.js"
|
rawText "}, 2000)" ]
|
||||||
_integrity "sha384-C6RzsynM9kWDrMNeT87bh95OGNyZPhcTNXj1NW7RuBCsyN/o0jlpcV8Qyq46cDfL"
|
script [ _src "/script/mpj.js" ] [] ]
|
||||||
_crossorigin "anonymous" ] []
|
|
||||||
script [] [
|
|
||||||
rawText "setTimeout(function () { "
|
|
||||||
rawText "if (!bootstrap) document.write('<script src=\"/script/bootstrap.bundle.min.js\"><\/script>') "
|
|
||||||
rawText "}, 2000)"
|
|
||||||
]
|
|
||||||
script [ _src "/script/mpj.js" ] []
|
|
||||||
]
|
|
||||||
|
|
||||||
/// Create the full view of the page
|
/// Create the full view of the page
|
||||||
let view ctx =
|
let view ctx =
|
||||||
html [ _lang "en" ] [
|
html [ _lang "en" ]
|
||||||
htmlHead ctx
|
[ htmlHead ctx
|
||||||
body [] [
|
body []
|
||||||
section [ _id "top"; _ariaLabel "Top navigation" ] [ navBar ctx; main [ _roleMain ] [ ctx.Content ] ]
|
[ section [ _id "top"; _ariaLabel "Top navigation" ] [ navBar ctx; main [ _roleMain ] [ ctx.Content ] ]
|
||||||
toaster
|
toaster
|
||||||
htmlFoot
|
htmlFoot ] ]
|
||||||
]
|
|
||||||
]
|
|
||||||
|
|
||||||
/// Create a partial view
|
/// Create a partial view
|
||||||
let partial ctx =
|
let partial ctx =
|
||||||
html [ _lang "en" ] [
|
html [ _lang "en" ] [ head [] [ titleTag ctx ]; body [] [ navBar ctx; main [ _roleMain ] [ ctx.Content ] ] ]
|
||||||
head [] [ titleTag ctx ]
|
|
||||||
body [] [ navBar ctx; main [ _roleMain ] [ ctx.Content ] ]
|
|
||||||
]
|
|
||||||
|
Loading…
Reference in New Issue
Block a user