Fix log on flow; add page title

This commit is contained in:
Daniel J. Summers 2021-10-04 13:55:29 -04:00
parent 6dc1ad746c
commit ade3430fb3
3 changed files with 64 additions and 21 deletions

View File

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

View File

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

View File

@ -19,10 +19,12 @@ const mpj = {
}, },
/** Whether the user is currently authenticated */ /** Whether the user is currently authenticated */
isAuthenticated: false, isAuthenticated: false,
/** Whether we should redirect to the journal the next time the menu items are refreshed */
redirToJournal: false,
/** Process a log on request */ /** Process a log on request */
logOn: async (e) => { logOn: async (e) => {
e.preventDefault() 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 */ /** Log the user off */
logOff: (e) => { logOff: (e) => {
@ -54,6 +56,27 @@ window.onload = async () => {
if (query.includes("code=") && query.includes("state=")) { if (query.includes("code=") && query.includes("state=")) {
await mpj.auth.auth0.handleRedirectCallback() await mpj.auth.auth0.handleRedirectCallback()
await establishAuth() 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()
}
})