Fix log on flow; add page title
This commit is contained in:
parent
6dc1ad746c
commit
ade3430fb3
@ -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" [
|
||||||
|
@ -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
|
||||||
@ -50,6 +50,13 @@ module Home =
|
|||||||
]
|
]
|
||||||
]
|
]
|
||||||
|
|
||||||
|
/// The log on page
|
||||||
|
let logOn = article [ _class "container mt-3" ] [
|
||||||
|
p [] [
|
||||||
|
em [] [ str "Verifying..." ]
|
||||||
|
]
|
||||||
|
]
|
||||||
|
|
||||||
|
|
||||||
/// Views for legal pages
|
/// Views for legal pages
|
||||||
module Legal =
|
module Legal =
|
||||||
@ -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 " « 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
|
||||||
]
|
]
|
||||||
]
|
]
|
||||||
|
@ -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 += " « 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()
|
||||||
|
}
|
||||||
|
})
|
||||||
|
Loading…
Reference in New Issue
Block a user