Version 3 #67

Merged
danieljsummers merged 53 commits from version-3 into master 2021-10-26 23:39:59 +00:00
3 changed files with 64 additions and 21 deletions
Showing only changes of commit ade3430fb3 - Show all commits

View File

@ -8,13 +8,20 @@ open Giraffe
open Giraffe.Htmx
open MyPrayerJournal.Data.Extensions
/// Send a partial result if this is not a full page load
let partialIfNotRefresh content : HttpHandler =
let writeView view : HttpHandler =
fun next ctx -> task {
match ctx.Request.IsHtmx && not ctx.Request.IsHtmxRefresh with
| true -> return! ctx.WriteHtmlViewAsync content
| false -> return! Views.Layout.view content |> ctx.WriteHtmlViewAsync
}
return! ctx.WriteHtmlViewAsync view
}
/// Send a partial result if this is not a full page load
let partialIfNotRefresh (pageTitle : string) content : HttpHandler =
fun next ctx ->
(next, ctx)
||> match ctx.Request.IsHtmx && not ctx.Request.IsHtmxRefresh with
| true ->
ctx.Response.Headers.["X-Page-Title"] <- Microsoft.Extensions.Primitives.StringValues pageTitle
withHxTriggerAfterSettle "menu-refresh" >=> writeView content
| false -> writeView (Views.Layout.view pageTitle content)
/// Handler to return Vue files
module Vue =
@ -22,7 +29,7 @@ module Vue =
/// The application index page
let app : HttpHandler =
withHxTrigger "menu-refresh"
>=> partialIfNotRefresh (ViewEngine.HtmlElements.str "It works")
>=> partialIfNotRefresh "" (ViewEngine.HtmlElements.str "It works")
open System
@ -180,7 +187,11 @@ module Home =
// GET /
let home : HttpHandler =
withMenuRefresh >=> partialIfNotRefresh Views.Home.home
withMenuRefresh >=> partialIfNotRefresh "Welcome!" Views.Home.home
// GET /user/log-on
let logOn : HttpHandler =
partialIfNotRefresh "Logging on..." Views.Home.logOn
/// /journal URL
@ -192,7 +203,7 @@ module Journal =
>=> withMenuRefresh
>=> fun next ctx -> task {
let usr = ctx.Request.Headers.["X-Given-Name"].[0]
return! partialIfNotRefresh (Views.Journal.journal usr) next ctx
return! partialIfNotRefresh "Your Prayer Journal" (Views.Journal.journal usr) next ctx
}
@ -201,11 +212,11 @@ module Legal =
// GET /legal/privacy-policy
let privacyPolicy : HttpHandler =
withMenuRefresh >=> partialIfNotRefresh Views.Legal.privacyPolicy
withMenuRefresh >=> partialIfNotRefresh "Privacy Policy" Views.Legal.privacyPolicy
// GET /legal/terms-of-service
let termsOfService : HttpHandler =
withMenuRefresh >=> partialIfNotRefresh Views.Legal.termsOfService
withMenuRefresh >=> partialIfNotRefresh "Terms of Service" Views.Legal.termsOfService
/// /api/request and /request(s) URLs
@ -292,7 +303,7 @@ module Request =
>=> withMenuRefresh
>=> fun next ctx -> task {
let! reqs = Data.journalByUserId (userId ctx) (db ctx)
return! partialIfNotRefresh (Views.Request.active reqs) next ctx
return! partialIfNotRefresh "Active Requests" (Views.Request.active reqs) next ctx
}
/// GET /requests/answered
@ -301,7 +312,7 @@ module Request =
>=> withMenuRefresh
>=> fun next ctx -> task {
let! reqs = Data.answeredRequests (userId ctx) (db ctx)
return! partialIfNotRefresh (Views.Request.answered reqs) next ctx
return! partialIfNotRefresh "Answered Requests" (Views.Request.answered reqs) next ctx
}
/// GET /api/request/[req-id]
@ -319,7 +330,7 @@ module Request =
>=> withMenuRefresh
>=> fun next ctx -> task {
match! Data.tryFullRequestById (toReqId requestId) (userId ctx) (db ctx) with
| Some req -> return! partialIfNotRefresh (Views.Request.full req) next ctx
| Some req -> return! partialIfNotRefresh "Full Prayer Request" (Views.Request.full req) next ctx
| None -> return! Error.notFound next ctx
}
@ -402,6 +413,7 @@ let routes =
route "s/answered" Request.answered
routef "/%s/full" Request.getFull
]
route "/user/log-on" Home.logOn
subRoute "/api/" [
GET [
subRoute "request" [

View File

@ -32,7 +32,7 @@ module Helpers =
span [ _title (date.ToString "f") ] [ Dates.formatDistance DateTime.Now date |> str ]
/// View for home page
/// Views for home and log on pages
module Home =
/// The home page
@ -49,6 +49,13 @@ module Home =
rawText "learn more about the site at the &ldquo;Docs&rdquo; link, also above."
]
]
/// The log on page
let logOn = article [ _class "container mt-3" ] [
p [] [
em [] [ str "Verifying..." ]
]
]
/// Views for legal pages
@ -406,8 +413,9 @@ module Request =
/// Layout views
module Layout =
let htmlHead =
let htmlHead pageTitle =
head [] [
title [] [ str pageTitle; rawText " &#xab; myPrayerJournal" ]
link [
_href "https://cdn.jsdelivr.net/npm/bootstrap@5.0.2/dist/css/bootstrap.min.css"
_rel "stylesheet"
@ -451,12 +459,12 @@ module Layout =
]
/// Create the full view of the page
let view content =
let view pageTitle content =
html [ _lang "en" ] [
htmlHead
htmlHead pageTitle
body [ _hxHeaders "" ] [
Navigation.navBar
main [] [ content ]
main [ _hxTrigger "setTitle from:body" ] [ content ]
htmlFoot
]
]

View File

@ -19,10 +19,12 @@ const mpj = {
},
/** Whether the user is currently authenticated */
isAuthenticated: false,
/** Whether we should redirect to the journal the next time the menu items are refreshed */
redirToJournal: false,
/** Process a log on request */
logOn: async (e) => {
e.preventDefault()
await mpj.auth.auth0.loginWithRedirect({ redirect_uri: window.location.origin })
await mpj.auth.auth0.loginWithRedirect({ redirect_uri: `${window.location.origin}/user/log-on` })
},
/** Log the user off */
logOff: (e) => {
@ -54,6 +56,27 @@ window.onload = async () => {
if (query.includes("code=") && query.includes("state=")) {
await mpj.auth.auth0.handleRedirectCallback()
await establishAuth()
window.history.replaceState({}, document.title, "/")
if (window.location.pathname === "/user/log-on") {
mpj.redirToJournal = true
} else {
window.history.replaceState({}, document.title, "/")
}
}
}
htmx.on("htmx:afterOnLoad", function (evt) {
// Set the page title if a header was in the response
if (evt.detail.xhr.getAllResponseHeaders().indexOf("x-page-title") >= 0) {
const title = document.querySelector("title")
title.innerText = evt.detail.xhr.getResponseHeader("x-page-title")
title.innerHTML += " &#xab; myPrayerJournal"
}
})
htmx.on("htmx:afterSettle", function (evt) {
// Redirect to the journal (once menu items load after log on)
if (mpj.redirToJournal
&& ([...evt.target.attributes].find(it => it.name === "hx-target")?.value ?? "") === ".navbar-nav") {
mpj.redirToJournal = false
document.querySelector(`a[href="/journal"]`).click()
}
})