Handle errors on htmx requests (#36)
- Use grouping for sets of links (#38)
This commit is contained in:
parent
1b48acd66a
commit
d0068577b3
|
@ -150,6 +150,9 @@ let _inputField = _inputFieldWith []
|
|||
/// The class that designates a checkbox / label pair
|
||||
let _checkboxField = _class "pt-checkbox-field"
|
||||
|
||||
/// A group of related fields, inputs, links, etc., displayed in a row
|
||||
let _group = _class "pt-group"
|
||||
|
||||
/// Create an input field of the given type, with matching name and ID and the given value
|
||||
let inputField typ name value attrs =
|
||||
List.concat [ [ _type typ; _name name; _id name; if value <> "" then _value value ]; attrs ] |> input
|
||||
|
|
|
@ -54,7 +54,7 @@ let edit (model : EditRequest) today ctx viewInfo =
|
|||
div [ _fieldRow ] [
|
||||
div [ _inputField ] [
|
||||
label [] [ locStr s["Expiration"] ]
|
||||
span [ _class "pt-radio-group" ] [
|
||||
span [ _group ] [
|
||||
for code, name in ReferenceList.expirationList s (not model.IsNew) do
|
||||
label [] [ radio (nameof model.Expiration) "" code model.Expiration; locStr name ]
|
||||
]
|
||||
|
@ -212,22 +212,22 @@ let maintain (model : MaintainRequests) (ctx : HttpContext) viewInfo =
|
|||
]
|
||||
])
|
||||
|> List.ofSeq
|
||||
[ div [ _class "pt-center-text" ] [
|
||||
br []
|
||||
a [ _href $"/prayer-request/{emptyGuid}/edit"; _title s["Add a New Request"].Value ] [
|
||||
icon "add_circle"; rawText " "; locStr s["Add a New Request"]
|
||||
]
|
||||
rawText " "
|
||||
a [ _href "/prayer-requests/view"; _title s["View Prayer Request List"].Value ] [
|
||||
icon "list"; rawText " "; locStr s["View Prayer Request List"]
|
||||
]
|
||||
match model.SearchTerm with
|
||||
| Some _ ->
|
||||
rawText " "
|
||||
a [ _href "/prayer-requests"; _title l["Clear Search Criteria"].Value ] [
|
||||
icon "highlight_off"; rawText " "; raw l["Clear Search Criteria"]
|
||||
[ br []
|
||||
div [ _fieldRow ] [
|
||||
span [ _group ] [
|
||||
a [ _href $"/prayer-request/{emptyGuid}/edit"; _title s["Add a New Request"].Value ] [
|
||||
icon "add_circle"; rawText " "; locStr s["Add a New Request"]
|
||||
]
|
||||
| None -> ()
|
||||
a [ _href "/prayer-requests/view"; _title s["View Prayer Request List"].Value ] [
|
||||
icon "list"; rawText " "; locStr s["View Prayer Request List"]
|
||||
]
|
||||
match model.SearchTerm with
|
||||
| Some _ ->
|
||||
a [ _href "/prayer-requests"; _title l["Clear Search Criteria"].Value ] [
|
||||
icon "highlight_off"; rawText " "; raw l["Clear Search Criteria"]
|
||||
]
|
||||
| None -> ()
|
||||
]
|
||||
]
|
||||
form [ _action "/prayer-requests"; _method "get"; _class "pt-center-text pt-search-form"; Target.content ] [
|
||||
inputField "text" "search" (defaultArg model.SearchTerm "") [ _placeholder l["Search requests..."].Value ]
|
||||
|
@ -300,9 +300,9 @@ let print model version =
|
|||
br []
|
||||
hr []
|
||||
div [ _style $"font-size:70%%;font-family:{model.SmallGroup.Preferences.FontStack};" ] [
|
||||
img [ _src $"""/img/{s["footer_en"].Value}.png"""
|
||||
img [ _src $"""/img/{s["footer_en"].Value}.png"""
|
||||
_style "vertical-align:text-bottom;"
|
||||
_alt imgAlt
|
||||
_alt imgAlt
|
||||
_title imgAlt ]
|
||||
space
|
||||
str version
|
||||
|
@ -315,38 +315,36 @@ let print model version =
|
|||
let view model viewInfo =
|
||||
let s = I18N.localizer.Force ()
|
||||
let pageTitle = $"""{s["Prayer Requests"].Value} • {model.SmallGroup.Name}"""
|
||||
let spacer = rawText " "
|
||||
let dtString = model.Date.ToString ("yyyy-MM-dd", CultureInfo.InvariantCulture)
|
||||
[ div [ _class "pt-center-text" ] [
|
||||
br []
|
||||
a [ _class "pt-icon-link"
|
||||
_href $"/prayer-requests/print/{dtString}"
|
||||
_target "_blank"
|
||||
_title s["View Printable"].Value ] [
|
||||
icon "print"; rawText " "; locStr s["View Printable"]
|
||||
]
|
||||
if model.CanEmail then
|
||||
spacer
|
||||
if model.Date.DayOfWeek <> IsoDayOfWeek.Sunday then
|
||||
let rec findSunday (date : LocalDate) =
|
||||
if date.DayOfWeek = IsoDayOfWeek.Sunday then date else findSunday (date.PlusDays 1)
|
||||
let sunday = findSunday model.Date
|
||||
a [ _class "pt-icon-link"
|
||||
_href $"""/prayer-requests/view/{sunday.ToString ("yyyy-MM-dd", CultureInfo.InvariantCulture)}"""
|
||||
_title s["List for Next Sunday"].Value ] [
|
||||
icon "update"; rawText " "; locStr s["List for Next Sunday"]
|
||||
]
|
||||
spacer
|
||||
let emailPrompt = s["This will e-mail the current list to every member of your group, without further prompting. Are you sure this is what you are ready to do?"].Value
|
||||
a [ _class "pt-icon-link"
|
||||
_href $"/prayer-requests/email/{dtString}"
|
||||
_title s["Send via E-mail"].Value
|
||||
_onclick $"return PT.requests.view.promptBeforeEmail('{emailPrompt}')" ] [
|
||||
icon "mail_outline"; rawText " "; locStr s["Send via E-mail"]
|
||||
[ br []
|
||||
div [ _fieldRow ] [
|
||||
span [ _group ] [
|
||||
a [ _class "pt-icon-link"
|
||||
_href $"/prayer-requests/print/{dtString}"
|
||||
_target "_blank"
|
||||
_title s["View Printable"].Value ] [
|
||||
icon "print"; rawText " "; locStr s["View Printable"]
|
||||
]
|
||||
spacer
|
||||
a [ _class "pt-icon-link"; _href "/prayer-requests"; _title s["Maintain Prayer Requests"].Value ] [
|
||||
icon "compare_arrows"; rawText " "; locStr s["Maintain Prayer Requests"]
|
||||
if model.CanEmail then
|
||||
if model.Date.DayOfWeek <> IsoDayOfWeek.Sunday then
|
||||
let rec findSunday (date : LocalDate) =
|
||||
if date.DayOfWeek = IsoDayOfWeek.Sunday then date else findSunday (date.PlusDays 1)
|
||||
let sunday = findSunday model.Date
|
||||
a [ _class "pt-icon-link"
|
||||
_href $"""/prayer-requests/view/{sunday.ToString ("yyyy-MM-dd", CultureInfo.InvariantCulture)}"""
|
||||
_title s["List for Next Sunday"].Value ] [
|
||||
icon "update"; rawText " "; locStr s["List for Next Sunday"]
|
||||
]
|
||||
let emailPrompt = s["This will e-mail the current list to every member of your group, without further prompting. Are you sure this is what you are ready to do?"].Value
|
||||
a [ _class "pt-icon-link"
|
||||
_href $"/prayer-requests/email/{dtString}"
|
||||
_title s["Send via E-mail"].Value
|
||||
_onclick $"return PT.requests.view.promptBeforeEmail('{emailPrompt}')" ] [
|
||||
icon "mail_outline"; rawText " "; locStr s["Send via E-mail"]
|
||||
]
|
||||
a [ _class "pt-icon-link"; _href "/prayer-requests"; _title s["Maintain Prayer Requests"].Value ] [
|
||||
icon "compare_arrows"; rawText " "; locStr s["Maintain Prayer Requests"]
|
||||
]
|
||||
]
|
||||
]
|
||||
br []
|
||||
|
|
|
@ -30,7 +30,7 @@ let announcement isAdmin ctx viewInfo =
|
|||
div [ _fieldRow ] [
|
||||
div [ _inputField ] [
|
||||
label [] [ locStr s["Send Announcement to"]; rawText ":" ]
|
||||
div [ _class "pt-radio-group" ] [
|
||||
div [ _group ] [
|
||||
label [] [
|
||||
radio (nameof model.SendToClass) $"{nameof model.SendToClass}_Y" "Y" "Y"
|
||||
locStr s["This Group"]
|
||||
|
@ -457,7 +457,7 @@ let preferences (model : EditPreferences) ctx viewInfo =
|
|||
div [ _fieldRow ] [
|
||||
div [ _inputField ] [
|
||||
label [] [ locStr s["Color of Heading Lines"] ]
|
||||
span [ _class "pt-radio-group" ] [
|
||||
span [ _group ] [
|
||||
span [] [
|
||||
label [] [
|
||||
radio (nameof model.LineColorType) $"{nameof model.LineColorType}_Name" "Name"
|
||||
|
@ -488,7 +488,7 @@ let preferences (model : EditPreferences) ctx viewInfo =
|
|||
div [ _fieldRow ] [
|
||||
div [ _inputField ] [
|
||||
label [] [ locStr s["Color of Heading Text"] ]
|
||||
span [ _class "pt-radio-group" ] [
|
||||
span [ _group ] [
|
||||
span [] [
|
||||
label [] [
|
||||
radio (nameof model.HeadingColorType) $"{nameof model.HeadingColorType}_Name" "Name"
|
||||
|
@ -522,14 +522,14 @@ let preferences (model : EditPreferences) ctx viewInfo =
|
|||
div [ _inputField ] [
|
||||
label [ _for (nameof model.Fonts) ] [ locStr s["Fonts** for List"] ]
|
||||
let value = if model.IsNative then "True" else "False"
|
||||
span [ _class "pt-radio-group" ] [
|
||||
span [ _group ] [
|
||||
label [] [
|
||||
radio (nameof model.IsNative) $"{nameof model.IsNative}_Y" "True" value
|
||||
locStr s["Native Fonts"]
|
||||
]
|
||||
inputField "text" "nativeFontSpacer" "" [ _style "visibility:hidden" ]
|
||||
]
|
||||
span [ _class "pt-radio-group" ] [
|
||||
span [ _group ] [
|
||||
label [] [
|
||||
radio (nameof model.IsNative) $"{nameof model.IsNative}_N" "False" value
|
||||
locStr s["Named Fonts"]
|
||||
|
@ -557,7 +557,7 @@ let preferences (model : EditPreferences) ctx viewInfo =
|
|||
div [ _fieldRow ] [
|
||||
div [ _inputField ] [
|
||||
label [] [ locStr s["Request List Visibility"] ]
|
||||
span [ _class "pt-radio-group" ] [
|
||||
span [ _group ] [
|
||||
let name = nameof model.Visibility
|
||||
let value = string model.Visibility
|
||||
label [] [
|
||||
|
|
|
@ -126,7 +126,7 @@ let expire reqId : HttpHandler = requireAccess [ User ] >=> fun next ctx -> task
|
|||
|
||||
/// GET /prayer-requests/[group-id]/list
|
||||
let list groupId : HttpHandler = requireAccess [ AccessLevel.Public ] >=> fun next ctx -> task {
|
||||
match! SmallGroups.tryByIdWithPreferences groupId ctx.Conn with
|
||||
match! SmallGroups.tryByIdWithPreferences (SmallGroupId groupId) ctx.Conn with
|
||||
| Some group when group.Preferences.IsPublic ->
|
||||
let! reqs =
|
||||
PrayerRequests.forGroup
|
||||
|
|
|
@ -254,7 +254,7 @@ footer a:hover {
|
|||
text-transform: uppercase;
|
||||
color: #777;
|
||||
}
|
||||
.pt-radio-group {
|
||||
.pt-group {
|
||||
display: flex;
|
||||
flex-flow: row;
|
||||
gap: 1.5rem;
|
||||
|
|
|
@ -301,3 +301,23 @@ this.PT = {
|
|||
htmx.on("htmx:configRequest", function (e) {
|
||||
e.detail.headers["X-Target"] = e.detail.target
|
||||
})
|
||||
htmx.on("htmx:responseError", function (e) {
|
||||
/** @type {XMLHttpRequest} */
|
||||
const xhr = e.detail.xhr
|
||||
|
||||
const detail = document.createElement("div")
|
||||
detail.className = "description"
|
||||
detail.innerHTML = `<em>(Status code ${xhr.status}: ${xhr.statusText})</em>`
|
||||
|
||||
const msg = document.createElement("div")
|
||||
msg.className = "pt-msg error"
|
||||
msg.innerHTML = `<strong>ERROR</strong> » ${xhr.responseText}<br>`
|
||||
msg.appendChild(detail)
|
||||
|
||||
const messages = document.createElement("div")
|
||||
messages.className = "pt-messages"
|
||||
messages.appendChild(msg)
|
||||
|
||||
const title = document.getElementById("pt-page-title")
|
||||
title.parentNode.insertBefore(messages, title.nextSibling)
|
||||
})
|
||||
|
|
Loading…
Reference in New Issue
Block a user