Fix request/announcement text (#36)
- Update defaults for small group - Add support for native font stack (#38) - Fix color picker error when named color is selected - Use invariant culture for URL formatting (#41)
This commit is contained in:
parent
ab3f8dcc43
commit
ae29a6c03b
src
@ -312,6 +312,13 @@ type ListPreferences =
|
||||
/// How the as-of date should be automatically displayed
|
||||
AsOfDateDisplay : AsOfDateDisplay
|
||||
}
|
||||
with
|
||||
|
||||
/// The list of fonts to use when displaying request lists (converts "native" to native font stack)
|
||||
member this.FontStack =
|
||||
if this.Fonts = "native" then
|
||||
"""system-ui,-apple-system,"Segoe UI",Roboto,Ubuntu,"Liberation Sans",Cantarell,"Helvetica Neue",sans-serif"""
|
||||
else this.Fonts
|
||||
|
||||
/// Functions to support list preferences
|
||||
module ListPreferences =
|
||||
@ -323,8 +330,8 @@ module ListPreferences =
|
||||
DaysToKeepNew = 7
|
||||
LongTermUpdateWeeks = 4
|
||||
EmailFromName = "PrayerTracker"
|
||||
EmailFromAddress = "prayer@djs-consulting.com"
|
||||
Fonts = "Century Gothic,Tahoma,Luxi Sans,sans-serif"
|
||||
EmailFromAddress = "prayer@bitbadger.solutions"
|
||||
Fonts = "native"
|
||||
HeadingColor = "maroon"
|
||||
LineColor = "navy"
|
||||
HeadingFontSize = 16
|
||||
|
@ -98,6 +98,15 @@ let expirationTests =
|
||||
[<Tests>]
|
||||
let listPreferencesTests =
|
||||
testList "ListPreferences" [
|
||||
test "FontStack is correct for native fonts" {
|
||||
Expect.equal ListPreferences.empty.FontStack
|
||||
"""system-ui,-apple-system,"Segoe UI",Roboto,Ubuntu,"Liberation Sans",Cantarell,"Helvetica Neue",sans-serif"""
|
||||
"The expected native font stack was incorrect"
|
||||
}
|
||||
test "FontStack is correct for specific fonts" {
|
||||
Expect.equal { ListPreferences.empty with Fonts = "Arial,sans-serif" }.FontStack "Arial,sans-serif"
|
||||
"The specified fonts were not returned correctly"
|
||||
}
|
||||
test "empty is as expected" {
|
||||
let mt = ListPreferences.empty
|
||||
Expect.equal mt.SmallGroupId.Value Guid.Empty "The small group ID should have been an empty GUID"
|
||||
@ -107,7 +116,7 @@ let listPreferencesTests =
|
||||
Expect.equal mt.EmailFromName "PrayerTracker" "The default e-mail from name should have been PrayerTracker"
|
||||
Expect.equal mt.EmailFromAddress "prayer@djs-consulting.com"
|
||||
"The default e-mail from address should have been prayer@djs-consulting.com"
|
||||
Expect.equal mt.Fonts "Century Gothic,Tahoma,Luxi Sans,sans-serif" "The default list fonts were incorrect"
|
||||
Expect.equal mt.Fonts "native" "The default list fonts were incorrect"
|
||||
Expect.equal mt.HeadingColor "maroon" "The default heading text color should have been maroon"
|
||||
Expect.equal mt.LineColor "navy" "The default heding line color should have been navy"
|
||||
Expect.equal mt.HeadingFontSize 16 "The default heading font size should have been 16"
|
||||
|
@ -78,6 +78,28 @@ let namedColorList name selected attrs (s : IStringLocalizer) =
|
||||
|> List.ofSeq
|
||||
|> select (_name name :: attrs)
|
||||
|
||||
/// Convert a named color to its hex notation
|
||||
let colorToHex (color : string) =
|
||||
match color with
|
||||
| it when it.StartsWith "#" -> color
|
||||
| "aqua" -> "#00ffff"
|
||||
| "black" -> "#000000"
|
||||
| "blue" -> "#0000ff"
|
||||
| "fuchsia" -> "#ff00ff"
|
||||
| "gray" -> "#808080"
|
||||
| "green" -> "#008000"
|
||||
| "lime" -> "#00ff00"
|
||||
| "maroon" -> "#800000"
|
||||
| "navy" -> "#000080"
|
||||
| "olive" -> "#808000"
|
||||
| "purple" -> "#800080"
|
||||
| "red" -> "#ff0000"
|
||||
| "silver" -> "#c0c0c0"
|
||||
| "teal" -> "#008080"
|
||||
| "white" -> "#ffffff"
|
||||
| "yellow" -> "#ffff00"
|
||||
| it -> it
|
||||
|
||||
/// Generate an input[type=radio] that is selected if its value is the current value
|
||||
let radio name domId value current =
|
||||
input [ _type "radio"
|
||||
|
@ -1,6 +1,6 @@
|
||||
module PrayerTracker.Views.PrayerRequest
|
||||
|
||||
open System
|
||||
open System.Globalization
|
||||
open System.IO
|
||||
open Giraffe
|
||||
open Giraffe.ViewEngine
|
||||
@ -17,7 +17,11 @@ let edit (model : EditRequest) today ctx viewInfo =
|
||||
let s = I18N.localizer.Force ()
|
||||
let pageTitle = if model.IsNew then "Add a New Request" else "Edit Request"
|
||||
let vi = AppViewInfo.withOnLoadScript "PT.initCKEditor" viewInfo
|
||||
form [ _action "/prayer-request/save"; _method "post"; _class "pt-center-columns"; Target.content ] [
|
||||
form [ _action "/prayer-request/save"
|
||||
_method "post"
|
||||
_class "pt-center-columns"
|
||||
_onsubmit "PT.updateCKEditor()"
|
||||
Target.content ] [
|
||||
csrfToken ctx
|
||||
inputField "hidden" (nameof model.RequestId) model.RequestId []
|
||||
div [ _fieldRow ] [
|
||||
@ -79,7 +83,7 @@ let email model viewInfo =
|
||||
let pageTitle = $"""{s["Prayer Requests"].Value} • {model.SmallGroup.Name}"""
|
||||
let prefs = model.SmallGroup.Preferences
|
||||
let addresses = model.Recipients |> List.map (fun mbr -> $"{mbr.Name} <{mbr.Email}>") |> String.concat ", "
|
||||
[ p [ _style $"font-family:{prefs.Fonts};font-size:%i{prefs.TextFontSize}pt;" ] [
|
||||
[ p [ _style $"font-family:{prefs.FontStack};font-size:%i{prefs.TextFontSize}pt;" ] [
|
||||
locStr s["The request list was sent to the following people, via individual e-mails"]
|
||||
rawText ":"
|
||||
br []
|
||||
@ -202,7 +206,7 @@ let maintain (model : MaintainRequests) (ctx : HttpContext) viewInfo =
|
||||
]
|
||||
]
|
||||
div [ updateClass ] [
|
||||
str (req.UpdatedDate.ToString(s["MMMM d, yyyy"].Value, Globalization.CultureInfo.CurrentUICulture))
|
||||
str (req.UpdatedDate.ToString(s["MMMM d, yyyy"].Value, CultureInfo.CurrentUICulture))
|
||||
]
|
||||
div [ _class "cell" ] [ locStr types[req.RequestType] ]
|
||||
div [ expiredClass ] [ str (match req.Requestor with Some r -> r | None -> " ") ]
|
||||
@ -300,7 +304,7 @@ let print model version =
|
||||
rawText (model.AsHtml s)
|
||||
br []
|
||||
hr []
|
||||
div [ _style $"font-size:70%%;font-family:{model.SmallGroup.Preferences.Fonts};" ] [
|
||||
div [ _style $"font-size:70%%;font-family:{model.SmallGroup.Preferences.FontStack};" ] [
|
||||
img [ _src $"""/img/{s["footer_en"].Value}.png"""
|
||||
_style "vertical-align:text-bottom;"
|
||||
_alt imgAlt
|
||||
@ -317,7 +321,7 @@ 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", null) // TODO: this should be invariant
|
||||
let dtString = model.Date.ToString ("yyyy-MM-dd", CultureInfo.InvariantCulture)
|
||||
[ div [ _class "pt-center-text" ] [
|
||||
br []
|
||||
a [ _class "pt-icon-link"
|
||||
@ -333,7 +337,7 @@ let view model viewInfo =
|
||||
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", null)}""" // TODO: make invariant
|
||||
_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"]
|
||||
]
|
||||
|
@ -14,7 +14,11 @@ let announcement isAdmin ctx viewInfo =
|
||||
let model = { SendToClass = ""; Text = ""; AddToRequestList = None; RequestType = None }
|
||||
let reqTypes = ReferenceList.requestTypeList s
|
||||
let vi = AppViewInfo.withOnLoadScript "PT.smallGroup.announcement.onPageLoad" viewInfo
|
||||
form [ _action "/small-group/announcement/send"; _method "post"; _class "pt-center-columns"; Target.content ] [
|
||||
form [ _action "/small-group/announcement/send"
|
||||
_method "post"
|
||||
_class "pt-center-columns"
|
||||
_onsubmit "PT.updateCKEditor()"
|
||||
Target.content ] [
|
||||
csrfToken ctx
|
||||
div [ _fieldRow ] [
|
||||
div [ _inputFieldWith [ "pt-editor" ] ] [
|
||||
@ -461,7 +465,7 @@ let preferences (model : EditPreferences) ctx viewInfo =
|
||||
input [ _type "color"
|
||||
_name (nameof model.LineColor)
|
||||
_id $"{nameof model.LineColor}_Color"
|
||||
_value model.LineColor // TODO: convert to hex or skip if named
|
||||
_value (colorToHex model.LineColor)
|
||||
if not (model.LineColor.StartsWith "#") then _disabled ]
|
||||
]
|
||||
]
|
||||
@ -483,7 +487,7 @@ let preferences (model : EditPreferences) ctx viewInfo =
|
||||
input [ _type "color"
|
||||
_name (nameof model.HeadingColor)
|
||||
_id $"{nameof model.HeadingColor}_Color"
|
||||
_value model.HeadingColor // TODO: convert to hex or skip if named
|
||||
_value (colorToHex model.HeadingColor)
|
||||
if not (model.HeadingColor.StartsWith "#") then _disabled ]
|
||||
]
|
||||
]
|
||||
|
@ -778,7 +778,7 @@ with
|
||||
let p = this.SmallGroup.Preferences
|
||||
let asOfSize = Math.Round (float p.TextFontSize * 0.8, 2)
|
||||
[ if this.ShowHeader then
|
||||
div [ _style $"text-align:center;font-family:{p.Fonts}" ] [
|
||||
div [ _style $"text-align:center;font-family:{p.FontStack}" ] [
|
||||
span [ _style $"font-size:%i{p.HeadingFontSize}pt;" ] [
|
||||
strong [] [ str s["Prayer Requests"].Value ]
|
||||
]
|
||||
@ -792,7 +792,7 @@ with
|
||||
br []
|
||||
for _, name, reqs in this.RequestsByType s do
|
||||
div [ _style "padding-left:10px;padding-bottom:.5em;" ] [
|
||||
table [ _style $"font-family:{p.Fonts};page-break-inside:avoid;" ] [
|
||||
table [ _style $"font-family:{p.FontStack};page-break-inside:avoid;" ] [
|
||||
tr [] [
|
||||
td [ _style $"font-size:%i{p.HeadingFontSize}pt;color:{p.HeadingColor};padding:3px 0;border-top:solid 3px {p.LineColor};border-bottom:solid 3px {p.LineColor};font-weight:bold;" ] [
|
||||
rawText " "; str name.Value; rawText " "
|
||||
@ -804,7 +804,7 @@ with
|
||||
reqs
|
||||
|> List.map (fun req ->
|
||||
let bullet = if this.IsNew req then "circle" else "disc"
|
||||
li [ _style $"list-style-type:{bullet};font-family:{p.Fonts};font-size:%i{p.TextFontSize}pt;padding-bottom:.25em;" ] [
|
||||
li [ _style $"list-style-type:{bullet};font-family:{p.FontStack};font-size:%i{p.TextFontSize}pt;padding-bottom:.25em;" ] [
|
||||
match req.Requestor with
|
||||
| Some r when r <> "" ->
|
||||
strong [] [ str r ]
|
||||
|
@ -260,7 +260,7 @@ let sendAnnouncement : HttpHandler = requireAccess [ User ] >=> validateCsrf >=>
|
||||
// Reformat the text to use the class's font stylings
|
||||
let requestText = ckEditorToText model.Text
|
||||
let htmlText =
|
||||
p [ _style $"font-family:{pref.Fonts};font-size:%d{pref.TextFontSize}pt;" ] [ rawText requestText ]
|
||||
p [ _style $"font-family:{pref.FontStack};font-size:%d{pref.TextFontSize}pt;" ] [ rawText requestText ]
|
||||
|> renderHtmlNode
|
||||
let plainText = (htmlToPlainText >> wordWrap 74) htmlText
|
||||
// Send the e-mails
|
||||
|
@ -86,9 +86,17 @@ this.PT = {
|
||||
initCKEditor() {
|
||||
ClassicEditor
|
||||
.create(document.querySelector("#Text"))
|
||||
.then(editor => window.ckEditor = editor)
|
||||
.catch(console.error)
|
||||
},
|
||||
|
||||
/**
|
||||
* Instruct the current CKEditor element to update its source (needed as htmx does not fire the submit event)
|
||||
*/
|
||||
updateCKEditor() {
|
||||
window.ckEditor.updateElement()
|
||||
},
|
||||
|
||||
/**
|
||||
* Scripts for pages served by the Church controller
|
||||
*/
|
||||
|
@ -29,11 +29,14 @@ ALTER TABLE pt."ListPreference" RENAME COLUMN "PageSize" TO page_size;
|
||||
ALTER TABLE pt."ListPreference" RENAME COLUMN "AsOfDateDisplay" TO as_of_date_display;
|
||||
ALTER TABLE pt."ListPreference" RENAME CONSTRAINT "PK_ListPreference" TO pk_list_preference;
|
||||
ALTER TABLE pt."ListPreference" RENAME CONSTRAINT "FK_ListPreference_SmallGroup_SmallGroupId" TO fk_list_preference_small_group_id;
|
||||
ALTER TABLE pt."ListPreference" RENAME CONSTRAINT "FK_ListPreference_TimeZone_TimeZoneId" TO fk_list_preference_time_zone_id;
|
||||
ALTER TABLE pt."ListPreference" DROP CONSTRAINT "FK_ListPreference_TimeZone_TimeZoneId";
|
||||
ALTER TABLE pt."ListPreference" RENAME TO list_preference;
|
||||
|
||||
ALTER INDEX pt."IX_ListPreference_TimeZoneId" RENAME TO ix_list_preference_time_zone_id;
|
||||
|
||||
ALTER TABLE pt.list_preference ALTER COLUMN email_from_address SET DEFAULT 'prayer@bitbadger.solutions';
|
||||
ALTER TABLE pt.list_preference ALTER COLUMN fonts SET DEFAULT 'native';
|
||||
|
||||
-- Small Group Member
|
||||
ALTER TABLE pt."Member" RENAME COLUMN "MemberId" TO id;
|
||||
ALTER TABLE pt."Member" RENAME COLUMN "SmallGroupId" TO small_group_id;
|
||||
@ -77,7 +80,6 @@ ALTER TABLE pt."SmallGroup" RENAME TO small_group;
|
||||
ALTER INDEX pt."IX_SmallGroup_ChurchId" RENAME TO ix_small_group_church_id;
|
||||
|
||||
-- Time Zone (goes away)
|
||||
ALTER TABLE pt.list_preference DROP CONSTRAINT fk_list_preference_time_zone_id;
|
||||
DROP TABLE pt."TimeZone";
|
||||
|
||||
-- User
|
||||
|
Loading…
Reference in New Issue
Block a user